changed indentation to use spaces only
[wmaker-crm.git] / WPrefs.app / xmodifier.c
blob1e5536b51544673c578d8e06781c673d87fc4d77
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
30 along with XEmacs; see the file COPYING. If not, write to
31 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 Boston, MA 02111-1307, USA. */
34 #include <string.h>
35 #include <X11/Xlib.h>
36 #include <X11/keysym.h>
38 #include <WINGs/WUtil.h>
42 /************************************************************************/
43 /* keymap handling */
44 /************************************************************************/
46 /* X bogusly doesn't define the interpretations of any bits besides
47 ModControl, ModShift, and ModLock; so the Interclient Communication
48 Conventions Manual says that we have to bend over backwards to figure
49 out what the other modifier bits mean. According to ICCCM:
51 - Any keycode which is assigned ModControl is a "control" key.
53 - Any modifier bit which is assigned to a keycode which generates Meta_L
54 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
55 etc.
57 - Any keypress event which contains ModControl in its state should be
58 interpreted as a "control" character.
60 - Any keypress event which contains a modifier bit in its state which is
61 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
62 should be interpreted as a "meta" character. Likewise for Super, Hyper,
63 etc.
65 - It is illegal for a keysym to be associated with more than one modifier
66 bit.
68 This means that the only thing that emacs can reasonably interpret as a
69 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
70 one of the modifier bits Mod1-Mod5.
72 Unfortunately, many keyboards don't have Meta keys in their default
73 configuration. So, if there are no Meta keys, but there are "Alt" keys,
74 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
75 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
76 mean "Symbol," but that just confused the hell out of way too many people).
78 This works with the default configurations of the 19 keyboard-types I've
79 checked.
81 Emacs detects keyboard configurations which violate the above rules, and
82 prints an error message on the standard-error-output. (Perhaps it should
83 use a pop-up-window instead.)
86 static int MetaIndex, HyperIndex, SuperIndex, AltIndex, ModeIndex;
88 static const char *
89 index_to_name (int indice)
91 switch (indice)
93 case ShiftMapIndex: return "ModShift";
94 case LockMapIndex: return "ModLock";
95 case ControlMapIndex: return "ModControl";
96 case Mod1MapIndex: return "Mod1";
97 case Mod2MapIndex: return "Mod2";
98 case Mod3MapIndex: return "Mod3";
99 case Mod4MapIndex: return "Mod4";
100 case Mod5MapIndex: return "Mod5";
101 default: return "???";
105 static void
106 x_reset_modifier_mapping (Display *display)
108 int modifier_index, modifier_key, column, mkpm;
109 int warned_about_overlapping_modifiers = 0;
110 int warned_about_predefined_modifiers = 0;
111 int warned_about_duplicate_modifiers = 0;
112 int meta_bit = 0;
113 int hyper_bit = 0;
114 int super_bit = 0;
115 int alt_bit = 0;
116 int mode_bit = 0;
117 XModifierKeymap *x_modifier_keymap = XGetModifierMapping (display);
119 #define modwarn(name,old,other) \
120 wwarning ("%s (0x%x) generates %s, which is generated by %s.\n\n", \
121 name, code, index_to_name (old), other), \
122 warned_about_overlapping_modifiers = 1
124 #define modbarf(name,other) \
125 wwarning ("%s (0x%x) generates %s, which is nonsensical.\n\n", \
126 name, code, other), \
127 warned_about_predefined_modifiers = 1
129 #define check_modifier(name,mask) \
130 if ((1<<modifier_index) != mask) \
131 wwarning ("%s (0x%x) generates %s, which is nonsensical.\n\n", \
132 name, code, index_to_name (modifier_index)), \
133 warned_about_predefined_modifiers = 1
135 #define store_modifier(name,old) \
136 if (old && old != modifier_index) \
137 wwarning ("%s (0x%x) generates both %s and %s, which is nonsensical.\n\n",\
138 name, code, index_to_name (old), \
139 index_to_name (modifier_index)), \
140 warned_about_duplicate_modifiers = 1; \
141 if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
142 else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
143 else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
144 else if (sym == XK_Mode_switch) \
145 mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
146 else if (modifier_index == meta_bit && old != meta_bit) \
147 modwarn (name, meta_bit, "Meta"); \
148 else if (modifier_index == super_bit && old != super_bit) \
149 modwarn (name, super_bit, "Super"); \
150 else if (modifier_index == hyper_bit && old != hyper_bit) \
151 modwarn (name, hyper_bit, "Hyper"); \
152 else if (modifier_index == alt_bit && old != alt_bit) \
153 modwarn (name, alt_bit, "Alt"); \
154 else \
155 old = modifier_index;
157 mkpm = x_modifier_keymap->max_keypermod;
158 for (modifier_index = 0; modifier_index < 8; modifier_index++)
159 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
160 KeySym last_sym = 0;
161 for (column = 0; column < 4; column += 2) {
162 KeyCode code = x_modifier_keymap->modifiermap[modifier_index * mkpm
163 + modifier_key];
164 KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
165 if (sym == last_sym) continue;
166 last_sym = sym;
167 switch (sym) {
168 case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
169 case XK_Meta_L: store_modifier ("Meta_L", meta_bit); break;
170 case XK_Meta_R: store_modifier ("Meta_R", meta_bit); break;
171 case XK_Super_L: store_modifier ("Super_L", super_bit); break;
172 case XK_Super_R: store_modifier ("Super_R", super_bit); break;
173 case XK_Hyper_L: store_modifier ("Hyper_L", hyper_bit); break;
174 case XK_Hyper_R: store_modifier ("Hyper_R", hyper_bit); break;
175 case XK_Alt_L: store_modifier ("Alt_L", alt_bit); break;
176 case XK_Alt_R: store_modifier ("Alt_R", alt_bit); break;
177 case XK_Control_L: check_modifier ("Control_L", ControlMask); break;
178 case XK_Control_R: check_modifier ("Control_R", ControlMask); break;
179 case XK_Shift_L: check_modifier ("Shift_L", ShiftMask); break;
180 case XK_Shift_R: check_modifier ("Shift_R", ShiftMask); break;
181 case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask); break;
182 case XK_Caps_Lock: check_modifier ("Caps_Lock", LockMask); break;
184 /* It probably doesn't make any sense for a modifier bit to be
185 assigned to a key that is not one of the above, but OpenWindows
186 assigns modifier bits to a couple of random function keys for
187 no reason that I can discern, so printing a warning here would
188 be annoying. */
192 #undef store_modifier
193 #undef check_modifier
194 #undef modwarn
195 #undef modbarf
197 /* If there was no Meta key, then try using the Alt key instead.
198 If there is both a Meta key and an Alt key, then the Alt key
199 is not disturbed and remains an Alt key. */
200 if (! meta_bit && alt_bit)
201 meta_bit = alt_bit, alt_bit = 0;
203 /* mode_bit overrides everything, since it's processed down inside of
204 XLookupString() instead of by us. If Meta and Mode_switch both
205 generate the same modifier bit (which is an error), then we don't
206 interpret that bit as Meta, because we can't make XLookupString()
207 not interpret it as Mode_switch; and interpreting it as both would
208 be totally wrong. */
209 if (mode_bit)
211 const char *warn = 0;
212 if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0;
213 else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
214 else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
215 else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0;
216 if (warn)
218 wwarning
219 ("%s is being used for both Mode_switch and %s.\n\n",
220 index_to_name (mode_bit), warn),
221 warned_about_overlapping_modifiers = 1;
225 MetaIndex = meta_bit;
226 HyperIndex = hyper_bit;
227 SuperIndex = super_bit;
228 AltIndex = alt_bit;
229 ModeIndex = mode_bit;
231 if (x_modifier_keymap != NULL)
232 XFreeModifiermap(x_modifier_keymap);
237 ModifierFromKey(Display *dpy, char *key)
239 static int eqw = 0;
241 if (!eqw)
242 x_reset_modifier_mapping(dpy);
243 eqw = 1;
245 if (strcasecmp(key, "SHIFT")==0)
246 return ShiftMapIndex;
247 else if (strcasecmp(key, "CONTROL")==0)
248 return ControlMapIndex;
249 else if (strcasecmp(key, "ALT")==0)
250 return AltIndex;
251 else if (strcasecmp(key, "META")==0)
252 return MetaIndex;
253 else if (strcasecmp(key, "SUPER")==0)
254 return SuperIndex;
255 else if (strcasecmp(key, "HYPER")==0)
256 return HyperIndex;
257 else if (strcasecmp(key, "MOD1")==0)
258 return Mod1MapIndex;
259 else if (strcasecmp(key, "MOD2")==0)
260 return Mod2MapIndex;
261 else if (strcasecmp(key, "MOD3")==0)
262 return Mod3MapIndex;
263 else if (strcasecmp(key, "MOD4")==0)
264 return Mod4MapIndex;
265 else if (strcasecmp(key, "MOD5")==0)
266 return Mod5MapIndex;
267 else
268 return -1;