]> granicus.if.org Git - nethack/commitdiff
Add <Someone>'s comments to file
authornethack.allison <nethack.allison>
Sun, 11 May 2003 23:42:25 +0000 (23:42 +0000)
committernethack.allison <nethack.allison>
Sun, 11 May 2003 23:42:25 +0000 (23:42 +0000)
sys/winnt/nhraykey.c

index 0e7345944a36c13d097180ed182931f7e0245aa7..bb2416e5151b83c680ad610a2c48a27c88c87391 100644 (file)
-/*     SCCS Id: @(#)nhdefkey.c 3.4     $Date$   */
+/*     SCCS Id: @(#)nhraykey.c 3.4     $Date$   */
 /* Copyright (c) NetHack PC Development Team 2003                      */
 /* NetHack may be freely redistributed.  See license for details.      */
 
 /*
- * This is the default NetHack keystroke processing.
- * It can be built as a run-time loadable dll (nhdefkey.dll).
- * Alternative keystroke handlers can be built using the
- * entry points in this file as a template.
- *
- * Use the defaults.nh "altkeyhandler" option to set a
- * different dll name (without the ".DLL" extension) to
- * get different processing. Ensure that the dll referenced
- * in defaults.nh exists in the same directory as NetHack in
- * order for it to load successfully.
- *
+ * Keystroke handling contributed by Ray Chason.
+ *  
+ * The problem
+ * ===========
+ * 
+ * The console-mode Nethack wants both keyboard and mouse input.  The
+ * problem is that the Windows API provides no easy way to get mouse input
+ * and also keyboard input properly translated according to the user's
+ * chosen keyboard layout.
+ * 
+ * The ReadConsoleInput function returns a stream of keyboard and mouse
+ * events.  Nethack is interested in those events that represent a key
+ * pressed, or a click on a mouse button.  The keyboard events from
+ * ReadConsoleInput are not translated according to the keyboard layout,
+ * and do not take into account the shift, control, or alt keys.
+ * 
+ * The PeekConsoleInput function works similarly to ReadConsoleInput,
+ * except that it does not remove an event from the queue and it returns
+ * instead of blocking when the queue is empty.
+ * 
+ * A program can also use ReadConsole to get a properly translated stream
+ * of characters.  Unfortunately, ReadConsole does not return mouse events,
+ * does not distinguish the keypad from the main keyboard, does not return
+ * keys shifted with Alt, and does not even return the ESC key when
+ * pressed.  
+ * 
+ * We want both the functionality of ReadConsole and the functionality of
+ * ReadConsoleInput.  But Microsoft didn't seem to think of that.
+ * 
+ * 
+ * The solution, in the original code
+ * ==================================
+ * 
+ * The original 3.4.1 distribution tries to get proper keyboard translation
+ * by passing keyboard events to the ToAscii function.  This works, to some
+ * extent -- it takes the shift key into account, and it processes dead
+ * keys properly.  But it doesn't take non-US keyboards into account.  It
+ * appears that ToAscii is meant for windowed applications, and does not
+ * have enough information to do its job properly in a console application.
+ * 
+ * 
+ * The Finnish keyboard patch
+ * ==========================
+ * 
+ * This patch adds the "subkeyvalue" option to the defaults.nh file.  The
+ * user can then add OPTIONS=sukeyvalue:171/92, for instance, to replace
+ * the 171 character with 92, which is \.  This works, once properly
+ * configured, but places too much burden on the user.  It also bars the
+ * use of the substituted characters in naming objects or monsters.
+ * 
+ * 
+ * The solution presented here
+ * ===========================
+ * 
+ * The best way I could find to combine the functionality of ReadConsole
+ * with that of ReadConsoleInput is simple in concept.  First, call
+ * PeekConsoleInput to get the first event.  If it represents a key press,
+ * call ReadConsole to retrieve the key.  Otherwise, pop it off the queue
+ * with ReadConsoleInput and, if it's a mouse click, return it as such.
+ * 
+ * But the Devil, as they say, is in the details.  The problem is in
+ * recognizing an event that ReadConsole will return as a key.  We don't
+ * want to call ReadConsole unless we know that it will immediately return:
+ * if it blocks, the mouse and the Alt sequences will cease to function
+ * until it returns.
+ * 
+ * Separating process_keystroke into two functions, one for commands and a
+ * new one, process_keystroke2, for answering prompts, makes the job a lot
+ * easier.  process_keystroke2 doesn't have to worry about mouse events or
+ * Alt sequences, and so the consequences are minor if ReadConsole blocks. 
+ * process_keystroke, OTOH, never needs to return a non-ASCII character
+ * that was read from ReadConsole; it returns bytes with the high bit set
+ * only in response to an Alt sequence.
+ * 
+ * So in process_keystroke, before calling ReadConsole, a bogus key event
+ * is pushed on the queue.  This event causes ReadConsole to return, even
+ * if there was no other character available.  Because the bogus key has
+ * the eighth bit set, it is filtered out.  This is not done in
+ * process_keystroke2, because that would render dead keys unusable.
+ * 
+ * A separate process_keystroke2 can also process the numeric keypad in a
+ * way that makes sense for prompts:  just return the corresponding symbol,
+ * and pay no mind to number_pad or the num lock key.
+ * 
+ * The recognition of Alt sequences is modified, to support the use of
+ * characters generated with the AltGr key.  A keystroke is an Alt sequence
+ * if an Alt key is seen that can't be an AltGr (since an AltGr sequence
+ * could be a character, and in some layouts it could even be an ASCII
+ * character).  This recognition is different on NT-based and 95-based
+ * Windows:
+ * 
+ *    * On NT-based Windows, AltGr signals as right Alt and left Ctrl
+ *      together.  So an Alt sequence is recognized if either Alt key is
+ *      pressed and if right Alt and left Ctrl are not both present.  This
+ *      is true even if the keyboard in use does not have an AltGr key, and
+ *      uses right Alt for AltGr.
+ * 
+ *    * On 95-based Windows, with a keyboard that lacks the AltGr key, the
+ *      right Alt key is used instead.  But it still signals as right Alt,
+ *      without left Ctrl.  There is no way for the application to know
+ *      whether right Alt is Alt or AltGr, and so it is always assumed
+ *      to be AltGr.  This means that Alt sequences must be formed with
+ *      left Alt.
+ * 
+ * So the patch processes keystrokes as follows:
+ * 
+ *     * If the scan and virtual key codes are both 0, it's the bogus key,
+ *       and we ignore it.
+ * 
+ *     * Keys on the numeric keypad are processed for commands as in the
+ *       unpatched Nethack, and for prompts by returning the ASCII
+ *       character, even if the num lock is off.
+ *        
+ *     * Alt sequences are processed for commands as in the unpatched
+ *       Nethack, and ignored for prompts.
+ *        
+ *     * Control codes are returned as received, because ReadConsole will
+ *       not return the ESC key.
+ *        
+ *     * Other key-down events are passed to ReadConsole.  The use of
+ *       ReadConsole is different for commands than for prompts:
+ * 
+ *       o For commands, the bogus key is pushed onto the queue before
+ *         ReadConsole is called.  On return, non-ASCII characters are
+ *         filtered, so they are not mistaken for Alt sequences; this also
+ *         filters the bogus key.
+ * 
+ *       o For prompts, the bogus key is not used, because that would
+ *         interfere with dead keys.  Eight bit characters may be returned,
+ *         and are coded in the configured code page.
+ * 
+ * 
+ * Possible improvements
+ * =====================
+ * 
+ * Some possible improvements remain:
+ * 
+ *     * Integrate the existing Finnish keyboard patch, for use with non-
+ *       QWERTY layouts such as the German QWERTZ keyboard or Dvorak.
+ *        
+ *     * Fix the keyboard glitches in the graphical version.  Namely, dead
+ *       keys don't work, and input comes in as ISO-8859-1 but is displayed
+ *       as code page 437 if IBMgraphics is set on startup.
+ * 
+ *     * Transform incoming text to ISO-8859-1, for full compatibility with
+ *       the graphical version.
+ * 
+ *     * After pushing the bogus key and calling ReadConsole, check to see
+ *       if we got the bogus key; if so, and an Alt is pressed, process the
+ *       event as an Alt sequence.
  */
 
 static char where_to_get_source[] = "http://www.nethack.org/";