summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog41
-rw-r--r--generic/tk.decls48
-rw-r--r--generic/tkBind.c271
-rw-r--r--generic/tkInt.decls12
-rw-r--r--generic/tkIntDecls.h18
-rw-r--r--generic/tkStubInit.c4
-rw-r--r--mac/tkMacKeyboard.c261
-rw-r--r--unix/tkUnixKey.c266
-rw-r--r--win/tkWinKey.c394
9 files changed, 1001 insertions, 314 deletions
diff --git a/ChangeLog b/ChangeLog
index 069265e..b89e1c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,46 @@
2000-02-08 Jeff Hobbs <hobbs@scriptics.com>
+ * generic/tk.decls:
+ * generic/tkBind.c:
+ * generic/tkInt.decls:
+ * generic/tkIntDecls.h:
+ * generic/tkStubInit.c:
+ * mac/tkMacKeyboard.c:
+ * unix/tkUnixKey.c:
+ * win/tkWinKey.c: Fix for keyboard handling of "dead" keys and
+ caps lock from Peter Spjuth.
+ Split functions into platform specific files:
+ Static functions GetKeySym(), SetKeycodeAndState() and InitKeymapInfo()
+ from tkBind.c moved into platform files tkWinKey.c tkUnixKey.c and
+ tkMacKeyboard.c. GetKeySym() and SetKeycodeAndState() renamed to
+ Tkp* and made public (as private functions) in tkInt.decls.
+
+ Step 2, fixes in tkWinKey.c
+ New static function: KeycodeToKeysym(), based on XKeycodeToKeysym()
+ but with different arguments, and a lot of improvements.
+ TkpGetString() changed to use KeycodeToKeysym() + other fixes.
+ TkpGetKeySym() changed to use KeycodeToKeysym() + other fixes.
+ InitKeymapInfo() changed to use KeycodeToKeysym().
+ TkpSetKeycodeAndState() rewritten, mostly by copying code from
+ XKeysymToKeycode().
+ XKeycodeToKeysym() rewritten. Preferably it should be removed.
+
+ EXPLANATION: The main problem is ToAscii() which has a lot of side
+ effects, and also that XKeycodeToKeysym() is not provided enough
+ input to do a proper job. The changes' main goal is to avoid
+ calling ToAscii() if not necessary, and to provide it with as
+ correct information as possible when called. Also some attempts
+ to clean up what ToAscii() did are done. See the code for details.
+
+ BUGS FIXED: Typing shifted (and AltGr) dead keys did not work.
+ Keyboard lock lamps did not work on Win98.
+ Events regarding AltGr-keys behaved badly.
+ Example: On a Swedish keyboard, $ is typed with AltGr-4.
+ That keyboard event would get the keysym '4' not 'dollar'.
+ Also, doing [event generete . <Key-dollar>] would send keysym '4'.
+ Translation to ascii in TkpGetString did not handle return and
+ tab correctly. I.e. [event generate . <Key-Return>] gave wrong %A
+
* generic/tkDecls.h:
* generic/tk.decls:
* generic/tk.h: moved new public functions created in dash patch
diff --git a/generic/tk.decls b/generic/tk.decls
index f152cbd..fe8b72e 100644
--- a/generic/tk.decls
+++ b/generic/tk.decls
@@ -10,7 +10,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tk.decls,v 1.6 2000/02/08 11:31:32 hobbs Exp $
+# RCS: @(#) $Id: tk.decls,v 1.7 2000/02/09 02:13:50 hobbs Exp $
library tk
@@ -1033,92 +1033,92 @@ declare 214 generic {
}
declare 215 generic {
- void Tk_InitConsoleChannels(Tcl_Interp *interp)
+ void Tk_InitConsoleChannels (Tcl_Interp *interp)
}
declare 216 generic {
- int Tk_CreateConsoleWindow(Tcl_Interp *interp)
+ int Tk_CreateConsoleWindow (Tcl_Interp *interp)
}
declare 217 generic {
- void Tk_CreateSmoothMethod(Tcl_Interp *interp, Tk_SmoothMethod *method)
+ void Tk_CreateSmoothMethod (Tcl_Interp *interp, Tk_SmoothMethod *method)
}
#declare 218 generic {
-# void Tk_CreateCanvasVisitor(Tcl_Interp *interp, VOID *typePtr)
+# void Tk_CreateCanvasVisitor (Tcl_Interp *interp, VOID *typePtr)
#}
#declare 219 generic {
-# VOID *Tk_GetCanvasVisitor(Tcl_Interp *interp, CONST char *name)
+# VOID *Tk_GetCanvasVisitor (Tcl_Interp *interp, CONST char *name)
#}
declare 220 generic {
- int Tk_GetDash(Tcl_Interp *interp, CONST char *value, Tk_Dash *dash)
+ int Tk_GetDash (Tcl_Interp *interp, CONST char *value, Tk_Dash *dash)
}
declare 221 generic {
- void Tk_CreateOutline(Tk_Outline *outline)
+ void Tk_CreateOutline (Tk_Outline *outline)
}
declare 222 generic {
- void Tk_DeleteOutline(Display *display, Tk_Outline *outline)
+ void Tk_DeleteOutline (Display *display, Tk_Outline *outline)
}
declare 223 generic {
- int Tk_ConfigOutlineGC(XGCValues *gcValues, Tk_Canvas canvas, \
+ int Tk_ConfigOutlineGC (XGCValues *gcValues, Tk_Canvas canvas, \
Tk_Item *item, Tk_Outline *outline)
}
declare 224 generic {
- int Tk_ChangeOutlineGC(Tk_Canvas canvas, Tk_Item *item, \
+ int Tk_ChangeOutlineGC (Tk_Canvas canvas, Tk_Item *item, \
Tk_Outline *outline)
}
declare 225 generic {
- int Tk_ResetOutlineGC(Tk_Canvas canvas, Tk_Item *item, \
+ int Tk_ResetOutlineGC (Tk_Canvas canvas, Tk_Item *item, \
Tk_Outline *outline)
}
declare 226 generic {
- int Tk_CanvasPsOutline(Tk_Canvas canvas, Tk_Item *item, \
+ int Tk_CanvasPsOutline (Tk_Canvas canvas, Tk_Item *item, \
Tk_Outline *outline)
}
declare 227 generic {
- void Tk_SetTSOrigin(Tk_Window tkwin, GC gc, int x, int y)
+ void Tk_SetTSOrigin (Tk_Window tkwin, GC gc, int x, int y)
}
declare 228 generic {
- int Tk_CanvasGetCoordFromObj(Tcl_Interp *interp, Tk_Canvas canvas, \
+ int Tk_CanvasGetCoordFromObj (Tcl_Interp *interp, Tk_Canvas canvas, \
Tcl_Obj *obj, double *doublePtr)
}
declare 229 generic {
- void Tk_CanvasSetOffset(Tk_Canvas canvas, GC gc, Tk_TSOffset *offset)
+ void Tk_CanvasSetOffset (Tk_Canvas canvas, GC gc, Tk_TSOffset *offset)
}
declare 230 generic {
- void Tk_DitherPhoto(Tk_PhotoHandle handle, int x, int y, int width, \
+ void Tk_DitherPhoto (Tk_PhotoHandle handle, int x, int y, int width, \
int height)
}
declare 231 generic {
- int Tk_PostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin, \
+ int Tk_PostscriptBitmap (Tcl_Interp *interp, Tk_Window tkwin, \
Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, \
int startY, int width, int height)
}
declare 232 generic {
- int Tk_PostscriptColor(Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
+ int Tk_PostscriptColor (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
XColor *colorPtr)
}
declare 233 generic {
- int Tk_PostscriptFont(Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
+ int Tk_PostscriptFont (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
Tk_Font font)
}
declare 234 generic {
- int Tk_PostscriptImage(Tk_Image image, Tcl_Interp *interp, \
+ int Tk_PostscriptImage (Tk_Image image, Tcl_Interp *interp, \
Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, \
int width, int height, int prepass)
}
declare 235 generic {
- void Tk_PostscriptPath(Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
+ void Tk_PostscriptPath (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
double *coordPtr, int numPoints)
}
declare 236 generic {
- int Tk_PostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin, \
+ int Tk_PostscriptStipple (Tcl_Interp *interp, Tk_Window tkwin, \
Tk_PostscriptInfo psInfo, Pixmap bitmap)
}
declare 237 generic {
- double Tk_PostscriptY(double y, Tk_PostscriptInfo psInfo)
+ double Tk_PostscriptY (double y, Tk_PostscriptInfo psInfo)
}
# Define the platform specific public Tk interface. These functions are
diff --git a/generic/tkBind.c b/generic/tkBind.c
index 5b53a4e..d54acfa 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkBind.c,v 1.10 2000/01/13 02:07:10 hobbs Exp $
+ * RCS: @(#) $Id: tkBind.c,v 1.11 2000/02/09 02:13:50 hobbs Exp $
*/
#include "tkPort.h"
@@ -665,8 +665,6 @@ static PatSeq * FindSequence _ANSI_ARGS_((Tcl_Interp *interp,
static void GetAllVirtualEvents _ANSI_ARGS_((Tcl_Interp *interp,
VirtualEventTable *vetPtr));
static char * GetField _ANSI_ARGS_((char *p, char *copy, int size));
-static KeySym GetKeySym _ANSI_ARGS_((TkDisplay *dispPtr,
- XEvent *eventPtr));
static void GetPatternString _ANSI_ARGS_((PatSeq *psPtr,
Tcl_DString *dsPtr));
static int GetVirtualEvent _ANSI_ARGS_((Tcl_Interp *interp,
@@ -676,7 +674,6 @@ static Tk_Uid GetVirtualEventUid _ANSI_ARGS_((Tcl_Interp *interp,
static int HandleEventGenerate _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window main, int objc,
Tcl_Obj *CONST objv[]));
-static void InitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr));
static void InitVirtualEventTable _ANSI_ARGS_((
VirtualEventTable *vetPtr));
static PatSeq * MatchPatterns _ANSI_ARGS_((TkDisplay *dispPtr,
@@ -689,8 +686,6 @@ static int NameToWindow _ANSI_ARGS_((Tcl_Interp *interp,
static int ParseEventDescription _ANSI_ARGS_((Tcl_Interp *interp,
char **eventStringPtr, Pattern *patPtr,
unsigned long *eventMaskPtr));
-static void SetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin,
- KeySym keySym, XEvent *eventPtr));
static void DoWarp _ANSI_ARGS_((ClientData clientData));
/*
@@ -1537,7 +1532,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
detail.clientData = 0;
flags = flagArray[ringPtr->type];
if (flags & KEY) {
- detail.keySym = GetKeySym(dispPtr, ringPtr);
+ detail.keySym = TkpGetKeySym(dispPtr, ringPtr);
if (detail.keySym == NoSymbol) {
detail.keySym = 0;
}
@@ -3257,7 +3252,7 @@ HandleEventGenerate(interp, mainWin, objc, objv)
if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) {
event.xkey.state = pat.needMods;
if ((flags & KEY) && (event.xany.type != MouseWheelEvent)) {
- SetKeycodeAndState(tkwin, pat.detail.keySym, &event);
+ TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event);
} else if (flags & BUTTON) {
event.xbutton.button = pat.detail.button;
} else if (flags & VIRTUAL) {
@@ -3440,7 +3435,7 @@ HandleEventGenerate(interp, mainWin, objc, objv)
return TCL_ERROR;
}
- SetKeycodeAndState(tkwin, keysym, &event);
+ TkpSetKeycodeAndState(tkwin, keysym, &event);
if (event.xkey.keycode == 0) {
Tcl_AppendResult(interp, "no keycode for keysym \"", value,
"\"", (char *) NULL);
@@ -3737,50 +3732,6 @@ NameToWindow(interp, mainWin, objPtr, tkwinPtr)
}
return TCL_OK;
}
-
-/*
- * When mapping from a keysym to a keycode, need
- * information about the modifier state that should be used
- * so that when they call XKeycodeToKeysym taking into
- * account the xkey.state, they will get back the original
- * keysym.
- */
-
-static void
-SetKeycodeAndState(tkwin, keySym, eventPtr)
- Tk_Window tkwin;
- KeySym keySym;
- XEvent *eventPtr;
-{
- Display *display;
- int state;
- KeyCode keycode;
-
- display = Tk_Display(tkwin);
-
- if (keySym == NoSymbol) {
- keycode = 0;
- } else {
- keycode = XKeysymToKeycode(display, keySym);
- }
- if (keycode != 0) {
- for (state = 0; state < 4; state++) {
- if (XKeycodeToKeysym(display, keycode, state) == keySym) {
- if (state & 1) {
- eventPtr->xkey.state |= ShiftMask;
- }
- if (state & 2) {
- TkDisplay *dispPtr;
-
- dispPtr = ((TkWindow *) tkwin)->dispPtr;
- eventPtr->xkey.state |= dispPtr->modeModMask;
- }
- break;
- }
- }
- }
- eventPtr->xkey.keycode = keycode;
-}
/*
*-------------------------------------------------------------------------
@@ -4431,220 +4382,6 @@ GetPatternString(psPtr, dsPtr)
}
/*
- *----------------------------------------------------------------------
- *
- * GetKeySym --
- *
- * Given an X KeyPress or KeyRelease event, map the
- * keycode in the event into a KeySym.
- *
- * Results:
- * The return value is the KeySym corresponding to
- * eventPtr, or NoSymbol if no matching Keysym could be
- * found.
- *
- * Side effects:
- * In the first call for a given display, keycode-to-
- * KeySym maps get loaded.
- *
- *----------------------------------------------------------------------
- */
-
-static KeySym
-GetKeySym(dispPtr, eventPtr)
- TkDisplay *dispPtr; /* Display in which to
- * map keycode. */
- XEvent *eventPtr; /* Description of X event. */
-{
- KeySym sym;
- int index;
-
- /*
- * Refresh the mapping information if it's stale
- */
-
- if (dispPtr->bindInfoStale) {
- InitKeymapInfo(dispPtr);
- }
-
- /*
- * Figure out which of the four slots in the keymap vector to
- * use for this key. Refer to Xlib documentation for more info
- * on how this computation works.
- */
-
- index = 0;
- if (eventPtr->xkey.state & dispPtr->modeModMask) {
- index = 2;
- }
- if ((eventPtr->xkey.state & ShiftMask)
- || ((dispPtr->lockUsage != LU_IGNORE)
- && (eventPtr->xkey.state & LockMask))) {
- index += 1;
- }
- sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
-
- /*
- * Special handling: if the key was shifted because of Lock, but
- * lock is only caps lock, not shift lock, and the shifted keysym
- * isn't upper-case alphabetic, then switch back to the unshifted
- * keysym.
- */
-
- if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
- && (dispPtr->lockUsage == LU_CAPS)) {
- if (!(((sym >= XK_A) && (sym <= XK_Z))
- || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
- || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
- index &= ~1;
- sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
- index);
- }
- }
-
- /*
- * Another bit of special handling: if this is a shifted key and there
- * is no keysym defined, then use the keysym for the unshifted key.
- */
-
- if ((index & 1) && (sym == NoSymbol)) {
- sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
- index & ~1);
- }
- return sym;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * InitKeymapInfo --
- *
- * This procedure is invoked to scan keymap information
- * to recompute stuff that's important for binding, such
- * as the modifier key (if any) that corresponds to "mode
- * switch".
- *
- * Results:
- * None.
- *
- * Side effects:
- * Keymap-related information in dispPtr is updated.
- *
- *--------------------------------------------------------------
- */
-
-static void
-InitKeymapInfo(dispPtr)
- TkDisplay *dispPtr; /* Display for which to recompute keymap
- * information. */
-{
- XModifierKeymap *modMapPtr;
- KeyCode *codePtr;
- KeySym keysym;
- int count, i, j, max, arraySize;
-#define KEYCODE_ARRAY_SIZE 20
-
- dispPtr->bindInfoStale = 0;
- modMapPtr = XGetModifierMapping(dispPtr->display);
-
- /*
- * Check the keycodes associated with the Lock modifier. If
- * any of them is associated with the XK_Shift_Lock modifier,
- * then Lock has to be interpreted as Shift Lock, not Caps Lock.
- */
-
- dispPtr->lockUsage = LU_IGNORE;
- codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
- for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
- keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
- if (keysym == XK_Shift_Lock) {
- dispPtr->lockUsage = LU_SHIFT;
- break;
- }
- if (keysym == XK_Caps_Lock) {
- dispPtr->lockUsage = LU_CAPS;
- break;
- }
- }
-
- /*
- * Look through the keycodes associated with modifiers to see if
- * the the "mode switch", "meta", or "alt" keysyms are associated
- * with any modifiers. If so, remember their modifier mask bits.
- */
-
- dispPtr->modeModMask = 0;
- dispPtr->metaModMask = 0;
- dispPtr->altModMask = 0;
- codePtr = modMapPtr->modifiermap;
- max = 8*modMapPtr->max_keypermod;
- for (i = 0; i < max; i++, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
- keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
- if (keysym == XK_Mode_switch) {
- dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
- dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
- dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- }
-
- /*
- * Create an array of the keycodes for all modifier keys.
- */
-
- if (dispPtr->modKeyCodes != NULL) {
- ckfree((char *) dispPtr->modKeyCodes);
- }
- dispPtr->numModKeyCodes = 0;
- arraySize = KEYCODE_ARRAY_SIZE;
- dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
- (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
- for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
-
- /*
- * Make sure that the keycode isn't already in the array.
- */
-
- for (j = 0; j < dispPtr->numModKeyCodes; j++) {
- if (dispPtr->modKeyCodes[j] == *codePtr) {
- goto nextModCode;
- }
- }
- if (dispPtr->numModKeyCodes >= arraySize) {
- KeyCode *new;
-
- /*
- * Ran out of space in the array; grow it.
- */
-
- arraySize *= 2;
- new = (KeyCode *) ckalloc((unsigned)
- (arraySize * sizeof(KeyCode)));
- memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
- (dispPtr->numModKeyCodes * sizeof(KeyCode)));
- ckfree((char *) dispPtr->modKeyCodes);
- dispPtr->modKeyCodes = new;
- }
- dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
- dispPtr->numModKeyCodes++;
- nextModCode: continue;
- }
- XFreeModifiermap(modMapPtr);
-}
-
-/*
*---------------------------------------------------------------------------
*
* EvalTclBinding --
diff --git a/generic/tkInt.decls b/generic/tkInt.decls
index 2c7def8..6a34794 100644
--- a/generic/tkInt.decls
+++ b/generic/tkInt.decls
@@ -9,7 +9,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tkInt.decls,v 1.14 2000/01/12 11:45:03 hobbs Exp $
+# RCS: @(#) $Id: tkInt.decls,v 1.15 2000/02/09 02:13:50 hobbs Exp $
library tk
@@ -619,6 +619,16 @@ declare 136 generic {
void TkSetFocusWin (TkWindow *winPtr, int force)
}
+declare 137 generic {
+ void TkpSetKeycodeAndState (Tk_Window tkwin, KeySym keySym, \
+ XEvent *eventPtr)
+}
+
+declare 138 generic {
+ KeySym TkpGetKeySym (TkDisplay *dispPtr, XEvent *eventPtr)
+}
+
+
##############################################################################
# Define the platform specific internal Tcl interface. These functions are
diff --git a/generic/tkIntDecls.h b/generic/tkIntDecls.h
index 8666b6a..fabe813 100644
--- a/generic/tkIntDecls.h
+++ b/generic/tkIntDecls.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkIntDecls.h,v 1.8 1999/08/10 16:58:37 hobbs Exp $
+ * RCS: @(#) $Id: tkIntDecls.h,v 1.9 2000/02/09 02:13:51 hobbs Exp $
*/
#ifndef _TKINTDECLS
@@ -506,6 +506,12 @@ EXTERN void TkpDrawHighlightBorder _ANSI_ARGS_((Tk_Window tkwin,
/* 136 */
EXTERN void TkSetFocusWin _ANSI_ARGS_((TkWindow * winPtr,
int force));
+/* 137 */
+EXTERN void TkpSetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin,
+ KeySym keySym, XEvent * eventPtr));
+/* 138 */
+EXTERN KeySym TkpGetKeySym _ANSI_ARGS_((TkDisplay * dispPtr,
+ XEvent * eventPtr));
typedef struct TkIntStubs {
int magic;
@@ -808,6 +814,8 @@ typedef struct TkIntStubs {
#endif /* MAC_TCL */
void (*tkpDrawHighlightBorder) _ANSI_ARGS_((Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable)); /* 135 */
void (*tkSetFocusWin) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 136 */
+ void (*tkpSetKeycodeAndState) _ANSI_ARGS_((Tk_Window tkwin, KeySym keySym, XEvent * eventPtr)); /* 137 */
+ KeySym (*tkpGetKeySym) _ANSI_ARGS_((TkDisplay * dispPtr, XEvent * eventPtr)); /* 138 */
} TkIntStubs;
#ifdef __cplusplus
@@ -1448,6 +1456,14 @@ extern TkIntStubs *tkIntStubsPtr;
#define TkSetFocusWin \
(tkIntStubsPtr->tkSetFocusWin) /* 136 */
#endif
+#ifndef TkpSetKeycodeAndState
+#define TkpSetKeycodeAndState \
+ (tkIntStubsPtr->tkpSetKeycodeAndState) /* 137 */
+#endif
+#ifndef TkpGetKeySym
+#define TkpGetKeySym \
+ (tkIntStubsPtr->tkpGetKeySym) /* 138 */
+#endif
#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index c1f2607..0b8472f 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkStubInit.c,v 1.16 2000/02/08 11:31:33 hobbs Exp $
+ * RCS: @(#) $Id: tkStubInit.c,v 1.17 2000/02/09 02:13:51 hobbs Exp $
*/
#include "tkInt.h"
@@ -344,6 +344,8 @@ TkIntStubs tkIntStubs = {
#endif /* MAC_TCL */
TkpDrawHighlightBorder, /* 135 */
TkSetFocusWin, /* 136 */
+ TkpSetKeycodeAndState, /* 137 */
+ TkpGetKeySym, /* 138 */
};
TkIntPlatStubs tkIntPlatStubs = {
diff --git a/mac/tkMacKeyboard.c b/mac/tkMacKeyboard.c
index 122cf06..b11afdd 100644
--- a/mac/tkMacKeyboard.c
+++ b/mac/tkMacKeyboard.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkMacKeyboard.c,v 1.3 1999/04/16 01:51:31 stanton Exp $
+ * RCS: @(#) $Id: tkMacKeyboard.c,v 1.4 2000/02/09 02:13:53 hobbs Exp $
*/
#include "tkInt.h"
@@ -72,6 +72,7 @@ static Ptr KCHRPtr; /* Pointer to 'KCHR' resource. */
* Prototypes for static functions used in this file.
*/
static void InitKeyMaps _ANSI_ARGS_((void));
+static void InitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr));
/*
@@ -386,3 +387,261 @@ XKeysymToKeycode(
return keycode;
}
+
+/*
+ * When mapping from a keysym to a keycode, need
+ * information about the modifier state that should be used
+ * so that when they call XKeycodeToKeysym taking into
+ * account the xkey.state, they will get back the original
+ * keysym.
+ */
+
+void
+TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
+ Tk_Window tkwin;
+ KeySym keySym;
+ XEvent *eventPtr;
+{
+ Display *display;
+ int state;
+ KeyCode keycode;
+
+ display = Tk_Display(tkwin);
+
+ if (keySym == NoSymbol) {
+ keycode = 0;
+ } else {
+ keycode = XKeysymToKeycode(display, keySym);
+ }
+ if (keycode != 0) {
+ for (state = 0; state < 4; state++) {
+ if (XKeycodeToKeysym(display, keycode, state) == keySym) {
+ if (state & 1) {
+ eventPtr->xkey.state |= ShiftMask;
+ }
+ if (state & 2) {
+ TkDisplay *dispPtr;
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ eventPtr->xkey.state |= dispPtr->modeModMask;
+ }
+ break;
+ }
+ }
+ }
+ eventPtr->xkey.keycode = keycode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetKeySym --
+ *
+ * Given an X KeyPress or KeyRelease event, map the
+ * keycode in the event into a KeySym.
+ *
+ * Results:
+ * The return value is the KeySym corresponding to
+ * eventPtr, or NoSymbol if no matching Keysym could be
+ * found.
+ *
+ * Side effects:
+ * In the first call for a given display, keycode-to-
+ * KeySym maps get loaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+TkpGetKeySym(dispPtr, eventPtr)
+ TkDisplay *dispPtr; /* Display in which to
+ * map keycode. */
+ XEvent *eventPtr; /* Description of X event. */
+{
+ KeySym sym;
+ int index;
+
+ /*
+ * Refresh the mapping information if it's stale
+ */
+
+ if (dispPtr->bindInfoStale) {
+ InitKeymapInfo(dispPtr);
+ }
+
+ /*
+ * Figure out which of the four slots in the keymap vector to
+ * use for this key. Refer to Xlib documentation for more info
+ * on how this computation works.
+ */
+
+ index = 0;
+ if (eventPtr->xkey.state & dispPtr->modeModMask) {
+ index = 2;
+ }
+ if ((eventPtr->xkey.state & ShiftMask)
+ || ((dispPtr->lockUsage != LU_IGNORE)
+ && (eventPtr->xkey.state & LockMask))) {
+ index += 1;
+ }
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
+
+ /*
+ * Special handling: if the key was shifted because of Lock, but
+ * lock is only caps lock, not shift lock, and the shifted keysym
+ * isn't upper-case alphabetic, then switch back to the unshifted
+ * keysym.
+ */
+
+ if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
+ && (dispPtr->lockUsage == LU_CAPS)) {
+ if (!(((sym >= XK_A) && (sym <= XK_Z))
+ || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
+ || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
+ index &= ~1;
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ index);
+ }
+ }
+
+ /*
+ * Another bit of special handling: if this is a shifted key and there
+ * is no keysym defined, then use the keysym for the unshifted key.
+ */
+
+ if ((index & 1) && (sym == NoSymbol)) {
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ index & ~1);
+ }
+ return sym;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitKeymapInfo --
+ *
+ * This procedure is invoked to scan keymap information
+ * to recompute stuff that's important for binding, such
+ * as the modifier key (if any) that corresponds to "mode
+ * switch".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Keymap-related information in dispPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+InitKeymapInfo(dispPtr)
+ TkDisplay *dispPtr; /* Display for which to recompute keymap
+ * information. */
+{
+ XModifierKeymap *modMapPtr;
+ KeyCode *codePtr;
+ KeySym keysym;
+ int count, i, j, max, arraySize;
+#define KEYCODE_ARRAY_SIZE 20
+
+ dispPtr->bindInfoStale = 0;
+ modMapPtr = XGetModifierMapping(dispPtr->display);
+
+ /*
+ * Check the keycodes associated with the Lock modifier. If
+ * any of them is associated with the XK_Shift_Lock modifier,
+ * then Lock has to be interpreted as Shift Lock, not Caps Lock.
+ */
+
+ dispPtr->lockUsage = LU_IGNORE;
+ codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
+ for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
+ if (keysym == XK_Shift_Lock) {
+ dispPtr->lockUsage = LU_SHIFT;
+ break;
+ }
+ if (keysym == XK_Caps_Lock) {
+ dispPtr->lockUsage = LU_CAPS;
+ break;
+ }
+ }
+
+ /*
+ * Look through the keycodes associated with modifiers to see if
+ * the the "mode switch", "meta", or "alt" keysyms are associated
+ * with any modifiers. If so, remember their modifier mask bits.
+ */
+
+ dispPtr->modeModMask = 0;
+ dispPtr->metaModMask = 0;
+ dispPtr->altModMask = 0;
+ codePtr = modMapPtr->modifiermap;
+ max = 8*modMapPtr->max_keypermod;
+ for (i = 0; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
+ if (keysym == XK_Mode_switch) {
+ dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
+ dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
+ dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ }
+
+ /*
+ * Create an array of the keycodes for all modifier keys.
+ */
+
+ if (dispPtr->modKeyCodes != NULL) {
+ ckfree((char *) dispPtr->modKeyCodes);
+ }
+ dispPtr->numModKeyCodes = 0;
+ arraySize = KEYCODE_ARRAY_SIZE;
+ dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
+ (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
+ for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+
+ /*
+ * Make sure that the keycode isn't already in the array.
+ */
+
+ for (j = 0; j < dispPtr->numModKeyCodes; j++) {
+ if (dispPtr->modKeyCodes[j] == *codePtr) {
+ goto nextModCode;
+ }
+ }
+ if (dispPtr->numModKeyCodes >= arraySize) {
+ KeyCode *new;
+
+ /*
+ * Ran out of space in the array; grow it.
+ */
+
+ arraySize *= 2;
+ new = (KeyCode *) ckalloc((unsigned)
+ (arraySize * sizeof(KeyCode)));
+ memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
+ (dispPtr->numModKeyCodes * sizeof(KeyCode)));
+ ckfree((char *) dispPtr->modKeyCodes);
+ dispPtr->modKeyCodes = new;
+ }
+ dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
+ dispPtr->numModKeyCodes++;
+ nextModCode: continue;
+ }
+ XFreeModifiermap(modMapPtr);
+}
diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c
index effce2f..efba728 100644
--- a/unix/tkUnixKey.c
+++ b/unix/tkUnixKey.c
@@ -9,11 +9,17 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixKey.c,v 1.3 1999/12/16 21:59:13 hobbs Exp $
+ * RCS: @(#) $Id: tkUnixKey.c,v 1.4 2000/02/09 02:13:54 hobbs Exp $
*/
#include "tkInt.h"
+/*
+ * Prototypes for local procedures defined in this file:
+ */
+
+static void InitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr));
+
/*
*----------------------------------------------------------------------
@@ -88,3 +94,261 @@ TkpGetString(winPtr, eventPtr, dsPtr)
return Tcl_DStringValue(dsPtr);
}
+
+/*
+ * When mapping from a keysym to a keycode, need
+ * information about the modifier state that should be used
+ * so that when they call XKeycodeToKeysym taking into
+ * account the xkey.state, they will get back the original
+ * keysym.
+ */
+
+void
+TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
+ Tk_Window tkwin;
+ KeySym keySym;
+ XEvent *eventPtr;
+{
+ Display *display;
+ int state;
+ KeyCode keycode;
+
+ display = Tk_Display(tkwin);
+
+ if (keySym == NoSymbol) {
+ keycode = 0;
+ } else {
+ keycode = XKeysymToKeycode(display, keySym);
+ }
+ if (keycode != 0) {
+ for (state = 0; state < 4; state++) {
+ if (XKeycodeToKeysym(display, keycode, state) == keySym) {
+ if (state & 1) {
+ eventPtr->xkey.state |= ShiftMask;
+ }
+ if (state & 2) {
+ TkDisplay *dispPtr;
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ eventPtr->xkey.state |= dispPtr->modeModMask;
+ }
+ break;
+ }
+ }
+ }
+ eventPtr->xkey.keycode = keycode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetKeySym --
+ *
+ * Given an X KeyPress or KeyRelease event, map the
+ * keycode in the event into a KeySym.
+ *
+ * Results:
+ * The return value is the KeySym corresponding to
+ * eventPtr, or NoSymbol if no matching Keysym could be
+ * found.
+ *
+ * Side effects:
+ * In the first call for a given display, keycode-to-
+ * KeySym maps get loaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+TkpGetKeySym(dispPtr, eventPtr)
+ TkDisplay *dispPtr; /* Display in which to
+ * map keycode. */
+ XEvent *eventPtr; /* Description of X event. */
+{
+ KeySym sym;
+ int index;
+
+ /*
+ * Refresh the mapping information if it's stale
+ */
+
+ if (dispPtr->bindInfoStale) {
+ InitKeymapInfo(dispPtr);
+ }
+
+ /*
+ * Figure out which of the four slots in the keymap vector to
+ * use for this key. Refer to Xlib documentation for more info
+ * on how this computation works.
+ */
+
+ index = 0;
+ if (eventPtr->xkey.state & dispPtr->modeModMask) {
+ index = 2;
+ }
+ if ((eventPtr->xkey.state & ShiftMask)
+ || ((dispPtr->lockUsage != LU_IGNORE)
+ && (eventPtr->xkey.state & LockMask))) {
+ index += 1;
+ }
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
+
+ /*
+ * Special handling: if the key was shifted because of Lock, but
+ * lock is only caps lock, not shift lock, and the shifted keysym
+ * isn't upper-case alphabetic, then switch back to the unshifted
+ * keysym.
+ */
+
+ if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
+ && (dispPtr->lockUsage == LU_CAPS)) {
+ if (!(((sym >= XK_A) && (sym <= XK_Z))
+ || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
+ || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
+ index &= ~1;
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ index);
+ }
+ }
+
+ /*
+ * Another bit of special handling: if this is a shifted key and there
+ * is no keysym defined, then use the keysym for the unshifted key.
+ */
+
+ if ((index & 1) && (sym == NoSymbol)) {
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ index & ~1);
+ }
+ return sym;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitKeymapInfo --
+ *
+ * This procedure is invoked to scan keymap information
+ * to recompute stuff that's important for binding, such
+ * as the modifier key (if any) that corresponds to "mode
+ * switch".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Keymap-related information in dispPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+InitKeymapInfo(dispPtr)
+ TkDisplay *dispPtr; /* Display for which to recompute keymap
+ * information. */
+{
+ XModifierKeymap *modMapPtr;
+ KeyCode *codePtr;
+ KeySym keysym;
+ int count, i, j, max, arraySize;
+#define KEYCODE_ARRAY_SIZE 20
+
+ dispPtr->bindInfoStale = 0;
+ modMapPtr = XGetModifierMapping(dispPtr->display);
+
+ /*
+ * Check the keycodes associated with the Lock modifier. If
+ * any of them is associated with the XK_Shift_Lock modifier,
+ * then Lock has to be interpreted as Shift Lock, not Caps Lock.
+ */
+
+ dispPtr->lockUsage = LU_IGNORE;
+ codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
+ for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
+ if (keysym == XK_Shift_Lock) {
+ dispPtr->lockUsage = LU_SHIFT;
+ break;
+ }
+ if (keysym == XK_Caps_Lock) {
+ dispPtr->lockUsage = LU_CAPS;
+ break;
+ }
+ }
+
+ /*
+ * Look through the keycodes associated with modifiers to see if
+ * the the "mode switch", "meta", or "alt" keysyms are associated
+ * with any modifiers. If so, remember their modifier mask bits.
+ */
+
+ dispPtr->modeModMask = 0;
+ dispPtr->metaModMask = 0;
+ dispPtr->altModMask = 0;
+ codePtr = modMapPtr->modifiermap;
+ max = 8*modMapPtr->max_keypermod;
+ for (i = 0; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
+ if (keysym == XK_Mode_switch) {
+ dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
+ dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
+ dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ }
+
+ /*
+ * Create an array of the keycodes for all modifier keys.
+ */
+
+ if (dispPtr->modKeyCodes != NULL) {
+ ckfree((char *) dispPtr->modKeyCodes);
+ }
+ dispPtr->numModKeyCodes = 0;
+ arraySize = KEYCODE_ARRAY_SIZE;
+ dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
+ (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
+ for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+
+ /*
+ * Make sure that the keycode isn't already in the array.
+ */
+
+ for (j = 0; j < dispPtr->numModKeyCodes; j++) {
+ if (dispPtr->modKeyCodes[j] == *codePtr) {
+ goto nextModCode;
+ }
+ }
+ if (dispPtr->numModKeyCodes >= arraySize) {
+ KeyCode *new;
+
+ /*
+ * Ran out of space in the array; grow it.
+ */
+
+ arraySize *= 2;
+ new = (KeyCode *) ckalloc((unsigned)
+ (arraySize * sizeof(KeyCode)));
+ memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
+ (dispPtr->numModKeyCodes * sizeof(KeyCode)));
+ ckfree((char *) dispPtr->modKeyCodes);
+ dispPtr->modKeyCodes = new;
+ }
+ dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
+ dispPtr->numModKeyCodes++;
+ nextModCode: continue;
+ }
+ XFreeModifiermap(modMapPtr);
+}
diff --git a/win/tkWinKey.c b/win/tkWinKey.c
index af826d5..d46f601 100644
--- a/win/tkWinKey.c
+++ b/win/tkWinKey.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinKey.c,v 1.6 1999/10/30 09:16:07 hobbs Exp $
+ * RCS: @(#) $Id: tkWinKey.c,v 1.7 2000/02/09 02:13:56 hobbs Exp $
*/
#include "tkWinInt.h"
@@ -85,6 +85,14 @@ static Keys keymap[] = {
0, NoSymbol
};
+/*
+ * Prototypes for local procedures defined in this file:
+ */
+
+static KeySym KeycodeToKeysym _ANSI_ARGS_((unsigned int keycode,
+ int state, int noascii));
+static void InitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr));
+
/*
*----------------------------------------------------------------------
@@ -110,7 +118,6 @@ TkpGetString(winPtr, eventPtr, dsPtr)
Tcl_DString *dsPtr; /* Uninitialized or empty string to hold
* result. */
{
- int index;
KeySym keysym;
XKeyEvent* keyEv = &eventPtr->xkey;
@@ -121,20 +128,13 @@ TkpGetString(winPtr, eventPtr, dsPtr)
* nchars or trans_chars members.
*/
- index = 0;
- if (eventPtr->xkey.state & ShiftMask) {
- index |= 1;
- }
- if (eventPtr->xkey.state & Mod1Mask) {
- index |= 2;
- }
- keysym = XKeycodeToKeysym(eventPtr->xkey.display,
- eventPtr->xkey.keycode, index);
+ keysym = KeycodeToKeysym(eventPtr->xkey.keycode,
+ eventPtr->xkey.state, 0);
if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
|| (keysym == XK_Return)
|| (keysym == XK_Tab)) {
char buf[TCL_UTF_MAX];
- int len = Tcl_UniCharToUtf((Tcl_UniChar) keysym, buf);
+ int len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
Tcl_DStringAppend(dsPtr, buf, len);
}
} else if (eventPtr->xkey.nbytes > 0) {
@@ -167,20 +167,132 @@ XKeycodeToKeysym(display, keycode, index)
unsigned int keycode;
int index;
{
+ int state = 0;
+
+ if (index & 0x01) {
+ state |= ShiftMask;
+ }
+ return KeycodeToKeysym(keycode, state, 0);
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * KeycodeToKeysym --
+ *
+ * Translate from a system-dependent keycode to a
+ * system-independent keysym.
+ *
+ * Results:
+ * Returns the translated keysym, or NoSymbol on failure.
+ *
+ * Side effects:
+ * It may affect the internal state of the keyboard, such as
+ * remembered dead key or lock indicator lamps.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static KeySym
+KeycodeToKeysym(keycode, state, noascii)
+ unsigned int keycode;
+ int state;
+ int noascii;
+{
Keys* key;
BYTE keys[256];
- int result;
+ int result, deadkey, shift;
char buf[4];
unsigned int scancode = MapVirtualKey(keycode, 0);
+ /*
+ * Do not run keycodes of lock keys through ToAscii().
+ * One of ToAscii()'s side effects is to handle the lights
+ * on the keyboard, and we don't want to mess that up.
+ */
+
+ if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL ||
+ keycode == VK_NUMLOCK)
+ goto skipToAscii;
+
+ /*
+ * Use MapVirtualKey() to detect some dead keys.
+ */
+
+ if (MapVirtualKey(keycode, 2) > 0x7fffUL)
+ return XK_Multi_key;
+
+ /*
+ * Set up a keyboard with correct modifiers
+ */
+
memset(keys, 0, 256);
- if (index & 0x02) {
+ if (state & ShiftMask)
+ keys[VK_SHIFT] = 0x80;
+ if (state & ControlMask)
+ keys[VK_CONTROL] = 0x80;
+ if (state & Mod2Mask)
+ keys[VK_MENU] = 0x80;
+
+ /*
+ * Make sure all lock button info is correct so we don't mess up the
+ * lights
+ */
+
+ if (state & LockMask)
+ keys[VK_CAPITAL] = 1;
+ if (state & Mod3Mask)
+ keys[VK_SCROLL] = 1;
+ if (state & Mod1Mask)
keys[VK_NUMLOCK] = 1;
+
+ result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
+
+ if (result < 0) {
+ /*
+ * Win95/98:
+ * This was a dead char, which is now remembered by the keyboard.
+ * Call ToAscii() again to forget it.
+ * WinNT:
+ * This was a dead char, overwriting any previously remembered
+ * key. Calling ToAscii() again does not affect anything.
+ */
+
+ ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
+ return XK_Multi_key;
}
- if (index & 0x01) {
- keys[VK_SHIFT] = 0x80;
+ if (result == 2) {
+ /*
+ * This was a dead char, and there were one previously remembered
+ * by the keyboard.
+ * Call ToAscii() again with proper parameters to restore it.
+ */
+
+ /*
+ * Get information about the old char
+ */
+
+ deadkey = VkKeyScan(buf[0]);
+ shift = deadkey >> 8;
+ deadkey &= 255;
+ scancode = MapVirtualKey(deadkey, 0);
+
+ /*
+ * Set up a keyboard with proper modifier keys
+ */
+
+ memset(keys, 0, 256);
+ if (shift & 1)
+ keys[VK_SHIFT] = 0x80;
+ if (shift & 2)
+ keys[VK_CONTROL] = 0x80;
+ if (shift & 4)
+ keys[VK_MENU] = 0x80;
+ ToAscii(deadkey, scancode, keys, (LPWORD) buf, 0);
+ return XK_Multi_key;
}
- result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
/*
* Keycode mapped to a valid Latin-1 character. Since the keysyms
@@ -195,6 +307,7 @@ XKeycodeToKeysym(display, keycode, index)
* Keycode is a non-alphanumeric key, so we have to do the lookup.
*/
+ skipToAscii:
for (key = keymap; key->keycode != 0; key++) {
if (key->keycode == keycode) {
return key->keysym;
@@ -204,6 +317,251 @@ XKeycodeToKeysym(display, keycode, index)
return NoSymbol;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetKeySym --
+ *
+ * Given an X KeyPress or KeyRelease event, map the
+ * keycode in the event into a KeySym.
+ *
+ * Results:
+ * The return value is the KeySym corresponding to
+ * eventPtr, or NoSymbol if no matching Keysym could be
+ * found.
+ *
+ * Side effects:
+ * In the first call for a given display, keycode-to-
+ * KeySym maps get loaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+TkpGetKeySym(dispPtr, eventPtr)
+ TkDisplay *dispPtr; /* Display in which to map keycode. */
+ XEvent *eventPtr; /* Description of X event. */
+{
+ KeySym sym;
+ int state = eventPtr->xkey.state;
+
+ /*
+ * Refresh the mapping information if it's stale
+ */
+
+ if (dispPtr->bindInfoStale) {
+ InitKeymapInfo(dispPtr);
+ }
+
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+
+ /*
+ * Special handling: if this is a ctrl-alt or shifted key, and there
+ * is no keysym defined, try without the modifiers.
+ */
+
+ if ((sym == NoSymbol) && ((state & ControlMask) || (state & Mod2Mask))) {
+ state &= ~(ControlMask | Mod2Mask);
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+ }
+ if ((sym == NoSymbol) && (state & ShiftMask)) {
+ state &= ~ShiftMask;
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+ }
+ return sym;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitKeymapInfo --
+ *
+ * This procedure is invoked to scan keymap information
+ * to recompute stuff that's important for binding, such
+ * as the modifier key (if any) that corresponds to "mode
+ * switch".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Keymap-related information in dispPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+InitKeymapInfo(dispPtr)
+ TkDisplay *dispPtr; /* Display for which to recompute keymap
+ * information. */
+{
+ XModifierKeymap *modMapPtr;
+ KeyCode *codePtr;
+ KeySym keysym;
+ int count, i, j, max, arraySize;
+#define KEYCODE_ARRAY_SIZE 20
+
+ dispPtr->bindInfoStale = 0;
+ modMapPtr = XGetModifierMapping(dispPtr->display);
+
+ /*
+ * Check the keycodes associated with the Lock modifier. If
+ * any of them is associated with the XK_Shift_Lock modifier,
+ * then Lock has to be interpreted as Shift Lock, not Caps Lock.
+ */
+
+ dispPtr->lockUsage = LU_IGNORE;
+ codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
+ for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = KeycodeToKeysym(*codePtr, 0, 1);
+ if (keysym == XK_Shift_Lock) {
+ dispPtr->lockUsage = LU_SHIFT;
+ break;
+ }
+ if (keysym == XK_Caps_Lock) {
+ dispPtr->lockUsage = LU_CAPS;
+ break;
+ }
+ }
+
+ /*
+ * Look through the keycodes associated with modifiers to see if
+ * the the "mode switch", "meta", or "alt" keysyms are associated
+ * with any modifiers. If so, remember their modifier mask bits.
+ */
+
+ dispPtr->modeModMask = 0;
+ dispPtr->metaModMask = 0;
+ dispPtr->altModMask = 0;
+ codePtr = modMapPtr->modifiermap;
+ max = 8*modMapPtr->max_keypermod;
+ for (i = 0; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = KeycodeToKeysym(*codePtr, 0, 1);
+ if (keysym == XK_Mode_switch) {
+ dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
+ dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
+ dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ }
+
+ /*
+ * Create an array of the keycodes for all modifier keys.
+ */
+
+ if (dispPtr->modKeyCodes != NULL) {
+ ckfree((char *) dispPtr->modKeyCodes);
+ }
+ dispPtr->numModKeyCodes = 0;
+ arraySize = KEYCODE_ARRAY_SIZE;
+ dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
+ (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
+ for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+
+ /*
+ * Make sure that the keycode isn't already in the array.
+ */
+
+ for (j = 0; j < dispPtr->numModKeyCodes; j++) {
+ if (dispPtr->modKeyCodes[j] == *codePtr) {
+ goto nextModCode;
+ }
+ }
+ if (dispPtr->numModKeyCodes >= arraySize) {
+ KeyCode *new;
+
+ /*
+ * Ran out of space in the array; grow it.
+ */
+
+ arraySize *= 2;
+ new = (KeyCode *) ckalloc((unsigned)
+ (arraySize * sizeof(KeyCode)));
+ memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
+ (dispPtr->numModKeyCodes * sizeof(KeyCode)));
+ ckfree((char *) dispPtr->modKeyCodes);
+ dispPtr->modKeyCodes = new;
+ }
+ dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
+ dispPtr->numModKeyCodes++;
+ nextModCode: continue;
+ }
+ XFreeModifiermap(modMapPtr);
+}
+
+/*
+ * When mapping from a keysym to a keycode, need
+ * information about the modifier state that should be used
+ * so that when they call XKeycodeToKeysym taking into
+ * account the xkey.state, they will get back the original
+ * keysym.
+ */
+
+void
+TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
+ Tk_Window tkwin;
+ KeySym keySym;
+ XEvent *eventPtr;
+{
+ Keys* key;
+ SHORT result;
+ int shift;
+
+ eventPtr->xkey.keycode = 0;
+ if (keySym == NoSymbol) {
+ return;
+ }
+
+ /*
+ * We check our private map first for a virtual keycode,
+ * as VkKeyScan will return values that don't map to X
+ * for the "extended" Syms. This may be due to just casting
+ * problems below, but this works.
+ */
+
+ for (key = keymap; key->keycode != 0; key++) {
+ if (key->keysym == keySym) {
+ eventPtr->xkey.keycode = key->keycode;
+ return;
+ }
+ }
+
+ if (keySym >= 0x20) {
+ result = VkKeyScan((char) keySym);
+ if (result != -1) {
+ shift = result >> 8;
+ if (shift & 1)
+ eventPtr->xkey.state |= ShiftMask;
+ if (shift & 2)
+ eventPtr->xkey.state |= ControlMask;
+ if (shift & 4)
+ eventPtr->xkey.state |= Mod2Mask;
+ eventPtr->xkey.keycode = (KeyCode) (result & 0xff);
+ }
+ }
+ {
+ /* Debug log */
+ FILE *fp = fopen("c:\\temp\\tklog.txt", "a");
+ if (fp != NULL) {
+ fprintf(fp, "TkpSetKeycode. Keycode %d State %d Keysym %d\n", eventPtr->xkey.keycode, eventPtr->xkey.state, keySym);
+ fclose(fp);
+ }
+ }
+}
+
/*
*----------------------------------------------------------------------
*
@@ -244,7 +602,7 @@ XKeysymToKeycode(display, keysym)
if (keysym >= 0x20) {
result = VkKeyScan((char) keysym);
if (result != -1) {
- return (KeyCode) (result & 0xfff);
+ return (KeyCode) (result & 0xff);
}
}