1ecce36beSmrg/* 2ecce36beSmrg * Copyright © 2008 Ian Osgood <iano@quirkster.com> 3ecce36beSmrg * Copyright © 2008 Jamey Sharp <jamey@minilop.net> 4ecce36beSmrg * Copyright © 2008 Josh Triplett <josh@freedesktop.org> 5ecce36beSmrg * Copyright © 2008 Ulrich Eckhardt <doomster@knuut.de> 6ecce36beSmrg * 7ecce36beSmrg * Permission is hereby granted, free of charge, to any person 8ecce36beSmrg * obtaining a copy of this software and associated documentation 9ecce36beSmrg * files (the "Software"), to deal in the Software without 10ecce36beSmrg * restriction, including without limitation the rights to use, copy, 11ecce36beSmrg * modify, merge, publish, distribute, sublicense, and/or sell copies 12ecce36beSmrg * of the Software, and to permit persons to whom the Software is 13ecce36beSmrg * furnished to do so, subject to the following conditions: 14ecce36beSmrg * 15ecce36beSmrg * The above copyright notice and this permission notice shall be 16ecce36beSmrg * included in all copies or substantial portions of the Software. 17ecce36beSmrg * 18ecce36beSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19ecce36beSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20ecce36beSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21ecce36beSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 22ecce36beSmrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 23ecce36beSmrg * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24ecce36beSmrg * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25ecce36beSmrg * 26ecce36beSmrg * Except as contained in this notice, the names of the authors or 27ecce36beSmrg * their institutions shall not be used in advertising or otherwise to 28ecce36beSmrg * promote the sale, use or other dealings in this Software without 29ecce36beSmrg * prior written authorization from the authors. 30ecce36beSmrg */ 31ecce36beSmrg 32ecce36beSmrg#include <stdlib.h> 33ecce36beSmrg 34ecce36beSmrg#include <xcb/xcb.h> 35ecce36beSmrg#define XK_MISCELLANY 36ecce36beSmrg#define XK_XKB_KEYS 37ecce36beSmrg#define XK_LATIN1 38ecce36beSmrg#define XK_LATIN2 39ecce36beSmrg#define XK_LATIN3 40ecce36beSmrg#define XK_LATIN4 41ecce36beSmrg#define XK_CYRILLIC 42ecce36beSmrg#define XK_GREEK 43ecce36beSmrg#define XK_ARMENIAN 44ecce36beSmrg#include <X11/keysymdef.h> 45ecce36beSmrg 46ecce36beSmrg#include "xcb_keysyms.h" 47ecce36beSmrg 48ecce36beSmrg/* Private declaration */ 49ecce36beSmrgenum tag_t { 50ecce36beSmrg TAG_COOKIE, 51ecce36beSmrg TAG_VALUE 52ecce36beSmrg}; 53ecce36beSmrg 54ecce36beSmrgstruct _XCBKeySymbols 55ecce36beSmrg{ 56ecce36beSmrg xcb_connection_t *c; 57ecce36beSmrg enum tag_t tag; 58ecce36beSmrg union { 59ecce36beSmrg xcb_get_keyboard_mapping_cookie_t cookie; 60ecce36beSmrg xcb_get_keyboard_mapping_reply_t *reply; 61ecce36beSmrg } u; 62ecce36beSmrg}; 63ecce36beSmrg 64ecce36beSmrgstatic void xcb_convert_case(xcb_keysym_t sym, 65ecce36beSmrg xcb_keysym_t *lower, 66ecce36beSmrg xcb_keysym_t *upper); 67ecce36beSmrg 68ecce36beSmrgstatic void xcb_key_symbols_get_reply (xcb_key_symbols_t *syms, 69ecce36beSmrg xcb_generic_error_t **e); 70ecce36beSmrg 71ecce36beSmrg/* public implementation */ 72ecce36beSmrg 73ecce36beSmrgxcb_key_symbols_t * 74ecce36beSmrgxcb_key_symbols_alloc (xcb_connection_t *c) 75ecce36beSmrg{ 76ecce36beSmrg xcb_key_symbols_t *syms; 77ecce36beSmrg xcb_keycode_t min_keycode; 78ecce36beSmrg xcb_keycode_t max_keycode; 79ecce36beSmrg 80ecce36beSmrg if (!c) 81ecce36beSmrg return NULL; 82ecce36beSmrg 83ecce36beSmrg syms = malloc (sizeof (xcb_key_symbols_t)); 84ecce36beSmrg 85ecce36beSmrg syms->c = c; 86ecce36beSmrg syms->tag = TAG_COOKIE; 87ecce36beSmrg 88ecce36beSmrg min_keycode = xcb_get_setup (c)->min_keycode; 89ecce36beSmrg max_keycode = xcb_get_setup (c)->max_keycode; 90ecce36beSmrg 91ecce36beSmrg syms->u.cookie = xcb_get_keyboard_mapping(c, 92ecce36beSmrg min_keycode, 93ecce36beSmrg max_keycode - min_keycode + 1); 94ecce36beSmrg 95ecce36beSmrg return syms; 96ecce36beSmrg} 97ecce36beSmrg 98ecce36beSmrgvoid 99ecce36beSmrgxcb_key_symbols_free (xcb_key_symbols_t *syms) 100ecce36beSmrg{ 101ecce36beSmrg if (syms) 102ecce36beSmrg { 103ecce36beSmrg if (syms->tag == TAG_VALUE) 104ecce36beSmrg free (syms->u.reply); 105ecce36beSmrg free (syms); 106ecce36beSmrg syms = NULL; 107ecce36beSmrg } 108ecce36beSmrg} 109ecce36beSmrg 110ecce36beSmrg/* Use of the 'col' parameter: 111ecce36beSmrg 112ecce36beSmrgA list of KeySyms is associated with each KeyCode. The list is intended 113ecce36beSmrgto convey the set of symbols on the corresponding key. If the list 114ecce36beSmrg(ignoring trailing NoSymbol entries) is a single KeySym ``K'', then the 115ecce36beSmrglist is treated as if it were the list ``K NoSymbol K NoSymbol''. If the 116ecce36beSmrglist (ignoring trailing NoSymbol entries) is a pair of KeySyms ``K1 117ecce36beSmrgK2'', then the list is treated as if it were the list ``K1 K2 K1 K2''. 118ecce36beSmrgIf the list (ignoring trailing NoSymbol entries) is a triple of KeySyms 119ecce36beSmrg``K1 K2 K3'', then the list is treated as if it were the list ``K1 K2 K3 120ecce36beSmrgNoSymbol''. When an explicit ``void'' element is desired in the list, 121ecce36beSmrgthe value VoidSymbol can be used. 122ecce36beSmrg 123ecce36beSmrgThe first four elements of the list are split into two groups of 124ecce36beSmrgKeySyms. Group 1 contains the first and second KeySyms; Group 2 contains 125ecce36beSmrgthe third and fourth KeySyms. Within each group, if the second element 126ecce36beSmrgof the group is NoSymbol , then the group should be treated as if the 127ecce36beSmrgsecond element were the same as the first element, except when the first 128ecce36beSmrgelement is an alphabetic KeySym ``K'' for which both lowercase and 129ecce36beSmrguppercase forms are defined. In that case, the group should be treated 130ecce36beSmrgas if the first element were the lowercase form of ``K'' and the second 131ecce36beSmrgelement were the uppercase form of ``K.'' 132ecce36beSmrg 133ecce36beSmrgThe standard rules for obtaining a KeySym from a KeyPress event make use 134ecce36beSmrgof only the Group 1 and Group 2 KeySyms; no interpretation of other 135ecce36beSmrgKeySyms in the list is given. Which group to use is determined by the 136ecce36beSmrgmodifier state. Switching between groups is controlled by the KeySym 137ecce36beSmrgnamed MODE SWITCH, by attaching that KeySym to some KeyCode and 138ecce36beSmrgattaching that KeyCode to any one of the modifiers Mod1 through Mod5. 139ecce36beSmrgThis modifier is called the group modifier. For any KeyCode, Group 1 is 140ecce36beSmrgused when the group modifier is off, and Group 2 is used when the group 141ecce36beSmrgmodifier is on. 142ecce36beSmrg 143ecce36beSmrgThe Lock modifier is interpreted as CapsLock when the KeySym named 144ecce36beSmrgXK_Caps_Lock is attached to some KeyCode and that KeyCode is attached to 145ecce36beSmrgthe Lock modifier. The Lock modifier is interpreted as ShiftLock when 146ecce36beSmrgthe KeySym named XK_Shift_Lock is attached to some KeyCode and that 147ecce36beSmrgKeyCode is attached to the Lock modifier. If the Lock modifier could be 148ecce36beSmrginterpreted as both CapsLock and ShiftLock, the CapsLock interpretation 149ecce36beSmrgis used. 150ecce36beSmrg 151ecce36beSmrgThe operation of keypad keys is controlled by the KeySym named 152ecce36beSmrgXK_Num_Lock, by attaching that KeySym to some KeyCode and attaching that 153ecce36beSmrgKeyCode to any one of the modifiers Mod1 through Mod5 . This modifier is 154ecce36beSmrgcalled the numlock modifier. The standard KeySyms with the prefix 155ecce36beSmrg``XK_KP_'' in their name are called keypad KeySyms; these are KeySyms 156ecce36beSmrgwith numeric value in the hexadecimal range 0xFF80 to 0xFFBD inclusive. 157ecce36beSmrgIn addition, vendor-specific KeySyms in the hexadecimal range 0x11000000 158ecce36beSmrgto 0x1100FFFF are also keypad KeySyms. 159ecce36beSmrg 160ecce36beSmrgWithin a group, the choice of KeySym is determined by applying the first 161ecce36beSmrgrule that is satisfied from the following list: 162ecce36beSmrg 163ecce36beSmrg* The numlock modifier is on and the second KeySym is a keypad KeySym. In 164ecce36beSmrg this case, if the Shift modifier is on, or if the Lock modifier is on 165ecce36beSmrg and is interpreted as ShiftLock, then the first KeySym is used, 166ecce36beSmrg otherwise the second KeySym is used. 167ecce36beSmrg 168ecce36beSmrg* The Shift and Lock modifiers are both off. In this case, the first 169ecce36beSmrg KeySym is used. 170ecce36beSmrg 171ecce36beSmrg* The Shift modifier is off, and the Lock modifier is on and is 172ecce36beSmrg interpreted as CapsLock. In this case, the first KeySym is used, but 173ecce36beSmrg if that KeySym is lowercase alphabetic, then the corresponding 174ecce36beSmrg uppercase KeySym is used instead. 175ecce36beSmrg 176ecce36beSmrg* The Shift modifier is on, and the Lock modifier is on and is 177ecce36beSmrg interpreted as CapsLock. In this case, the second KeySym is used, but 178ecce36beSmrg if that KeySym is lowercase alphabetic, then the corresponding 179ecce36beSmrg uppercase KeySym is used instead. 180ecce36beSmrg 181ecce36beSmrg* The Shift modifier is on, or the Lock modifier is on and is 182ecce36beSmrg interpreted as ShiftLock, or both. In this case, the second KeySym is 183ecce36beSmrg used. 184ecce36beSmrg 185ecce36beSmrg*/ 186ecce36beSmrg 187ecce36beSmrgxcb_keysym_t xcb_key_symbols_get_keysym (xcb_key_symbols_t *syms, 188ecce36beSmrg xcb_keycode_t keycode, 189ecce36beSmrg int col) 190ecce36beSmrg{ 191ecce36beSmrg xcb_keysym_t *keysyms; 192ecce36beSmrg xcb_keysym_t keysym_null = { XCB_NO_SYMBOL }; 193ecce36beSmrg xcb_keysym_t lsym; 194ecce36beSmrg xcb_keysym_t usym; 195ecce36beSmrg xcb_keycode_t min_keycode; 196ecce36beSmrg xcb_keycode_t max_keycode; 197ecce36beSmrg int per; 198ecce36beSmrg 199ecce36beSmrg if (!syms) 200ecce36beSmrg return keysym_null; 201ecce36beSmrg 202ecce36beSmrg xcb_key_symbols_get_reply (syms, NULL); 203ecce36beSmrg 204ecce36beSmrg keysyms = xcb_get_keyboard_mapping_keysyms (syms->u.reply); 205ecce36beSmrg min_keycode = xcb_get_setup (syms->c)->min_keycode; 206ecce36beSmrg max_keycode = xcb_get_setup (syms->c)->max_keycode; 207ecce36beSmrg 208ecce36beSmrg per = syms->u.reply->keysyms_per_keycode; 209ecce36beSmrg if ((col < 0) || ((col >= per) && (col > 3)) || 210ecce36beSmrg (keycode < min_keycode) || 211ecce36beSmrg (keycode > max_keycode)) 212ecce36beSmrg return keysym_null; 213ecce36beSmrg 214ecce36beSmrg keysyms = &keysyms[(keycode - min_keycode) * per]; 215ecce36beSmrg if (col < 4) 216ecce36beSmrg { 217ecce36beSmrg if (col > 1) 218ecce36beSmrg { 219ecce36beSmrg while ((per > 2) && (keysyms[per - 1] == XCB_NO_SYMBOL)) 220ecce36beSmrg per--; 221ecce36beSmrg if (per < 3) 222ecce36beSmrg col -= 2; 223ecce36beSmrg } 224ecce36beSmrg if ((per <= (col|1)) || (keysyms[col|1] == XCB_NO_SYMBOL)) 225ecce36beSmrg { 226ecce36beSmrg xcb_convert_case(keysyms[col&~1], &lsym, &usym); 227ecce36beSmrg if (!(col & 1)) 228ecce36beSmrg return lsym; 229ecce36beSmrg else if (usym == lsym) 230ecce36beSmrg return keysym_null; 231ecce36beSmrg else 232ecce36beSmrg return usym; 233ecce36beSmrg } 234ecce36beSmrg } 235ecce36beSmrg return keysyms[col]; 236ecce36beSmrg} 237ecce36beSmrg 238ecce36beSmrgxcb_keycode_t * 239ecce36beSmrgxcb_key_symbols_get_keycode(xcb_key_symbols_t *syms, 240ecce36beSmrg xcb_keysym_t keysym) 241ecce36beSmrg{ 242ecce36beSmrg xcb_keysym_t ks; 243ecce36beSmrg int j, nresult = 0; 244ecce36beSmrg xcb_keycode_t i, min, max, *result = NULL; 245ecce36beSmrg 246ecce36beSmrg if(syms) 247ecce36beSmrg { 248ecce36beSmrg xcb_key_symbols_get_reply (syms, NULL); 249ecce36beSmrg min = xcb_get_setup(syms->c)->min_keycode; 250ecce36beSmrg max = xcb_get_setup(syms->c)->max_keycode; 251ecce36beSmrg 252ecce36beSmrg for(j = 0; j < syms->u.reply->keysyms_per_keycode; j++) 253ecce36beSmrg for(i = min; i && i <= max; i++) 254ecce36beSmrg { 255ecce36beSmrg ks = xcb_key_symbols_get_keysym(syms, i, j); 256ecce36beSmrg if(ks == keysym) 257ecce36beSmrg { 258ecce36beSmrg nresult++; 259ecce36beSmrg result = realloc(result, sizeof(xcb_keycode_t) * (nresult + 1)); 260ecce36beSmrg result[nresult - 1] = i; 261ecce36beSmrg result[nresult] = XCB_NO_SYMBOL; 262ecce36beSmrg } 263ecce36beSmrg } 264ecce36beSmrg } 265ecce36beSmrg 266ecce36beSmrg return result; 267ecce36beSmrg} 268ecce36beSmrg 269ecce36beSmrgxcb_keysym_t 270ecce36beSmrgxcb_key_press_lookup_keysym (xcb_key_symbols_t *syms, 271ecce36beSmrg xcb_key_press_event_t *event, 272ecce36beSmrg int col) 273ecce36beSmrg{ 274ecce36beSmrg return xcb_key_symbols_get_keysym (syms, event->detail, col); 275ecce36beSmrg} 276ecce36beSmrg 277ecce36beSmrgxcb_keysym_t 278ecce36beSmrgxcb_key_release_lookup_keysym (xcb_key_symbols_t *syms, 279ecce36beSmrg xcb_key_release_event_t *event, 280ecce36beSmrg int col) 281ecce36beSmrg{ 282ecce36beSmrg return xcb_key_symbols_get_keysym (syms, event->detail, col); 283ecce36beSmrg} 284ecce36beSmrg 285ecce36beSmrgint 286ecce36beSmrgxcb_refresh_keyboard_mapping (xcb_key_symbols_t *syms, 287ecce36beSmrg xcb_mapping_notify_event_t *event) 288ecce36beSmrg{ 289ecce36beSmrg if (event->request == XCB_MAPPING_KEYBOARD && syms) { 290ecce36beSmrg if (syms->tag == TAG_VALUE) { 291ecce36beSmrg xcb_keycode_t min_keycode; 292ecce36beSmrg xcb_keycode_t max_keycode; 293ecce36beSmrg 294ecce36beSmrg if (syms->u.reply) { 295ecce36beSmrg free (syms->u.reply); 296ecce36beSmrg syms->u.reply = NULL; 297ecce36beSmrg } 298ecce36beSmrg syms->tag = TAG_COOKIE; 299ecce36beSmrg min_keycode = xcb_get_setup (syms->c)->min_keycode; 300ecce36beSmrg max_keycode = xcb_get_setup (syms->c)->max_keycode; 301ecce36beSmrg 302ecce36beSmrg syms->u.cookie = xcb_get_keyboard_mapping(syms->c, 303ecce36beSmrg min_keycode, 304ecce36beSmrg max_keycode - min_keycode + 1); 305ecce36beSmrg 306ecce36beSmrg } 307ecce36beSmrg return 1; 308ecce36beSmrg } 309ecce36beSmrg return 0; 310ecce36beSmrg} 311ecce36beSmrg 312ecce36beSmrg 313ecce36beSmrg/* Tests for classes of symbols */ 314ecce36beSmrg 315ecce36beSmrgint 316ecce36beSmrgxcb_is_keypad_key (xcb_keysym_t keysym) 317ecce36beSmrg{ 318ecce36beSmrg return ((keysym >= XK_KP_Space) && (keysym <= XK_KP_Equal)); 319ecce36beSmrg} 320ecce36beSmrg 321ecce36beSmrgint 322ecce36beSmrgxcb_is_private_keypad_key (xcb_keysym_t keysym) 323ecce36beSmrg{ 324ecce36beSmrg return ((keysym >= 0x11000000) && (keysym <= 0x1100FFFF)); 325ecce36beSmrg} 326ecce36beSmrg 327ecce36beSmrgint 328ecce36beSmrgxcb_is_cursor_key (xcb_keysym_t keysym) 329ecce36beSmrg{ 330ecce36beSmrg return ((keysym >= XK_Home) && (keysym <= XK_Select)); 331ecce36beSmrg} 332ecce36beSmrg 333ecce36beSmrgint 334ecce36beSmrgxcb_is_pf_key (xcb_keysym_t keysym) 335ecce36beSmrg{ 336ecce36beSmrg return ((keysym >= XK_KP_F1) && (keysym <= XK_KP_F4)); 337ecce36beSmrg} 338ecce36beSmrg 339ecce36beSmrgint 340ecce36beSmrgxcb_is_function_key (xcb_keysym_t keysym) 341ecce36beSmrg{ 342ecce36beSmrg return ((keysym >= XK_F1) && (keysym <= XK_F35)); 343ecce36beSmrg} 344ecce36beSmrg 345ecce36beSmrgint 346ecce36beSmrgxcb_is_misc_function_key (xcb_keysym_t keysym) 347ecce36beSmrg{ 348ecce36beSmrg return ((keysym >= XK_Select) && (keysym <= XK_Break)); 349ecce36beSmrg} 350ecce36beSmrg 351ecce36beSmrgint 352ecce36beSmrgxcb_is_modifier_key (xcb_keysym_t keysym) 353ecce36beSmrg{ 354ecce36beSmrg return (((keysym >= XK_Shift_L) && (keysym <= XK_Hyper_R)) || 355ecce36beSmrg ((keysym >= XK_ISO_Lock) && (keysym <= XK_ISO_Last_Group_Lock)) || 356ecce36beSmrg (keysym == XK_Mode_switch) || 357ecce36beSmrg (keysym == XK_Num_Lock)); 358ecce36beSmrg} 359ecce36beSmrg 360ecce36beSmrg/* private functions */ 361ecce36beSmrg 362ecce36beSmrgvoid 363ecce36beSmrgxcb_convert_case(xcb_keysym_t sym, 364ecce36beSmrg xcb_keysym_t *lower, 365ecce36beSmrg xcb_keysym_t *upper) 366ecce36beSmrg{ 367ecce36beSmrg *lower = sym; 368ecce36beSmrg *upper = sym; 369ecce36beSmrg 370ecce36beSmrg switch(sym >> 8) 371ecce36beSmrg { 372ecce36beSmrg case 0: /* Latin 1 */ 373ecce36beSmrg if ((sym >= XK_A) && (sym <= XK_Z)) 374ecce36beSmrg *lower += (XK_a - XK_A); 375ecce36beSmrg else if ((sym >= XK_a) && (sym <= XK_z)) 376ecce36beSmrg *upper -= (XK_a - XK_A); 377ecce36beSmrg else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) 378ecce36beSmrg *lower += (XK_agrave - XK_Agrave); 379ecce36beSmrg else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) 380ecce36beSmrg *upper -= (XK_agrave - XK_Agrave); 381ecce36beSmrg else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) 382ecce36beSmrg *lower += (XK_oslash - XK_Ooblique); 383ecce36beSmrg else if ((sym >= XK_oslash) && (sym <= XK_thorn)) 384ecce36beSmrg *upper -= (XK_oslash - XK_Ooblique); 385ecce36beSmrg break; 386ecce36beSmrg case 1: /* Latin 2 */ 387ecce36beSmrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 388ecce36beSmrg if (sym == XK_Aogonek) 389ecce36beSmrg *lower = XK_aogonek; 390ecce36beSmrg else if (sym >= XK_Lstroke && sym <= XK_Sacute) 391ecce36beSmrg *lower += (XK_lstroke - XK_Lstroke); 392ecce36beSmrg else if (sym >= XK_Scaron && sym <= XK_Zacute) 393ecce36beSmrg *lower += (XK_scaron - XK_Scaron); 394ecce36beSmrg else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) 395ecce36beSmrg *lower += (XK_zcaron - XK_Zcaron); 396ecce36beSmrg else if (sym == XK_aogonek) 397ecce36beSmrg *upper = XK_Aogonek; 398ecce36beSmrg else if (sym >= XK_lstroke && sym <= XK_sacute) 399ecce36beSmrg *upper -= (XK_lstroke - XK_Lstroke); 400ecce36beSmrg else if (sym >= XK_scaron && sym <= XK_zacute) 401ecce36beSmrg *upper -= (XK_scaron - XK_Scaron); 402ecce36beSmrg else if (sym >= XK_zcaron && sym <= XK_zabovedot) 403ecce36beSmrg *upper -= (XK_zcaron - XK_Zcaron); 404ecce36beSmrg else if (sym >= XK_Racute && sym <= XK_Tcedilla) 405ecce36beSmrg *lower += (XK_racute - XK_Racute); 406ecce36beSmrg else if (sym >= XK_racute && sym <= XK_tcedilla) 407ecce36beSmrg *upper -= (XK_racute - XK_Racute); 408ecce36beSmrg break; 409ecce36beSmrg case 2: /* Latin 3 */ 410ecce36beSmrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 411ecce36beSmrg if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) 412ecce36beSmrg *lower += (XK_hstroke - XK_Hstroke); 413ecce36beSmrg else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) 414ecce36beSmrg *lower += (XK_gbreve - XK_Gbreve); 415ecce36beSmrg else if (sym >= XK_hstroke && sym <= XK_hcircumflex) 416ecce36beSmrg *upper -= (XK_hstroke - XK_Hstroke); 417ecce36beSmrg else if (sym >= XK_gbreve && sym <= XK_jcircumflex) 418ecce36beSmrg *upper -= (XK_gbreve - XK_Gbreve); 419ecce36beSmrg else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) 420ecce36beSmrg *lower += (XK_cabovedot - XK_Cabovedot); 421ecce36beSmrg else if (sym >= XK_cabovedot && sym <= XK_scircumflex) 422ecce36beSmrg *upper -= (XK_cabovedot - XK_Cabovedot); 423ecce36beSmrg break; 424ecce36beSmrg case 3: /* Latin 4 */ 425ecce36beSmrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 426ecce36beSmrg if (sym >= XK_Rcedilla && sym <= XK_Tslash) 427ecce36beSmrg *lower += (XK_rcedilla - XK_Rcedilla); 428ecce36beSmrg else if (sym >= XK_rcedilla && sym <= XK_tslash) 429ecce36beSmrg *upper -= (XK_rcedilla - XK_Rcedilla); 430ecce36beSmrg else if (sym == XK_ENG) 431ecce36beSmrg *lower = XK_eng; 432ecce36beSmrg else if (sym == XK_eng) 433ecce36beSmrg *upper = XK_ENG; 434ecce36beSmrg else if (sym >= XK_Amacron && sym <= XK_Umacron) 435ecce36beSmrg *lower += (XK_amacron - XK_Amacron); 436ecce36beSmrg else if (sym >= XK_amacron && sym <= XK_umacron) 437ecce36beSmrg *upper -= (XK_amacron - XK_Amacron); 438ecce36beSmrg break; 439ecce36beSmrg case 6: /* Cyrillic */ 440ecce36beSmrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 441ecce36beSmrg if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) 442ecce36beSmrg *lower -= (XK_Serbian_DJE - XK_Serbian_dje); 443ecce36beSmrg else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) 444ecce36beSmrg *upper += (XK_Serbian_DJE - XK_Serbian_dje); 445ecce36beSmrg else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) 446ecce36beSmrg *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); 447ecce36beSmrg else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) 448ecce36beSmrg *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); 449ecce36beSmrg break; 450ecce36beSmrg case 7: /* Greek */ 451ecce36beSmrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 452ecce36beSmrg if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) 453ecce36beSmrg *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 454ecce36beSmrg else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && 455ecce36beSmrg sym != XK_Greek_iotaaccentdieresis && 456ecce36beSmrg sym != XK_Greek_upsilonaccentdieresis) 457ecce36beSmrg *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 458ecce36beSmrg else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) 459ecce36beSmrg *lower += (XK_Greek_alpha - XK_Greek_ALPHA); 460ecce36beSmrg else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && 461ecce36beSmrg sym != XK_Greek_finalsmallsigma) 462ecce36beSmrg *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); 463ecce36beSmrg break; 464ecce36beSmrg case 0x14: /* Armenian */ 465ecce36beSmrg if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) { 466ecce36beSmrg *lower = sym | 1; 467ecce36beSmrg *upper = sym & ~1; 468ecce36beSmrg } 469ecce36beSmrg break; 470ecce36beSmrg } 471ecce36beSmrg} 472ecce36beSmrg 473ecce36beSmrgvoid 474ecce36beSmrgxcb_key_symbols_get_reply (xcb_key_symbols_t *syms, 475ecce36beSmrg xcb_generic_error_t **e) 476ecce36beSmrg{ 477ecce36beSmrg if (!syms) 478ecce36beSmrg return; 479ecce36beSmrg 480ecce36beSmrg if (syms->tag == TAG_COOKIE) 481ecce36beSmrg { 482ecce36beSmrg syms->tag = TAG_VALUE; 483ecce36beSmrg syms->u.reply = xcb_get_keyboard_mapping_reply(syms->c, 484ecce36beSmrg syms->u.cookie, 485ecce36beSmrg e); 486ecce36beSmrg } 487ecce36beSmrg} 488