3 Copyright 1985, 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
27 /* Beware, here be monsters (still under construction... - JG */
32 #include <X11/Xlibint.h>
33 #include <X11/Xutil.h>
48 #include <X11/keysymdef.h>
51 #ifdef USE_OWN_COMPOSE
56 #include "Xresource.h"
61 #include "XKBlibint.h"
62 #define XKeycodeToKeysym _XKeycodeToKeysym
63 #define XKeysymToKeycode _XKeysymToKeycode
64 #define XLookupKeysym _XLookupKeysym
65 #define XRefreshKeyboardMapping _XRefreshKeyboardMapping
66 #define XLookupString _XLookupString
69 #define XkbKeysymToModifiers _XKeysymToModifiers
72 #define AllMods (ShiftMask|LockMask|ControlMask| \
73 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
76 ComputeMaskFromKeytrans(
78 register struct _XKeytrans *p);
81 struct _XKeytrans *next;/* next on list */
82 char *string; /* string to return when the time comes */
83 int len; /* length of string (since NULL is legit)*/
84 KeySym key; /* keysym rebound */
85 unsigned int state; /* modifier state */
86 KeySym *modifiers; /* modifier keysyms you want */
87 int mlen; /* length of modifier list */
91 KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col)
93 register int per = dpy->keysyms_per_keycode;
94 register KeySym *syms;
97 if ((col < 0) || ((col >= per) && (col > 3)) ||
98 ((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
101 syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
104 while ((per > 2) && (syms[per - 1] == NoSymbol))
109 if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
110 XConvertCase(syms[col&~1], &lsym, &usym);
113 else if (usym == lsym)
123 XKeycodeToKeysym(Display *dpy,
124 #if NeedWidePrototypes
131 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
133 return KeyCodetoKeySym(dpy, kc, col);
143 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
145 for (j = 0; j < dpy->keysyms_per_keycode; j++) {
146 for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
147 if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
156 register XKeyEvent *event,
159 if ((! event->display->keysyms) && (! _XKeyInitialize(event->display)))
161 return KeyCodetoKeySym(event->display, event->keycode, col);
168 register XModifierKeymap *map;
169 register int i, j, n;
171 register struct _XKeytrans *p;
173 map = dpy->modifiermap;
174 /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
175 * else if any contains Shift_Lock, then interpret as Shift_Lock,
176 * else ignore Lock altogether.
178 dpy->lock_meaning = NoSymbol;
179 /* Lock modifiers are in the second row of the matrix */
180 n = 2 * map->max_keypermod;
181 for (i = map->max_keypermod; i < n; i++) {
182 for (j = 0; j < dpy->keysyms_per_keycode; j++) {
183 sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
184 if (sym == XK_Caps_Lock) {
185 dpy->lock_meaning = XK_Caps_Lock;
187 } else if (sym == XK_Shift_Lock) {
188 dpy->lock_meaning = XK_Shift_Lock;
190 else if (sym == XK_ISO_Lock) {
191 dpy->lock_meaning = XK_Caps_Lock;
196 /* Now find any Mod<n> modifier acting as the Group or Numlock modifier */
197 dpy->mode_switch = 0;
200 for (i = 3*map->max_keypermod; i < n; i++) {
201 for (j = 0; j < dpy->keysyms_per_keycode; j++) {
202 sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
203 if (sym == XK_Mode_switch)
204 dpy->mode_switch |= 1 << (i / map->max_keypermod);
205 if (sym == XK_Num_Lock)
206 dpy->num_lock |= 1 << (i / map->max_keypermod);
209 for (p = dpy->key_bindings; p; p = p->next)
210 ComputeMaskFromKeytrans(dpy, p);
217 register XModifierKeymap *map;
219 if (! (map = XGetModifierMapping(dpy)))
222 if (dpy->modifiermap)
223 XFreeModifiermap(dpy->modifiermap);
224 dpy->modifiermap = map;
225 dpy->free_funcs->modifiermap = XFreeModifiermap;
233 XRefreshKeyboardMapping(register XMappingEvent *event)
236 if(event->request == MappingKeyboard) {
237 /* XXX should really only refresh what is necessary
238 * for now, make initialize test fail
240 LockDisplay(event->display);
241 if (event->display->keysyms) {
242 Xfree ((char *)event->display->keysyms);
243 event->display->keysyms = NULL;
245 UnlockDisplay(event->display);
247 if(event->request == MappingModifier) {
248 LockDisplay(event->display);
249 if (event->display->modifiermap) {
250 XFreeModifiermap(event->display->modifiermap);
251 event->display->modifiermap = NULL;
253 UnlockDisplay(event->display);
254 /* go ahead and get it now, since initialize test may not fail */
255 if (event->display->keysyms)
256 (void) InitModMap(event->display);
269 * lets go get the keysyms from the server.
272 n = dpy->max_keycode - dpy->min_keycode + 1;
273 keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
275 /* keysyms may be NULL */
276 if (! keysyms) return 0;
280 Xfree ((char *)dpy->keysyms);
281 dpy->keysyms = keysyms;
282 dpy->keysyms_per_keycode = per;
283 if (dpy->modifiermap)
287 if (!dpy->modifiermap)
288 return InitModMap(dpy);
293 UCSConvertCase( register unsigned code,
297 /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
298 /* NB: Only converts simple one-to-one mappings. */
300 /* Tables are used where they take less space than */
301 /* the code to work out the mappings. Zero values mean */
302 /* undefined code points. */
304 static unsigned short const IPAExt_upper_mapping[] = { /* part only */
305 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
306 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
307 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
308 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
309 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
310 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
311 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
312 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
313 0x0290, 0x0291, 0x01B7
316 static unsigned short const LatinExtB_upper_mapping[] = { /* first part only */
317 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
318 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
319 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
320 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
321 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
322 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
323 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
324 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
325 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
326 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
329 static unsigned short const LatinExtB_lower_mapping[] = { /* first part only */
330 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
331 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
332 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
333 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
334 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
335 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
336 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
337 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
338 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
339 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
342 static unsigned short const Greek_upper_mapping[] = {
343 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
344 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
345 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
346 0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
347 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
348 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
349 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
350 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
351 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
352 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
353 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
354 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
355 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
356 0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
357 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
358 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
359 0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7,
360 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
363 static unsigned short const Greek_lower_mapping[] = {
364 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
365 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
366 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
367 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
368 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
369 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
370 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
371 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
372 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
373 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
374 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
375 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
376 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
377 0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
378 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
379 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
380 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
381 0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
384 static unsigned short const GreekExt_lower_mapping[] = {
385 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
386 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
387 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
388 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
389 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
390 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
391 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
392 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
393 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
394 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
395 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
396 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
397 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
398 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
399 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
400 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
401 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
402 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
403 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
404 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
405 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
406 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
407 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
408 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
409 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
410 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
411 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
412 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
413 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
414 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
415 0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
416 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
419 static unsigned short const GreekExt_upper_mapping[] = {
420 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
421 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
422 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
423 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
424 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
425 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
426 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
427 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
428 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
429 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
430 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
431 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
432 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
433 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
434 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
435 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
436 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
437 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
438 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
439 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
440 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
441 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
442 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
443 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
444 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
445 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
446 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
447 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
448 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
449 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
450 0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
451 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
457 /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
458 if (code <= 0x00ff) {
459 if (code >= 0x0041 && code <= 0x005a) /* A-Z */
461 else if (code >= 0x0061 && code <= 0x007a) /* a-z */
463 else if ( (code >= 0x00c0 && code <= 0x00d6) ||
464 (code >= 0x00d8 && code <= 0x00de) )
466 else if ( (code >= 0x00e0 && code <= 0x00f6) ||
467 (code >= 0x00f8 && code <= 0x00fe) )
469 else if (code == 0x00ff) /* y with diaeresis */
471 else if (code == 0x00b5) /* micro sign */
476 /* Latin Extended-A, U+0100 to U+017F */
477 if (code >= 0x0100 && code <= 0x017f) {
478 if ( (code >= 0x0100 && code <= 0x012f) ||
479 (code >= 0x0132 && code <= 0x0137) ||
480 (code >= 0x014a && code <= 0x0177) ) {
484 else if ( (code >= 0x0139 && code <= 0x0148) ||
485 (code >= 0x0179 && code <= 0x017e) ) {
491 else if (code == 0x0130)
493 else if (code == 0x0131)
495 else if (code == 0x0178)
497 else if (code == 0x017f)
502 /* Latin Extended-B, U+0180 to U+024F */
503 if (code >= 0x0180 && code <= 0x024f) {
504 if (code >= 0x01cd && code <= 0x01dc) {
510 else if ( (code >= 0x01de && code <= 0x01ef) ||
511 (code >= 0x01f4 && code <= 0x01f5) ||
512 (code >= 0x01f8 && code <= 0x021f) ||
513 (code >= 0x0222 && code <= 0x0233) ) {
517 else if (code >= 0x0180 && code <= 0x01cc) {
518 *lower = LatinExtB_lower_mapping[code - 0x0180];
519 *upper = LatinExtB_upper_mapping[code - 0x0180];
521 else if (code == 0x01dd)
523 else if (code == 0x01f1 || code == 0x01f2) {
527 else if (code == 0x01f3)
529 else if (code == 0x01f6)
531 else if (code == 0x01f7)
533 else if (code == 0x0220)
538 /* IPA Extensions, U+0250 to U+02AF */
539 if (code >= 0x0253 && code <= 0x0292) {
540 *upper = IPAExt_upper_mapping[code - 0x0253];
543 /* Combining Diacritical Marks, U+0300 to U+036F */
544 if (code == 0x0345) {
548 /* Greek and Coptic, U+0370 to U+03FF */
549 if (code >= 0x0370 && code <= 0x03ff) {
550 *lower = Greek_lower_mapping[code - 0x0370];
551 *upper = Greek_upper_mapping[code - 0x0370];
558 /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
559 if ( (code >= 0x0400 && code <= 0x04ff) ||
560 (code >= 0x0500 && code <= 0x052f) ) {
561 if (code >= 0x0400 && code <= 0x040f)
563 else if (code >= 0x0410 && code <= 0x042f)
565 else if (code >= 0x0430 && code <= 0x044f)
567 else if (code >= 0x0450 && code <= 0x045f)
569 else if ( (code >= 0x0460 && code <= 0x0481) ||
570 (code >= 0x048a && code <= 0x04bf) ||
571 (code >= 0x04d0 && code <= 0x04f5) ||
572 (code >= 0x04f8 && code <= 0x04f9) ||
573 (code >= 0x0500 && code <= 0x050f) ) {
577 else if (code >= 0x04c1 && code <= 0x04ce) {
585 /* Armenian, U+0530 to U+058F */
586 if (code >= 0x0530 && code <= 0x058f) {
587 if (code >= 0x0531 && code <= 0x0556)
589 else if (code >=0x0561 && code <= 0x0586)
593 /* Latin Extended Additional, U+1E00 to U+1EFF */
594 if (code >= 0x1e00 && code <= 0x1eff) {
595 if ( (code >= 0x1e00 && code <= 0x1e95) ||
596 (code >= 0x1ea0 && code <= 0x1ef9) ) {
600 else if (code == 0x1e9b)
604 /* Greek Extended, U+1F00 to U+1FFF */
605 if (code >= 0x1f00 && code <= 0x1fff) {
606 *lower = GreekExt_lower_mapping[code - 0x1f00];
607 *upper = GreekExt_upper_mapping[code - 0x1f00];
614 /* Letterlike Symbols, U+2100 to U+214F */
615 if (code >= 0x2100 && code <= 0x214f) {
617 case 0x2126: *lower = 0x03c9; break;
618 case 0x212a: *lower = 0x006b; break;
619 case 0x212b: *lower = 0x00e5; break;
622 /* Number Forms, U+2150 to U+218F */
623 else if (code >= 0x2160 && code <= 0x216f)
625 else if (code >= 0x2170 && code <= 0x217f)
627 /* Enclosed Alphanumerics, U+2460 to U+24FF */
628 else if (code >= 0x24b6 && code <= 0x24cf)
630 else if (code >= 0x24d0 && code <= 0x24e9)
632 /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
633 else if (code >= 0xff21 && code <= 0xff3a)
635 else if (code >= 0xff41 && code <= 0xff5a)
637 /* Deseret, U+10400 to U+104FF */
638 else if (code >= 0x10400 && code <= 0x10427)
640 else if (code >= 0x10428 && code <= 0x1044f)
652 UCSConvertCase(sym, lower, upper);
657 if ((sym & 0xff000000) == 0x01000000) {
658 UCSConvertCase((sym & 0x00ffffff), lower, upper);
659 *upper |= 0x01000000;
660 *lower |= 0x01000000;
670 case 1: /* Latin 2 */
671 /* Assume the KeySym is a legal value (ignore discontinuities) */
672 if (sym == XK_Aogonek)
674 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
675 *lower += (XK_lstroke - XK_Lstroke);
676 else if (sym >= XK_Scaron && sym <= XK_Zacute)
677 *lower += (XK_scaron - XK_Scaron);
678 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
679 *lower += (XK_zcaron - XK_Zcaron);
680 else if (sym == XK_aogonek)
682 else if (sym >= XK_lstroke && sym <= XK_sacute)
683 *upper -= (XK_lstroke - XK_Lstroke);
684 else if (sym >= XK_scaron && sym <= XK_zacute)
685 *upper -= (XK_scaron - XK_Scaron);
686 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
687 *upper -= (XK_zcaron - XK_Zcaron);
688 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
689 *lower += (XK_racute - XK_Racute);
690 else if (sym >= XK_racute && sym <= XK_tcedilla)
691 *upper -= (XK_racute - XK_Racute);
693 case 2: /* Latin 3 */
694 /* Assume the KeySym is a legal value (ignore discontinuities) */
695 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
696 *lower += (XK_hstroke - XK_Hstroke);
697 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
698 *lower += (XK_gbreve - XK_Gbreve);
699 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
700 *upper -= (XK_hstroke - XK_Hstroke);
701 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
702 *upper -= (XK_gbreve - XK_Gbreve);
703 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
704 *lower += (XK_cabovedot - XK_Cabovedot);
705 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
706 *upper -= (XK_cabovedot - XK_Cabovedot);
708 case 3: /* Latin 4 */
709 /* Assume the KeySym is a legal value (ignore discontinuities) */
710 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
711 *lower += (XK_rcedilla - XK_Rcedilla);
712 else if (sym >= XK_rcedilla && sym <= XK_tslash)
713 *upper -= (XK_rcedilla - XK_Rcedilla);
714 else if (sym == XK_ENG)
716 else if (sym == XK_eng)
718 else if (sym >= XK_Amacron && sym <= XK_Umacron)
719 *lower += (XK_amacron - XK_Amacron);
720 else if (sym >= XK_amacron && sym <= XK_umacron)
721 *upper -= (XK_amacron - XK_Amacron);
723 case 6: /* Cyrillic */
724 /* Assume the KeySym is a legal value (ignore discontinuities) */
725 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
726 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
727 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
728 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
729 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
730 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
731 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
732 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
735 /* Assume the KeySym is a legal value (ignore discontinuities) */
736 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
737 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
738 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
739 sym != XK_Greek_iotaaccentdieresis &&
740 sym != XK_Greek_upsilonaccentdieresis)
741 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
742 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
743 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
744 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
745 sym != XK_Greek_finalsmallsigma)
746 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
748 case 0x13: /* Latin 9 */
751 else if (sym == XK_oe)
753 else if (sym == XK_Ydiaeresis)
754 *lower = XK_ydiaeresis;
760 _XTranslateKey( register Display *dpy,
762 register unsigned int modifiers,
763 unsigned int *modifiers_return,
764 KeySym *keysym_return)
767 register KeySym *syms;
768 KeySym sym, lsym, usym;
770 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
772 *modifiers_return = ((ShiftMask|LockMask)
773 | dpy->mode_switch | dpy->num_lock);
774 if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
776 *keysym_return = NoSymbol;
779 per = dpy->keysyms_per_keycode;
780 syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
781 while ((per > 2) && (syms[per - 1] == NoSymbol))
783 if ((per > 2) && (modifiers & dpy->mode_switch)) {
787 if ((modifiers & dpy->num_lock) &&
788 (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
789 if ((modifiers & ShiftMask) ||
790 ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
791 *keysym_return = syms[0];
793 *keysym_return = syms[1];
794 } else if (!(modifiers & ShiftMask) &&
795 (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
796 if ((per == 1) || (syms[1] == NoSymbol))
797 XConvertCase(syms[0], keysym_return, &usym);
799 *keysym_return = syms[0];
800 } else if (!(modifiers & LockMask) ||
801 (dpy->lock_meaning != XK_Caps_Lock)) {
802 if ((per == 1) || ((usym = syms[1]) == NoSymbol))
803 XConvertCase(syms[0], &lsym, &usym);
804 *keysym_return = usym;
806 if ((per == 1) || ((sym = syms[1]) == NoSymbol))
808 XConvertCase(sym, &lsym, &usym);
809 if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
810 ((sym != usym) || (lsym == usym)))
811 XConvertCase(syms[0], &lsym, &usym);
812 *keysym_return = usym;
814 if (*keysym_return == XK_VoidSymbol)
815 *keysym_return = NoSymbol;
822 register KeySym symbol,
823 unsigned int modifiers,
827 register struct _XKeytrans *p;
829 unsigned long hiBytes;
830 register unsigned char c;
834 /* see if symbol rebound, if so, return that string. */
835 for (p = dpy->key_bindings; p; p = p->next) {
836 if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
838 if (length > nbytes) length = nbytes;
839 memcpy (buffer, p->string, length);
843 /* try to convert to Latin-1, handling control */
844 hiBytes = symbol >> 8;
847 ((hiBytes == 0xFF) &&
848 (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
849 (symbol == XK_Return) ||
850 (symbol == XK_Escape) ||
851 (symbol == XK_KP_Space) ||
852 (symbol == XK_KP_Tab) ||
853 (symbol == XK_KP_Enter) ||
854 ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
855 (symbol == XK_KP_Equal) ||
856 (symbol == XK_Delete))))))
859 /* if X keysym, convert to ascii by grabbing low 7 bits */
860 if (symbol == XK_KP_Space)
861 c = XK_space & 0x7F; /* patch encoding botch */
862 else if (hiBytes == 0xFF)
866 /* only apply Control key if it makes sense, else ignore it */
867 if (modifiers & ControlMask) {
868 if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
869 else if (c == '2') c = '\000';
870 else if (c >= '3' && c <= '7') c -= ('3' - '\033');
871 else if (c == '8') c = '\177';
872 else if (c == '/') c = '_' & 0x1F;
881 register XKeyEvent *event,
882 char *buffer, /* buffer */
883 int nbytes, /* space in buffer for characters */
885 XComposeStatus *status) /* not implemented */
887 unsigned int modifiers;
890 if (! _XTranslateKey(event->display, event->keycode, event->state,
891 &modifiers, &symbol))
894 #ifdef USE_OWN_COMPOSE
896 static int been_here= 0;
901 if ( !XimCompLegalStatus(status) ) {
902 status->compose_ptr = NULL;
903 status->chars_matched = 0;
905 if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
906 XimCompIsComposeKey(symbol,event->keycode,status) ) {
908 switch (XimCompProcessSym(status,symbol,&rtrn)) {
909 case XIM_COMP_IGNORE:
911 case XIM_COMP_IN_PROGRESS:
918 for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
919 if ( nbytes-len > 0 ) {
920 len+= _XTranslateKeySym(event->display,rtrn.sym[n],
922 buffer+len,nbytes-len);
925 if ( keysym!=NULL ) {
926 if ( n==1 ) *keysym = rtrn.sym[0];
927 else *keysym = NoSymbol;
931 case XIM_COMP_SUCCEED:
935 symbol = rtrn.matchSym;
936 if ( keysym!=NULL ) *keysym = symbol;
937 if ( rtrn.str[0]!='\0' ) {
938 strncpy(buffer,rtrn.str,nbytes-1);
939 buffer[nbytes-1]= '\0';
940 len = strlen(buffer);
943 len = _XTranslateKeySym(event->display,symbol,
947 for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
948 if ( nbytes-len > 0 ) {
949 len+= _XTranslateKeySym(event->display,rtrn.sym[n],
951 buffer+len,nbytes-len);
963 /* arguable whether to use (event->state & ~modifiers) here */
964 return _XTranslateKeySym(event->display, symbol, event->state,
972 register struct _XKeytrans *p, *np;
974 for (p = dpy->key_bindings; p; p = np) {
977 Xfree((char *)p->modifiers);
987 int nm, /* number of modifiers in mlist */
988 _Xconst unsigned char *str,
991 register struct _XKeytrans *tmp, *p;
994 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
997 tmp = dpy->key_bindings;
998 nb = sizeof(KeySym) * nm;
1000 if ((! (p = (struct _XKeytrans *) Xcalloc( 1, sizeof(struct _XKeytrans)))) ||
1001 ((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) &&
1003 ((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) &&
1006 if (p->string) Xfree(p->string);
1007 if (p->modifiers) Xfree((char *) p->modifiers);
1014 dpy->key_bindings = p;
1015 dpy->free_funcs->key_bindings = _XFreeKeyBindings;
1016 p->next = tmp; /* chain onto list */
1017 memcpy (p->string, (char *) str, nbytes);
1019 memcpy ((char *) p->modifiers, (char *) mlist, nb);
1022 ComputeMaskFromKeytrans(dpy, p);
1028 _XKeysymToModifiers(
1033 register KeySym *kmax;
1035 register XModifierKeymap *m;
1037 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
1039 kmax = dpy->keysyms +
1040 (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
1042 m = dpy->modifiermap;
1046 register int j = m->max_keypermod<<3;
1048 code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode);
1051 if (code == m->modifiermap[j])
1052 mods|= (1<<(j/m->max_keypermod));
1061 * given a list of modifiers, computes the mask necessary for later matching.
1062 * This routine must lookup the key in the Keymap and then search to see
1063 * what modifier it is bound to, if any. Sets the AnyModifier bit if it
1064 * can't map some keysym to a modifier.
1067 ComputeMaskFromKeytrans(
1069 register struct _XKeytrans *p)
1073 p->state = AnyModifier;
1074 for (i = 0; i < p->mlen; i++) {
1075 p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
1077 p->state &= AllMods;