1 /* key.c
2  *
3  * $Id$
4  *
5  * Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin
6  * Copyright 2002, 2003 Sam Hocevar <sam@hocevar.net>, Paris
7  *
8  * This software was derived from Elk 1.2, which was Copyright 1987, 1988,
9  * 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written
10  * by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project
11  * between TELES and Nixdorf Microprocessor Engineering, Berlin).
12  *
13  * Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co-
14  * owners or individual owners of copyright in this software, grant to any
15  * person or company a worldwide, royalty free, license to
16  *
17  *    i) copy this software,
18  *   ii) prepare derivative works based on this software,
19  *  iii) distribute copies of this software or derivative works,
20  *   iv) perform this software, or
21  *    v) display this software,
22  *
23  * provided that this notice is not removed and that neither Oliver Laumann
24  * nor Teles nor Nixdorf are deemed to have made any representations as to
25  * the suitability of this software for any purpose nor are held responsible
26  * for any defects of this software.
27  *
28  * THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
29  */
30 
31 #include "xlib.h"
32 
33 #include <string.h>
34 
35 #ifdef XLIB_RELEASE_5_OR_LATER
36 
37 /* I don't know if XDisplayKeycodes() was already there in X11R4.
38  */
P_Display_Min_Keycode(Object d)39 static Object P_Display_Min_Keycode (Object d) {
40     int mink, maxk;
41 
42     Check_Type (d, T_Display);
43     XDisplayKeycodes(DISPLAY(d)->dpy, &mink, &maxk);
44     return Make_Integer (mink);
45 }
46 
P_Display_Max_Keycode(Object d)47 static Object P_Display_Max_Keycode (Object d) {
48     int mink, maxk;
49 
50     Check_Type (d, T_Display);
51     XDisplayKeycodes(DISPLAY(d)->dpy, &mink, &maxk);
52     return Make_Integer (maxk);
53 }
54 
55 #else
P_Display_Min_Keycode(Object d)56 static Object P_Display_Min_Keycode (Object d) {
57     Check_Type (d, T_Display);
58     return Make_Integer (DISPLAY(d)->dpy->min_keycode);
59 }
60 
P_Display_Max_Keycode(Object d)61 static Object P_Display_Max_Keycode (Object d) {
62     Check_Type (d, T_Display);
63     return Make_Integer (DISPLAY(d)->dpy->max_keycode);
64 }
65 #endif
66 
67 #ifdef XLIB_RELEASE_5_OR_LATER
68 
69 /* I'm not sure if this works correctly in X11R4:
70  */
P_Display_Keysyms_Per_Keycode(Object d)71 static Object P_Display_Keysyms_Per_Keycode (Object d) {
72     KeySym *ksyms;
73     int mink, maxk, ksyms_per_kode;
74 
75     Check_Type (d, T_Display);
76     XDisplayKeycodes(DISPLAY(d)->dpy, &mink, &maxk);
77     ksyms = XGetKeyboardMapping(DISPLAY(d)->dpy, (KeyCode)mink,
78         maxk - mink + 1, &ksyms_per_kode);
79     return Make_Integer (ksyms_per_kode);
80 }
81 
82 #else
P_Display_Keysyms_Per_Keycode(Object d)83 static Object P_Display_Keysyms_Per_Keycode (Object d) {
84     Check_Type (d, T_Display);
85     /* Force initialization: */
86     Disable_Interrupts;
87     (void)XKeycodeToKeysym (DISPLAY(d)->dpy, DISPLAY(d)->dpy->min_keycode, 0);
88     Enable_Interrupts;
89     return Make_Integer (DISPLAY(d)->dpy->keysyms_per_keycode);
90 }
91 #endif
92 
P_String_To_Keysym(Object s)93 static Object P_String_To_Keysym (Object s) {
94     KeySym k;
95 
96     k = XStringToKeysym (Get_Strsym (s));
97     return k == NoSymbol ? False : Make_Unsigned_Long ((unsigned long)k);
98 }
99 
P_Keysym_To_String(Object k)100 static Object P_Keysym_To_String (Object k) {
101     register char *s;
102 
103     s = XKeysymToString ((KeySym)Get_Long (k));
104     return s ? Make_String (s, strlen (s)) : False;
105 }
106 
P_Keycode_To_Keysym(Object d,Object k,Object index)107 static Object P_Keycode_To_Keysym (Object d, Object k, Object index) {
108     Object ret;
109 
110     Check_Type (d, T_Display);
111     Disable_Interrupts;
112     ret = Make_Unsigned_Long ((unsigned long)XKeycodeToKeysym (DISPLAY(d)->dpy,
113         Get_Integer (k), Get_Integer (index)));
114     Enable_Interrupts;
115     return ret;
116 }
117 
P_Keysym_To_Keycode(Object d,Object k)118 static Object P_Keysym_To_Keycode (Object d, Object k) {
119     Object ret;
120 
121     Check_Type (d, T_Display);
122     Disable_Interrupts;
123     ret = Make_Unsigned (XKeysymToKeycode (DISPLAY(d)->dpy,
124         (KeySym)Get_Long (k)));
125     Enable_Interrupts;
126     return ret;
127 }
128 
P_Lookup_String(Object d,Object k,Object mask)129 static Object P_Lookup_String (Object d, Object k, Object mask) {
130     XKeyEvent e;
131     char buf[1024];
132     register int len;
133     KeySym keysym_return;
134     XComposeStatus status_return;
135 
136     Check_Type (d, T_Display);
137     e.display = DISPLAY(d)->dpy;
138     e.keycode = Get_Integer (k);
139     e.state = Symbols_To_Bits (mask, 1, State_Syms);
140     Disable_Interrupts;
141     len = XLookupString (&e, buf, 1024, &keysym_return, &status_return);
142     Enable_Interrupts;
143     return Make_String (buf, len);
144 }
145 
P_Rebind_Keysym(Object d,Object k,Object mods,Object str)146 static Object P_Rebind_Keysym (Object d, Object k, Object mods, Object str) {
147     KeySym *p;
148     register int i, n;
149     Alloca_Begin;
150 
151     Check_Type (d, T_Display);
152     Check_Type (str, T_String);
153     Check_Type (mods, T_Vector);
154     n = VECTOR(mods)->size;
155     Alloca (p, KeySym*, n * sizeof (KeySym));
156     for (i = 0; i < n; i++)
157         p[i] = (KeySym)Get_Long (VECTOR(mods)->data[i]);
158     XRebindKeysym (DISPLAY(d)->dpy, (KeySym)Get_Long (k), p, n,
159         (unsigned char *)STRING(str)->data, STRING(str)->size);
160     Alloca_End;
161     return Void;
162 }
163 
P_Refresh_Keyboard_Mapping(Object w,Object event)164 static Object P_Refresh_Keyboard_Mapping (Object w, Object event) {
165     static XMappingEvent fake;
166 
167     Check_Type (w, T_Window);
168     fake.type = MappingNotify;
169     fake.display = WINDOW(w)->dpy;
170     fake.window = WINDOW(w)->win;
171     fake.request = Symbols_To_Bits (event, 0, Mapping_Syms);
172     XRefreshKeyboardMapping (&fake);
173     return Void;
174 }
175 
elk_init_xlib_key()176 void elk_init_xlib_key () {
177     Define_Primitive (P_Display_Min_Keycode, "display-min-keycode",
178                                                               1, 1, EVAL);
179     Define_Primitive (P_Display_Max_Keycode, "display-max-keycode",
180                                                               1, 1, EVAL);
181     Define_Primitive (P_Display_Keysyms_Per_Keycode,
182                         "display-keysyms-per-keycode",        1, 1, EVAL);
183     Define_Primitive (P_String_To_Keysym,  "string->keysym",  1, 1, EVAL);
184     Define_Primitive (P_Keysym_To_String,  "keysym->string",  1, 1, EVAL);
185     Define_Primitive (P_Keycode_To_Keysym, "keycode->keysym", 3, 3, EVAL);
186     Define_Primitive (P_Keysym_To_Keycode, "keysym->keycode", 2, 2, EVAL);
187     Define_Primitive (P_Lookup_String,     "lookup-string",   3, 3, EVAL);
188     Define_Primitive (P_Rebind_Keysym,     "rebind-keysym",   4, 4, EVAL);
189     Define_Primitive (P_Refresh_Keyboard_Mapping,
190                         "refresh-keyboard-mapping",           2, 2, EVAL);
191 }
192