WindowMaker: New get_texture_image function
[wmaker-crm.git] / WPrefs.app / xmodifier.c
blob35046f2bbb88126eac28dec4f3ffc909a4f04ba7
1 /* Grok X modifier mappings for shortcuts.
3 Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17.
4 The copyright(s) from the original XEmacs code are included below.
6 Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997. */
8 /*
9 * More changes for WPrefs by Alfredo Kojima, Aug 1998
12 /* The event_stream interface for X11 with Xt, and/or tty frames.
13 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
14 Copyright (C) 1995 Sun Microsystems, Inc.
15 Copyright (C) 1996 Ben Wing.
17 This file is part of XEmacs.
19 XEmacs is free software; you can redistribute it and/or modify it
20 under the terms of the GNU General Public License as published by the
21 Free Software Foundation; either version 2, or (at your option) any
22 later version.
24 XEmacs is distributed in the hope that it will be useful, but WITHOUT
25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 for more details.
29 You should have received a copy of the GNU General Public License along
30 with XEmacs; see the file COPYING. if not, write to the
31 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
32 Boston, MA 02110-1301 USA. */
34 #include <string.h>
35 #include <strings.h>
36 #include <X11/Xlib.h>
37 #include <X11/keysym.h>
39 #include <WINGs/WUtil.h>
41 /************************************************************************/
42 /* keymap handling */
43 /************************************************************************/
45 /* X bogusly doesn't define the interpretations of any bits besides
46 ModControl, ModShift, and ModLock; so the Interclient Communication
47 Conventions Manual says that we have to bend over backwards to figure
48 out what the other modifier bits mean. According to ICCCM:
50 - Any keycode which is assigned ModControl is a "control" key.
52 - Any modifier bit which is assigned to a keycode which generates Meta_L
53 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
54 etc.
56 - Any keypress event which contains ModControl in its state should be
57 interpreted as a "control" character.
59 - Any keypress event which contains a modifier bit in its state which is
60 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
61 should be interpreted as a "meta" character. Likewise for Super, Hyper,
62 etc.
64 - It is illegal for a keysym to be associated with more than one modifier
65 bit.
67 This means that the only thing that emacs can reasonably interpret as a
68 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
69 one of the modifier bits Mod1-Mod5.
71 Unfortunately, many keyboards don't have Meta keys in their default
72 configuration. So, if there are no Meta keys, but there are "Alt" keys,
73 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
74 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
75 mean "Symbol," but that just confused the hell out of way too many people).
77 This works with the default configurations of the 19 keyboard-types I've
78 checked.
80 Emacs detects keyboard configurations which violate the above rules, and
81 prints an error message on the standard-error-output. (Perhaps it should
82 use a pop-up-window instead.)
85 static int MetaIndex, HyperIndex, SuperIndex, AltIndex, ModeIndex;
87 static const char *index_to_name(int indice)
89 switch (indice) {
90 case ShiftMapIndex:
91 return "ModShift";
92 case LockMapIndex:
93 return "ModLock";
94 case ControlMapIndex:
95 return "ModControl";
96 case Mod1MapIndex:
97 return "Mod1";
98 case Mod2MapIndex:
99 return "Mod2";
100 case Mod3MapIndex:
101 return "Mod3";
102 case Mod4MapIndex:
103 return "Mod4";
104 case Mod5MapIndex:
105 return "Mod5";
106 default:
107 return "???";
111 static void x_reset_modifier_mapping(Display * display)
113 int modifier_index, modifier_key, column, mkpm;
114 int meta_bit = 0;
115 int hyper_bit = 0;
116 int super_bit = 0;
117 int alt_bit = 0;
118 int mode_bit = 0;
119 XModifierKeymap *x_modifier_keymap = XGetModifierMapping(display);
121 #define modwarn(name,old,other) \
122 wwarning ("%s (0x%x) generates %s, which is generated by %s.", \
123 name, code, index_to_name (old), other)
125 #define modbarf(name,other) \
126 wwarning ("%s (0x%x) generates %s, which is nonsensical.", \
127 name, code, other)
129 #define check_modifier(name,mask) \
130 if ((1<<modifier_index) != mask) \
131 wwarning ("%s (0x%x) generates %s, which is nonsensical.", \
132 name, code, index_to_name (modifier_index))
134 #define store_modifier(name,old) \
135 if (old && old != modifier_index) \
136 wwarning ("%s (0x%x) generates both %s and %s, which is nonsensical.", \
137 name, code, index_to_name (old), \
138 index_to_name (modifier_index)); \
139 if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
140 else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
141 else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
142 else if (sym == XK_Mode_switch) \
143 mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
144 else if (modifier_index == meta_bit && old != meta_bit) \
145 modwarn (name, meta_bit, "Meta"); \
146 else if (modifier_index == super_bit && old != super_bit) \
147 modwarn (name, super_bit, "Super"); \
148 else if (modifier_index == hyper_bit && old != hyper_bit) \
149 modwarn (name, hyper_bit, "Hyper"); \
150 else if (modifier_index == alt_bit && old != alt_bit) \
151 modwarn (name, alt_bit, "Alt"); \
152 else \
153 old = modifier_index;
155 mkpm = x_modifier_keymap->max_keypermod;
156 for (modifier_index = 0; modifier_index < 8; modifier_index++)
157 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
158 KeySym last_sym = 0;
159 for (column = 0; column < 4; column += 2) {
160 KeyCode code = x_modifier_keymap->modifiermap[modifier_index * mkpm
161 + modifier_key];
162 KeySym sym = (code ? XKeycodeToKeysym(display, code, column) : 0);
163 if (sym == last_sym)
164 continue;
165 last_sym = sym;
166 switch (sym) {
167 case XK_Mode_switch:
168 store_modifier("Mode_switch", mode_bit);
169 break;
170 case XK_Meta_L:
171 store_modifier("Meta_L", meta_bit);
172 break;
173 case XK_Meta_R:
174 store_modifier("Meta_R", meta_bit);
175 break;
176 case XK_Super_L:
177 store_modifier("Super_L", super_bit);
178 break;
179 case XK_Super_R:
180 store_modifier("Super_R", super_bit);
181 break;
182 case XK_Hyper_L:
183 store_modifier("Hyper_L", hyper_bit);
184 break;
185 case XK_Hyper_R:
186 store_modifier("Hyper_R", hyper_bit);
187 break;
188 case XK_Alt_L:
189 store_modifier("Alt_L", alt_bit);
190 break;
191 case XK_Alt_R:
192 store_modifier("Alt_R", alt_bit);
193 break;
194 case XK_Control_L:
195 check_modifier("Control_L", ControlMask);
196 break;
197 case XK_Control_R:
198 check_modifier("Control_R", ControlMask);
199 break;
200 case XK_Shift_L:
201 check_modifier("Shift_L", ShiftMask);
202 break;
203 case XK_Shift_R:
204 check_modifier("Shift_R", ShiftMask);
205 break;
206 case XK_Shift_Lock:
207 check_modifier("Shift_Lock", LockMask);
208 break;
209 case XK_Caps_Lock:
210 check_modifier("Caps_Lock", LockMask);
211 break;
213 /* It probably doesn't make any sense for a modifier bit to be
214 assigned to a key that is not one of the above, but OpenWindows
215 assigns modifier bits to a couple of random function keys for
216 no reason that I can discern, so printing a warning here would
217 be annoying. */
221 #undef store_modifier
222 #undef check_modifier
223 #undef modwarn
224 #undef modbarf
226 /* If there was no Meta key, then try using the Alt key instead.
227 If there is both a Meta key and an Alt key, then the Alt key
228 is not disturbed and remains an Alt key. */
229 if (!meta_bit && alt_bit)
230 meta_bit = alt_bit, alt_bit = 0;
232 /* mode_bit overrides everything, since it's processed down inside of
233 XLookupString() instead of by us. If Meta and Mode_switch both
234 generate the same modifier bit (which is an error), then we don't
235 interpret that bit as Meta, because we can't make XLookupString()
236 not interpret it as Mode_switch; and interpreting it as both would
237 be totally wrong. */
238 if (mode_bit) {
239 const char *warn = 0;
240 if (mode_bit == meta_bit)
241 warn = "Meta", meta_bit = 0;
242 else if (mode_bit == hyper_bit)
243 warn = "Hyper", hyper_bit = 0;
244 else if (mode_bit == super_bit)
245 warn = "Super", super_bit = 0;
246 else if (mode_bit == alt_bit)
247 warn = "Alt", alt_bit = 0;
248 if (warn) {
249 wwarning("%s is being used for both Mode_switch and %s.",
250 index_to_name(mode_bit), warn);
254 MetaIndex = meta_bit;
255 HyperIndex = hyper_bit;
256 SuperIndex = super_bit;
257 AltIndex = alt_bit;
258 ModeIndex = mode_bit;
260 if (x_modifier_keymap != NULL)
261 XFreeModifiermap(x_modifier_keymap);
264 int ModifierFromKey(Display * dpy, char *key)
266 static int eqw = 0;
268 if (!eqw)
269 x_reset_modifier_mapping(dpy);
270 eqw = 1;
272 if (strcasecmp(key, "SHIFT") == 0)
273 return ShiftMapIndex;
274 else if (strcasecmp(key, "CONTROL") == 0)
275 return ControlMapIndex;
276 else if (strcasecmp(key, "ALT") == 0)
277 return AltIndex;
278 else if (strcasecmp(key, "META") == 0)
279 return MetaIndex;
280 else if (strcasecmp(key, "SUPER") == 0)
281 return SuperIndex;
282 else if (strcasecmp(key, "HYPER") == 0)
283 return HyperIndex;
284 else if (strcasecmp(key, "MOD1") == 0)
285 return Mod1MapIndex;
286 else if (strcasecmp(key, "MOD2") == 0)
287 return Mod2MapIndex;
288 else if (strcasecmp(key, "MOD3") == 0)
289 return Mod3MapIndex;
290 else if (strcasecmp(key, "MOD4") == 0)
291 return Mod4MapIndex;
292 else if (strcasecmp(key, "MOD5") == 0)
293 return Mod5MapIndex;
294 else
295 return -1;