TMparse.c revision 362b94d5
1444c061aSmrg/***********************************************************
24f45da70SmrgCopyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3697b1bafSmrg
4697b1bafSmrgPermission is hereby granted, free of charge, to any person obtaining a
5697b1bafSmrgcopy of this software and associated documentation files (the "Software"),
6697b1bafSmrgto deal in the Software without restriction, including without limitation
7697b1bafSmrgthe rights to use, copy, modify, merge, publish, distribute, sublicense,
8697b1bafSmrgand/or sell copies of the Software, and to permit persons to whom the
9697b1bafSmrgSoftware is furnished to do so, subject to the following conditions:
10697b1bafSmrg
11697b1bafSmrgThe above copyright notice and this permission notice (including the next
12697b1bafSmrgparagraph) shall be included in all copies or substantial portions of the
13697b1bafSmrgSoftware.
14697b1bafSmrg
15697b1bafSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16697b1bafSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17697b1bafSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18697b1bafSmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19697b1bafSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20697b1bafSmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21697b1bafSmrgDEALINGS IN THE SOFTWARE.
22697b1bafSmrg
23697b1bafSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24444c061aSmrg
25444c061aSmrg                        All Rights Reserved
26444c061aSmrg
27444c061aSmrgPermission to use, copy, modify, and distribute this software and its
28444c061aSmrgdocumentation for any purpose and without fee is hereby granted,
29444c061aSmrgprovided that the above copyright notice appear in all copies and that
30444c061aSmrgboth that copyright notice and this permission notice appear in
31697b1bafSmrgsupporting documentation, and that the name of Digital not be
32444c061aSmrgused in advertising or publicity pertaining to distribution of the
33444c061aSmrgsoftware without specific, written prior permission.
34444c061aSmrg
35444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41444c061aSmrgSOFTWARE.
42444c061aSmrg
43444c061aSmrg******************************************************************/
44444c061aSmrg
45444c061aSmrg/*
46444c061aSmrg
47444c061aSmrgCopyright 1987, 1988, 1998  The Open Group
48444c061aSmrg
49444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its
50444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that
51444c061aSmrgthe above copyright notice appear in all copies and that both that
52444c061aSmrgcopyright notice and this permission notice appear in supporting
53444c061aSmrgdocumentation.
54444c061aSmrg
55444c061aSmrgThe above copyright notice and this permission notice shall be included in
56444c061aSmrgall copies or substantial portions of the Software.
57444c061aSmrg
58444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64444c061aSmrg
65444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be
66444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings
67444c061aSmrgin this Software without prior written authorization from The Open Group.
68444c061aSmrg
69444c061aSmrg*/
70444c061aSmrg
71444c061aSmrg#ifdef HAVE_CONFIG_H
72444c061aSmrg#include <config.h>
73444c061aSmrg#endif
74444c061aSmrg#include "IntrinsicI.h"
75444c061aSmrg#include "StringDefs.h"
76444c061aSmrg#include <ctype.h>
77444c061aSmrg#include <stdlib.h>
78444c061aSmrg#ifndef NOTASCII
79444c061aSmrg#define XK_LATIN1
80444c061aSmrg#endif
81444c061aSmrg#define XK_MISCELLANY
82444c061aSmrg#include <X11/keysymdef.h>
83444c061aSmrg
84444c061aSmrg#ifdef CACHE_TRANSLATIONS
85362b94d5Smrg#ifdef REFCNT_TRANSLATIONS
86362b94d5Smrg#define CACHED XtCacheAll | XtCacheRefCount
87444c061aSmrg#else
88362b94d5Smrg#define CACHED XtCacheAll
89362b94d5Smrg#endif
90362b94d5Smrg#else
91362b94d5Smrg#define CACHED XtCacheNone
92444c061aSmrg#endif
93444c061aSmrg
94444c061aSmrg#ifndef MAX
95444c061aSmrg#define MAX(a,b) (((a) > (b)) ? (a) : (b))
96444c061aSmrg#endif
97444c061aSmrg
98444c061aSmrg#ifndef MIN
99444c061aSmrg#define MIN(a,b) (((a) < (b)) ? (a) : (b))
100444c061aSmrg#endif
101444c061aSmrg
10272af6995Smrgstatic _Xconst char *XtNtranslationParseError = "translationParseError";
103444c061aSmrg
104362b94d5Smrgtypedef int EventType;
105444c061aSmrg
10672af6995Smrg#define PARSE_PROC_DECL String, Opaque, EventPtr, Boolean*
10772af6995Smrg
108362b94d5Smrgtypedef String(*ParseProc) (String /* str; */ ,
109362b94d5Smrg                            Opaque /* closure; */ ,
110362b94d5Smrg                            EventPtr /* event; */ ,
111362b94d5Smrg                            Boolean * /* error */ );
112444c061aSmrg
113362b94d5Smrgtypedef TMShortCard Value;
114362b94d5Smrgtypedef void (*ModifierProc) (Value, LateBindingsPtr *, Boolean, Value *);
115444c061aSmrg
116444c061aSmrgtypedef struct _ModifierRec {
1178584976cSmrg    const char *name;
118362b94d5Smrg    XrmQuark signature;
119444c061aSmrg    ModifierProc modifierParseProc;
120362b94d5Smrg    Value value;
121444c061aSmrg} ModifierRec, *ModifierKeys;
122444c061aSmrg
123444c061aSmrgtypedef struct _EventKey {
124362b94d5Smrg    const char *event;
125362b94d5Smrg    XrmQuark signature;
126362b94d5Smrg    EventType eventType;
127362b94d5Smrg    ParseProc parseDetail;
128362b94d5Smrg    Opaque closure;
129362b94d5Smrg} EventKey, *EventKeys;
130444c061aSmrg
131444c061aSmrgtypedef struct {
132362b94d5Smrg    const char *name;
133362b94d5Smrg    XrmQuark signature;
134362b94d5Smrg    Value value;
135444c061aSmrg} NameValueRec, *NameValueTable;
136444c061aSmrg
137362b94d5Smrgstatic void ParseModImmed(Value, LateBindingsPtr *, Boolean, Value *);
138362b94d5Smrgstatic void ParseModSym(Value, LateBindingsPtr *, Boolean, Value *);
139444c061aSmrgstatic String PanicModeRecovery(String);
140444c061aSmrgstatic String CheckForPoundSign(String, _XtTranslateOp, _XtTranslateOp *);
141444c061aSmrgstatic KeySym StringToKeySym(String, Boolean *);
142362b94d5Smrg/* *INDENT-OFF* */
143444c061aSmrgstatic ModifierRec modifiers[] = {
144362b94d5Smrg    {"Shift",   0,      ParseModImmed, ShiftMask},
145362b94d5Smrg    {"Lock",    0,      ParseModImmed, LockMask},
146362b94d5Smrg    {"Ctrl",    0,      ParseModImmed, ControlMask},
147362b94d5Smrg    {"Mod1",    0,      ParseModImmed, Mod1Mask},
148362b94d5Smrg    {"Mod2",    0,      ParseModImmed, Mod2Mask},
149362b94d5Smrg    {"Mod3",    0,      ParseModImmed, Mod3Mask},
150362b94d5Smrg    {"Mod4",    0,      ParseModImmed, Mod4Mask},
151362b94d5Smrg    {"Mod5",    0,      ParseModImmed, Mod5Mask},
152362b94d5Smrg    {"Meta",    0,      ParseModSym,   XK_Meta_L},
153362b94d5Smrg    {"m",       0,      ParseModSym,   XK_Meta_L},
154362b94d5Smrg    {"h",       0,      ParseModSym,   XK_Hyper_L},
155362b94d5Smrg    {"su",      0,      ParseModSym,   XK_Super_L},
156362b94d5Smrg    {"a",       0,      ParseModSym,   XK_Alt_L},
157362b94d5Smrg    {"Hyper",   0,      ParseModSym,   XK_Hyper_L},
158362b94d5Smrg    {"Super",   0,      ParseModSym,   XK_Super_L},
159362b94d5Smrg    {"Alt",     0,      ParseModSym,   XK_Alt_L},
160362b94d5Smrg    {"Button1", 0,      ParseModImmed, Button1Mask},
161362b94d5Smrg    {"Button2", 0,      ParseModImmed, Button2Mask},
162362b94d5Smrg    {"Button3", 0,      ParseModImmed, Button3Mask},
163362b94d5Smrg    {"Button4", 0,      ParseModImmed, Button4Mask},
164362b94d5Smrg    {"Button5", 0,      ParseModImmed, Button5Mask},
165362b94d5Smrg    {"c",       0,      ParseModImmed, ControlMask},
166362b94d5Smrg    {"s",       0,      ParseModImmed, ShiftMask},
167362b94d5Smrg    {"l",       0,      ParseModImmed, LockMask},
168444c061aSmrg};
169444c061aSmrg
170444c061aSmrgstatic NameValueRec buttonNames[] = {
171362b94d5Smrg    {"Button1",             0,         Button1},
172362b94d5Smrg    {"Button2",             0,         Button2},
173362b94d5Smrg    {"Button3",             0,         Button3},
174362b94d5Smrg    {"Button4",             0,         Button4},
175362b94d5Smrg    {"Button5",             0,         Button5},
176362b94d5Smrg    {NULL,                  NULLQUARK, 0},
177444c061aSmrg};
178444c061aSmrg
179444c061aSmrgstatic NameValueRec motionDetails[] = {
180362b94d5Smrg    {"Normal",              0,         NotifyNormal},
181362b94d5Smrg    {"Hint",                0,         NotifyHint},
182362b94d5Smrg    {NULL,                  NULLQUARK, 0},
183444c061aSmrg};
184444c061aSmrg
185444c061aSmrgstatic NameValueRec notifyModes[] = {
186362b94d5Smrg    {"Normal",              0,         NotifyNormal},
187362b94d5Smrg    {"Grab",                0,         NotifyGrab},
188362b94d5Smrg    {"Ungrab",              0,         NotifyUngrab},
189362b94d5Smrg    {"WhileGrabbed",        0,         NotifyWhileGrabbed},
190362b94d5Smrg    {NULL,                  NULLQUARK, 0},
191444c061aSmrg};
192444c061aSmrg
193444c061aSmrg#if 0
194444c061aSmrgstatic NameValueRec notifyDetail[] = {
195362b94d5Smrg    {"Ancestor",            0,         NotifyAncestor},
196362b94d5Smrg    {"Virtual",             0,         NotifyVirtual},
197362b94d5Smrg    {"Inferior",            0,         NotifyInferior},
198362b94d5Smrg    {"Nonlinear",           0,         NotifyNonlinear},
199362b94d5Smrg    {"NonlinearVirtual",    0,         NotifyNonlinearVirtual},
200362b94d5Smrg    {"Pointer",             0,         NotifyPointer},
201362b94d5Smrg    {"PointerRoot",         0,         NotifyPointerRoot},
202362b94d5Smrg    {"DetailNone",          0,         NotifyDetailNone},
203362b94d5Smrg    {NULL,                  NULLQUARK, 0},
204444c061aSmrg};
205444c061aSmrg
206444c061aSmrgstatic NameValueRec visibilityNotify[] = {
207362b94d5Smrg    {"Unobscured",          0,         VisibilityUnobscured},
208362b94d5Smrg    {"PartiallyObscured",   0,         VisibilityPartiallyObscured},
209362b94d5Smrg    {"FullyObscured",       0,         VisibilityFullyObscured},
210362b94d5Smrg    {NULL,                  NULLQUARK, 0},
211444c061aSmrg};
212444c061aSmrg
213444c061aSmrgstatic NameValueRec circulation[] = {
214362b94d5Smrg    {"OnTop",               0,         PlaceOnTop},
215362b94d5Smrg    {"OnBottom",            0,         PlaceOnBottom},
216362b94d5Smrg    {NULL,                  NULLQUARK, 0},
217444c061aSmrg};
218444c061aSmrg
219444c061aSmrgstatic NameValueRec propertyChanged[] = {
220362b94d5Smrg    {"NewValue",            0,         PropertyNewValue},
221362b94d5Smrg    {"Delete",              0,         PropertyDelete},
222362b94d5Smrg    {NULL,                  NULLQUARK, 0},
223444c061aSmrg};
224444c061aSmrg#endif /*0*/
225444c061aSmrg
226444c061aSmrgstatic NameValueRec mappingNotify[] = {
227362b94d5Smrg    {"Modifier",            0,         MappingModifier},
228362b94d5Smrg    {"Keyboard",            0,         MappingKeyboard},
229362b94d5Smrg    {"Pointer",             0,         MappingPointer},
230362b94d5Smrg    {NULL,                  NULLQUARK, 0},
231444c061aSmrg};
232362b94d5Smrg/* *INDENT-ON* */
233444c061aSmrg
23472af6995Smrgstatic String ParseKeySym(PARSE_PROC_DECL);
23572af6995Smrgstatic String ParseKeyAndModifiers(PARSE_PROC_DECL);
23672af6995Smrgstatic String ParseTable(PARSE_PROC_DECL);
23772af6995Smrgstatic String ParseImmed(PARSE_PROC_DECL);
23872af6995Smrgstatic String ParseAddModifier(PARSE_PROC_DECL);
23972af6995Smrgstatic String ParseNone(PARSE_PROC_DECL);
24072af6995Smrgstatic String ParseAtom(PARSE_PROC_DECL);
241444c061aSmrg
242362b94d5Smrg/* *INDENT-OFF* */
243444c061aSmrgstatic EventKey events[] = {
244444c061aSmrg
245362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
246444c061aSmrg
247362b94d5Smrg{"KeyPress",        NULLQUARK, KeyPress,        ParseKeySym,    NULL},
248362b94d5Smrg{"Key",             NULLQUARK, KeyPress,        ParseKeySym,    NULL},
249362b94d5Smrg{"KeyDown",         NULLQUARK, KeyPress,        ParseKeySym,    NULL},
250362b94d5Smrg{"Ctrl",            NULLQUARK, KeyPress,        ParseKeyAndModifiers, (Opaque)ControlMask},
251362b94d5Smrg{"Shift",           NULLQUARK, KeyPress,        ParseKeyAndModifiers, (Opaque)ShiftMask},
252362b94d5Smrg{"Meta",            NULLQUARK, KeyPress,        ParseKeyAndModifiers, (Opaque)NULL},
253362b94d5Smrg{"KeyUp",           NULLQUARK, KeyRelease,      ParseKeySym,    NULL},
254362b94d5Smrg{"KeyRelease",      NULLQUARK, KeyRelease,      ParseKeySym,    NULL},
255444c061aSmrg
256362b94d5Smrg{"ButtonPress",     NULLQUARK, ButtonPress,     ParseTable, (Opaque)buttonNames},
257362b94d5Smrg{"BtnDown",         NULLQUARK, ButtonPress,     ParseTable, (Opaque)buttonNames},
258362b94d5Smrg{"Btn1Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button1},
259362b94d5Smrg{"Btn2Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button2},
260362b94d5Smrg{"Btn3Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button3},
261362b94d5Smrg{"Btn4Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button4},
262362b94d5Smrg{"Btn5Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button5},
263444c061aSmrg
264362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
265444c061aSmrg
266362b94d5Smrg{"ButtonRelease",   NULLQUARK, ButtonRelease,   ParseTable, (Opaque)buttonNames},
267362b94d5Smrg{"BtnUp",           NULLQUARK, ButtonRelease,   ParseTable, (Opaque)buttonNames},
268362b94d5Smrg{"Btn1Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button1},
269362b94d5Smrg{"Btn2Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button2},
270362b94d5Smrg{"Btn3Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button3},
271362b94d5Smrg{"Btn4Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button4},
272362b94d5Smrg{"Btn5Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button5},
273444c061aSmrg
274362b94d5Smrg{"MotionNotify",    NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
275362b94d5Smrg{"PtrMoved",        NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
276362b94d5Smrg{"Motion",          NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
277362b94d5Smrg{"MouseMoved",      NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
278362b94d5Smrg{"BtnMotion",       NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)AnyButtonMask},
279362b94d5Smrg{"Btn1Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button1Mask},
280362b94d5Smrg{"Btn2Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button2Mask},
281362b94d5Smrg{"Btn3Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button3Mask},
282362b94d5Smrg{"Btn4Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button4Mask},
283362b94d5Smrg{"Btn5Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button5Mask},
284444c061aSmrg
285362b94d5Smrg{"EnterNotify",     NULLQUARK, EnterNotify,     ParseTable, (Opaque)notifyModes},
286362b94d5Smrg{"Enter",           NULLQUARK, EnterNotify,     ParseTable, (Opaque)notifyModes},
287362b94d5Smrg{"EnterWindow",     NULLQUARK, EnterNotify,     ParseTable, (Opaque)notifyModes},
288444c061aSmrg
289362b94d5Smrg{"LeaveNotify",     NULLQUARK, LeaveNotify,     ParseTable, (Opaque)notifyModes},
290362b94d5Smrg{"LeaveWindow",     NULLQUARK, LeaveNotify,     ParseTable, (Opaque)notifyModes},
291362b94d5Smrg{"Leave",           NULLQUARK, LeaveNotify,     ParseTable, (Opaque)notifyModes},
292444c061aSmrg
293362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
294444c061aSmrg
295362b94d5Smrg{"FocusIn",         NULLQUARK, FocusIn,         ParseTable, (Opaque)notifyModes},
296444c061aSmrg
297362b94d5Smrg{"FocusOut",        NULLQUARK, FocusOut,        ParseTable, (Opaque)notifyModes},
298444c061aSmrg
299362b94d5Smrg{"KeymapNotify",    NULLQUARK, KeymapNotify,    ParseNone,      NULL},
300362b94d5Smrg{"Keymap",          NULLQUARK, KeymapNotify,    ParseNone,      NULL},
301444c061aSmrg
302362b94d5Smrg{"Expose",          NULLQUARK, Expose,          ParseNone,      NULL},
303444c061aSmrg
304362b94d5Smrg{"GraphicsExpose",  NULLQUARK, GraphicsExpose,  ParseNone,      NULL},
305362b94d5Smrg{"GrExp",           NULLQUARK, GraphicsExpose,  ParseNone,      NULL},
306444c061aSmrg
307362b94d5Smrg{"NoExpose",        NULLQUARK, NoExpose,        ParseNone,      NULL},
308362b94d5Smrg{"NoExp",           NULLQUARK, NoExpose,        ParseNone,      NULL},
309444c061aSmrg
310362b94d5Smrg{"VisibilityNotify",NULLQUARK, VisibilityNotify,ParseNone,      NULL},
311362b94d5Smrg{"Visible",         NULLQUARK, VisibilityNotify,ParseNone,      NULL},
312444c061aSmrg
313362b94d5Smrg{"CreateNotify",    NULLQUARK, CreateNotify,    ParseNone,      NULL},
314362b94d5Smrg{"Create",          NULLQUARK, CreateNotify,    ParseNone,      NULL},
315444c061aSmrg
316362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
317444c061aSmrg
318362b94d5Smrg{"DestroyNotify",   NULLQUARK, DestroyNotify,   ParseNone,      NULL},
319362b94d5Smrg{"Destroy",         NULLQUARK, DestroyNotify,   ParseNone,      NULL},
320444c061aSmrg
321362b94d5Smrg{"UnmapNotify",     NULLQUARK, UnmapNotify,     ParseNone,      NULL},
322362b94d5Smrg{"Unmap",           NULLQUARK, UnmapNotify,     ParseNone,      NULL},
323444c061aSmrg
324362b94d5Smrg{"MapNotify",       NULLQUARK, MapNotify,       ParseNone,      NULL},
325362b94d5Smrg{"Map",             NULLQUARK, MapNotify,       ParseNone,      NULL},
326444c061aSmrg
327362b94d5Smrg{"MapRequest",      NULLQUARK, MapRequest,      ParseNone,      NULL},
328362b94d5Smrg{"MapReq",          NULLQUARK, MapRequest,      ParseNone,      NULL},
329444c061aSmrg
330362b94d5Smrg{"ReparentNotify",  NULLQUARK, ReparentNotify,  ParseNone,      NULL},
331362b94d5Smrg{"Reparent",        NULLQUARK, ReparentNotify,  ParseNone,      NULL},
332444c061aSmrg
333362b94d5Smrg{"ConfigureNotify", NULLQUARK, ConfigureNotify, ParseNone,      NULL},
334362b94d5Smrg{"Configure",       NULLQUARK, ConfigureNotify, ParseNone,      NULL},
335444c061aSmrg
336362b94d5Smrg{"ConfigureRequest",NULLQUARK, ConfigureRequest,ParseNone,      NULL},
337362b94d5Smrg{"ConfigureReq",    NULLQUARK, ConfigureRequest,ParseNone,      NULL},
338444c061aSmrg
339362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
340444c061aSmrg
341362b94d5Smrg{"GravityNotify",   NULLQUARK, GravityNotify,   ParseNone,      NULL},
342362b94d5Smrg{"Grav",            NULLQUARK, GravityNotify,   ParseNone,      NULL},
343444c061aSmrg
344362b94d5Smrg{"ResizeRequest",   NULLQUARK, ResizeRequest,   ParseNone,      NULL},
345362b94d5Smrg{"ResReq",          NULLQUARK, ResizeRequest,   ParseNone,      NULL},
346444c061aSmrg
347362b94d5Smrg{"CirculateNotify", NULLQUARK, CirculateNotify, ParseNone,      NULL},
348362b94d5Smrg{"Circ",            NULLQUARK, CirculateNotify, ParseNone,      NULL},
349444c061aSmrg
350362b94d5Smrg{"CirculateRequest",NULLQUARK, CirculateRequest,ParseNone,      NULL},
351362b94d5Smrg{"CircReq",         NULLQUARK, CirculateRequest,ParseNone,      NULL},
352444c061aSmrg
353362b94d5Smrg{"PropertyNotify",  NULLQUARK, PropertyNotify,  ParseAtom,      NULL},
354362b94d5Smrg{"Prop",            NULLQUARK, PropertyNotify,  ParseAtom,      NULL},
355444c061aSmrg
356362b94d5Smrg{"SelectionClear",  NULLQUARK, SelectionClear,  ParseAtom,      NULL},
357362b94d5Smrg{"SelClr",          NULLQUARK, SelectionClear,  ParseAtom,      NULL},
358444c061aSmrg
359362b94d5Smrg{"SelectionRequest",NULLQUARK, SelectionRequest,ParseAtom,      NULL},
360362b94d5Smrg{"SelReq",          NULLQUARK, SelectionRequest,ParseAtom,      NULL},
361444c061aSmrg
362362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
363444c061aSmrg
364362b94d5Smrg{"SelectionNotify", NULLQUARK, SelectionNotify, ParseAtom,      NULL},
365362b94d5Smrg{"Select",          NULLQUARK, SelectionNotify, ParseAtom,      NULL},
366444c061aSmrg
367362b94d5Smrg{"ColormapNotify",  NULLQUARK, ColormapNotify,  ParseNone,      NULL},
368362b94d5Smrg{"Clrmap",          NULLQUARK, ColormapNotify,  ParseNone,      NULL},
369444c061aSmrg
370362b94d5Smrg{"ClientMessage",   NULLQUARK, ClientMessage,   ParseAtom,      NULL},
371362b94d5Smrg{"Message",         NULLQUARK, ClientMessage,   ParseAtom,      NULL},
372444c061aSmrg
373362b94d5Smrg{"MappingNotify",   NULLQUARK, MappingNotify,   ParseTable, (Opaque)mappingNotify},
374362b94d5Smrg{"Mapping",         NULLQUARK, MappingNotify,   ParseTable, (Opaque)mappingNotify},
375444c061aSmrg
376444c061aSmrg#ifdef DEBUG
377444c061aSmrg# ifdef notdef
378362b94d5Smrg{"Timer",           NULLQUARK, _XtTimerEventType, ParseNone,     NULL},
379362b94d5Smrg{"EventTimer",      NULLQUARK, _XtEventTimerEventType, ParseNone,NULL},
3801bd39548Schristos# endif /* notdef */
381444c061aSmrg#endif /* DEBUG */
382444c061aSmrg
383362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
384444c061aSmrg
385444c061aSmrg};
386362b94d5Smrg/* *INDENT-ON* */
387444c061aSmrg
388444c061aSmrg#define IsNewline(str) ((str) == '\n')
389444c061aSmrg
390444c061aSmrg#define ScanFor(str, ch) \
391444c061aSmrg    while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))) (str)++
392444c061aSmrg
393444c061aSmrg#define ScanNumeric(str)  while ('0' <= *(str) && *(str) <= '9') (str)++
394444c061aSmrg
395444c061aSmrg#define ScanAlphanumeric(str) \
396444c061aSmrg    while (('A' <= *(str) && *(str) <= 'Z') || \
397444c061aSmrg           ('a' <= *(str) && *(str) <= 'z') || \
398444c061aSmrg           ('0' <= *(str) && *(str) <= '9')) (str)++
399444c061aSmrg
400444c061aSmrg#define ScanWhitespace(str) \
401444c061aSmrg    while (*(str) == ' ' || *(str) == '\t') (str)++
402444c061aSmrg
403444c061aSmrgstatic Boolean initialized = FALSE;
404444c061aSmrgstatic XrmQuark QMeta;
405444c061aSmrgstatic XrmQuark QCtrl;
406444c061aSmrgstatic XrmQuark QNone;
407444c061aSmrgstatic XrmQuark QAny;
408444c061aSmrg
409362b94d5Smrgstatic void
410362b94d5SmrgFreeEventSeq(EventSeqPtr eventSeq)
411444c061aSmrg{
412444c061aSmrg    register EventSeqPtr evs = eventSeq;
413444c061aSmrg
414444c061aSmrg    while (evs != NULL) {
415362b94d5Smrg        evs->state = (StatePtr) evs;
416362b94d5Smrg        if (evs->next != NULL && evs->next->state == (StatePtr) evs->next)
417362b94d5Smrg            evs->next = NULL;
418362b94d5Smrg        evs = evs->next;
419444c061aSmrg    }
420444c061aSmrg
421444c061aSmrg    evs = eventSeq;
422444c061aSmrg    while (evs != NULL) {
423362b94d5Smrg        register EventPtr event = evs;
424362b94d5Smrg
425362b94d5Smrg        evs = evs->next;
426362b94d5Smrg        if (evs == event)
427362b94d5Smrg            evs = NULL;
428362b94d5Smrg        XtFree((char *) event);
429444c061aSmrg    }
430444c061aSmrg}
431444c061aSmrg
432362b94d5Smrgstatic void
433362b94d5SmrgCompileNameValueTable(NameValueTable table)
434444c061aSmrg{
435444c061aSmrg    register int i;
436444c061aSmrg
437362b94d5Smrg    for (i = 0; table[i].name; i++)
438444c061aSmrg        table[i].signature = XrmPermStringToQuark(table[i].name);
439444c061aSmrg}
440444c061aSmrg
441362b94d5Smrgstatic int
442362b94d5SmrgOrderEvents(_Xconst void *a, _Xconst void *b)
443444c061aSmrg{
444362b94d5Smrg    return ((((_Xconst EventKey *) a)->signature <
445362b94d5Smrg             ((_Xconst EventKey *) b)->signature) ? -1 : 1);
446444c061aSmrg}
447444c061aSmrg
448362b94d5Smrgstatic void
449362b94d5SmrgCompile_XtEventTable(EventKeys table, Cardinal count)
450444c061aSmrg{
451444c061aSmrg    register int i;
452444c061aSmrg    register EventKeys entry = table;
453444c061aSmrg
454362b94d5Smrg    for (i = (int) count; --i >= 0; entry++)
455362b94d5Smrg        entry->signature = XrmPermStringToQuark(entry->event);
456444c061aSmrg    qsort(table, count, sizeof(EventKey), OrderEvents);
457444c061aSmrg}
458444c061aSmrg
459362b94d5Smrgstatic int
460362b94d5SmrgOrderModifiers(_Xconst void *a, _Xconst void *b)
461444c061aSmrg{
462362b94d5Smrg    return ((((_Xconst ModifierRec *) a)->signature <
463362b94d5Smrg             ((_Xconst ModifierRec *) b)->signature) ? -1 : 1);
464444c061aSmrg}
465444c061aSmrg
466362b94d5Smrgstatic void
467362b94d5SmrgCompile_XtModifierTable(ModifierKeys table, Cardinal count)
468444c061aSmrg{
469444c061aSmrg    register int i;
470444c061aSmrg    register ModifierKeys entry = table;
471444c061aSmrg
472362b94d5Smrg    for (i = (int) count; --i >= 0; entry++)
473362b94d5Smrg        entry->signature = XrmPermStringToQuark(entry->name);
474444c061aSmrg    qsort(table, count, sizeof(ModifierRec), OrderModifiers);
475444c061aSmrg}
476444c061aSmrg
477362b94d5Smrgstatic String
478362b94d5SmrgPanicModeRecovery(String str)
479444c061aSmrg{
480362b94d5Smrg    ScanFor(str, '\n');
481362b94d5Smrg    if (*str == '\n')
482362b94d5Smrg        str++;
483362b94d5Smrg    return str;
484444c061aSmrg
485444c061aSmrg}
486444c061aSmrg
487362b94d5Smrgstatic void
488362b94d5SmrgSyntax(_Xconst char *str0, _Xconst char *str1)
489444c061aSmrg{
490444c061aSmrg    Cardinal num_params = 2;
491444c061aSmrg    String params[2];
492444c061aSmrg
49372af6995Smrg    params[0] = (String) str0;
49472af6995Smrg    params[1] = (String) str1;
495362b94d5Smrg    XtWarningMsg(XtNtranslationParseError, "parseError", XtCXtToolkitError,
496362b94d5Smrg                 "translation table syntax error: %s %s", params, &num_params);
497444c061aSmrg}
498444c061aSmrg
499362b94d5Smrgstatic Cardinal
500362b94d5SmrgLookupTMEventType(String eventStr, Boolean *error)
501444c061aSmrg{
502362b94d5Smrg    register int i = 0, left, right;
503362b94d5Smrg    register XrmQuark signature;
504362b94d5Smrg    static int previous = 0;
505444c061aSmrg
506444c061aSmrg    LOCK_PROCESS;
507444c061aSmrg    if ((signature = StringToQuark(eventStr)) == events[previous].signature) {
508362b94d5Smrg        UNLOCK_PROCESS;
509362b94d5Smrg        return (Cardinal) previous;
510444c061aSmrg    }
511444c061aSmrg
512444c061aSmrg    left = 0;
513444c061aSmrg    right = XtNumber(events) - 1;
514444c061aSmrg    while (left <= right) {
515362b94d5Smrg        i = (left + right) >> 1;
516362b94d5Smrg        if (signature < events[i].signature)
517362b94d5Smrg            right = i - 1;
518362b94d5Smrg        else if (signature > events[i].signature)
519362b94d5Smrg            left = i + 1;
520362b94d5Smrg        else {
521362b94d5Smrg            previous = i;
522362b94d5Smrg            UNLOCK_PROCESS;
523362b94d5Smrg            return (Cardinal) i;
524362b94d5Smrg        }
525362b94d5Smrg    }
526362b94d5Smrg
527362b94d5Smrg    Syntax("Unknown event type :  ", eventStr);
528444c061aSmrg    *error = TRUE;
529444c061aSmrg    UNLOCK_PROCESS;
530444c061aSmrg    return (Cardinal) i;
531444c061aSmrg}
532444c061aSmrg
533362b94d5Smrgstatic void
534362b94d5SmrgStoreLateBindings(KeySym keysymL,
535362b94d5Smrg                  Boolean notL,
536362b94d5Smrg                  KeySym keysymR,
537362b94d5Smrg                  Boolean notR,
538362b94d5Smrg                  LateBindingsPtr *lateBindings)
539444c061aSmrg{
540444c061aSmrg    LateBindingsPtr temp;
54172af6995Smrg
542362b94d5Smrg    if (lateBindings != NULL) {
543362b94d5Smrg        Boolean pair = FALSE;
544362b94d5Smrg        unsigned long count;
545362b94d5Smrg        unsigned long number;
54672af6995Smrg
547444c061aSmrg        temp = *lateBindings;
548444c061aSmrg        if (temp != NULL) {
549362b94d5Smrg            for (count = 0; temp[count].keysym; count++) {
550362b94d5Smrg                /*EMPTY*/
551362b94d5Smrg            }
552444c061aSmrg        }
553362b94d5Smrg        else
554362b94d5Smrg            count = 0;
555362b94d5Smrg        if (!keysymR) {
556362b94d5Smrg            number = 1;
557362b94d5Smrg            pair = FALSE;
558362b94d5Smrg        }
559362b94d5Smrg        else {
560362b94d5Smrg            number = 2;
561362b94d5Smrg            pair = TRUE;
562444c061aSmrg        }
563444c061aSmrg
564362b94d5Smrg        temp = (LateBindingsPtr) XtRealloc((char *) temp,
565362b94d5Smrg                                           (unsigned) ((count + number +
566362b94d5Smrg                                                        1) *
567362b94d5Smrg                                                       sizeof(LateBindings)));
568444c061aSmrg        *lateBindings = temp;
56972af6995Smrg        XtSetBit(temp[count].knot, notL);
57072af6995Smrg        XtSetBit(temp[count].pair, pair);
571362b94d5Smrg        if (count == 0)
572362b94d5Smrg            temp[count].ref_count = 1;
573444c061aSmrg        temp[count++].keysym = keysymL;
574362b94d5Smrg        if (keysymR) {
57572af6995Smrg            XtSetBit(temp[count].knot, notR);
576444c061aSmrg            temp[count].pair = FALSE;
577362b94d5Smrg            temp[count].ref_count = 0;
578444c061aSmrg            temp[count++].keysym = keysymR;
579444c061aSmrg        }
580444c061aSmrg        temp[count].knot = temp[count].pair = FALSE;
581444c061aSmrg        temp[count].ref_count = 0;
582444c061aSmrg        temp[count].keysym = 0;
583444c061aSmrg    }
584444c061aSmrg}
585444c061aSmrg
586362b94d5Smrgstatic void
587362b94d5Smrg_XtParseKeysymMod(String name,
588362b94d5Smrg                  LateBindingsPtr *lateBindings,
589362b94d5Smrg                  Boolean notFlag,
590362b94d5Smrg                  Value *valueP,
591362b94d5Smrg                  Boolean *error)
592444c061aSmrg{
593444c061aSmrg    KeySym keySym;
594362b94d5Smrg
595444c061aSmrg    keySym = StringToKeySym(name, error);
596444c061aSmrg    *valueP = 0;
597444c061aSmrg    if (keySym != NoSymbol) {
598362b94d5Smrg        StoreLateBindings(keySym, notFlag, (KeySym) NULL, FALSE, lateBindings);
599444c061aSmrg    }
600444c061aSmrg}
601444c061aSmrg
602362b94d5Smrgstatic Boolean
603362b94d5Smrg_XtLookupModifier(XrmQuark signature,
604362b94d5Smrg                  LateBindingsPtr *lateBindings,
605362b94d5Smrg                  Boolean notFlag,
606362b94d5Smrg                  Value *valueP,
607362b94d5Smrg                  Bool constMask)
608444c061aSmrg{
60972af6995Smrg    int left, right;
610444c061aSmrg    static int previous = 0;
611444c061aSmrg
612444c061aSmrg    LOCK_PROCESS;
613444c061aSmrg    if (signature == modifiers[previous].signature) {
614362b94d5Smrg        if (constMask)
615362b94d5Smrg            *valueP = modifiers[previous].value;
616362b94d5Smrg        else                    /* if (modifiers[previous].modifierParseProc) always true */
617362b94d5Smrg            (*modifiers[previous].modifierParseProc)
618362b94d5Smrg                (modifiers[previous].value, lateBindings, notFlag, valueP);
619362b94d5Smrg        UNLOCK_PROCESS;
620362b94d5Smrg        return TRUE;
621444c061aSmrg    }
622444c061aSmrg
623444c061aSmrg    left = 0;
624444c061aSmrg    right = XtNumber(modifiers) - 1;
625444c061aSmrg    while (left <= right) {
626362b94d5Smrg        int i = (left + right) >> 1;
627362b94d5Smrg
628362b94d5Smrg        if (signature < modifiers[i].signature)
629362b94d5Smrg            right = i - 1;
630362b94d5Smrg        else if (signature > modifiers[i].signature)
631362b94d5Smrg            left = i + 1;
632362b94d5Smrg        else {
633362b94d5Smrg            previous = i;
634362b94d5Smrg            if (constMask)
635362b94d5Smrg                *valueP = modifiers[i].value;
636362b94d5Smrg            else                /* if (modifiers[i].modifierParseProc) always true */
637362b94d5Smrg                (*modifiers[i].modifierParseProc)
638362b94d5Smrg                    (modifiers[i].value, lateBindings, notFlag, valueP);
639362b94d5Smrg            UNLOCK_PROCESS;
640362b94d5Smrg            return TRUE;
641362b94d5Smrg        }
642444c061aSmrg    }
643444c061aSmrg    UNLOCK_PROCESS;
644444c061aSmrg    return FALSE;
645444c061aSmrg}
646444c061aSmrg
647362b94d5Smrgstatic String
648362b94d5SmrgScanIdent(register String str)
649444c061aSmrg{
650444c061aSmrg    ScanAlphanumeric(str);
651362b94d5Smrg    while (('A' <= *str && *str <= 'Z')
652362b94d5Smrg           || ('a' <= *str && *str <= 'z')
653362b94d5Smrg           || ('0' <= *str && *str <= '9')
654362b94d5Smrg           || (*str == '-')
655362b94d5Smrg           || (*str == '_')
656362b94d5Smrg           || (*str == '$')
657362b94d5Smrg        )
658362b94d5Smrg        str++;
659444c061aSmrg    return str;
660444c061aSmrg}
661444c061aSmrg
662362b94d5Smrgstatic String
663362b94d5SmrgFetchModifierToken(String str, XrmQuark *token_return)
664444c061aSmrg{
665444c061aSmrg    String start = str;
666444c061aSmrg
667444c061aSmrg    if (*str == '$') {
668444c061aSmrg        *token_return = QMeta;
669444c061aSmrg        str++;
670362b94d5Smrg    }
671362b94d5Smrg    else if (*str == '^') {
672444c061aSmrg        *token_return = QCtrl;
673444c061aSmrg        str++;
674362b94d5Smrg    }
675362b94d5Smrg    else {
676362b94d5Smrg        str = ScanIdent(str);
677362b94d5Smrg        if (start != str) {
678362b94d5Smrg            char modStrbuf[100];
679362b94d5Smrg            char *modStr;
680362b94d5Smrg
681362b94d5Smrg            modStr = XtStackAlloc((size_t) (str - start + 1), modStrbuf);
682362b94d5Smrg            if (modStr == NULL)
683362b94d5Smrg                _XtAllocError(NULL);
684362b94d5Smrg            (void) memmove(modStr, start, (size_t) (str - start));
685362b94d5Smrg            modStr[str - start] = '\0';
686362b94d5Smrg            *token_return = XrmStringToQuark(modStr);
687362b94d5Smrg            XtStackFree(modStr, modStrbuf);
688362b94d5Smrg        }
689444c061aSmrg    }
690444c061aSmrg    return str;
691444c061aSmrg}
692444c061aSmrg
693362b94d5Smrgstatic String
694362b94d5SmrgParseModifiers(register String str, EventPtr event, Boolean *error)
695444c061aSmrg{
696444c061aSmrg    register String start;
697444c061aSmrg    Boolean notFlag, exclusive, keysymAsMod;
698444c061aSmrg    Value maskBit;
69972af6995Smrg    XrmQuark Qmod = QNone;
700444c061aSmrg
701444c061aSmrg    ScanWhitespace(str);
702444c061aSmrg    start = str;
703444c061aSmrg    str = FetchModifierToken(str, &Qmod);
704444c061aSmrg    exclusive = FALSE;
705444c061aSmrg    if (start != str) {
706362b94d5Smrg        if (Qmod == QNone) {
707362b94d5Smrg            event->event.modifierMask = (unsigned long) (~0);
708362b94d5Smrg            event->event.modifiers = 0;
709362b94d5Smrg            ScanWhitespace(str);
710362b94d5Smrg            return str;
711444c061aSmrg        }
712362b94d5Smrg        else if (Qmod == QAny) {        /*backward compatability */
713362b94d5Smrg            event->event.modifierMask = 0;
714362b94d5Smrg            event->event.modifiers = AnyModifier;
715362b94d5Smrg            ScanWhitespace(str);
716362b94d5Smrg            return str;
717444c061aSmrg        }
718362b94d5Smrg        str = start;            /*if plain modifier, reset to beginning */
719444c061aSmrg    }
720362b94d5Smrg    else
721362b94d5Smrg        while (*str == '!' || *str == ':') {
722362b94d5Smrg            if (*str == '!') {
723362b94d5Smrg                exclusive = TRUE;
724362b94d5Smrg                str++;
725362b94d5Smrg                ScanWhitespace(str);
726362b94d5Smrg            }
727362b94d5Smrg            if (*str == ':') {
728362b94d5Smrg                event->event.standard = TRUE;
729362b94d5Smrg                str++;
730362b94d5Smrg                ScanWhitespace(str);
731362b94d5Smrg            }
732362b94d5Smrg        }
733444c061aSmrg
734444c061aSmrg    while (*str != '<') {
735444c061aSmrg        if (*str == '~') {
736362b94d5Smrg            notFlag = TRUE;
737362b94d5Smrg            str++;
738362b94d5Smrg        }
739362b94d5Smrg        else
740362b94d5Smrg            notFlag = FALSE;
741444c061aSmrg        if (*str == '@') {
742444c061aSmrg            keysymAsMod = TRUE;
743444c061aSmrg            str++;
744444c061aSmrg        }
745362b94d5Smrg        else
746362b94d5Smrg            keysymAsMod = FALSE;
747362b94d5Smrg        start = str;
748444c061aSmrg        str = FetchModifierToken(str, &Qmod);
749444c061aSmrg        if (start == str) {
750362b94d5Smrg            Syntax("Modifier or '<' expected", "");
751362b94d5Smrg            *error = TRUE;
752362b94d5Smrg            return PanicModeRecovery(str);
753362b94d5Smrg        }
754362b94d5Smrg        if (keysymAsMod) {
755362b94d5Smrg            _XtParseKeysymMod(XrmQuarkToString(Qmod),
756362b94d5Smrg                              &event->event.lateModifiers,
757362b94d5Smrg                              notFlag, &maskBit, error);
758362b94d5Smrg            if (*error)
759362b94d5Smrg                return PanicModeRecovery(str);
760362b94d5Smrg
761362b94d5Smrg        }
762362b94d5Smrg        else if (!_XtLookupModifier(Qmod, &event->event.lateModifiers,
763362b94d5Smrg                                    notFlag, &maskBit, FALSE)) {
764362b94d5Smrg            Syntax("Unknown modifier name:  ", XrmQuarkToString(Qmod));
765444c061aSmrg            *error = TRUE;
766444c061aSmrg            return PanicModeRecovery(str);
767444c061aSmrg        }
768444c061aSmrg        event->event.modifierMask |= maskBit;
769362b94d5Smrg        if (notFlag)
770362b94d5Smrg            event->event.modifiers =
771362b94d5Smrg                (event->event.modifiers & (TMLongCard) (~maskBit));
772362b94d5Smrg        else
773362b94d5Smrg            event->event.modifiers |= maskBit;
774444c061aSmrg        ScanWhitespace(str);
775444c061aSmrg    }
776362b94d5Smrg    if (exclusive)
777362b94d5Smrg        event->event.modifierMask = (unsigned long) (~0);
778444c061aSmrg    return str;
779444c061aSmrg}
780444c061aSmrg
781362b94d5Smrgstatic String
782362b94d5SmrgParseXtEventType(register String str,
783362b94d5Smrg                 EventPtr event,
784362b94d5Smrg                 Cardinal *tmEventP,
785362b94d5Smrg                 Boolean *error)
786444c061aSmrg{
787444c061aSmrg    String start = str;
788444c061aSmrg    char eventTypeStrbuf[100];
789362b94d5Smrg    char *eventTypeStr;
790444c061aSmrg
791444c061aSmrg    ScanAlphanumeric(str);
792362b94d5Smrg    eventTypeStr = XtStackAlloc((size_t) (str - start + 1), eventTypeStrbuf);
793362b94d5Smrg    if (eventTypeStr == NULL)
794362b94d5Smrg        _XtAllocError(NULL);
795362b94d5Smrg    (void) memmove(eventTypeStr, start, (size_t) (str - start));
796362b94d5Smrg    eventTypeStr[str - start] = '\0';
797362b94d5Smrg    *tmEventP = LookupTMEventType(eventTypeStr, error);
798362b94d5Smrg    XtStackFree(eventTypeStr, eventTypeStrbuf);
799444c061aSmrg    if (*error)
800444c061aSmrg        return PanicModeRecovery(str);
80172af6995Smrg    event->event.eventType = (TMLongCard) events[*tmEventP].eventType;
802444c061aSmrg    return str;
803444c061aSmrg}
804444c061aSmrg
805362b94d5Smrgstatic unsigned long
806362b94d5SmrgStrToHex(String str)
807444c061aSmrg{
808362b94d5Smrg    register char c;
809362b94d5Smrg    register unsigned long val = 0;
810444c061aSmrg
811444c061aSmrg    while ((c = *str)) {
812362b94d5Smrg        if ('0' <= c && c <= '9')
813362b94d5Smrg            val = (unsigned long) (val * 16 + (unsigned long) c - '0');
814362b94d5Smrg        else if ('a' <= c && c <= 'z')
815362b94d5Smrg            val = (unsigned long) (val * 16 + (unsigned long) c - 'a' + 10);
816362b94d5Smrg        else if ('A' <= c && c <= 'Z')
817362b94d5Smrg            val = (unsigned long) (val * 16 + (unsigned long) c - 'A' + 10);
818362b94d5Smrg        else
819362b94d5Smrg            return 0;
820362b94d5Smrg        str++;
821444c061aSmrg    }
822444c061aSmrg
823444c061aSmrg    return val;
824444c061aSmrg}
825444c061aSmrg
826362b94d5Smrgstatic unsigned long
827362b94d5SmrgStrToOct(String str)
828444c061aSmrg{
829444c061aSmrg    register char c;
830362b94d5Smrg    register unsigned long val = 0;
831444c061aSmrg
832444c061aSmrg    while ((c = *str)) {
833362b94d5Smrg        if ('0' <= c && c <= '7')
834362b94d5Smrg            val = val * 8 + (unsigned long) c - '0';
835362b94d5Smrg        else
836362b94d5Smrg            return 0;
837362b94d5Smrg        str++;
838444c061aSmrg    }
839444c061aSmrg
840444c061aSmrg    return val;
841444c061aSmrg}
842444c061aSmrg
843362b94d5Smrgstatic unsigned long
844362b94d5SmrgStrToNum(String str)
845444c061aSmrg{
846444c061aSmrg    register char c;
847444c061aSmrg    register unsigned long val = 0;
848444c061aSmrg
849444c061aSmrg    if (*str == '0') {
850362b94d5Smrg        str++;
851362b94d5Smrg        if (*str == 'x' || *str == 'X')
852362b94d5Smrg            return StrToHex(++str);
853362b94d5Smrg        else
854362b94d5Smrg            return StrToOct(str);
855444c061aSmrg    }
856444c061aSmrg
857444c061aSmrg    while ((c = *str)) {
858362b94d5Smrg        if ('0' <= c && c <= '9')
859362b94d5Smrg            val = val * 10 + (unsigned long) c - '0';
860362b94d5Smrg        else
861362b94d5Smrg            return 0;
862362b94d5Smrg        str++;
863444c061aSmrg    }
864444c061aSmrg
865444c061aSmrg    return val;
866444c061aSmrg}
867444c061aSmrg
868362b94d5Smrgstatic KeySym
869362b94d5SmrgStringToKeySym(String str, Boolean *error)
870444c061aSmrg{
871444c061aSmrg    KeySym k;
872444c061aSmrg
873362b94d5Smrg    if (str == NULL || *str == '\0')
874362b94d5Smrg        return (KeySym) 0;
875444c061aSmrg
876444c061aSmrg#ifndef NOTASCII
877444c061aSmrg    /* special case single character ASCII, for speed */
878362b94d5Smrg    if (*(str + 1) == '\0') {
879362b94d5Smrg        if (' ' <= *str && *str <= '~')
880362b94d5Smrg            return (KeySym) (XK_space + (*str - ' '));
881444c061aSmrg    }
882444c061aSmrg#endif
883444c061aSmrg
884362b94d5Smrg    if ('0' <= *str && *str <= '9')
885362b94d5Smrg        return (KeySym) StrToNum(str);
886444c061aSmrg    k = XStringToKeysym(str);
887362b94d5Smrg    if (k != NoSymbol)
888362b94d5Smrg        return k;
889444c061aSmrg
890444c061aSmrg#ifdef NOTASCII
891444c061aSmrg    /* fall-back case to preserve backwards compatibility; no-one
892444c061aSmrg     * should be relying upon this!
893444c061aSmrg     */
894362b94d5Smrg    if (*(str + 1) == '\0')
895362b94d5Smrg        return (KeySym) * str;
896444c061aSmrg#endif
897444c061aSmrg
898444c061aSmrg    Syntax("Unknown keysym name: ", str);
899444c061aSmrg    *error = TRUE;
900444c061aSmrg    return NoSymbol;
901444c061aSmrg}
902362b94d5Smrg
903362b94d5Smrgstatic void
904362b94d5SmrgParseModImmed(Value value,
905362b94d5Smrg              LateBindingsPtr *lateBindings _X_UNUSED,
906362b94d5Smrg              Boolean notFlag _X_UNUSED,
907362b94d5Smrg              Value *valueP)
908444c061aSmrg{
909444c061aSmrg    *valueP = value;
910444c061aSmrg}
911444c061aSmrg
912362b94d5Smrg/* is only valid with keysyms that have an _L and _R in their name;
913362b94d5Smrg * and ignores keysym lookup errors (i.e. assumes only valid keysyms)
914362b94d5Smrg */
915362b94d5Smrgstatic void
916362b94d5SmrgParseModSym(Value value,
917362b94d5Smrg            LateBindingsPtr *lateBindings, Boolean notFlag, Value *valueP)
918444c061aSmrg{
919362b94d5Smrg    register KeySym keysymL = (KeySym) value;
920362b94d5Smrg    register KeySym keysymR = keysymL + 1;      /* valid for supported keysyms */
921362b94d5Smrg
922362b94d5Smrg    StoreLateBindings(keysymL, notFlag, keysymR, notFlag, lateBindings);
923444c061aSmrg    *valueP = 0;
924444c061aSmrg}
925444c061aSmrg
926444c061aSmrg#ifdef sparc
927444c061aSmrg/*
928444c061aSmrg * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that
929444c061aSmrg * causes the value of the most recently used variable to be returned instead
930444c061aSmrg * of the value passed in.
931444c061aSmrg */
932444c061aSmrgstatic String stupid_optimizer_kludge;
933362b94d5Smrg
934444c061aSmrg#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val)
935444c061aSmrg#else
936444c061aSmrg#define BROKEN_OPTIMIZER_HACK(val) val
937444c061aSmrg#endif
938444c061aSmrg
939362b94d5Smrgstatic String
940362b94d5SmrgParseImmed(register String str,
941362b94d5Smrg           register Opaque closure,
942362b94d5Smrg           register EventPtr event,
943362b94d5Smrg           Boolean *error _X_UNUSED)
944444c061aSmrg{
945362b94d5Smrg    event->event.eventCode = (unsigned long) closure;
94672af6995Smrg    event->event.eventCodeMask = (unsigned long) (~0UL);
947444c061aSmrg
948444c061aSmrg    return BROKEN_OPTIMIZER_HACK(str);
949444c061aSmrg}
950444c061aSmrg
951362b94d5Smrgstatic String
952362b94d5SmrgParseAddModifier(register String str,
953362b94d5Smrg                 register Opaque closure,
954362b94d5Smrg                 register EventPtr event,
955362b94d5Smrg                 Boolean *error _X_UNUSED)
956444c061aSmrg{
957362b94d5Smrg    register unsigned long modval = (unsigned long) closure;
958362b94d5Smrg
959444c061aSmrg    event->event.modifiers |= modval;
960362b94d5Smrg    if (modval != AnyButtonMask)        /* AnyButtonMask is don't-care mask */
961362b94d5Smrg        event->event.modifierMask |= modval;
962444c061aSmrg
963444c061aSmrg    return BROKEN_OPTIMIZER_HACK(str);
964444c061aSmrg}
965444c061aSmrg
966362b94d5Smrgstatic String
967362b94d5SmrgParseKeyAndModifiers(String str,
968362b94d5Smrg                     Opaque closure,
969362b94d5Smrg                     EventPtr event,
970362b94d5Smrg                     Boolean *error)
971444c061aSmrg{
972362b94d5Smrg    str = ParseKeySym(str, closure, event, error);
973444c061aSmrg    if ((unsigned long) closure == 0) {
974362b94d5Smrg        Value metaMask;         /* unused */
975362b94d5Smrg
976362b94d5Smrg        (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
977362b94d5Smrg                                 &metaMask, FALSE);
978362b94d5Smrg    }
979362b94d5Smrg    else {
980362b94d5Smrg        event->event.modifiers |= (unsigned long) closure;
981362b94d5Smrg        event->event.modifierMask |= (unsigned long) closure;
982444c061aSmrg    }
983444c061aSmrg    return str;
984444c061aSmrg}
985444c061aSmrg
986362b94d5Smrgstatic String
987362b94d5SmrgParseKeySym(register String str,
988362b94d5Smrg            Opaque closure _X_UNUSED,
989362b94d5Smrg            EventPtr event,
990362b94d5Smrg            Boolean *error)
991444c061aSmrg{
99272af6995Smrg    String start;
993444c061aSmrg    char keySymNamebuf[100];
994362b94d5Smrg    char *keySymName = NULL;
995444c061aSmrg
996444c061aSmrg    ScanWhitespace(str);
997444c061aSmrg
998444c061aSmrg    if (*str == '\\') {
999362b94d5Smrg        keySymName = keySymNamebuf;
1000362b94d5Smrg        str++;
1001362b94d5Smrg        keySymName[0] = *str;
1002362b94d5Smrg        if (*str != '\0' && !IsNewline(*str))
1003362b94d5Smrg            str++;
1004362b94d5Smrg        keySymName[1] = '\0';
1005362b94d5Smrg        event->event.eventCode = StringToKeySym(keySymName, error);
1006362b94d5Smrg        event->event.eventCodeMask = (unsigned long) (~0L);
1007362b94d5Smrg    }
1008362b94d5Smrg    else if (*str == ',' || *str == ':' ||
1009444c061aSmrg             /* allow leftparen to be single char symbol,
1010444c061aSmrg              * for backwards compatibility
1011444c061aSmrg              */
1012362b94d5Smrg             (*str == '(' && *(str + 1) >= '0' && *(str + 1) <= '9')) {
1013362b94d5Smrg        keySymName = keySymNamebuf;     /* just so we can stackfree it later */
1014362b94d5Smrg        /* no detail */
1015362b94d5Smrg        event->event.eventCode = 0L;
1016444c061aSmrg        event->event.eventCodeMask = 0L;
1017362b94d5Smrg    }
1018362b94d5Smrg    else {
1019362b94d5Smrg        start = str;
1020362b94d5Smrg        while (*str != ','
1021362b94d5Smrg               && *str != ':' && *str != ' ' && *str != '\t' && !IsNewline(*str)
1022362b94d5Smrg               && (*str != '(' || *(str + 1) <= '0' || *(str + 1) >= '9')
1023362b94d5Smrg               && *str != '\0')
1024362b94d5Smrg            str++;
1025362b94d5Smrg        keySymName = XtStackAlloc((size_t) (str - start + 1), keySymNamebuf);
1026362b94d5Smrg        (void) memmove(keySymName, start, (size_t) (str - start));
1027362b94d5Smrg        keySymName[str - start] = '\0';
1028362b94d5Smrg        event->event.eventCode = StringToKeySym(keySymName, error);
1029362b94d5Smrg        event->event.eventCodeMask = (unsigned long) (~0L);
1030444c061aSmrg    }
103172af6995Smrg    if (*error && keySymName) {
1032362b94d5Smrg        /* We never get here when keySymName hasn't been allocated */
1033362b94d5Smrg        if (keySymName[0] == '<') {
1034362b94d5Smrg            /* special case for common error */
1035362b94d5Smrg            XtWarningMsg(XtNtranslationParseError, "missingComma",
1036362b94d5Smrg                         XtCXtToolkitError,
1037362b94d5Smrg                         "... possibly due to missing ',' in event sequence.",
1038362b94d5Smrg                         (String *) NULL, (Cardinal *) NULL);
1039362b94d5Smrg        }
1040362b94d5Smrg        XtStackFree(keySymName, keySymNamebuf);
1041362b94d5Smrg        return PanicModeRecovery(str);
1042444c061aSmrg    }
1043444c061aSmrg    if (event->event.standard)
1044362b94d5Smrg        event->event.matchEvent = _XtMatchUsingStandardMods;
1045444c061aSmrg    else
1046362b94d5Smrg        event->event.matchEvent = _XtMatchUsingDontCareMods;
1047444c061aSmrg
1048362b94d5Smrg    XtStackFree(keySymName, keySymNamebuf);
1049444c061aSmrg
1050444c061aSmrg    return str;
1051444c061aSmrg}
1052444c061aSmrg
1053362b94d5Smrgstatic String
1054362b94d5SmrgParseTable(register String str, Opaque closure, EventPtr event, Boolean *error)
1055444c061aSmrg{
1056444c061aSmrg    register String start = str;
1057444c061aSmrg    register XrmQuark signature;
1058444c061aSmrg    NameValueTable table = (NameValueTable) closure;
1059444c061aSmrg    char tableSymName[100];
1060444c061aSmrg
1061444c061aSmrg    event->event.eventCode = 0L;
1062444c061aSmrg    ScanAlphanumeric(str);
1063362b94d5Smrg    if (str == start) {
1064362b94d5Smrg        event->event.eventCodeMask = 0L;
1065362b94d5Smrg        return str;
1066362b94d5Smrg    }
1067362b94d5Smrg    if (str - start >= 99) {
1068362b94d5Smrg        Syntax("Invalid Detail Type (string is too long).", "");
1069362b94d5Smrg        *error = TRUE;
1070362b94d5Smrg        return str;
1071362b94d5Smrg    }
1072362b94d5Smrg    (void) memmove(tableSymName, start, (size_t) (str - start));
1073362b94d5Smrg    tableSymName[str - start] = '\0';
1074444c061aSmrg    signature = StringToQuark(tableSymName);
1075444c061aSmrg    for (; table->signature != NULLQUARK; table++)
1076362b94d5Smrg        if (table->signature == signature) {
1077362b94d5Smrg            event->event.eventCode = table->value;
1078362b94d5Smrg            event->event.eventCodeMask = (unsigned long) (~0L);
1079362b94d5Smrg            return str;
1080362b94d5Smrg        }
1081444c061aSmrg
1082444c061aSmrg    Syntax("Unknown Detail Type:  ", tableSymName);
1083444c061aSmrg    *error = TRUE;
1084444c061aSmrg    return PanicModeRecovery(str);
1085444c061aSmrg}
1086444c061aSmrg
1087362b94d5Smrgstatic String
1088362b94d5SmrgParseNone(String str,
1089362b94d5Smrg          Opaque closure _X_UNUSED,
1090362b94d5Smrg          EventPtr event,
1091362b94d5Smrg          Boolean *error _X_UNUSED)
1092444c061aSmrg{
1093444c061aSmrg    event->event.eventCode = 0;
1094444c061aSmrg    event->event.eventCodeMask = 0;
1095444c061aSmrg
1096444c061aSmrg    return BROKEN_OPTIMIZER_HACK(str);
1097444c061aSmrg}
1098444c061aSmrg
1099362b94d5Smrgstatic String
1100362b94d5SmrgParseAtom(String str, Opaque closure _X_UNUSED, EventPtr event, Boolean *error)
1101444c061aSmrg{
1102444c061aSmrg    ScanWhitespace(str);
1103444c061aSmrg
1104444c061aSmrg    if (*str == ',' || *str == ':') {
1105362b94d5Smrg        /* no detail */
1106362b94d5Smrg        event->event.eventCode = 0L;
1107444c061aSmrg        event->event.eventCodeMask = 0L;
1108362b94d5Smrg    }
1109362b94d5Smrg    else {
1110362b94d5Smrg        String start;
1111362b94d5Smrg        char atomName[1000];
1112362b94d5Smrg
1113362b94d5Smrg        start = str;
1114362b94d5Smrg        while (*str != ','
1115362b94d5Smrg               && *str != ':' && *str != ' ' && *str != '\t' && !IsNewline(*str)
1116362b94d5Smrg               && *str != '\0')
1117362b94d5Smrg            str++;
1118362b94d5Smrg        if (str - start >= 999) {
1119362b94d5Smrg            Syntax("Atom name must be less than 1000 characters long.", "");
1120362b94d5Smrg            *error = TRUE;
1121362b94d5Smrg            return str;
1122362b94d5Smrg        }
1123362b94d5Smrg        (void) memmove(atomName, start, (size_t) (str - start));
1124362b94d5Smrg        atomName[str - start] = '\0';
1125362b94d5Smrg        event->event.eventCode = (TMLongCard) XrmStringToQuark(atomName);
1126362b94d5Smrg        event->event.matchEvent = _XtMatchAtom;
1127444c061aSmrg    }
1128444c061aSmrg    return str;
1129444c061aSmrg}
1130444c061aSmrg
1131444c061aSmrgstatic ModifierMask buttonModifierMasks[] = {
1132444c061aSmrg    0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
1133444c061aSmrg};
1134362b94d5Smrg
1135444c061aSmrgstatic String ParseRepeat(String, int *, Boolean *, Boolean *);
1136444c061aSmrg
1137362b94d5Smrgstatic String
1138362b94d5SmrgParseEvent(register String str,
1139362b94d5Smrg           EventPtr event, int *reps,
1140362b94d5Smrg           Boolean *plus,
1141362b94d5Smrg           Boolean *error)
1142444c061aSmrg{
1143362b94d5Smrg    Cardinal tmEvent;
1144444c061aSmrg
1145362b94d5Smrg    str = ParseModifiers(str, event, error);
1146362b94d5Smrg    if (*error)
1147362b94d5Smrg        return str;
1148444c061aSmrg    if (*str != '<') {
1149362b94d5Smrg        Syntax("Missing '<' while parsing event type.", "");
1150362b94d5Smrg        *error = TRUE;
1151362b94d5Smrg        return PanicModeRecovery(str);
1152362b94d5Smrg    }
1153362b94d5Smrg    else
1154362b94d5Smrg        str++;
1155362b94d5Smrg    str = ParseXtEventType(str, event, &tmEvent, error);
1156362b94d5Smrg    if (*error)
1157362b94d5Smrg        return str;
1158362b94d5Smrg    if (*str != '>') {
1159362b94d5Smrg        Syntax("Missing '>' while parsing event type", "");
1160362b94d5Smrg        *error = TRUE;
1161362b94d5Smrg        return PanicModeRecovery(str);
1162362b94d5Smrg    }
1163362b94d5Smrg    else
1164362b94d5Smrg        str++;
1165444c061aSmrg    if (*str == '(') {
1166362b94d5Smrg        str = ParseRepeat(str, reps, plus, error);
1167362b94d5Smrg        if (*error)
1168362b94d5Smrg            return str;
1169444c061aSmrg    }
1170362b94d5Smrg    str =
1171362b94d5Smrg        (*(events[tmEvent].parseDetail)) (str, events[tmEvent].closure, event,
1172362b94d5Smrg                                          error);
1173362b94d5Smrg    if (*error)
1174362b94d5Smrg        return str;
1175444c061aSmrg
1176444c061aSmrg/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t.
1177444c061aSmrg * modifiers in grabs.
1178444c061aSmrg */
1179444c061aSmrg    if ((event->event.eventType == ButtonRelease)
1180362b94d5Smrg        && (event->event.modifiers | event->event.modifierMask) /* any */
1181362b94d5Smrg        &&(event->event.modifiers != AnyModifier)) {
1182362b94d5Smrg        event->event.modifiers = (event->event.modifiers
1183362b94d5Smrg                                  | (TMLongCard) buttonModifierMasks[event->
1184362b94d5Smrg                                                                     event.
1185362b94d5Smrg                                                                     eventCode]);
1186362b94d5Smrg        /* the button that is going up will always be in the modifiers... */
1187444c061aSmrg    }
1188444c061aSmrg
1189444c061aSmrg    return str;
1190444c061aSmrg}
1191444c061aSmrg
1192362b94d5Smrgstatic String
1193362b94d5SmrgParseQuotedStringEvent(register String str,
1194362b94d5Smrg                       register EventPtr event,
1195362b94d5Smrg                       Boolean *error)
1196444c061aSmrg{
1197444c061aSmrg    Value metaMask;
1198362b94d5Smrg    char s[2];
1199444c061aSmrg
1200362b94d5Smrg    if (*str == '^') {
1201362b94d5Smrg        str++;
1202362b94d5Smrg        event->event.modifiers = ControlMask;
1203362b94d5Smrg    }
1204362b94d5Smrg    else if (*str == '$') {
1205362b94d5Smrg        str++;
1206362b94d5Smrg        (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
1207362b94d5Smrg                                 &metaMask, FALSE);
1208444c061aSmrg    }
1209444c061aSmrg    if (*str == '\\')
1210362b94d5Smrg        str++;
1211444c061aSmrg    s[0] = *str;
1212444c061aSmrg    s[1] = '\0';
1213362b94d5Smrg    if (*str != '\0' && !IsNewline(*str))
1214362b94d5Smrg        str++;
1215444c061aSmrg    event->event.eventType = KeyPress;
1216444c061aSmrg    event->event.eventCode = StringToKeySym(s, error);
1217362b94d5Smrg    if (*error)
1218362b94d5Smrg        return PanicModeRecovery(str);
121972af6995Smrg    event->event.eventCodeMask = (unsigned long) (~0L);
1220444c061aSmrg    event->event.matchEvent = _XtMatchUsingStandardMods;
1221444c061aSmrg    event->event.standard = TRUE;
1222444c061aSmrg
1223444c061aSmrg    return str;
1224444c061aSmrg}
1225444c061aSmrg
1226444c061aSmrgstatic EventSeqRec timerEventRec = {
1227444c061aSmrg    {0, 0, NULL, _XtEventTimerEventType, 0L, 0L, NULL, False},
1228444c061aSmrg    /* (StatePtr) -1 */ NULL,
1229444c061aSmrg    NULL,
1230444c061aSmrg    NULL
1231444c061aSmrg};
1232444c061aSmrg
1233362b94d5Smrgstatic void
1234362b94d5SmrgRepeatDown(EventPtr *eventP, int reps, ActionPtr **actionsP)
1235444c061aSmrg{
1236444c061aSmrg    EventRec upEventRec;
1237444c061aSmrg    register EventPtr event, downEvent;
1238444c061aSmrg    EventPtr upEvent = &upEventRec;
1239444c061aSmrg    register int i;
1240444c061aSmrg
1241444c061aSmrg    downEvent = event = *eventP;
1242444c061aSmrg    *upEvent = *downEvent;
1243444c061aSmrg    upEvent->event.eventType = ((event->event.eventType == ButtonPress) ?
1244362b94d5Smrg                                ButtonRelease : KeyRelease);
1245444c061aSmrg    if ((upEvent->event.eventType == ButtonRelease)
1246362b94d5Smrg        && (upEvent->event.modifiers != AnyModifier)
1247444c061aSmrg        && (upEvent->event.modifiers | upEvent->event.modifierMask))
1248362b94d5Smrg        upEvent->event.modifiers = (upEvent->event.modifiers
1249362b94d5Smrg                                    | (TMLongCard) buttonModifierMasks[event->
1250362b94d5Smrg                                                                       event.
1251362b94d5Smrg                                                                       eventCode]);
1252444c061aSmrg
1253444c061aSmrg    if (event->event.lateModifiers)
1254362b94d5Smrg        event->event.lateModifiers->ref_count =
1255362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count +
1256362b94d5Smrg                              (reps - 1) * 2);
1257444c061aSmrg
1258362b94d5Smrg    for (i = 1; i < reps; i++) {
1259444c061aSmrg
1260362b94d5Smrg        /* up */
1261362b94d5Smrg        event->next = XtNew(EventSeqRec);
1262362b94d5Smrg        event = event->next;
1263362b94d5Smrg        *event = *upEvent;
1264444c061aSmrg
1265362b94d5Smrg        /* timer */
1266362b94d5Smrg        event->next = XtNew(EventSeqRec);
1267362b94d5Smrg        event = event->next;
1268362b94d5Smrg        *event = timerEventRec;
1269444c061aSmrg
1270362b94d5Smrg        /* down */
1271362b94d5Smrg        event->next = XtNew(EventSeqRec);
1272362b94d5Smrg        event = event->next;
1273362b94d5Smrg        *event = *downEvent;
1274444c061aSmrg
1275444c061aSmrg    }
1276444c061aSmrg
1277444c061aSmrg    event->next = NULL;
1278444c061aSmrg    *eventP = event;
1279444c061aSmrg    *actionsP = &event->actions;
1280444c061aSmrg}
1281444c061aSmrg
1282362b94d5Smrgstatic void
1283362b94d5SmrgRepeatDownPlus(EventPtr *eventP, int reps, ActionPtr **actionsP)
1284444c061aSmrg{
1285444c061aSmrg    EventRec upEventRec;
1286444c061aSmrg    register EventPtr event, downEvent, lastDownEvent = NULL;
1287444c061aSmrg    EventPtr upEvent = &upEventRec;
1288444c061aSmrg    register int i;
1289444c061aSmrg
1290444c061aSmrg    downEvent = event = *eventP;
1291444c061aSmrg    *upEvent = *downEvent;
1292444c061aSmrg    upEvent->event.eventType = ((event->event.eventType == ButtonPress) ?
1293362b94d5Smrg                                ButtonRelease : KeyRelease);
1294444c061aSmrg    if ((upEvent->event.eventType == ButtonRelease)
1295362b94d5Smrg        && (upEvent->event.modifiers != AnyModifier)
1296444c061aSmrg        && (upEvent->event.modifiers | upEvent->event.modifierMask))
1297362b94d5Smrg        upEvent->event.modifiers = (upEvent->event.modifiers
1298362b94d5Smrg                                    | (TMLongCard) buttonModifierMasks[event->
1299362b94d5Smrg                                                                       event.
1300362b94d5Smrg                                                                       eventCode]);
1301444c061aSmrg
1302444c061aSmrg    if (event->event.lateModifiers)
1303362b94d5Smrg        event->event.lateModifiers->ref_count =
1304362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps * 2 -
1305362b94d5Smrg                              1);
1306444c061aSmrg
1307362b94d5Smrg    for (i = 0; i < reps; i++) {
1308444c061aSmrg
1309362b94d5Smrg        if (i > 0) {
1310362b94d5Smrg            /* down */
1311362b94d5Smrg            event->next = XtNew(EventSeqRec);
1312362b94d5Smrg            event = event->next;
1313362b94d5Smrg            *event = *downEvent;
1314362b94d5Smrg        }
1315362b94d5Smrg        lastDownEvent = event;
1316444c061aSmrg
1317362b94d5Smrg        /* up */
1318362b94d5Smrg        event->next = XtNew(EventSeqRec);
1319362b94d5Smrg        event = event->next;
1320362b94d5Smrg        *event = *upEvent;
1321444c061aSmrg
1322362b94d5Smrg        /* timer */
1323362b94d5Smrg        event->next = XtNew(EventSeqRec);
1324362b94d5Smrg        event = event->next;
1325362b94d5Smrg        *event = timerEventRec;
1326444c061aSmrg
1327444c061aSmrg    }
1328444c061aSmrg
1329444c061aSmrg    event->next = lastDownEvent;
1330444c061aSmrg    *eventP = event;
1331444c061aSmrg    *actionsP = &lastDownEvent->actions;
1332444c061aSmrg}
1333444c061aSmrg
1334362b94d5Smrgstatic void
1335362b94d5SmrgRepeatUp(EventPtr *eventP, int reps, ActionPtr **actionsP)
1336444c061aSmrg{
1337444c061aSmrg    EventRec upEventRec;
1338444c061aSmrg    register EventPtr event, downEvent;
1339444c061aSmrg    EventPtr upEvent = &upEventRec;
1340444c061aSmrg    register int i;
1341444c061aSmrg
1342444c061aSmrg    /* the event currently sitting in *eventP is an "up" event */
1343444c061aSmrg    /* we want to make it a "down" event followed by an "up" event, */
1344444c061aSmrg    /* so that sequence matching on the "state" side works correctly. */
1345444c061aSmrg
1346444c061aSmrg    downEvent = event = *eventP;
1347444c061aSmrg    *upEvent = *downEvent;
1348444c061aSmrg    downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ?
1349362b94d5Smrg                                  ButtonPress : KeyPress);
1350444c061aSmrg    if ((downEvent->event.eventType == ButtonPress)
1351362b94d5Smrg        && (downEvent->event.modifiers != AnyModifier)
1352444c061aSmrg        && (downEvent->event.modifiers | downEvent->event.modifierMask))
1353362b94d5Smrg        downEvent->event.modifiers = (downEvent->event.modifiers
1354362b94d5Smrg                                      &
1355362b94d5Smrg                                      (TMLongCard) (~buttonModifierMasks
1356362b94d5Smrg                                                    [event->event.eventCode]));
1357444c061aSmrg
1358444c061aSmrg    if (event->event.lateModifiers)
1359362b94d5Smrg        event->event.lateModifiers->ref_count =
1360362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps * 2 -
1361362b94d5Smrg                              1);
1362444c061aSmrg
1363444c061aSmrg    /* up */
1364444c061aSmrg    event->next = XtNew(EventSeqRec);
1365444c061aSmrg    event = event->next;
1366444c061aSmrg    *event = *upEvent;
1367444c061aSmrg
1368362b94d5Smrg    for (i = 1; i < reps; i++) {
1369444c061aSmrg
1370362b94d5Smrg        /* timer */
1371362b94d5Smrg        event->next = XtNew(EventSeqRec);
1372362b94d5Smrg        event = event->next;
1373362b94d5Smrg        *event = timerEventRec;
1374444c061aSmrg
1375362b94d5Smrg        /* down */
1376362b94d5Smrg        event->next = XtNew(EventSeqRec);
1377362b94d5Smrg        event = event->next;
1378362b94d5Smrg        *event = *downEvent;
1379444c061aSmrg
1380362b94d5Smrg        /* up */
1381362b94d5Smrg        event->next = XtNew(EventSeqRec);
1382362b94d5Smrg        event = event->next;
1383362b94d5Smrg        *event = *upEvent;
1384444c061aSmrg
1385362b94d5Smrg    }
1386444c061aSmrg
1387444c061aSmrg    event->next = NULL;
1388444c061aSmrg    *eventP = event;
1389444c061aSmrg    *actionsP = &event->actions;
1390444c061aSmrg}
1391444c061aSmrg
1392362b94d5Smrgstatic void
1393362b94d5SmrgRepeatUpPlus(EventPtr *eventP, int reps, ActionPtr **actionsP)
1394444c061aSmrg{
1395444c061aSmrg    EventRec upEventRec;
1396444c061aSmrg    register EventPtr event, downEvent, lastUpEvent = NULL;
1397444c061aSmrg    EventPtr upEvent = &upEventRec;
1398444c061aSmrg    register int i;
1399444c061aSmrg
1400444c061aSmrg    /* the event currently sitting in *eventP is an "up" event */
1401444c061aSmrg    /* we want to make it a "down" event followed by an "up" event, */
1402444c061aSmrg    /* so that sequence matching on the "state" side works correctly. */
1403444c061aSmrg
1404444c061aSmrg    downEvent = event = *eventP;
1405444c061aSmrg    *upEvent = *downEvent;
1406444c061aSmrg    downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ?
1407362b94d5Smrg                                  ButtonPress : KeyPress);
1408444c061aSmrg    if ((downEvent->event.eventType == ButtonPress)
1409362b94d5Smrg        && (downEvent->event.modifiers != AnyModifier)
1410444c061aSmrg        && (downEvent->event.modifiers | downEvent->event.modifierMask))
1411362b94d5Smrg        downEvent->event.modifiers = (downEvent->event.modifiers
1412362b94d5Smrg                                      &
1413362b94d5Smrg                                      (TMLongCard) (~buttonModifierMasks
1414362b94d5Smrg                                                    [event->event.eventCode]));
1415444c061aSmrg
1416444c061aSmrg    if (event->event.lateModifiers)
1417362b94d5Smrg        event->event.lateModifiers->ref_count =
1418362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps * 2);
1419444c061aSmrg
1420362b94d5Smrg    for (i = 0; i < reps; i++) {
1421444c061aSmrg
1422362b94d5Smrg        /* up */
1423362b94d5Smrg        event->next = XtNew(EventSeqRec);
1424362b94d5Smrg        lastUpEvent = event = event->next;
1425362b94d5Smrg        *event = *upEvent;
1426444c061aSmrg
1427362b94d5Smrg        /* timer */
1428362b94d5Smrg        event->next = XtNew(EventSeqRec);
1429362b94d5Smrg        event = event->next;
1430362b94d5Smrg        *event = timerEventRec;
1431444c061aSmrg
1432362b94d5Smrg        /* down */
1433362b94d5Smrg        event->next = XtNew(EventSeqRec);
1434444c061aSmrg        event = event->next;
1435362b94d5Smrg        *event = *downEvent;
1436444c061aSmrg
1437362b94d5Smrg    }
1438444c061aSmrg
1439444c061aSmrg    event->next = lastUpEvent;
1440444c061aSmrg    *eventP = event;
1441444c061aSmrg    *actionsP = &lastUpEvent->actions;
1442444c061aSmrg}
1443444c061aSmrg
1444362b94d5Smrgstatic void
1445362b94d5SmrgRepeatOther(EventPtr *eventP, int reps, ActionPtr **actionsP)
1446444c061aSmrg{
1447444c061aSmrg    register EventPtr event, tempEvent;
1448444c061aSmrg    register int i;
1449444c061aSmrg
1450444c061aSmrg    tempEvent = event = *eventP;
1451444c061aSmrg
1452444c061aSmrg    if (event->event.lateModifiers)
1453362b94d5Smrg        event->event.lateModifiers->ref_count =
1454362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps - 1);
1455444c061aSmrg
1456362b94d5Smrg    for (i = 1; i < reps; i++) {
1457362b94d5Smrg        event->next = XtNew(EventSeqRec);
1458362b94d5Smrg        event = event->next;
1459362b94d5Smrg        *event = *tempEvent;
1460444c061aSmrg    }
1461444c061aSmrg
1462444c061aSmrg    *eventP = event;
1463444c061aSmrg    *actionsP = &event->actions;
1464444c061aSmrg}
1465444c061aSmrg
1466362b94d5Smrgstatic void
1467362b94d5SmrgRepeatOtherPlus(EventPtr *eventP, int reps, ActionPtr **actionsP)
1468444c061aSmrg{
1469444c061aSmrg    register EventPtr event, tempEvent;
1470444c061aSmrg    register int i;
1471444c061aSmrg
1472444c061aSmrg    tempEvent = event = *eventP;
1473444c061aSmrg
1474444c061aSmrg    if (event->event.lateModifiers)
1475362b94d5Smrg        event->event.lateModifiers->ref_count =
1476362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps - 1);
1477444c061aSmrg
1478362b94d5Smrg    for (i = 1; i < reps; i++) {
1479362b94d5Smrg        event->next = XtNew(EventSeqRec);
1480362b94d5Smrg        event = event->next;
1481362b94d5Smrg        *event = *tempEvent;
1482444c061aSmrg    }
1483444c061aSmrg
1484444c061aSmrg    event->next = event;
1485444c061aSmrg    *eventP = event;
1486444c061aSmrg    *actionsP = &event->actions;
1487444c061aSmrg}
1488444c061aSmrg
1489362b94d5Smrgstatic void
1490362b94d5SmrgRepeatEvent(EventPtr *eventP, int reps, Boolean plus, ActionPtr **actionsP)
1491444c061aSmrg{
1492444c061aSmrg    switch ((*eventP)->event.eventType) {
1493444c061aSmrg
1494362b94d5Smrg    case ButtonPress:
1495362b94d5Smrg    case KeyPress:
1496362b94d5Smrg        if (plus)
1497362b94d5Smrg            RepeatDownPlus(eventP, reps, actionsP);
1498362b94d5Smrg        else
1499362b94d5Smrg            RepeatDown(eventP, reps, actionsP);
1500362b94d5Smrg        break;
1501362b94d5Smrg
1502362b94d5Smrg    case ButtonRelease:
1503362b94d5Smrg    case KeyRelease:
1504362b94d5Smrg        if (plus)
1505362b94d5Smrg            RepeatUpPlus(eventP, reps, actionsP);
1506362b94d5Smrg        else
1507362b94d5Smrg            RepeatUp(eventP, reps, actionsP);
1508362b94d5Smrg        break;
1509362b94d5Smrg
1510362b94d5Smrg    default:
1511362b94d5Smrg        if (plus)
1512362b94d5Smrg            RepeatOtherPlus(eventP, reps, actionsP);
1513362b94d5Smrg        else
1514362b94d5Smrg            RepeatOther(eventP, reps, actionsP);
1515444c061aSmrg    }
1516444c061aSmrg}
1517444c061aSmrg
1518362b94d5Smrgstatic String
1519362b94d5SmrgParseRepeat(register String str, int *reps, Boolean *plus, Boolean *error)
1520444c061aSmrg{
1521444c061aSmrg
1522444c061aSmrg    /*** Parse the repetitions, for double click etc... ***/
1523362b94d5Smrg    if (*str != '(' ||
1524362b94d5Smrg        !(isdigit((unsigned char) str[1]) || str[1] == '+' || str[1] == ')'))
1525362b94d5Smrg        return str;
1526444c061aSmrg    str++;
1527362b94d5Smrg    if (isdigit((unsigned char) *str)) {
1528362b94d5Smrg        String start = str;
1529362b94d5Smrg        char repStr[7];
1530362b94d5Smrg        size_t len;
1531362b94d5Smrg
1532362b94d5Smrg        ScanNumeric(str);
1533362b94d5Smrg        len = (size_t) (str - start);
1534362b94d5Smrg        if (len < sizeof repStr) {
1535362b94d5Smrg            (void) memmove(repStr, start, len);
1536362b94d5Smrg            repStr[len] = '\0';
1537362b94d5Smrg            *reps = (int) StrToNum(repStr);
1538362b94d5Smrg        }
1539362b94d5Smrg        else {
1540362b94d5Smrg            Syntax("Repeat count too large.", "");
1541362b94d5Smrg            *error = TRUE;
1542362b94d5Smrg            return str;
1543362b94d5Smrg        }
1544444c061aSmrg    }
1545444c061aSmrg    if (*reps == 0) {
1546362b94d5Smrg        Syntax("Missing repeat count.", "");
1547362b94d5Smrg        *error = True;
1548362b94d5Smrg        return str;
1549444c061aSmrg    }
1550444c061aSmrg
1551444c061aSmrg    if (*str == '+') {
1552362b94d5Smrg        *plus = TRUE;
1553362b94d5Smrg        str++;
1554444c061aSmrg    }
1555444c061aSmrg    if (*str == ')')
1556362b94d5Smrg        str++;
1557444c061aSmrg    else {
1558362b94d5Smrg        Syntax("Missing ')'.", "");
1559362b94d5Smrg        *error = TRUE;
1560444c061aSmrg    }
1561444c061aSmrg
1562444c061aSmrg    return str;
1563444c061aSmrg}
1564444c061aSmrg
1565444c061aSmrg/***********************************************************************
1566444c061aSmrg * ParseEventSeq
1567444c061aSmrg * Parses the left hand side of a translation table production
1568444c061aSmrg * up to, and consuming the ":".
1569444c061aSmrg * Takes a pointer to a char* (where to start parsing) and returns an
1570444c061aSmrg * event seq (in a passed in variable), having updated the String
1571444c061aSmrg **********************************************************************/
1572444c061aSmrg
1573362b94d5Smrgstatic String
1574362b94d5SmrgParseEventSeq(register String str,
1575362b94d5Smrg              EventSeqPtr *eventSeqP,
1576362b94d5Smrg              ActionPtr ** actionsP,
1577362b94d5Smrg              Boolean *error)
1578444c061aSmrg{
1579444c061aSmrg    EventSeqPtr *nextEvent = eventSeqP;
1580444c061aSmrg
1581444c061aSmrg    *eventSeqP = NULL;
1582444c061aSmrg
1583362b94d5Smrg    while (*str != '\0' && !IsNewline(*str)) {
1584362b94d5Smrg        static Event nullEvent =
1585362b94d5Smrg            { 0, 0, NULL, 0, 0L, 0L, _XtRegularMatch, FALSE };
1586362b94d5Smrg        EventPtr event;
1587444c061aSmrg
1588362b94d5Smrg        ScanWhitespace(str);
1589444c061aSmrg
1590362b94d5Smrg        if (*str == '"') {
1591362b94d5Smrg            str++;
1592362b94d5Smrg            while (*str != '"' && *str != '\0' && !IsNewline(*str)) {
1593444c061aSmrg                event = XtNew(EventRec);
1594444c061aSmrg                event->event = nullEvent;
1595444c061aSmrg                event->state = /* (StatePtr) -1 */ NULL;
1596444c061aSmrg                event->next = NULL;
1597444c061aSmrg                event->actions = NULL;
1598362b94d5Smrg                str = ParseQuotedStringEvent(str, event, error);
1599362b94d5Smrg                if (*error) {
1600362b94d5Smrg                    XtWarningMsg(XtNtranslationParseError, "nonLatin1",
1601362b94d5Smrg                                 XtCXtToolkitError,
1602362b94d5Smrg                                 "... probably due to non-Latin1 character in quoted string",
1603362b94d5Smrg                                 (String *) NULL, (Cardinal *) NULL);
1604362b94d5Smrg                    XtFree((char *) event);
1605362b94d5Smrg                    return PanicModeRecovery(str);
1606362b94d5Smrg                }
1607362b94d5Smrg                *nextEvent = event;
1608362b94d5Smrg                *actionsP = &event->actions;
1609362b94d5Smrg                nextEvent = &event->next;
1610362b94d5Smrg            }
1611362b94d5Smrg            if (*str != '"') {
1612362b94d5Smrg                Syntax("Missing '\"'.", "");
1613444c061aSmrg                *error = TRUE;
1614444c061aSmrg                return PanicModeRecovery(str);
1615362b94d5Smrg            }
1616362b94d5Smrg            else
1617362b94d5Smrg                str++;
1618362b94d5Smrg        }
1619362b94d5Smrg        else {
1620362b94d5Smrg            int reps = 0;
1621362b94d5Smrg            Boolean plus = FALSE;
1622444c061aSmrg
1623444c061aSmrg            event = XtNew(EventRec);
1624444c061aSmrg            event->event = nullEvent;
1625444c061aSmrg            event->state = /* (StatePtr) -1 */ NULL;
1626444c061aSmrg            event->next = NULL;
1627444c061aSmrg            event->actions = NULL;
1628444c061aSmrg
1629362b94d5Smrg            str = ParseEvent(str, event, &reps, &plus, error);
1630362b94d5Smrg            if (*error)
1631362b94d5Smrg                return str;
1632362b94d5Smrg            *nextEvent = event;
1633362b94d5Smrg            *actionsP = &event->actions;
1634362b94d5Smrg            if (reps > 1 || plus)
1635362b94d5Smrg                RepeatEvent(&event, reps, plus, actionsP);
1636362b94d5Smrg            nextEvent = &event->next;
1637362b94d5Smrg        }
1638362b94d5Smrg        ScanWhitespace(str);
1639362b94d5Smrg        if (*str == ':')
1640362b94d5Smrg            break;
1641444c061aSmrg        else {
1642444c061aSmrg            if (*str != ',') {
1643362b94d5Smrg                Syntax("',' or ':' expected while parsing event sequence.", "");
1644444c061aSmrg                *error = TRUE;
1645444c061aSmrg                return PanicModeRecovery(str);
1646362b94d5Smrg            }
1647362b94d5Smrg            else
1648362b94d5Smrg                str++;
1649444c061aSmrg        }
1650444c061aSmrg    }
1651444c061aSmrg
1652444c061aSmrg    if (*str != ':') {
1653362b94d5Smrg        Syntax("Missing ':'after event sequence.", "");
1654444c061aSmrg        *error = TRUE;
1655444c061aSmrg        return PanicModeRecovery(str);
1656362b94d5Smrg    }
1657362b94d5Smrg    else
1658362b94d5Smrg        str++;
1659444c061aSmrg
1660444c061aSmrg    return str;
1661444c061aSmrg}
1662444c061aSmrg
1663362b94d5Smrgstatic String
1664362b94d5SmrgParseActionProc(register String str, XrmQuark *actionProcNameP, Boolean *error)
1665444c061aSmrg{
1666444c061aSmrg    register String start = str;
1667444c061aSmrg    char procName[200];
1668444c061aSmrg
1669444c061aSmrg    str = ScanIdent(str);
1670362b94d5Smrg    if (str - start >= 199) {
1671362b94d5Smrg        Syntax("Action procedure name is longer than 199 chars", "");
1672362b94d5Smrg        *error = TRUE;
1673362b94d5Smrg        return str;
1674362b94d5Smrg    }
1675362b94d5Smrg    (void) memmove(procName, start, (size_t) (str - start));
1676362b94d5Smrg    procName[str - start] = '\0';
1677362b94d5Smrg    *actionProcNameP = XrmStringToQuark(procName);
1678444c061aSmrg    return str;
1679444c061aSmrg}
1680444c061aSmrg
1681362b94d5Smrgstatic String
1682362b94d5SmrgParseString(register String str, _XtString *strP)
1683444c061aSmrg{
1684444c061aSmrg    register String start;
1685444c061aSmrg
1686444c061aSmrg    if (*str == '"') {
1687362b94d5Smrg        register unsigned prev_len, len;
1688362b94d5Smrg
1689362b94d5Smrg        str++;
1690362b94d5Smrg        start = str;
1691362b94d5Smrg        *strP = NULL;
1692362b94d5Smrg        prev_len = 0;
1693362b94d5Smrg
1694362b94d5Smrg        while (*str != '"' && *str != '\0') {
1695362b94d5Smrg            /* \"  produces double quote embedded in a quoted parameter
1696362b94d5Smrg             * \\" produces backslash as last character of a quoted parameter
1697362b94d5Smrg             */
1698362b94d5Smrg            if (*str == '\\' &&
1699362b94d5Smrg                (*(str + 1) == '"' ||
1700362b94d5Smrg                 (*(str + 1) == '\\' && *(str + 2) == '"'))) {
1701362b94d5Smrg                len = (unsigned) (prev_len + (str - start + 2));
1702362b94d5Smrg                *strP = XtRealloc(*strP, len);
1703362b94d5Smrg                (void) memmove(*strP + prev_len, start, (size_t) (str - start));
1704362b94d5Smrg                prev_len = len - 1;
1705362b94d5Smrg                str++;
1706362b94d5Smrg                (*strP)[prev_len - 1] = *str;
1707362b94d5Smrg                (*strP)[prev_len] = '\0';
1708362b94d5Smrg                start = str + 1;
1709362b94d5Smrg            }
1710362b94d5Smrg            str++;
1711362b94d5Smrg        }
1712362b94d5Smrg        len = (unsigned) (prev_len + (str - start + 1));
1713362b94d5Smrg        *strP = XtRealloc(*strP, len);
1714362b94d5Smrg        (void) memmove(*strP + prev_len, start, (size_t) (str - start));
1715362b94d5Smrg        (*strP)[len - 1] = '\0';
1716362b94d5Smrg        if (*str == '"')
1717362b94d5Smrg            str++;
1718362b94d5Smrg        else
1719362b94d5Smrg            XtWarningMsg(XtNtranslationParseError, "parseString",
1720362b94d5Smrg                         XtCXtToolkitError, "Missing '\"'.",
1721362b94d5Smrg                         (String *) NULL, (Cardinal *) NULL);
1722362b94d5Smrg    }
1723362b94d5Smrg    else {
1724362b94d5Smrg        /* scan non-quoted string, stop on whitespace, ',' or ')' */
1725362b94d5Smrg        start = str;
1726362b94d5Smrg        while (*str != ' '
1727362b94d5Smrg               && *str != '\t' && *str != ',' && *str != ')' && !IsNewline(*str)
1728362b94d5Smrg               && *str != '\0')
1729362b94d5Smrg            str++;
1730362b94d5Smrg        *strP = __XtMalloc((unsigned) (str - start + 1));
1731362b94d5Smrg        (void) memmove(*strP, start, (size_t) (str - start));
1732362b94d5Smrg        (*strP)[str - start] = '\0';
1733444c061aSmrg    }
1734444c061aSmrg    return str;
1735444c061aSmrg}
1736444c061aSmrg
1737362b94d5Smrgstatic String
1738362b94d5SmrgParseParamSeq(register String str, String **paramSeqP, Cardinal *paramNumP)
1739444c061aSmrg{
1740444c061aSmrg    typedef struct _ParamRec *ParamPtr;
1741444c061aSmrg    typedef struct _ParamRec {
1742362b94d5Smrg        ParamPtr next;
1743362b94d5Smrg        String param;
1744444c061aSmrg    } ParamRec;
1745444c061aSmrg
1746444c061aSmrg    ParamPtr params = NULL;
174772af6995Smrg    Cardinal num_params = 0;
1748444c061aSmrg
1749444c061aSmrg    ScanWhitespace(str);
1750444c061aSmrg    while (*str != ')' && *str != '\0' && !IsNewline(*str)) {
1751362b94d5Smrg        _XtString newStr;
1752362b94d5Smrg
1753362b94d5Smrg        str = ParseString(str, &newStr);
1754362b94d5Smrg        if (newStr != NULL) {
1755362b94d5Smrg            ParamPtr temp = (ParamRec *)
1756362b94d5Smrg                ALLOCATE_LOCAL((unsigned) sizeof(ParamRec));
1757362b94d5Smrg
1758362b94d5Smrg            if (temp == NULL)
1759362b94d5Smrg                _XtAllocError(NULL);
1760362b94d5Smrg
1761362b94d5Smrg            num_params++;
1762362b94d5Smrg            temp->next = params;
1763362b94d5Smrg            params = temp;
1764362b94d5Smrg            temp->param = newStr;
1765362b94d5Smrg            ScanWhitespace(str);
1766362b94d5Smrg            if (*str == ',') {
1767362b94d5Smrg                str++;
1768362b94d5Smrg                ScanWhitespace(str);
1769362b94d5Smrg            }
1770362b94d5Smrg        }
1771444c061aSmrg    }
1772444c061aSmrg
1773444c061aSmrg    if (num_params != 0) {
1774362b94d5Smrg        String *paramP = (String *)
1775362b94d5Smrg            __XtMalloc((Cardinal) ((num_params + 1) * sizeof(String)));
1776362b94d5Smrg        Cardinal i;
1777362b94d5Smrg
1778362b94d5Smrg        *paramSeqP = paramP;
1779362b94d5Smrg        *paramNumP = num_params;
1780362b94d5Smrg        paramP += num_params;   /* list is LIFO right now */
1781362b94d5Smrg        *paramP-- = NULL;
1782362b94d5Smrg        for (i = 0; i < num_params; i++) {
1783362b94d5Smrg            ParamPtr next = params->next;
1784362b94d5Smrg
1785362b94d5Smrg            *paramP-- = params->param;
1786362b94d5Smrg            DEALLOCATE_LOCAL((char *) params);
1787362b94d5Smrg            params = next;
1788362b94d5Smrg        }
1789362b94d5Smrg    }
1790362b94d5Smrg    else {
1791362b94d5Smrg        *paramSeqP = NULL;
1792362b94d5Smrg        *paramNumP = 0;
1793444c061aSmrg    }
1794444c061aSmrg
1795444c061aSmrg    return str;
1796444c061aSmrg}
1797444c061aSmrg
1798362b94d5Smrgstatic String
1799362b94d5SmrgParseAction(String str, ActionPtr actionP, XrmQuark *quarkP, Boolean *error)
1800444c061aSmrg{
1801444c061aSmrg    str = ParseActionProc(str, quarkP, error);
1802362b94d5Smrg    if (*error)
1803362b94d5Smrg        return str;
1804444c061aSmrg
1805444c061aSmrg    if (*str == '(') {
1806362b94d5Smrg        str++;
1807362b94d5Smrg        str = ParseParamSeq(str, &actionP->params, &actionP->num_params);
1808362b94d5Smrg    }
1809362b94d5Smrg    else {
1810362b94d5Smrg        Syntax("Missing '(' while parsing action sequence", "");
1811444c061aSmrg        *error = TRUE;
1812444c061aSmrg        return str;
1813444c061aSmrg    }
1814362b94d5Smrg    if (*str == ')')
1815362b94d5Smrg        str++;
1816362b94d5Smrg    else {
1817362b94d5Smrg        Syntax("Missing ')' while parsing action sequence", "");
1818444c061aSmrg        *error = TRUE;
1819444c061aSmrg        return str;
1820444c061aSmrg    }
1821444c061aSmrg    return str;
1822444c061aSmrg}
1823444c061aSmrg
1824362b94d5Smrgstatic String
1825362b94d5SmrgParseActionSeq(TMParseStateTree parseTree,
1826362b94d5Smrg               String str,
1827362b94d5Smrg               ActionPtr *actionsP,
1828362b94d5Smrg               Boolean *error)
1829444c061aSmrg{
183072af6995Smrg    ActionPtr *nextActionP;
183172af6995Smrg
183272af6995Smrg    if ((nextActionP = actionsP) != NULL)
1833362b94d5Smrg        *actionsP = NULL;
1834444c061aSmrg
1835444c061aSmrg    while (*str != '\0' && !IsNewline(*str)) {
1836362b94d5Smrg        register ActionPtr action;
1837362b94d5Smrg        XrmQuark quark = NULLQUARK;
1838444c061aSmrg
1839362b94d5Smrg        action = XtNew(ActionRec);
1840444c061aSmrg        action->params = NULL;
1841444c061aSmrg        action->num_params = 0;
1842444c061aSmrg        action->next = NULL;
1843444c061aSmrg
1844362b94d5Smrg        str = ParseAction(str, action, &quark, error);
1845362b94d5Smrg        if (*error) {
1846362b94d5Smrg            XtFree((char *) action);
1847362b94d5Smrg            return PanicModeRecovery(str);
1848362b94d5Smrg        }
1849444c061aSmrg
1850362b94d5Smrg        action->idx = _XtGetQuarkIndex(parseTree, quark);
1851362b94d5Smrg        ScanWhitespace(str);
1852362b94d5Smrg        if (nextActionP) {
1853362b94d5Smrg            *nextActionP = action;
1854362b94d5Smrg            nextActionP = &action->next;
1855362b94d5Smrg        }
1856444c061aSmrg    }
1857362b94d5Smrg    if (IsNewline(*str))
1858362b94d5Smrg        str++;
1859444c061aSmrg    ScanWhitespace(str);
1860444c061aSmrg    return str;
1861444c061aSmrg}
1862444c061aSmrg
1863362b94d5Smrgstatic void
1864362b94d5SmrgShowProduction(String currentProduction)
1865444c061aSmrg{
1866444c061aSmrg    Cardinal num_params = 1;
1867444c061aSmrg    String params[1];
1868444c061aSmrg    size_t len;
1869444c061aSmrg    char *eol, *production, productionbuf[500];
1870444c061aSmrg
18718584976cSmrg    eol = strchr(currentProduction, '\n');
1872362b94d5Smrg    if (eol)
1873362b94d5Smrg        len = (size_t) (eol - currentProduction);
1874362b94d5Smrg    else
1875362b94d5Smrg        len = strlen(currentProduction);
1876362b94d5Smrg    production = XtStackAlloc(len + 1, productionbuf);
1877362b94d5Smrg    if (production == NULL)
1878362b94d5Smrg        _XtAllocError(NULL);
1879444c061aSmrg    (void) memmove(production, currentProduction, len);
1880444c061aSmrg    production[len] = '\0';
1881444c061aSmrg
1882444c061aSmrg    params[0] = production;
1883444c061aSmrg    XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError,
1884362b94d5Smrg                 "... found while parsing '%s'", params, &num_params);
1885444c061aSmrg
1886362b94d5Smrg    XtStackFree(production, productionbuf);
1887444c061aSmrg}
1888444c061aSmrg
1889444c061aSmrg/***********************************************************************
1890444c061aSmrg * ParseTranslationTableProduction
1891444c061aSmrg * Parses one line of event bindings.
1892444c061aSmrg ***********************************************************************/
1893444c061aSmrg
1894362b94d5Smrgstatic String
1895362b94d5SmrgParseTranslationTableProduction(TMParseStateTree parseTree,
1896362b94d5Smrg                                register String str,
1897362b94d5Smrg                                Boolean *error)
1898444c061aSmrg{
1899362b94d5Smrg    EventSeqPtr eventSeq = NULL;
1900362b94d5Smrg    ActionPtr *actionsP;
1901362b94d5Smrg    String production = str;
1902444c061aSmrg
19032265a131Smrg    actionsP = NULL;
190472af6995Smrg    str = ParseEventSeq(str, &eventSeq, &actionsP, error);
1905444c061aSmrg    if (*error == TRUE) {
1906362b94d5Smrg        ShowProduction(production);
1907362b94d5Smrg    }
1908362b94d5Smrg    else {
1909362b94d5Smrg        ScanWhitespace(str);
1910362b94d5Smrg        str = ParseActionSeq(parseTree, str, actionsP, error);
1911362b94d5Smrg        if (*error == TRUE) {
1912362b94d5Smrg            ShowProduction(production);
1913362b94d5Smrg        }
1914362b94d5Smrg        else {
1915362b94d5Smrg            _XtAddEventSeqToStateTree(eventSeq, parseTree);
1916362b94d5Smrg        }
1917444c061aSmrg    }
1918444c061aSmrg    FreeEventSeq(eventSeq);
1919444c061aSmrg    return (str);
1920444c061aSmrg}
1921444c061aSmrg
1922362b94d5Smrgstatic String
1923362b94d5SmrgCheckForPoundSign(String str,
1924362b94d5Smrg                  _XtTranslateOp defaultOp,
1925362b94d5Smrg                  _XtTranslateOp *actualOpRtn)
1926444c061aSmrg{
1927444c061aSmrg    _XtTranslateOp opType;
1928444c061aSmrg
1929444c061aSmrg    opType = defaultOp;
1930444c061aSmrg    ScanWhitespace(str);
193172af6995Smrg
1932444c061aSmrg    if (*str == '#') {
1933362b94d5Smrg        String start;
1934362b94d5Smrg        char operation[20];
1935362b94d5Smrg        int len;
1936362b94d5Smrg
1937362b94d5Smrg        str++;
1938362b94d5Smrg        start = str;
1939362b94d5Smrg        str = ScanIdent(str);
1940362b94d5Smrg        len = MIN(19, (int) (str - start));
1941362b94d5Smrg        (void) memmove(operation, start, (size_t) len);
1942362b94d5Smrg        operation[len] = '\0';
1943362b94d5Smrg        if (!strcmp(operation, "replace"))
1944362b94d5Smrg            opType = XtTableReplace;
1945362b94d5Smrg        else if (!strcmp(operation, "augment"))
1946362b94d5Smrg            opType = XtTableAugment;
1947362b94d5Smrg        else if (!strcmp(operation, "override"))
1948362b94d5Smrg            opType = XtTableOverride;
1949362b94d5Smrg        ScanWhitespace(str);
1950362b94d5Smrg        if (IsNewline(*str)) {
1951362b94d5Smrg            str++;
1952362b94d5Smrg            ScanWhitespace(str);
1953362b94d5Smrg        }
1954444c061aSmrg    }
1955444c061aSmrg    *actualOpRtn = opType;
1956444c061aSmrg    return str;
1957444c061aSmrg}
1958444c061aSmrg
1959362b94d5Smrgstatic XtTranslations
1960362b94d5SmrgParseTranslationTable(String source,
1961362b94d5Smrg                      Boolean isAccelerator,
1962362b94d5Smrg                      _XtTranslateOp defaultOp,
1963362b94d5Smrg                      Boolean *error)
1964444c061aSmrg{
1965362b94d5Smrg    XtTranslations xlations;
1966362b94d5Smrg    TMStateTree stateTrees[8];
1967362b94d5Smrg    TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec;
1968362b94d5Smrg    XrmQuark stackQuarks[200];
1969362b94d5Smrg    TMBranchHeadRec stackBranchHeads[200];
1970362b94d5Smrg    StatePtr stackComplexBranchHeads[200];
1971362b94d5Smrg    _XtTranslateOp actualOp;
1972444c061aSmrg
1973444c061aSmrg    if (source == NULL)
1974362b94d5Smrg        return (XtTranslations) NULL;
1975444c061aSmrg
1976444c061aSmrg    source = CheckForPoundSign(source, defaultOp, &actualOp);
1977444c061aSmrg    if (isAccelerator && actualOp == XtTableReplace)
1978362b94d5Smrg        actualOp = defaultOp;
1979444c061aSmrg
1980444c061aSmrg    parseTree->isSimple = TRUE;
1981444c061aSmrg    parseTree->mappingNotifyInterest = FALSE;
198272af6995Smrg    XtSetBit(parseTree->isAccelerator, isAccelerator);
1983444c061aSmrg    parseTree->isStackBranchHeads =
1984362b94d5Smrg        parseTree->isStackQuarks = parseTree->isStackComplexBranchHeads = TRUE;
1985444c061aSmrg
1986444c061aSmrg    parseTree->numQuarks =
1987362b94d5Smrg        parseTree->numBranchHeads = parseTree->numComplexBranchHeads = 0;
1988444c061aSmrg
1989444c061aSmrg    parseTree->quarkTblSize =
1990362b94d5Smrg        parseTree->branchHeadTblSize =
1991362b94d5Smrg        parseTree->complexBranchHeadTblSize = 200;
1992444c061aSmrg
1993444c061aSmrg    parseTree->quarkTbl = stackQuarks;
1994444c061aSmrg    parseTree->branchHeadTbl = stackBranchHeads;
1995444c061aSmrg    parseTree->complexBranchHeadTbl = stackComplexBranchHeads;
1996444c061aSmrg
1997444c061aSmrg    while (source != NULL && *source != '\0') {
1998362b94d5Smrg        source = ParseTranslationTableProduction(parseTree, source, error);
1999362b94d5Smrg        if (*error == TRUE)
2000362b94d5Smrg            break;
2001444c061aSmrg    }
2002444c061aSmrg    stateTrees[0] = _XtParseTreeToStateTree(parseTree);
2003444c061aSmrg
2004444c061aSmrg    if (!parseTree->isStackQuarks)
2005362b94d5Smrg        XtFree((char *) parseTree->quarkTbl);
2006444c061aSmrg    if (!parseTree->isStackBranchHeads)
2007362b94d5Smrg        XtFree((char *) parseTree->branchHeadTbl);
2008444c061aSmrg    if (!parseTree->isStackComplexBranchHeads)
2009362b94d5Smrg        XtFree((char *) parseTree->complexBranchHeadTbl);
2010444c061aSmrg
2011444c061aSmrg    xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL);
201272af6995Smrg    xlations->operation = (unsigned char) actualOp;
2013444c061aSmrg
2014444c061aSmrg#ifdef notdef
2015444c061aSmrg    XtFree(stateTrees);
2016362b94d5Smrg#endif                          /* notdef */
2017444c061aSmrg    return xlations;
2018444c061aSmrg}
2019444c061aSmrg
2020444c061aSmrg/*** public procedures ***/
2021444c061aSmrg
2022362b94d5SmrgBoolean
2023362b94d5SmrgXtCvtStringToAcceleratorTable(Display *dpy,
2024362b94d5Smrg                              XrmValuePtr args _X_UNUSED,
2025362b94d5Smrg                              Cardinal *num_args,
2026362b94d5Smrg                              XrmValuePtr from,
2027362b94d5Smrg                              XrmValuePtr to,
2028362b94d5Smrg                              XtPointer *closure _X_UNUSED)
2029444c061aSmrg{
2030444c061aSmrg    String str;
2031444c061aSmrg    Boolean error = FALSE;
2032444c061aSmrg
2033444c061aSmrg    if (*num_args != 0)
2034444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2035362b94d5Smrg                        "wrongParameters", "cvtStringToAcceleratorTable",
2036362b94d5Smrg                        XtCXtToolkitError,
2037362b94d5Smrg                        "String to AcceleratorTable conversion needs no extra arguments",
2038362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2039362b94d5Smrg    str = (String) (from->addr);
2040444c061aSmrg    if (str == NULL) {
2041444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2042362b94d5Smrg                        "badParameters", "cvtStringToAcceleratorTable",
2043362b94d5Smrg                        XtCXtToolkitError,
2044362b94d5Smrg                        "String to AcceleratorTable conversion needs string",
2045362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2046362b94d5Smrg        return FALSE;
2047444c061aSmrg    }
2048444c061aSmrg    if (to->addr != NULL) {
2049362b94d5Smrg        if (to->size < sizeof(XtAccelerators)) {
2050362b94d5Smrg            to->size = sizeof(XtAccelerators);
2051362b94d5Smrg            return FALSE;
2052362b94d5Smrg        }
2053362b94d5Smrg        *(XtAccelerators *) to->addr =
2054362b94d5Smrg            (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment,
2055362b94d5Smrg                                                   &error);
2056444c061aSmrg    }
2057444c061aSmrg    else {
2058362b94d5Smrg        static XtAccelerators staticStateTable;
2059362b94d5Smrg
2060362b94d5Smrg        staticStateTable =
2061362b94d5Smrg            (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment,
2062362b94d5Smrg                                                   &error);
2063362b94d5Smrg        to->addr = (XPointer) &staticStateTable;
2064362b94d5Smrg        to->size = sizeof(XtAccelerators);
2065444c061aSmrg    }
2066444c061aSmrg    if (error == TRUE)
2067444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2068362b94d5Smrg                        "parseError", "cvtStringToAcceleratorTable",
2069362b94d5Smrg                        XtCXtToolkitError,
2070362b94d5Smrg                        "String to AcceleratorTable conversion encountered errors",
2071362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2072444c061aSmrg    return (error != TRUE);
2073444c061aSmrg}
2074444c061aSmrg
2075444c061aSmrgBoolean
2076362b94d5SmrgXtCvtStringToTranslationTable(Display *dpy,
2077362b94d5Smrg                              XrmValuePtr args _X_UNUSED,
2078362b94d5Smrg                              Cardinal *num_args,
2079362b94d5Smrg                              XrmValuePtr from,
2080362b94d5Smrg                              XrmValuePtr to,
2081362b94d5Smrg                              XtPointer *closure_ret _X_UNUSED)
2082444c061aSmrg{
2083444c061aSmrg    String str;
2084444c061aSmrg    Boolean error = FALSE;
2085444c061aSmrg
2086444c061aSmrg    if (*num_args != 0)
2087362b94d5Smrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2088362b94d5Smrg                        "wrongParameters", "cvtStringToTranslationTable",
2089362b94d5Smrg                        XtCXtToolkitError,
2090362b94d5Smrg                        "String to TranslationTable conversion needs no extra arguments",
2091362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2092362b94d5Smrg    str = (String) (from->addr);
2093444c061aSmrg    if (str == NULL) {
2094444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2095362b94d5Smrg                        "badParameters", "cvtStringToTranslation",
2096362b94d5Smrg                        XtCXtToolkitError,
2097362b94d5Smrg                        "String to TranslationTable conversion needs string",
2098362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2099362b94d5Smrg        return FALSE;
2100444c061aSmrg    }
2101444c061aSmrg    if (to->addr != NULL) {
2102362b94d5Smrg        if (to->size < sizeof(XtTranslations)) {
2103362b94d5Smrg            to->size = sizeof(XtTranslations);
2104362b94d5Smrg            return FALSE;
2105362b94d5Smrg        }
2106362b94d5Smrg        *(XtTranslations *) to->addr =
2107362b94d5Smrg            ParseTranslationTable(str, FALSE, XtTableReplace, &error);
2108444c061aSmrg    }
2109444c061aSmrg    else {
2110362b94d5Smrg        static XtTranslations staticStateTable;
2111362b94d5Smrg
2112362b94d5Smrg        staticStateTable =
2113362b94d5Smrg            ParseTranslationTable(str, FALSE, XtTableReplace, &error);
2114362b94d5Smrg        to->addr = (XPointer) &staticStateTable;
2115362b94d5Smrg        to->size = sizeof(XtTranslations);
2116444c061aSmrg    }
2117444c061aSmrg    if (error == TRUE)
2118444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2119362b94d5Smrg                        "parseError", "cvtStringToTranslationTable",
2120362b94d5Smrg                        XtCXtToolkitError,
2121362b94d5Smrg                        "String to TranslationTable conversion encountered errors",
2122362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2123444c061aSmrg    return (error != TRUE);
2124444c061aSmrg}
2125444c061aSmrg
2126444c061aSmrg/*
2127444c061aSmrg * Parses a user's or applications translation table
2128444c061aSmrg */
2129362b94d5SmrgXtAccelerators
2130362b94d5SmrgXtParseAcceleratorTable(_Xconst char *source)
2131444c061aSmrg{
2132444c061aSmrg    Boolean error = FALSE;
2133444c061aSmrg    XtAccelerators ret =
2134362b94d5Smrg        (XtAccelerators) ParseTranslationTable(source, TRUE, XtTableAugment,
2135362b94d5Smrg                                               &error);
2136362b94d5Smrg
2137444c061aSmrg    if (error == TRUE)
2138362b94d5Smrg        XtWarningMsg("parseError", "cvtStringToAcceleratorTable",
2139362b94d5Smrg                     XtCXtToolkitError,
2140362b94d5Smrg                     "String to AcceleratorTable conversion encountered errors",
2141362b94d5Smrg                     (String *) NULL, (Cardinal *) NULL);
2142444c061aSmrg    return ret;
2143444c061aSmrg}
2144444c061aSmrg
2145362b94d5SmrgXtTranslations
2146362b94d5SmrgXtParseTranslationTable(_Xconst char *source)
2147444c061aSmrg{
2148444c061aSmrg    Boolean error = FALSE;
2149362b94d5Smrg    XtTranslations ret =
2150362b94d5Smrg        ParseTranslationTable(source, FALSE, XtTableReplace, &error);
2151444c061aSmrg    if (error == TRUE)
2152362b94d5Smrg        XtWarningMsg("parseError",
2153362b94d5Smrg                     "cvtStringToTranslationTable", XtCXtToolkitError,
2154362b94d5Smrg                     "String to TranslationTable conversion encountered errors",
2155362b94d5Smrg                     (String *) NULL, (Cardinal *) NULL);
2156444c061aSmrg    return ret;
2157444c061aSmrg}
2158444c061aSmrg
2159362b94d5Smrgvoid
2160362b94d5Smrg_XtTranslateInitialize(void)
2161444c061aSmrg{
2162444c061aSmrg    LOCK_PROCESS;
2163444c061aSmrg    if (initialized) {
2164362b94d5Smrg        XtWarningMsg("translationError", "xtTranslateInitialize",
2165362b94d5Smrg                     XtCXtToolkitError,
2166362b94d5Smrg                     "Initializing Translation manager twice.", (String *) NULL,
2167362b94d5Smrg                     (Cardinal *) NULL);
2168362b94d5Smrg        UNLOCK_PROCESS;
2169362b94d5Smrg        return;
2170444c061aSmrg    }
2171444c061aSmrg
2172444c061aSmrg    initialized = TRUE;
2173444c061aSmrg    UNLOCK_PROCESS;
2174444c061aSmrg    QMeta = XrmPermStringToQuark("Meta");
2175444c061aSmrg    QCtrl = XrmPermStringToQuark("Ctrl");
2176444c061aSmrg    QNone = XrmPermStringToQuark("None");
2177362b94d5Smrg    QAny = XrmPermStringToQuark("Any");
2178444c061aSmrg
2179362b94d5Smrg    Compile_XtEventTable(events, XtNumber(events));
2180362b94d5Smrg    Compile_XtModifierTable(modifiers, XtNumber(modifiers));
2181362b94d5Smrg    CompileNameValueTable(buttonNames);
2182362b94d5Smrg    CompileNameValueTable(notifyModes);
2183362b94d5Smrg    CompileNameValueTable(motionDetails);
2184444c061aSmrg#if 0
2185362b94d5Smrg    CompileNameValueTable(notifyDetail);
2186362b94d5Smrg    CompileNameValueTable(visibilityNotify);
2187362b94d5Smrg    CompileNameValueTable(circulation);
2188362b94d5Smrg    CompileNameValueTable(propertyChanged);
2189444c061aSmrg#endif
2190362b94d5Smrg    CompileNameValueTable(mappingNotify);
2191444c061aSmrg}
2192444c061aSmrg
2193362b94d5Smrgvoid
2194362b94d5Smrg_XtAddTMConverters(ConverterTable table)
2195444c061aSmrg{
2196362b94d5Smrg    _XtTableAddConverter(table,
2197362b94d5Smrg                         _XtQString,
2198362b94d5Smrg                         XrmPermStringToQuark(XtRTranslationTable),
2199362b94d5Smrg                         XtCvtStringToTranslationTable, (XtConvertArgList) NULL,
2200362b94d5Smrg                         (Cardinal) 0, True, CACHED, _XtFreeTranslations, True);
2201362b94d5Smrg    _XtTableAddConverter(table, _XtQString,
2202362b94d5Smrg                         XrmPermStringToQuark(XtRAcceleratorTable),
2203362b94d5Smrg                         XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL,
2204362b94d5Smrg                         (Cardinal) 0, True, CACHED, _XtFreeTranslations, True);
2205362b94d5Smrg    _XtTableAddConverter(table,
2206362b94d5Smrg                         XrmPermStringToQuark(_XtRStateTablePair),
2207362b94d5Smrg                         XrmPermStringToQuark(XtRTranslationTable),
2208362b94d5Smrg                         _XtCvtMergeTranslations, (XtConvertArgList) NULL,
2209362b94d5Smrg                         (Cardinal) 0, True, CACHED, _XtFreeTranslations, True);
2210444c061aSmrg}
2211