/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinkey.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinkey.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkWinKey.c --   * tkWinKey.c --
5   *   *
6   *      This file contains X emulation routines for keyboard related   *      This file contains X emulation routines for keyboard related
7   *      functions.   *      functions.
8   *   *
9   * Copyright (c) 1995 Sun Microsystems, Inc.   * Copyright (c) 1995 Sun Microsystems, Inc.
10   *   *
11   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
12   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13   *   *
14   * RCS: @(#) $Id: tkwinkey.c,v 1.1.1.1 2001/06/13 05:13:42 dtashley Exp $   * RCS: @(#) $Id: tkwinkey.c,v 1.1.1.1 2001/06/13 05:13:42 dtashley Exp $
15   */   */
16    
17  #include "tkWinInt.h"  #include "tkWinInt.h"
18  /*  /*
19   * The keymap table holds mappings of Windows keycodes to X keysyms.   * The keymap table holds mappings of Windows keycodes to X keysyms.
20   * If Windows ever comes along and changes the value of their keycodes,   * If Windows ever comes along and changes the value of their keycodes,
21   * this will break all kinds of things.  However, this table lookup is much   * this will break all kinds of things.  However, this table lookup is much
22   * faster than the alternative, in which we walked a list of keycodes looking   * faster than the alternative, in which we walked a list of keycodes looking
23   * for a match.  Since this lookup is performed for every Windows keypress   * for a match.  Since this lookup is performed for every Windows keypress
24   * event, it seems like a worthwhile improvement to use the table.   * event, it seems like a worthwhile improvement to use the table.
25   */   */
26  #define MAX_KEYCODE 145 /* VK_SCROLL is the last entry in our table below */  #define MAX_KEYCODE 145 /* VK_SCROLL is the last entry in our table below */
27  static KeySym keymap[] = {  static KeySym keymap[] = {
28      NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol,      NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol,
29          NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab,          NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab,
30          NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol,          NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol,
31          NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause,          NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause,
32          XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
33          NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol,
34          NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next,          NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next,
35          XK_End, XK_Home, XK_Left, XK_Up, XK_Right,          XK_End, XK_Home, XK_Left, XK_Up, XK_Right,
36          XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol,          XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol,
37          XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol,          XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol,
38          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
39          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
40          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
41          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
42          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
43          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
44          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
45          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
46          NoSymbol, XK_Win_L, XK_Win_R, XK_App, NoSymbol,          NoSymbol, XK_Win_L, XK_Win_R, XK_App, NoSymbol,
47          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
48          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
49          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
50          NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3,          NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3,
51          XK_F4, XK_F5, XK_F6, XK_F7, XK_F8,          XK_F4, XK_F5, XK_F6, XK_F7, XK_F8,
52          XK_F9, XK_F10, XK_F11, XK_F12, XK_F13,          XK_F9, XK_F10, XK_F11, XK_F12, XK_F13,
53          XK_F14, XK_F15, XK_F16, XK_F17, XK_F18,          XK_F14, XK_F15, XK_F16, XK_F17, XK_F18,
54          XK_F19, XK_F20, XK_F21, XK_F22, XK_F23,          XK_F19, XK_F20, XK_F21, XK_F22, XK_F23,
55          XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol,          XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
56          NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock,          NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock,
57          XK_Scroll_Lock          XK_Scroll_Lock
58  };  };
59    
60  /*  /*
61   * Prototypes for local procedures defined in this file:   * Prototypes for local procedures defined in this file:
62   */   */
63    
64  static KeySym           KeycodeToKeysym _ANSI_ARGS_((unsigned int keycode,  static KeySym           KeycodeToKeysym _ANSI_ARGS_((unsigned int keycode,
65                              int state, int noascii));                              int state, int noascii));
66    
67  /*  /*
68   *----------------------------------------------------------------------   *----------------------------------------------------------------------
69   *   *
70   * TkpGetString --   * TkpGetString --
71   *   *
72   *      Retrieve the UTF string equivalent for the given keyboard event.   *      Retrieve the UTF string equivalent for the given keyboard event.
73   *   *
74   * Results:   * Results:
75   *      Returns the UTF string.   *      Returns the UTF string.
76   *   *
77   * Side effects:   * Side effects:
78   *      None.   *      None.
79   *   *
80   *----------------------------------------------------------------------   *----------------------------------------------------------------------
81   */   */
82    
83  char *  char *
84  TkpGetString(winPtr, eventPtr, dsPtr)  TkpGetString(winPtr, eventPtr, dsPtr)
85      TkWindow *winPtr;           /* Window where event occurred:  needed to      TkWindow *winPtr;           /* Window where event occurred:  needed to
86                                   * get input context. */                                   * get input context. */
87      XEvent *eventPtr;           /* X keyboard event. */      XEvent *eventPtr;           /* X keyboard event. */
88      Tcl_DString *dsPtr;         /* Uninitialized or empty string to hold      Tcl_DString *dsPtr;         /* Uninitialized or empty string to hold
89                                   * result. */                                   * result. */
90  {  {
91      KeySym keysym;      KeySym keysym;
92      XKeyEvent* keyEv = &eventPtr->xkey;      XKeyEvent* keyEv = &eventPtr->xkey;
93    
94      Tcl_DStringInit(dsPtr);      Tcl_DStringInit(dsPtr);
95      if (eventPtr->xkey.send_event != -1) {      if (eventPtr->xkey.send_event != -1) {
96          /*          /*
97           * This is an event generated from generic code.  It has no           * This is an event generated from generic code.  It has no
98           * nchars or trans_chars members.           * nchars or trans_chars members.
99           */           */
100    
101          keysym = KeycodeToKeysym(eventPtr->xkey.keycode,          keysym = KeycodeToKeysym(eventPtr->xkey.keycode,
102                  eventPtr->xkey.state, 0);                  eventPtr->xkey.state, 0);
103          if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))          if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
104                  || (keysym == XK_Return)                  || (keysym == XK_Return)
105                  || (keysym == XK_Tab)) {                  || (keysym == XK_Tab)) {
106              char buf[TCL_UTF_MAX];              char buf[TCL_UTF_MAX];
107              int len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);              int len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
108              Tcl_DStringAppend(dsPtr, buf, len);              Tcl_DStringAppend(dsPtr, buf, len);
109          }          }
110      } else if (eventPtr->xkey.nbytes > 0) {      } else if (eventPtr->xkey.nbytes > 0) {
111          Tcl_ExternalToUtfDString(NULL, eventPtr->xkey.trans_chars,          Tcl_ExternalToUtfDString(NULL, eventPtr->xkey.trans_chars,
112                  eventPtr->xkey.nbytes, dsPtr);                  eventPtr->xkey.nbytes, dsPtr);
113      }      }
114      return Tcl_DStringValue(dsPtr);      return Tcl_DStringValue(dsPtr);
115  }  }
116    
117  /*  /*
118   *----------------------------------------------------------------------   *----------------------------------------------------------------------
119   *   *
120   * XKeycodeToKeysym --   * XKeycodeToKeysym --
121   *   *
122   *      Translate from a system-dependent keycode to a   *      Translate from a system-dependent keycode to a
123   *      system-independent keysym.   *      system-independent keysym.
124   *   *
125   * Results:   * Results:
126   *      Returns the translated keysym, or NoSymbol on failure.   *      Returns the translated keysym, or NoSymbol on failure.
127   *   *
128   * Side effects:   * Side effects:
129   *      None.   *      None.
130   *   *
131   *----------------------------------------------------------------------   *----------------------------------------------------------------------
132   */   */
133    
134  KeySym  KeySym
135  XKeycodeToKeysym(display, keycode, index)  XKeycodeToKeysym(display, keycode, index)
136      Display* display;      Display* display;
137      unsigned int keycode;      unsigned int keycode;
138      int index;      int index;
139  {  {
140      int state = 0;      int state = 0;
141    
142      if (index & 0x01) {      if (index & 0x01) {
143          state |= ShiftMask;          state |= ShiftMask;
144      }      }
145      return KeycodeToKeysym(keycode, state, 0);      return KeycodeToKeysym(keycode, state, 0);
146  }  }
147    
148    
149    
150  /*  /*
151   *----------------------------------------------------------------------   *----------------------------------------------------------------------
152   *   *
153   * KeycodeToKeysym --   * KeycodeToKeysym --
154   *   *
155   *      Translate from a system-dependent keycode to a   *      Translate from a system-dependent keycode to a
156   *      system-independent keysym.   *      system-independent keysym.
157   *   *
158   * Results:   * Results:
159   *      Returns the translated keysym, or NoSymbol on failure.   *      Returns the translated keysym, or NoSymbol on failure.
160   *   *
161   * Side effects:   * Side effects:
162   *      It may affect the internal state of the keyboard, such as   *      It may affect the internal state of the keyboard, such as
163   *      remembered dead key or lock indicator lamps.   *      remembered dead key or lock indicator lamps.
164   *   *
165   *----------------------------------------------------------------------   *----------------------------------------------------------------------
166   */   */
167    
168  static KeySym  static KeySym
169  KeycodeToKeysym(keycode, state, noascii)  KeycodeToKeysym(keycode, state, noascii)
170      unsigned int keycode;      unsigned int keycode;
171      int state;      int state;
172      int noascii;      int noascii;
173  {  {
174      BYTE keys[256];      BYTE keys[256];
175      int result, deadkey, shift;      int result, deadkey, shift;
176      char buf[4];      char buf[4];
177      unsigned int scancode = MapVirtualKey(keycode, 0);      unsigned int scancode = MapVirtualKey(keycode, 0);
178    
179      /*      /*
180       * Do not run keycodes of lock keys through ToAscii().       * Do not run keycodes of lock keys through ToAscii().
181       * One of ToAscii()'s side effects is to handle the lights       * One of ToAscii()'s side effects is to handle the lights
182       * on the keyboard, and we don't want to mess that up.       * on the keyboard, and we don't want to mess that up.
183       */       */
184    
185      if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL ||      if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL ||
186              keycode == VK_NUMLOCK)              keycode == VK_NUMLOCK)
187          goto skipToAscii;          goto skipToAscii;
188    
189      /*      /*
190       * Use MapVirtualKey() to detect some dead keys.       * Use MapVirtualKey() to detect some dead keys.
191       */       */
192    
193      if (MapVirtualKey(keycode, 2) > 0x7fffUL)      if (MapVirtualKey(keycode, 2) > 0x7fffUL)
194          return XK_Multi_key;          return XK_Multi_key;
195    
196      /*      /*
197       * Set up a keyboard with correct modifiers       * Set up a keyboard with correct modifiers
198       */       */
199    
200      memset(keys, 0, 256);      memset(keys, 0, 256);
201      if (state & ShiftMask)      if (state & ShiftMask)
202          keys[VK_SHIFT] = 0x80;          keys[VK_SHIFT] = 0x80;
203      if (state & ControlMask)      if (state & ControlMask)
204          keys[VK_CONTROL] = 0x80;          keys[VK_CONTROL] = 0x80;
205      if (state & Mod2Mask)      if (state & Mod2Mask)
206          keys[VK_MENU] = 0x80;          keys[VK_MENU] = 0x80;
207    
208      /*      /*
209       * Make sure all lock button info is correct so we don't mess up the       * Make sure all lock button info is correct so we don't mess up the
210       * lights       * lights
211       */       */
212    
213      if (state & LockMask)      if (state & LockMask)
214          keys[VK_CAPITAL] = 1;          keys[VK_CAPITAL] = 1;
215      if (state & Mod3Mask)      if (state & Mod3Mask)
216          keys[VK_SCROLL] = 1;          keys[VK_SCROLL] = 1;
217      if (state & Mod1Mask)      if (state & Mod1Mask)
218          keys[VK_NUMLOCK] = 1;          keys[VK_NUMLOCK] = 1;
219    
220      result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);      result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
221    
222      if (result < 0) {      if (result < 0) {
223          /*          /*
224           * Win95/98:           * Win95/98:
225           * This was a dead char, which is now remembered by the keyboard.           * This was a dead char, which is now remembered by the keyboard.
226           * Call ToAscii() again to forget it.           * Call ToAscii() again to forget it.
227           * WinNT:           * WinNT:
228           * This was a dead char, overwriting any previously remembered           * This was a dead char, overwriting any previously remembered
229           * key. Calling ToAscii() again does not affect anything.           * key. Calling ToAscii() again does not affect anything.
230           */           */
231    
232          ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);          ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
233          return XK_Multi_key;          return XK_Multi_key;
234      }      }
235      if (result == 2) {      if (result == 2) {
236          /*          /*
237           * This was a dead char, and there were one previously remembered           * This was a dead char, and there were one previously remembered
238           * by the keyboard.           * by the keyboard.
239           * Call ToAscii() again with proper parameters to restore it.           * Call ToAscii() again with proper parameters to restore it.
240           */           */
241    
242          /*          /*
243           * Get information about the old char           * Get information about the old char
244           */           */
245    
246          deadkey = VkKeyScan(buf[0]);          deadkey = VkKeyScan(buf[0]);
247          shift = deadkey >> 8;          shift = deadkey >> 8;
248          deadkey &= 255;          deadkey &= 255;
249          scancode = MapVirtualKey(deadkey, 0);          scancode = MapVirtualKey(deadkey, 0);
250    
251          /*          /*
252           * Set up a keyboard with proper modifier keys           * Set up a keyboard with proper modifier keys
253           */           */
254    
255          memset(keys, 0, 256);          memset(keys, 0, 256);
256          if (shift & 1)          if (shift & 1)
257              keys[VK_SHIFT] = 0x80;              keys[VK_SHIFT] = 0x80;
258          if (shift & 2)          if (shift & 2)
259              keys[VK_CONTROL] = 0x80;              keys[VK_CONTROL] = 0x80;
260          if (shift & 4)          if (shift & 4)
261              keys[VK_MENU] = 0x80;              keys[VK_MENU] = 0x80;
262          ToAscii(deadkey, scancode, keys, (LPWORD) buf, 0);          ToAscii(deadkey, scancode, keys, (LPWORD) buf, 0);
263          return XK_Multi_key;          return XK_Multi_key;
264      }      }
265    
266      /*      /*
267       * Keycode mapped to a valid Latin-1 character.  Since the keysyms       * Keycode mapped to a valid Latin-1 character.  Since the keysyms
268       * for alphanumeric characters map onto Latin-1, we just return it.       * for alphanumeric characters map onto Latin-1, we just return it.
269       *       *
270       * We treat 0x7F as a special case mostly for backwards compatibility.       * We treat 0x7F as a special case mostly for backwards compatibility.
271       * In versions of Tk<=8.2, Control-Backspace returned "XK_BackSpace"       * In versions of Tk<=8.2, Control-Backspace returned "XK_BackSpace"
272       * as the X Keysym.  This was due to the fact that we did not       * as the X Keysym.  This was due to the fact that we did not
273       * initialize the keys array properly when we passed it to ToAscii, above.       * initialize the keys array properly when we passed it to ToAscii, above.
274       * We had previously not been setting the state bit for the Control key.       * We had previously not been setting the state bit for the Control key.
275       * When we fixed that, we found that Control-Backspace on Windows is       * When we fixed that, we found that Control-Backspace on Windows is
276       * interpreted as ASCII-127 (0x7F), which corresponds to the Delete key.       * interpreted as ASCII-127 (0x7F), which corresponds to the Delete key.
277       *       *
278       * Upon discovering this, we realized we had two choices:  return XK_Delete       * Upon discovering this, we realized we had two choices:  return XK_Delete
279       * or return XK_BackSpace.  If we returned XK_Delete, that could be       * or return XK_BackSpace.  If we returned XK_Delete, that could be
280       * considered "more correct" (although the correctness would be dependant       * considered "more correct" (although the correctness would be dependant
281       * on whether you believe that ToAscii is doing the right thing in that       * on whether you believe that ToAscii is doing the right thing in that
282       * case); however, this would break backwards compatibility, and worse,       * case); however, this would break backwards compatibility, and worse,
283       * it would limit application programmers -- they would effectively be       * it would limit application programmers -- they would effectively be
284       * unable to bind to <Control-Backspace> on Windows.  We therefore chose       * unable to bind to <Control-Backspace> on Windows.  We therefore chose
285       * instead to return XK_BackSpace (handled here by letting the code       * instead to return XK_BackSpace (handled here by letting the code
286       * "fall-through" to the return statement below, which works because the       * "fall-through" to the return statement below, which works because the
287       * keycode for this event is VK_BACKSPACE, and the keymap table maps that       * keycode for this event is VK_BACKSPACE, and the keymap table maps that
288       * keycode to XK_BackSpace).       * keycode to XK_BackSpace).
289       */       */
290    
291      if (result == 1 && UCHAR(buf[0]) >= 0x20 && UCHAR(buf[0]) != 0x7F) {      if (result == 1 && UCHAR(buf[0]) >= 0x20 && UCHAR(buf[0]) != 0x7F) {
292          return (KeySym) UCHAR(buf[0]);          return (KeySym) UCHAR(buf[0]);
293      }      }
294    
295      /*      /*
296       * Keycode is a non-alphanumeric key, so we have to do the lookup.       * Keycode is a non-alphanumeric key, so we have to do the lookup.
297       */       */
298    
299      skipToAscii:      skipToAscii:
300      if (keycode < 0 || keycode > MAX_KEYCODE) {      if (keycode < 0 || keycode > MAX_KEYCODE) {
301          return NoSymbol;          return NoSymbol;
302      }      }
303      switch (keycode) {      switch (keycode) {
304          /*          /*
305           * Windows only gives us an undifferentiated VK_CONTROL           * Windows only gives us an undifferentiated VK_CONTROL
306           * code (for example) when either Control key is pressed.           * code (for example) when either Control key is pressed.
307           * To distinguish between left and right, we have to query the           * To distinguish between left and right, we have to query the
308           * state of one of the two to determine which was actually           * state of one of the two to determine which was actually
309           * pressed.  So if the keycode indicates Control, Shift, or Menu           * pressed.  So if the keycode indicates Control, Shift, or Menu
310           * (the key that everybody else calls Alt), do this extra test.           * (the key that everybody else calls Alt), do this extra test.
311           * If the right-side key was pressed, return the appropriate           * If the right-side key was pressed, return the appropriate
312           * keycode.  Otherwise, we fall through and rely on the           * keycode.  Otherwise, we fall through and rely on the
313           * keymap table to hold the correct keysym value.           * keymap table to hold the correct keysym value.
314           */           */
315          case VK_CONTROL: {          case VK_CONTROL: {
316              if (GetKeyState(VK_RCONTROL) & 0x80) {              if (GetKeyState(VK_RCONTROL) & 0x80) {
317                  return XK_Control_R;                  return XK_Control_R;
318              }              }
319              break;              break;
320          }          }
321          case VK_SHIFT: {          case VK_SHIFT: {
322              if (GetKeyState(VK_RSHIFT) & 0x80) {              if (GetKeyState(VK_RSHIFT) & 0x80) {
323                  return XK_Shift_R;                  return XK_Shift_R;
324              }              }
325              break;              break;
326          }          }
327          case VK_MENU: {          case VK_MENU: {
328              if (GetKeyState(VK_RMENU) & 0x80) {              if (GetKeyState(VK_RMENU) & 0x80) {
329                  return XK_Alt_R;                  return XK_Alt_R;
330              }              }
331              break;              break;
332          }          }
333      }      }
334      return keymap[keycode];      return keymap[keycode];
335  }  }
336    
337    
338  /*  /*
339   *----------------------------------------------------------------------   *----------------------------------------------------------------------
340   *   *
341   * TkpGetKeySym --   * TkpGetKeySym --
342   *   *
343   *      Given an X KeyPress or KeyRelease event, map the   *      Given an X KeyPress or KeyRelease event, map the
344   *      keycode in the event into a KeySym.   *      keycode in the event into a KeySym.
345   *   *
346   * Results:   * Results:
347   *      The return value is the KeySym corresponding to   *      The return value is the KeySym corresponding to
348   *      eventPtr, or NoSymbol if no matching Keysym could be   *      eventPtr, or NoSymbol if no matching Keysym could be
349   *      found.   *      found.
350   *   *
351   * Side effects:   * Side effects:
352   *      In the first call for a given display, keycode-to-   *      In the first call for a given display, keycode-to-
353   *      KeySym maps get loaded.   *      KeySym maps get loaded.
354   *   *
355   *----------------------------------------------------------------------   *----------------------------------------------------------------------
356   */   */
357    
358  KeySym  KeySym
359  TkpGetKeySym(dispPtr, eventPtr)  TkpGetKeySym(dispPtr, eventPtr)
360      TkDisplay *dispPtr;         /* Display in which to map keycode. */      TkDisplay *dispPtr;         /* Display in which to map keycode. */
361      XEvent *eventPtr;           /* Description of X event. */      XEvent *eventPtr;           /* Description of X event. */
362  {  {
363      KeySym sym;      KeySym sym;
364      int state = eventPtr->xkey.state;      int state = eventPtr->xkey.state;
365    
366      /*      /*
367       * Refresh the mapping information if it's stale       * Refresh the mapping information if it's stale
368       */       */
369    
370      if (dispPtr->bindInfoStale) {      if (dispPtr->bindInfoStale) {
371          TkpInitKeymapInfo(dispPtr);          TkpInitKeymapInfo(dispPtr);
372      }      }
373    
374      sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);      sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
375    
376      /*      /*
377       * Special handling: if this is a ctrl-alt or shifted key, and there       * Special handling: if this is a ctrl-alt or shifted key, and there
378       * is no keysym defined, try without the modifiers.       * is no keysym defined, try without the modifiers.
379       */       */
380    
381      if ((sym == NoSymbol) && ((state & ControlMask) || (state & Mod2Mask))) {      if ((sym == NoSymbol) && ((state & ControlMask) || (state & Mod2Mask))) {
382          state &=  ~(ControlMask | Mod2Mask);          state &=  ~(ControlMask | Mod2Mask);
383          sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);          sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
384      }      }
385      if ((sym == NoSymbol) && (state & ShiftMask)) {      if ((sym == NoSymbol) && (state & ShiftMask)) {
386          state &=  ~ShiftMask;          state &=  ~ShiftMask;
387          sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);          sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
388      }      }
389      return sym;      return sym;
390  }  }
391    
392  /*  /*
393   *--------------------------------------------------------------   *--------------------------------------------------------------
394   *   *
395   * TkpInitKeymapInfo --   * TkpInitKeymapInfo --
396   *   *
397   *      This procedure is invoked to scan keymap information   *      This procedure is invoked to scan keymap information
398   *      to recompute stuff that's important for binding, such   *      to recompute stuff that's important for binding, such
399   *      as the modifier key (if any) that corresponds to "mode   *      as the modifier key (if any) that corresponds to "mode
400   *      switch".   *      switch".
401   *   *
402   * Results:   * Results:
403   *      None.   *      None.
404   *   *
405   * Side effects:   * Side effects:
406   *      Keymap-related information in dispPtr is updated.   *      Keymap-related information in dispPtr is updated.
407   *   *
408   *--------------------------------------------------------------   *--------------------------------------------------------------
409   */   */
410    
411  void  void
412  TkpInitKeymapInfo(dispPtr)  TkpInitKeymapInfo(dispPtr)
413      TkDisplay *dispPtr;         /* Display for which to recompute keymap      TkDisplay *dispPtr;         /* Display for which to recompute keymap
414                                   * information. */                                   * information. */
415  {  {
416      XModifierKeymap *modMapPtr;      XModifierKeymap *modMapPtr;
417      KeyCode *codePtr;      KeyCode *codePtr;
418      KeySym keysym;      KeySym keysym;
419      int count, i, j, max, arraySize;      int count, i, j, max, arraySize;
420  #define KEYCODE_ARRAY_SIZE 20  #define KEYCODE_ARRAY_SIZE 20
421    
422      dispPtr->bindInfoStale = 0;      dispPtr->bindInfoStale = 0;
423      modMapPtr = XGetModifierMapping(dispPtr->display);      modMapPtr = XGetModifierMapping(dispPtr->display);
424    
425      /*      /*
426       * Check the keycodes associated with the Lock modifier.  If       * Check the keycodes associated with the Lock modifier.  If
427       * any of them is associated with the XK_Shift_Lock modifier,       * any of them is associated with the XK_Shift_Lock modifier,
428       * then Lock has to be interpreted as Shift Lock, not Caps Lock.       * then Lock has to be interpreted as Shift Lock, not Caps Lock.
429       */       */
430    
431      dispPtr->lockUsage = LU_IGNORE;      dispPtr->lockUsage = LU_IGNORE;
432      codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;      codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
433      for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {      for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
434          if (*codePtr == 0) {          if (*codePtr == 0) {
435              continue;              continue;
436          }          }
437          keysym = KeycodeToKeysym(*codePtr, 0, 1);          keysym = KeycodeToKeysym(*codePtr, 0, 1);
438          if (keysym == XK_Shift_Lock) {          if (keysym == XK_Shift_Lock) {
439              dispPtr->lockUsage = LU_SHIFT;              dispPtr->lockUsage = LU_SHIFT;
440              break;              break;
441          }          }
442          if (keysym == XK_Caps_Lock) {          if (keysym == XK_Caps_Lock) {
443              dispPtr->lockUsage = LU_CAPS;              dispPtr->lockUsage = LU_CAPS;
444              break;              break;
445          }          }
446      }      }
447    
448      /*      /*
449       * Look through the keycodes associated with modifiers to see if       * Look through the keycodes associated with modifiers to see if
450       * the the "mode switch", "meta", or "alt" keysyms are associated       * the the "mode switch", "meta", or "alt" keysyms are associated
451       * with any modifiers.  If so, remember their modifier mask bits.       * with any modifiers.  If so, remember their modifier mask bits.
452       */       */
453    
454      dispPtr->modeModMask = 0;      dispPtr->modeModMask = 0;
455      dispPtr->metaModMask = 0;      dispPtr->metaModMask = 0;
456      dispPtr->altModMask = 0;      dispPtr->altModMask = 0;
457      codePtr = modMapPtr->modifiermap;      codePtr = modMapPtr->modifiermap;
458      max = 8*modMapPtr->max_keypermod;      max = 8*modMapPtr->max_keypermod;
459      for (i = 0; i < max; i++, codePtr++) {      for (i = 0; i < max; i++, codePtr++) {
460          if (*codePtr == 0) {          if (*codePtr == 0) {
461              continue;              continue;
462          }          }
463          keysym = KeycodeToKeysym(*codePtr, 0, 1);          keysym = KeycodeToKeysym(*codePtr, 0, 1);
464          if (keysym == XK_Mode_switch) {          if (keysym == XK_Mode_switch) {
465              dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);              dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
466          }          }
467          if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {          if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
468              dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);              dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
469          }          }
470          if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {          if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
471              dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);              dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
472          }          }
473      }      }
474    
475      /*      /*
476       * Create an array of the keycodes for all modifier keys.       * Create an array of the keycodes for all modifier keys.
477       */       */
478    
479      if (dispPtr->modKeyCodes != NULL) {      if (dispPtr->modKeyCodes != NULL) {
480          ckfree((char *) dispPtr->modKeyCodes);          ckfree((char *) dispPtr->modKeyCodes);
481      }      }
482      dispPtr->numModKeyCodes = 0;      dispPtr->numModKeyCodes = 0;
483      arraySize = KEYCODE_ARRAY_SIZE;      arraySize = KEYCODE_ARRAY_SIZE;
484      dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)      dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
485              (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));              (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
486      for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {      for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
487          if (*codePtr == 0) {          if (*codePtr == 0) {
488              continue;              continue;
489          }          }
490    
491          /*          /*
492           * Make sure that the keycode isn't already in the array.           * Make sure that the keycode isn't already in the array.
493           */           */
494    
495          for (j = 0; j < dispPtr->numModKeyCodes; j++) {          for (j = 0; j < dispPtr->numModKeyCodes; j++) {
496              if (dispPtr->modKeyCodes[j] == *codePtr) {              if (dispPtr->modKeyCodes[j] == *codePtr) {
497                  goto nextModCode;                  goto nextModCode;
498              }              }
499          }          }
500          if (dispPtr->numModKeyCodes >= arraySize) {          if (dispPtr->numModKeyCodes >= arraySize) {
501              KeyCode *new;              KeyCode *new;
502    
503              /*              /*
504               * Ran out of space in the array;  grow it.               * Ran out of space in the array;  grow it.
505               */               */
506    
507              arraySize *= 2;              arraySize *= 2;
508              new = (KeyCode *) ckalloc((unsigned)              new = (KeyCode *) ckalloc((unsigned)
509                      (arraySize * sizeof(KeyCode)));                      (arraySize * sizeof(KeyCode)));
510              memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,              memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
511                      (dispPtr->numModKeyCodes * sizeof(KeyCode)));                      (dispPtr->numModKeyCodes * sizeof(KeyCode)));
512              ckfree((char *) dispPtr->modKeyCodes);              ckfree((char *) dispPtr->modKeyCodes);
513              dispPtr->modKeyCodes = new;              dispPtr->modKeyCodes = new;
514          }          }
515          dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;          dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
516          dispPtr->numModKeyCodes++;          dispPtr->numModKeyCodes++;
517          nextModCode: continue;          nextModCode: continue;
518      }      }
519      XFreeModifiermap(modMapPtr);      XFreeModifiermap(modMapPtr);
520  }  }
521    
522  /*  /*
523   * When mapping from a keysym to a keycode, need   * When mapping from a keysym to a keycode, need
524   * information about the modifier state that should be used   * information about the modifier state that should be used
525   * so that when they call XKeycodeToKeysym taking into   * so that when they call XKeycodeToKeysym taking into
526   * account the xkey.state, they will get back the original   * account the xkey.state, they will get back the original
527   * keysym.   * keysym.
528   */   */
529    
530  void  void
531  TkpSetKeycodeAndState(tkwin, keySym, eventPtr)  TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
532      Tk_Window tkwin;      Tk_Window tkwin;
533      KeySym keySym;      KeySym keySym;
534      XEvent *eventPtr;      XEvent *eventPtr;
535  {  {
536      int i;      int i;
537      SHORT result;      SHORT result;
538      int shift;      int shift;
539            
540      eventPtr->xkey.keycode = 0;      eventPtr->xkey.keycode = 0;
541      if (keySym == NoSymbol) {      if (keySym == NoSymbol) {
542          return;          return;
543      }      }
544    
545      /*      /*
546       * We check our private map first for a virtual keycode,       * We check our private map first for a virtual keycode,
547       * as VkKeyScan will return values that don't map to X       * as VkKeyScan will return values that don't map to X
548       * for the "extended" Syms.  This may be due to just casting       * for the "extended" Syms.  This may be due to just casting
549       * problems below, but this works.       * problems below, but this works.
550       */       */
551      for (i = 0; i <= MAX_KEYCODE; i++) {      for (i = 0; i <= MAX_KEYCODE; i++) {
552          if (keymap[i] == keySym) {          if (keymap[i] == keySym) {
553              eventPtr->xkey.keycode = i;              eventPtr->xkey.keycode = i;
554              return;              return;
555          }          }
556      }      }
557      if (keySym >= 0x20) {      if (keySym >= 0x20) {
558          result = VkKeyScan((char) keySym);          result = VkKeyScan((char) keySym);
559          if (result != -1) {          if (result != -1) {
560              shift = result >> 8;              shift = result >> 8;
561              if (shift & 1)              if (shift & 1)
562                  eventPtr->xkey.state |= ShiftMask;                  eventPtr->xkey.state |= ShiftMask;
563              if (shift & 2)              if (shift & 2)
564                  eventPtr->xkey.state |= ControlMask;                  eventPtr->xkey.state |= ControlMask;
565              if (shift & 4)              if (shift & 4)
566                  eventPtr->xkey.state |= Mod2Mask;                  eventPtr->xkey.state |= Mod2Mask;
567              eventPtr->xkey.keycode = (KeyCode) (result & 0xff);              eventPtr->xkey.keycode = (KeyCode) (result & 0xff);
568          }          }
569      }      }
570      {      {
571          /* Debug log */          /* Debug log */
572          FILE *fp = fopen("c:\\temp\\tklog.txt", "a");          FILE *fp = fopen("c:\\temp\\tklog.txt", "a");
573          if (fp != NULL) {          if (fp != NULL) {
574              fprintf(fp, "TkpSetKeycode. Keycode %d State %d Keysym %d\n", eventPtr->xkey.keycode, eventPtr->xkey.state, keySym);              fprintf(fp, "TkpSetKeycode. Keycode %d State %d Keysym %d\n", eventPtr->xkey.keycode, eventPtr->xkey.state, keySym);
575              fclose(fp);              fclose(fp);
576          }          }
577      }      }
578  }  }
579    
580  /*  /*
581   *----------------------------------------------------------------------   *----------------------------------------------------------------------
582   *   *
583   * XKeysymToKeycode --   * XKeysymToKeycode --
584   *   *
585   *      Translate a keysym back into a keycode.   *      Translate a keysym back into a keycode.
586   *   *
587   * Results:   * Results:
588   *      Returns the keycode that would generate the specified keysym.   *      Returns the keycode that would generate the specified keysym.
589   *   *
590   * Side effects:   * Side effects:
591   *      None.   *      None.
592   *   *
593   *----------------------------------------------------------------------   *----------------------------------------------------------------------
594   */   */
595    
596  KeyCode  KeyCode
597  XKeysymToKeycode(display, keysym)  XKeysymToKeycode(display, keysym)
598      Display* display;      Display* display;
599      KeySym keysym;      KeySym keysym;
600  {  {
601      int i;      int i;
602      SHORT result;      SHORT result;
603    
604      /*      /*
605       * We check our private map first for a virtual keycode,       * We check our private map first for a virtual keycode,
606       * as VkKeyScan will return values that don't map to X       * as VkKeyScan will return values that don't map to X
607       * for the "extended" Syms.  This may be due to just casting       * for the "extended" Syms.  This may be due to just casting
608       * problems below, but this works.       * problems below, but this works.
609       */       */
610      if (keysym == NoSymbol) {      if (keysym == NoSymbol) {
611          return 0;          return 0;
612      }      }
613      for (i = 0; i <= MAX_KEYCODE; i++) {      for (i = 0; i <= MAX_KEYCODE; i++) {
614          if (keymap[i] == keysym) {          if (keymap[i] == keysym) {
615              return ((KeyCode) i);              return ((KeyCode) i);
616          }          }
617      }      }
618      if (keysym >= 0x20) {      if (keysym >= 0x20) {
619          result = VkKeyScan((char) keysym);          result = VkKeyScan((char) keysym);
620          if (result != -1) {          if (result != -1) {
621              return (KeyCode) (result & 0xff);              return (KeyCode) (result & 0xff);
622          }          }
623      }      }
624    
625      return 0;      return 0;
626  }  }
627    
628  /*  /*
629   *----------------------------------------------------------------------   *----------------------------------------------------------------------
630   *   *
631   * XGetModifierMapping --   * XGetModifierMapping --
632   *   *
633   *      Fetch the current keycodes used as modifiers.   *      Fetch the current keycodes used as modifiers.
634   *   *
635   * Results:   * Results:
636   *      Returns a new modifier map.   *      Returns a new modifier map.
637   *   *
638   * Side effects:   * Side effects:
639   *      Allocates a new modifier map data structure.   *      Allocates a new modifier map data structure.
640   *   *
641   *----------------------------------------------------------------------   *----------------------------------------------------------------------
642   */   */
643    
644  XModifierKeymap *  XModifierKeymap *
645  XGetModifierMapping(display)  XGetModifierMapping(display)
646      Display* display;      Display* display;
647  {  {
648      XModifierKeymap *map = (XModifierKeymap *)ckalloc(sizeof(XModifierKeymap));      XModifierKeymap *map = (XModifierKeymap *)ckalloc(sizeof(XModifierKeymap));
649    
650      map->max_keypermod = 1;      map->max_keypermod = 1;
651      map->modifiermap = (KeyCode *) ckalloc(sizeof(KeyCode)*8);      map->modifiermap = (KeyCode *) ckalloc(sizeof(KeyCode)*8);
652      map->modifiermap[ShiftMapIndex] = VK_SHIFT;      map->modifiermap[ShiftMapIndex] = VK_SHIFT;
653      map->modifiermap[LockMapIndex] = VK_CAPITAL;      map->modifiermap[LockMapIndex] = VK_CAPITAL;
654      map->modifiermap[ControlMapIndex] = VK_CONTROL;      map->modifiermap[ControlMapIndex] = VK_CONTROL;
655      map->modifiermap[Mod1MapIndex] = VK_NUMLOCK;      map->modifiermap[Mod1MapIndex] = VK_NUMLOCK;
656      map->modifiermap[Mod2MapIndex] = VK_MENU;      map->modifiermap[Mod2MapIndex] = VK_MENU;
657      map->modifiermap[Mod3MapIndex] = VK_SCROLL;      map->modifiermap[Mod3MapIndex] = VK_SCROLL;
658      map->modifiermap[Mod4MapIndex] = 0;      map->modifiermap[Mod4MapIndex] = 0;
659      map->modifiermap[Mod5MapIndex] = 0;      map->modifiermap[Mod5MapIndex] = 0;
660      return map;      return map;
661  }  }
662    
663  /*  /*
664   *----------------------------------------------------------------------   *----------------------------------------------------------------------
665   *   *
666   * XFreeModifiermap --   * XFreeModifiermap --
667   *   *
668   *      Deallocate a modifier map that was created by   *      Deallocate a modifier map that was created by
669   *      XGetModifierMapping.   *      XGetModifierMapping.
670   *   *
671   * Results:   * Results:
672   *      None.   *      None.
673   *   *
674   * Side effects:   * Side effects:
675   *      Frees the datastructure referenced by modmap.   *      Frees the datastructure referenced by modmap.
676   *   *
677   *----------------------------------------------------------------------   *----------------------------------------------------------------------
678   */   */
679    
680  void  void
681  XFreeModifiermap(modmap)  XFreeModifiermap(modmap)
682      XModifierKeymap* modmap;      XModifierKeymap* modmap;
683  {  {
684      ckfree((char *) modmap->modifiermap);      ckfree((char *) modmap->modifiermap);
685      ckfree((char *) modmap);      ckfree((char *) modmap);
686  }  }
687    
688  /*  /*
689   *----------------------------------------------------------------------   *----------------------------------------------------------------------
690   *   *
691   * XStringToKeysym --   * XStringToKeysym --
692   *   *
693   *      Translate a keysym name to the matching keysym.   *      Translate a keysym name to the matching keysym.
694   *   *
695   * Results:   * Results:
696   *      Returns the keysym.  Since this is already handled by   *      Returns the keysym.  Since this is already handled by
697   *      Tk's StringToKeysym function, we just return NoSymbol.   *      Tk's StringToKeysym function, we just return NoSymbol.
698   *   *
699   * Side effects:   * Side effects:
700   *      None.   *      None.
701   *   *
702   *----------------------------------------------------------------------   *----------------------------------------------------------------------
703   */   */
704    
705  KeySym  KeySym
706  XStringToKeysym(string)  XStringToKeysym(string)
707      _Xconst char *string;      _Xconst char *string;
708  {  {
709      return NoSymbol;      return NoSymbol;
710  }  }
711    
712  /*  /*
713   *----------------------------------------------------------------------   *----------------------------------------------------------------------
714   *   *
715   * XKeysymToString --   * XKeysymToString --
716   *   *
717   *      Convert a keysym to character form.   *      Convert a keysym to character form.
718   *   *
719   * Results:   * Results:
720   *      Returns NULL, since Tk will have handled this already.   *      Returns NULL, since Tk will have handled this already.
721   *   *
722   * Side effects:   * Side effects:
723   *      None.   *      None.
724   *   *
725   *----------------------------------------------------------------------   *----------------------------------------------------------------------
726   */   */
727    
728  char *  char *
729  XKeysymToString(keysym)  XKeysymToString(keysym)
730      KeySym keysym;      KeySym keysym;
731  {  {
732      return NULL;      return NULL;
733  }  }
734    
735  /* End of tkwinkey.c */  /* End of tkwinkey.c */

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25