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