1444c061aSmrg/***********************************************************
2a773ec55SmrgCopyright (c) 1993, Oracle and/or its affiliates.
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 motionDetails[] = {
171362b94d5Smrg    {"Normal",              0,         NotifyNormal},
172362b94d5Smrg    {"Hint",                0,         NotifyHint},
173362b94d5Smrg    {NULL,                  NULLQUARK, 0},
174444c061aSmrg};
175444c061aSmrg
176444c061aSmrgstatic NameValueRec notifyModes[] = {
177362b94d5Smrg    {"Normal",              0,         NotifyNormal},
178362b94d5Smrg    {"Grab",                0,         NotifyGrab},
179362b94d5Smrg    {"Ungrab",              0,         NotifyUngrab},
180362b94d5Smrg    {"WhileGrabbed",        0,         NotifyWhileGrabbed},
181362b94d5Smrg    {NULL,                  NULLQUARK, 0},
182444c061aSmrg};
183444c061aSmrg
184444c061aSmrg#if 0
185444c061aSmrgstatic NameValueRec notifyDetail[] = {
186362b94d5Smrg    {"Ancestor",            0,         NotifyAncestor},
187362b94d5Smrg    {"Virtual",             0,         NotifyVirtual},
188362b94d5Smrg    {"Inferior",            0,         NotifyInferior},
189362b94d5Smrg    {"Nonlinear",           0,         NotifyNonlinear},
190362b94d5Smrg    {"NonlinearVirtual",    0,         NotifyNonlinearVirtual},
191362b94d5Smrg    {"Pointer",             0,         NotifyPointer},
192362b94d5Smrg    {"PointerRoot",         0,         NotifyPointerRoot},
193362b94d5Smrg    {"DetailNone",          0,         NotifyDetailNone},
194362b94d5Smrg    {NULL,                  NULLQUARK, 0},
195444c061aSmrg};
196444c061aSmrg
197444c061aSmrgstatic NameValueRec visibilityNotify[] = {
198362b94d5Smrg    {"Unobscured",          0,         VisibilityUnobscured},
199362b94d5Smrg    {"PartiallyObscured",   0,         VisibilityPartiallyObscured},
200362b94d5Smrg    {"FullyObscured",       0,         VisibilityFullyObscured},
201362b94d5Smrg    {NULL,                  NULLQUARK, 0},
202444c061aSmrg};
203444c061aSmrg
204444c061aSmrgstatic NameValueRec circulation[] = {
205362b94d5Smrg    {"OnTop",               0,         PlaceOnTop},
206362b94d5Smrg    {"OnBottom",            0,         PlaceOnBottom},
207362b94d5Smrg    {NULL,                  NULLQUARK, 0},
208444c061aSmrg};
209444c061aSmrg
210444c061aSmrgstatic NameValueRec propertyChanged[] = {
211362b94d5Smrg    {"NewValue",            0,         PropertyNewValue},
212362b94d5Smrg    {"Delete",              0,         PropertyDelete},
213362b94d5Smrg    {NULL,                  NULLQUARK, 0},
214444c061aSmrg};
215444c061aSmrg#endif /*0*/
216444c061aSmrg
217444c061aSmrgstatic NameValueRec mappingNotify[] = {
218362b94d5Smrg    {"Modifier",            0,         MappingModifier},
219362b94d5Smrg    {"Keyboard",            0,         MappingKeyboard},
220362b94d5Smrg    {"Pointer",             0,         MappingPointer},
221362b94d5Smrg    {NULL,                  NULLQUARK, 0},
222444c061aSmrg};
223362b94d5Smrg/* *INDENT-ON* */
224444c061aSmrg
22572af6995Smrgstatic String ParseKeySym(PARSE_PROC_DECL);
22672af6995Smrgstatic String ParseKeyAndModifiers(PARSE_PROC_DECL);
22772af6995Smrgstatic String ParseTable(PARSE_PROC_DECL);
228a773ec55Smrgstatic String ParseButton(PARSE_PROC_DECL);
22972af6995Smrgstatic String ParseImmed(PARSE_PROC_DECL);
23072af6995Smrgstatic String ParseAddModifier(PARSE_PROC_DECL);
23172af6995Smrgstatic String ParseNone(PARSE_PROC_DECL);
23272af6995Smrgstatic String ParseAtom(PARSE_PROC_DECL);
233444c061aSmrg
234362b94d5Smrg/* *INDENT-OFF* */
235444c061aSmrgstatic EventKey events[] = {
236444c061aSmrg
237362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
238444c061aSmrg
239362b94d5Smrg{"KeyPress",        NULLQUARK, KeyPress,        ParseKeySym,    NULL},
240362b94d5Smrg{"Key",             NULLQUARK, KeyPress,        ParseKeySym,    NULL},
241362b94d5Smrg{"KeyDown",         NULLQUARK, KeyPress,        ParseKeySym,    NULL},
242362b94d5Smrg{"Ctrl",            NULLQUARK, KeyPress,        ParseKeyAndModifiers, (Opaque)ControlMask},
243362b94d5Smrg{"Shift",           NULLQUARK, KeyPress,        ParseKeyAndModifiers, (Opaque)ShiftMask},
244362b94d5Smrg{"Meta",            NULLQUARK, KeyPress,        ParseKeyAndModifiers, (Opaque)NULL},
245362b94d5Smrg{"KeyUp",           NULLQUARK, KeyRelease,      ParseKeySym,    NULL},
246362b94d5Smrg{"KeyRelease",      NULLQUARK, KeyRelease,      ParseKeySym,    NULL},
247444c061aSmrg
248a773ec55Smrg{"ButtonPress",     NULLQUARK, ButtonPress,     ParseButton, NULL },
249a773ec55Smrg{"BtnDown",         NULLQUARK, ButtonPress,     ParseButton, NULL },
250362b94d5Smrg{"Btn1Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button1},
251362b94d5Smrg{"Btn2Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button2},
252362b94d5Smrg{"Btn3Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button3},
253362b94d5Smrg{"Btn4Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button4},
254362b94d5Smrg{"Btn5Down",        NULLQUARK, ButtonPress,     ParseImmed, (Opaque)Button5},
255444c061aSmrg
256362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
257444c061aSmrg
258a773ec55Smrg{"ButtonRelease",   NULLQUARK, ButtonRelease,   ParseButton, NULL },
259a773ec55Smrg{"BtnUp",           NULLQUARK, ButtonRelease,   ParseButton, NULL },
260362b94d5Smrg{"Btn1Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button1},
261362b94d5Smrg{"Btn2Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button2},
262362b94d5Smrg{"Btn3Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button3},
263362b94d5Smrg{"Btn4Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button4},
264362b94d5Smrg{"Btn5Up",          NULLQUARK, ButtonRelease,   ParseImmed, (Opaque)Button5},
265444c061aSmrg
266362b94d5Smrg{"MotionNotify",    NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
267362b94d5Smrg{"PtrMoved",        NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
268362b94d5Smrg{"Motion",          NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
269362b94d5Smrg{"MouseMoved",      NULLQUARK, MotionNotify,    ParseTable, (Opaque)motionDetails},
270362b94d5Smrg{"BtnMotion",       NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)AnyButtonMask},
271362b94d5Smrg{"Btn1Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button1Mask},
272362b94d5Smrg{"Btn2Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button2Mask},
273362b94d5Smrg{"Btn3Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button3Mask},
274362b94d5Smrg{"Btn4Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button4Mask},
275362b94d5Smrg{"Btn5Motion",      NULLQUARK, MotionNotify,    ParseAddModifier, (Opaque)Button5Mask},
276444c061aSmrg
277362b94d5Smrg{"EnterNotify",     NULLQUARK, EnterNotify,     ParseTable, (Opaque)notifyModes},
278362b94d5Smrg{"Enter",           NULLQUARK, EnterNotify,     ParseTable, (Opaque)notifyModes},
279362b94d5Smrg{"EnterWindow",     NULLQUARK, EnterNotify,     ParseTable, (Opaque)notifyModes},
280444c061aSmrg
281362b94d5Smrg{"LeaveNotify",     NULLQUARK, LeaveNotify,     ParseTable, (Opaque)notifyModes},
282362b94d5Smrg{"LeaveWindow",     NULLQUARK, LeaveNotify,     ParseTable, (Opaque)notifyModes},
283362b94d5Smrg{"Leave",           NULLQUARK, LeaveNotify,     ParseTable, (Opaque)notifyModes},
284444c061aSmrg
285362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
286444c061aSmrg
287362b94d5Smrg{"FocusIn",         NULLQUARK, FocusIn,         ParseTable, (Opaque)notifyModes},
288444c061aSmrg
289362b94d5Smrg{"FocusOut",        NULLQUARK, FocusOut,        ParseTable, (Opaque)notifyModes},
290444c061aSmrg
291362b94d5Smrg{"KeymapNotify",    NULLQUARK, KeymapNotify,    ParseNone,      NULL},
292362b94d5Smrg{"Keymap",          NULLQUARK, KeymapNotify,    ParseNone,      NULL},
293444c061aSmrg
294362b94d5Smrg{"Expose",          NULLQUARK, Expose,          ParseNone,      NULL},
295444c061aSmrg
296362b94d5Smrg{"GraphicsExpose",  NULLQUARK, GraphicsExpose,  ParseNone,      NULL},
297362b94d5Smrg{"GrExp",           NULLQUARK, GraphicsExpose,  ParseNone,      NULL},
298444c061aSmrg
299362b94d5Smrg{"NoExpose",        NULLQUARK, NoExpose,        ParseNone,      NULL},
300362b94d5Smrg{"NoExp",           NULLQUARK, NoExpose,        ParseNone,      NULL},
301444c061aSmrg
302362b94d5Smrg{"VisibilityNotify",NULLQUARK, VisibilityNotify,ParseNone,      NULL},
303362b94d5Smrg{"Visible",         NULLQUARK, VisibilityNotify,ParseNone,      NULL},
304444c061aSmrg
305362b94d5Smrg{"CreateNotify",    NULLQUARK, CreateNotify,    ParseNone,      NULL},
306362b94d5Smrg{"Create",          NULLQUARK, CreateNotify,    ParseNone,      NULL},
307444c061aSmrg
308362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
309444c061aSmrg
310362b94d5Smrg{"DestroyNotify",   NULLQUARK, DestroyNotify,   ParseNone,      NULL},
311362b94d5Smrg{"Destroy",         NULLQUARK, DestroyNotify,   ParseNone,      NULL},
312444c061aSmrg
313362b94d5Smrg{"UnmapNotify",     NULLQUARK, UnmapNotify,     ParseNone,      NULL},
314362b94d5Smrg{"Unmap",           NULLQUARK, UnmapNotify,     ParseNone,      NULL},
315444c061aSmrg
316362b94d5Smrg{"MapNotify",       NULLQUARK, MapNotify,       ParseNone,      NULL},
317362b94d5Smrg{"Map",             NULLQUARK, MapNotify,       ParseNone,      NULL},
318444c061aSmrg
319362b94d5Smrg{"MapRequest",      NULLQUARK, MapRequest,      ParseNone,      NULL},
320362b94d5Smrg{"MapReq",          NULLQUARK, MapRequest,      ParseNone,      NULL},
321444c061aSmrg
322362b94d5Smrg{"ReparentNotify",  NULLQUARK, ReparentNotify,  ParseNone,      NULL},
323362b94d5Smrg{"Reparent",        NULLQUARK, ReparentNotify,  ParseNone,      NULL},
324444c061aSmrg
325362b94d5Smrg{"ConfigureNotify", NULLQUARK, ConfigureNotify, ParseNone,      NULL},
326362b94d5Smrg{"Configure",       NULLQUARK, ConfigureNotify, ParseNone,      NULL},
327444c061aSmrg
328362b94d5Smrg{"ConfigureRequest",NULLQUARK, ConfigureRequest,ParseNone,      NULL},
329362b94d5Smrg{"ConfigureReq",    NULLQUARK, ConfigureRequest,ParseNone,      NULL},
330444c061aSmrg
331362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
332444c061aSmrg
333362b94d5Smrg{"GravityNotify",   NULLQUARK, GravityNotify,   ParseNone,      NULL},
334362b94d5Smrg{"Grav",            NULLQUARK, GravityNotify,   ParseNone,      NULL},
335444c061aSmrg
336362b94d5Smrg{"ResizeRequest",   NULLQUARK, ResizeRequest,   ParseNone,      NULL},
337362b94d5Smrg{"ResReq",          NULLQUARK, ResizeRequest,   ParseNone,      NULL},
338444c061aSmrg
339362b94d5Smrg{"CirculateNotify", NULLQUARK, CirculateNotify, ParseNone,      NULL},
340362b94d5Smrg{"Circ",            NULLQUARK, CirculateNotify, ParseNone,      NULL},
341444c061aSmrg
342362b94d5Smrg{"CirculateRequest",NULLQUARK, CirculateRequest,ParseNone,      NULL},
343362b94d5Smrg{"CircReq",         NULLQUARK, CirculateRequest,ParseNone,      NULL},
344444c061aSmrg
345362b94d5Smrg{"PropertyNotify",  NULLQUARK, PropertyNotify,  ParseAtom,      NULL},
346362b94d5Smrg{"Prop",            NULLQUARK, PropertyNotify,  ParseAtom,      NULL},
347444c061aSmrg
348362b94d5Smrg{"SelectionClear",  NULLQUARK, SelectionClear,  ParseAtom,      NULL},
349362b94d5Smrg{"SelClr",          NULLQUARK, SelectionClear,  ParseAtom,      NULL},
350444c061aSmrg
351362b94d5Smrg{"SelectionRequest",NULLQUARK, SelectionRequest,ParseAtom,      NULL},
352362b94d5Smrg{"SelReq",          NULLQUARK, SelectionRequest,ParseAtom,      NULL},
353444c061aSmrg
354362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
355444c061aSmrg
356362b94d5Smrg{"SelectionNotify", NULLQUARK, SelectionNotify, ParseAtom,      NULL},
357362b94d5Smrg{"Select",          NULLQUARK, SelectionNotify, ParseAtom,      NULL},
358444c061aSmrg
359362b94d5Smrg{"ColormapNotify",  NULLQUARK, ColormapNotify,  ParseNone,      NULL},
360362b94d5Smrg{"Clrmap",          NULLQUARK, ColormapNotify,  ParseNone,      NULL},
361444c061aSmrg
362362b94d5Smrg{"ClientMessage",   NULLQUARK, ClientMessage,   ParseAtom,      NULL},
363362b94d5Smrg{"Message",         NULLQUARK, ClientMessage,   ParseAtom,      NULL},
364444c061aSmrg
365362b94d5Smrg{"MappingNotify",   NULLQUARK, MappingNotify,   ParseTable, (Opaque)mappingNotify},
366362b94d5Smrg{"Mapping",         NULLQUARK, MappingNotify,   ParseTable, (Opaque)mappingNotify},
367444c061aSmrg
368444c061aSmrg#ifdef DEBUG
369444c061aSmrg# ifdef notdef
370362b94d5Smrg{"Timer",           NULLQUARK, _XtTimerEventType, ParseNone,     NULL},
371362b94d5Smrg{"EventTimer",      NULLQUARK, _XtEventTimerEventType, ParseNone,NULL},
3721bd39548Schristos# endif /* notdef */
373444c061aSmrg#endif /* DEBUG */
374444c061aSmrg
375362b94d5Smrg/* Event Name,    Quark, Event Type,    Detail Parser, Closure */
376444c061aSmrg
377444c061aSmrg};
378362b94d5Smrg/* *INDENT-ON* */
379444c061aSmrg
380444c061aSmrg#define IsNewline(str) ((str) == '\n')
381444c061aSmrg
382444c061aSmrg#define ScanFor(str, ch) \
383444c061aSmrg    while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))) (str)++
384444c061aSmrg
385444c061aSmrg#define ScanNumeric(str)  while ('0' <= *(str) && *(str) <= '9') (str)++
386444c061aSmrg
387444c061aSmrg#define ScanAlphanumeric(str) \
388444c061aSmrg    while (('A' <= *(str) && *(str) <= 'Z') || \
389444c061aSmrg           ('a' <= *(str) && *(str) <= 'z') || \
390444c061aSmrg           ('0' <= *(str) && *(str) <= '9')) (str)++
391444c061aSmrg
392444c061aSmrg#define ScanWhitespace(str) \
393444c061aSmrg    while (*(str) == ' ' || *(str) == '\t') (str)++
394444c061aSmrg
395444c061aSmrgstatic Boolean initialized = FALSE;
396444c061aSmrgstatic XrmQuark QMeta;
397444c061aSmrgstatic XrmQuark QCtrl;
398444c061aSmrgstatic XrmQuark QNone;
399444c061aSmrgstatic XrmQuark QAny;
400444c061aSmrg
401362b94d5Smrgstatic void
402362b94d5SmrgFreeEventSeq(EventSeqPtr eventSeq)
403444c061aSmrg{
404444c061aSmrg    register EventSeqPtr evs = eventSeq;
405444c061aSmrg
406444c061aSmrg    while (evs != NULL) {
407362b94d5Smrg        evs->state = (StatePtr) evs;
408362b94d5Smrg        if (evs->next != NULL && evs->next->state == (StatePtr) evs->next)
409362b94d5Smrg            evs->next = NULL;
410362b94d5Smrg        evs = evs->next;
411444c061aSmrg    }
412444c061aSmrg
413444c061aSmrg    evs = eventSeq;
414444c061aSmrg    while (evs != NULL) {
415362b94d5Smrg        register EventPtr event = evs;
416362b94d5Smrg
417362b94d5Smrg        evs = evs->next;
418362b94d5Smrg        if (evs == event)
419362b94d5Smrg            evs = NULL;
420362b94d5Smrg        XtFree((char *) event);
421444c061aSmrg    }
422444c061aSmrg}
423444c061aSmrg
424362b94d5Smrgstatic void
425362b94d5SmrgCompileNameValueTable(NameValueTable table)
426444c061aSmrg{
427444c061aSmrg    register int i;
428444c061aSmrg
429362b94d5Smrg    for (i = 0; table[i].name; i++)
430444c061aSmrg        table[i].signature = XrmPermStringToQuark(table[i].name);
431444c061aSmrg}
432444c061aSmrg
433362b94d5Smrgstatic int
434362b94d5SmrgOrderEvents(_Xconst void *a, _Xconst void *b)
435444c061aSmrg{
436362b94d5Smrg    return ((((_Xconst EventKey *) a)->signature <
437362b94d5Smrg             ((_Xconst EventKey *) b)->signature) ? -1 : 1);
438444c061aSmrg}
439444c061aSmrg
440362b94d5Smrgstatic void
441362b94d5SmrgCompile_XtEventTable(EventKeys table, Cardinal count)
442444c061aSmrg{
443444c061aSmrg    register int i;
444444c061aSmrg    register EventKeys entry = table;
445444c061aSmrg
446362b94d5Smrg    for (i = (int) count; --i >= 0; entry++)
447362b94d5Smrg        entry->signature = XrmPermStringToQuark(entry->event);
448444c061aSmrg    qsort(table, count, sizeof(EventKey), OrderEvents);
449444c061aSmrg}
450444c061aSmrg
451362b94d5Smrgstatic int
452362b94d5SmrgOrderModifiers(_Xconst void *a, _Xconst void *b)
453444c061aSmrg{
454362b94d5Smrg    return ((((_Xconst ModifierRec *) a)->signature <
455362b94d5Smrg             ((_Xconst ModifierRec *) b)->signature) ? -1 : 1);
456444c061aSmrg}
457444c061aSmrg
458362b94d5Smrgstatic void
459362b94d5SmrgCompile_XtModifierTable(ModifierKeys table, Cardinal count)
460444c061aSmrg{
461444c061aSmrg    register int i;
462444c061aSmrg    register ModifierKeys entry = table;
463444c061aSmrg
464362b94d5Smrg    for (i = (int) count; --i >= 0; entry++)
465362b94d5Smrg        entry->signature = XrmPermStringToQuark(entry->name);
466444c061aSmrg    qsort(table, count, sizeof(ModifierRec), OrderModifiers);
467444c061aSmrg}
468444c061aSmrg
469362b94d5Smrgstatic String
470362b94d5SmrgPanicModeRecovery(String str)
471444c061aSmrg{
472362b94d5Smrg    ScanFor(str, '\n');
473362b94d5Smrg    if (*str == '\n')
474362b94d5Smrg        str++;
475362b94d5Smrg    return str;
476444c061aSmrg
477444c061aSmrg}
478444c061aSmrg
479362b94d5Smrgstatic void
480362b94d5SmrgSyntax(_Xconst char *str0, _Xconst char *str1)
481444c061aSmrg{
482444c061aSmrg    Cardinal num_params = 2;
483444c061aSmrg    String params[2];
484444c061aSmrg
48572af6995Smrg    params[0] = (String) str0;
48672af6995Smrg    params[1] = (String) str1;
487362b94d5Smrg    XtWarningMsg(XtNtranslationParseError, "parseError", XtCXtToolkitError,
488362b94d5Smrg                 "translation table syntax error: %s %s", params, &num_params);
489444c061aSmrg}
490444c061aSmrg
491362b94d5Smrgstatic Cardinal
492362b94d5SmrgLookupTMEventType(String eventStr, Boolean *error)
493444c061aSmrg{
494362b94d5Smrg    register int i = 0, left, right;
495362b94d5Smrg    register XrmQuark signature;
496362b94d5Smrg    static int previous = 0;
497444c061aSmrg
498444c061aSmrg    LOCK_PROCESS;
499444c061aSmrg    if ((signature = StringToQuark(eventStr)) == events[previous].signature) {
500362b94d5Smrg        UNLOCK_PROCESS;
501362b94d5Smrg        return (Cardinal) previous;
502444c061aSmrg    }
503444c061aSmrg
504444c061aSmrg    left = 0;
505444c061aSmrg    right = XtNumber(events) - 1;
506444c061aSmrg    while (left <= right) {
507362b94d5Smrg        i = (left + right) >> 1;
508362b94d5Smrg        if (signature < events[i].signature)
509362b94d5Smrg            right = i - 1;
510362b94d5Smrg        else if (signature > events[i].signature)
511362b94d5Smrg            left = i + 1;
512362b94d5Smrg        else {
513362b94d5Smrg            previous = i;
514362b94d5Smrg            UNLOCK_PROCESS;
515362b94d5Smrg            return (Cardinal) i;
516362b94d5Smrg        }
517362b94d5Smrg    }
518362b94d5Smrg
519362b94d5Smrg    Syntax("Unknown event type :  ", eventStr);
520444c061aSmrg    *error = TRUE;
521444c061aSmrg    UNLOCK_PROCESS;
522444c061aSmrg    return (Cardinal) i;
523444c061aSmrg}
524444c061aSmrg
525362b94d5Smrgstatic void
526362b94d5SmrgStoreLateBindings(KeySym keysymL,
527362b94d5Smrg                  Boolean notL,
528362b94d5Smrg                  KeySym keysymR,
529362b94d5Smrg                  Boolean notR,
530362b94d5Smrg                  LateBindingsPtr *lateBindings)
531444c061aSmrg{
532444c061aSmrg    LateBindingsPtr temp;
53372af6995Smrg
534362b94d5Smrg    if (lateBindings != NULL) {
535362b94d5Smrg        Boolean pair = FALSE;
536362b94d5Smrg        unsigned long count;
537362b94d5Smrg        unsigned long number;
53872af6995Smrg
539444c061aSmrg        temp = *lateBindings;
540444c061aSmrg        if (temp != NULL) {
541362b94d5Smrg            for (count = 0; temp[count].keysym; count++) {
542362b94d5Smrg                /*EMPTY*/
543362b94d5Smrg            }
544444c061aSmrg        }
545362b94d5Smrg        else
546362b94d5Smrg            count = 0;
547362b94d5Smrg        if (!keysymR) {
548362b94d5Smrg            number = 1;
549362b94d5Smrg            pair = FALSE;
550362b94d5Smrg        }
551362b94d5Smrg        else {
552362b94d5Smrg            number = 2;
553362b94d5Smrg            pair = TRUE;
554444c061aSmrg        }
555444c061aSmrg
556a773ec55Smrg        temp = XtReallocArray(temp, (Cardinal) (count + number + 1),
557a773ec55Smrg                              (Cardinal) sizeof(LateBindings));
558444c061aSmrg        *lateBindings = temp;
55972af6995Smrg        XtSetBit(temp[count].knot, notL);
56072af6995Smrg        XtSetBit(temp[count].pair, pair);
561362b94d5Smrg        if (count == 0)
562362b94d5Smrg            temp[count].ref_count = 1;
563444c061aSmrg        temp[count++].keysym = keysymL;
564362b94d5Smrg        if (keysymR) {
56572af6995Smrg            XtSetBit(temp[count].knot, notR);
566444c061aSmrg            temp[count].pair = FALSE;
567362b94d5Smrg            temp[count].ref_count = 0;
568444c061aSmrg            temp[count++].keysym = keysymR;
569444c061aSmrg        }
570444c061aSmrg        temp[count].knot = temp[count].pair = FALSE;
571444c061aSmrg        temp[count].ref_count = 0;
572444c061aSmrg        temp[count].keysym = 0;
573444c061aSmrg    }
574444c061aSmrg}
575444c061aSmrg
576362b94d5Smrgstatic void
577362b94d5Smrg_XtParseKeysymMod(String name,
578362b94d5Smrg                  LateBindingsPtr *lateBindings,
579362b94d5Smrg                  Boolean notFlag,
580362b94d5Smrg                  Value *valueP,
581362b94d5Smrg                  Boolean *error)
582444c061aSmrg{
583444c061aSmrg    KeySym keySym;
584362b94d5Smrg
585444c061aSmrg    keySym = StringToKeySym(name, error);
586444c061aSmrg    *valueP = 0;
587444c061aSmrg    if (keySym != NoSymbol) {
588362b94d5Smrg        StoreLateBindings(keySym, notFlag, (KeySym) NULL, FALSE, lateBindings);
589444c061aSmrg    }
590444c061aSmrg}
591444c061aSmrg
592362b94d5Smrgstatic Boolean
593362b94d5Smrg_XtLookupModifier(XrmQuark signature,
594362b94d5Smrg                  LateBindingsPtr *lateBindings,
595362b94d5Smrg                  Boolean notFlag,
596362b94d5Smrg                  Value *valueP,
597362b94d5Smrg                  Bool constMask)
598444c061aSmrg{
59972af6995Smrg    int left, right;
600444c061aSmrg    static int previous = 0;
601444c061aSmrg
602444c061aSmrg    LOCK_PROCESS;
603444c061aSmrg    if (signature == modifiers[previous].signature) {
604362b94d5Smrg        if (constMask)
605362b94d5Smrg            *valueP = modifiers[previous].value;
606362b94d5Smrg        else                    /* if (modifiers[previous].modifierParseProc) always true */
607362b94d5Smrg            (*modifiers[previous].modifierParseProc)
608362b94d5Smrg                (modifiers[previous].value, lateBindings, notFlag, valueP);
609362b94d5Smrg        UNLOCK_PROCESS;
610362b94d5Smrg        return TRUE;
611444c061aSmrg    }
612444c061aSmrg
613444c061aSmrg    left = 0;
614444c061aSmrg    right = XtNumber(modifiers) - 1;
615444c061aSmrg    while (left <= right) {
616362b94d5Smrg        int i = (left + right) >> 1;
617362b94d5Smrg
618362b94d5Smrg        if (signature < modifiers[i].signature)
619362b94d5Smrg            right = i - 1;
620362b94d5Smrg        else if (signature > modifiers[i].signature)
621362b94d5Smrg            left = i + 1;
622362b94d5Smrg        else {
623362b94d5Smrg            previous = i;
624362b94d5Smrg            if (constMask)
625362b94d5Smrg                *valueP = modifiers[i].value;
626362b94d5Smrg            else                /* if (modifiers[i].modifierParseProc) always true */
627362b94d5Smrg                (*modifiers[i].modifierParseProc)
628362b94d5Smrg                    (modifiers[i].value, lateBindings, notFlag, valueP);
629362b94d5Smrg            UNLOCK_PROCESS;
630362b94d5Smrg            return TRUE;
631362b94d5Smrg        }
632444c061aSmrg    }
633444c061aSmrg    UNLOCK_PROCESS;
634444c061aSmrg    return FALSE;
635444c061aSmrg}
636444c061aSmrg
637362b94d5Smrgstatic String
638362b94d5SmrgScanIdent(register String str)
639444c061aSmrg{
640444c061aSmrg    ScanAlphanumeric(str);
641362b94d5Smrg    while (('A' <= *str && *str <= 'Z')
642362b94d5Smrg           || ('a' <= *str && *str <= 'z')
643362b94d5Smrg           || ('0' <= *str && *str <= '9')
644362b94d5Smrg           || (*str == '-')
645362b94d5Smrg           || (*str == '_')
646362b94d5Smrg           || (*str == '$')
647362b94d5Smrg        )
648362b94d5Smrg        str++;
649444c061aSmrg    return str;
650444c061aSmrg}
651444c061aSmrg
652362b94d5Smrgstatic String
653362b94d5SmrgFetchModifierToken(String str, XrmQuark *token_return)
654444c061aSmrg{
655444c061aSmrg    String start = str;
656444c061aSmrg
657444c061aSmrg    if (*str == '$') {
658444c061aSmrg        *token_return = QMeta;
659444c061aSmrg        str++;
660362b94d5Smrg    }
661362b94d5Smrg    else if (*str == '^') {
662444c061aSmrg        *token_return = QCtrl;
663444c061aSmrg        str++;
664362b94d5Smrg    }
665362b94d5Smrg    else {
666362b94d5Smrg        str = ScanIdent(str);
667362b94d5Smrg        if (start != str) {
668362b94d5Smrg            char modStrbuf[100];
669362b94d5Smrg            char *modStr;
670362b94d5Smrg
671362b94d5Smrg            modStr = XtStackAlloc((size_t) (str - start + 1), modStrbuf);
672362b94d5Smrg            if (modStr == NULL)
673362b94d5Smrg                _XtAllocError(NULL);
674a773ec55Smrg            (void) memcpy(modStr, start, (size_t) (str - start));
675362b94d5Smrg            modStr[str - start] = '\0';
676362b94d5Smrg            *token_return = XrmStringToQuark(modStr);
677362b94d5Smrg            XtStackFree(modStr, modStrbuf);
678362b94d5Smrg        }
679444c061aSmrg    }
680444c061aSmrg    return str;
681444c061aSmrg}
682444c061aSmrg
683362b94d5Smrgstatic String
684362b94d5SmrgParseModifiers(register String str, EventPtr event, Boolean *error)
685444c061aSmrg{
686444c061aSmrg    register String start;
687444c061aSmrg    Boolean notFlag, exclusive, keysymAsMod;
688444c061aSmrg    Value maskBit;
68972af6995Smrg    XrmQuark Qmod = QNone;
690444c061aSmrg
691444c061aSmrg    ScanWhitespace(str);
692444c061aSmrg    start = str;
693444c061aSmrg    str = FetchModifierToken(str, &Qmod);
694444c061aSmrg    exclusive = FALSE;
695444c061aSmrg    if (start != str) {
696362b94d5Smrg        if (Qmod == QNone) {
697362b94d5Smrg            event->event.modifierMask = (unsigned long) (~0);
698362b94d5Smrg            event->event.modifiers = 0;
699362b94d5Smrg            ScanWhitespace(str);
700362b94d5Smrg            return str;
701444c061aSmrg        }
702a773ec55Smrg        else if (Qmod == QAny) {        /*backward compatibility */
703362b94d5Smrg            event->event.modifierMask = 0;
704362b94d5Smrg            event->event.modifiers = AnyModifier;
705362b94d5Smrg            ScanWhitespace(str);
706362b94d5Smrg            return str;
707444c061aSmrg        }
708362b94d5Smrg        str = start;            /*if plain modifier, reset to beginning */
709444c061aSmrg    }
710362b94d5Smrg    else
711362b94d5Smrg        while (*str == '!' || *str == ':') {
712362b94d5Smrg            if (*str == '!') {
713362b94d5Smrg                exclusive = TRUE;
714362b94d5Smrg                str++;
715362b94d5Smrg                ScanWhitespace(str);
716362b94d5Smrg            }
717362b94d5Smrg            if (*str == ':') {
718362b94d5Smrg                event->event.standard = TRUE;
719362b94d5Smrg                str++;
720362b94d5Smrg                ScanWhitespace(str);
721362b94d5Smrg            }
722362b94d5Smrg        }
723444c061aSmrg
724444c061aSmrg    while (*str != '<') {
725444c061aSmrg        if (*str == '~') {
726362b94d5Smrg            notFlag = TRUE;
727362b94d5Smrg            str++;
728362b94d5Smrg        }
729362b94d5Smrg        else
730362b94d5Smrg            notFlag = FALSE;
731444c061aSmrg        if (*str == '@') {
732444c061aSmrg            keysymAsMod = TRUE;
733444c061aSmrg            str++;
734444c061aSmrg        }
735362b94d5Smrg        else
736362b94d5Smrg            keysymAsMod = FALSE;
737362b94d5Smrg        start = str;
738444c061aSmrg        str = FetchModifierToken(str, &Qmod);
739444c061aSmrg        if (start == str) {
740362b94d5Smrg            Syntax("Modifier or '<' expected", "");
741362b94d5Smrg            *error = TRUE;
742362b94d5Smrg            return PanicModeRecovery(str);
743362b94d5Smrg        }
744362b94d5Smrg        if (keysymAsMod) {
745362b94d5Smrg            _XtParseKeysymMod(XrmQuarkToString(Qmod),
746362b94d5Smrg                              &event->event.lateModifiers,
747362b94d5Smrg                              notFlag, &maskBit, error);
748362b94d5Smrg            if (*error)
749362b94d5Smrg                return PanicModeRecovery(str);
750362b94d5Smrg
751362b94d5Smrg        }
752362b94d5Smrg        else if (!_XtLookupModifier(Qmod, &event->event.lateModifiers,
753362b94d5Smrg                                    notFlag, &maskBit, FALSE)) {
754362b94d5Smrg            Syntax("Unknown modifier name:  ", XrmQuarkToString(Qmod));
755444c061aSmrg            *error = TRUE;
756444c061aSmrg            return PanicModeRecovery(str);
757444c061aSmrg        }
758444c061aSmrg        event->event.modifierMask |= maskBit;
759362b94d5Smrg        if (notFlag)
760362b94d5Smrg            event->event.modifiers =
761362b94d5Smrg                (event->event.modifiers & (TMLongCard) (~maskBit));
762362b94d5Smrg        else
763362b94d5Smrg            event->event.modifiers |= maskBit;
764444c061aSmrg        ScanWhitespace(str);
765444c061aSmrg    }
766362b94d5Smrg    if (exclusive)
767362b94d5Smrg        event->event.modifierMask = (unsigned long) (~0);
768444c061aSmrg    return str;
769444c061aSmrg}
770444c061aSmrg
771362b94d5Smrgstatic String
772362b94d5SmrgParseXtEventType(register String str,
773362b94d5Smrg                 EventPtr event,
774362b94d5Smrg                 Cardinal *tmEventP,
775362b94d5Smrg                 Boolean *error)
776444c061aSmrg{
777444c061aSmrg    String start = str;
778444c061aSmrg    char eventTypeStrbuf[100];
779362b94d5Smrg    char *eventTypeStr;
780444c061aSmrg
781444c061aSmrg    ScanAlphanumeric(str);
782362b94d5Smrg    eventTypeStr = XtStackAlloc((size_t) (str - start + 1), eventTypeStrbuf);
783362b94d5Smrg    if (eventTypeStr == NULL)
784362b94d5Smrg        _XtAllocError(NULL);
785a773ec55Smrg    (void) memcpy(eventTypeStr, start, (size_t) (str - start));
786362b94d5Smrg    eventTypeStr[str - start] = '\0';
787362b94d5Smrg    *tmEventP = LookupTMEventType(eventTypeStr, error);
788362b94d5Smrg    XtStackFree(eventTypeStr, eventTypeStrbuf);
789444c061aSmrg    if (*error)
790444c061aSmrg        return PanicModeRecovery(str);
79172af6995Smrg    event->event.eventType = (TMLongCard) events[*tmEventP].eventType;
792444c061aSmrg    return str;
793444c061aSmrg}
794444c061aSmrg
795362b94d5Smrgstatic unsigned long
796362b94d5SmrgStrToHex(String str)
797444c061aSmrg{
798362b94d5Smrg    register char c;
799362b94d5Smrg    register unsigned long val = 0;
800444c061aSmrg
801444c061aSmrg    while ((c = *str)) {
802362b94d5Smrg        if ('0' <= c && c <= '9')
803362b94d5Smrg            val = (unsigned long) (val * 16 + (unsigned long) c - '0');
804362b94d5Smrg        else if ('a' <= c && c <= 'z')
805362b94d5Smrg            val = (unsigned long) (val * 16 + (unsigned long) c - 'a' + 10);
806362b94d5Smrg        else if ('A' <= c && c <= 'Z')
807362b94d5Smrg            val = (unsigned long) (val * 16 + (unsigned long) c - 'A' + 10);
808362b94d5Smrg        else
809362b94d5Smrg            return 0;
810362b94d5Smrg        str++;
811444c061aSmrg    }
812444c061aSmrg
813444c061aSmrg    return val;
814444c061aSmrg}
815444c061aSmrg
816362b94d5Smrgstatic unsigned long
817362b94d5SmrgStrToOct(String str)
818444c061aSmrg{
819444c061aSmrg    register char c;
820362b94d5Smrg    register unsigned long val = 0;
821444c061aSmrg
822444c061aSmrg    while ((c = *str)) {
823362b94d5Smrg        if ('0' <= c && c <= '7')
824362b94d5Smrg            val = val * 8 + (unsigned long) c - '0';
825362b94d5Smrg        else
826362b94d5Smrg            return 0;
827362b94d5Smrg        str++;
828444c061aSmrg    }
829444c061aSmrg
830444c061aSmrg    return val;
831444c061aSmrg}
832444c061aSmrg
833362b94d5Smrgstatic unsigned long
834362b94d5SmrgStrToNum(String str)
835444c061aSmrg{
836444c061aSmrg    register char c;
837444c061aSmrg    register unsigned long val = 0;
838444c061aSmrg
839444c061aSmrg    if (*str == '0') {
840362b94d5Smrg        str++;
841362b94d5Smrg        if (*str == 'x' || *str == 'X')
842362b94d5Smrg            return StrToHex(++str);
843362b94d5Smrg        else
844362b94d5Smrg            return StrToOct(str);
845444c061aSmrg    }
846444c061aSmrg
847444c061aSmrg    while ((c = *str)) {
848362b94d5Smrg        if ('0' <= c && c <= '9')
849362b94d5Smrg            val = val * 10 + (unsigned long) c - '0';
850362b94d5Smrg        else
851362b94d5Smrg            return 0;
852362b94d5Smrg        str++;
853444c061aSmrg    }
854444c061aSmrg
855444c061aSmrg    return val;
856444c061aSmrg}
857444c061aSmrg
858362b94d5Smrgstatic KeySym
859362b94d5SmrgStringToKeySym(String str, Boolean *error)
860444c061aSmrg{
861444c061aSmrg    KeySym k;
862444c061aSmrg
863362b94d5Smrg    if (str == NULL || *str == '\0')
864362b94d5Smrg        return (KeySym) 0;
865444c061aSmrg
866444c061aSmrg#ifndef NOTASCII
867444c061aSmrg    /* special case single character ASCII, for speed */
868362b94d5Smrg    if (*(str + 1) == '\0') {
869362b94d5Smrg        if (' ' <= *str && *str <= '~')
870362b94d5Smrg            return (KeySym) (XK_space + (*str - ' '));
871444c061aSmrg    }
872444c061aSmrg#endif
873444c061aSmrg
874362b94d5Smrg    if ('0' <= *str && *str <= '9')
875362b94d5Smrg        return (KeySym) StrToNum(str);
876444c061aSmrg    k = XStringToKeysym(str);
877362b94d5Smrg    if (k != NoSymbol)
878362b94d5Smrg        return k;
879444c061aSmrg
880444c061aSmrg#ifdef NOTASCII
881444c061aSmrg    /* fall-back case to preserve backwards compatibility; no-one
882444c061aSmrg     * should be relying upon this!
883444c061aSmrg     */
884362b94d5Smrg    if (*(str + 1) == '\0')
885362b94d5Smrg        return (KeySym) * str;
886444c061aSmrg#endif
887444c061aSmrg
888444c061aSmrg    Syntax("Unknown keysym name: ", str);
889444c061aSmrg    *error = TRUE;
890444c061aSmrg    return NoSymbol;
891444c061aSmrg}
892362b94d5Smrg
893362b94d5Smrgstatic void
894362b94d5SmrgParseModImmed(Value value,
895362b94d5Smrg              LateBindingsPtr *lateBindings _X_UNUSED,
896362b94d5Smrg              Boolean notFlag _X_UNUSED,
897362b94d5Smrg              Value *valueP)
898444c061aSmrg{
899444c061aSmrg    *valueP = value;
900444c061aSmrg}
901444c061aSmrg
902362b94d5Smrg/* is only valid with keysyms that have an _L and _R in their name;
903362b94d5Smrg * and ignores keysym lookup errors (i.e. assumes only valid keysyms)
904362b94d5Smrg */
905362b94d5Smrgstatic void
906362b94d5SmrgParseModSym(Value value,
907362b94d5Smrg            LateBindingsPtr *lateBindings, Boolean notFlag, Value *valueP)
908444c061aSmrg{
909362b94d5Smrg    register KeySym keysymL = (KeySym) value;
910362b94d5Smrg    register KeySym keysymR = keysymL + 1;      /* valid for supported keysyms */
911362b94d5Smrg
912362b94d5Smrg    StoreLateBindings(keysymL, notFlag, keysymR, notFlag, lateBindings);
913444c061aSmrg    *valueP = 0;
914444c061aSmrg}
915444c061aSmrg
916444c061aSmrg#ifdef sparc
917444c061aSmrg/*
918444c061aSmrg * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that
919444c061aSmrg * causes the value of the most recently used variable to be returned instead
920444c061aSmrg * of the value passed in.
921444c061aSmrg */
922444c061aSmrgstatic String stupid_optimizer_kludge;
923362b94d5Smrg
924444c061aSmrg#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val)
925444c061aSmrg#else
926444c061aSmrg#define BROKEN_OPTIMIZER_HACK(val) val
927444c061aSmrg#endif
928444c061aSmrg
929362b94d5Smrgstatic String
930362b94d5SmrgParseImmed(register String str,
931362b94d5Smrg           register Opaque closure,
932362b94d5Smrg           register EventPtr event,
933362b94d5Smrg           Boolean *error _X_UNUSED)
934444c061aSmrg{
935362b94d5Smrg    event->event.eventCode = (unsigned long) closure;
93672af6995Smrg    event->event.eventCodeMask = (unsigned long) (~0UL);
937444c061aSmrg
938444c061aSmrg    return BROKEN_OPTIMIZER_HACK(str);
939444c061aSmrg}
940444c061aSmrg
941362b94d5Smrgstatic String
942362b94d5SmrgParseAddModifier(register String str,
943362b94d5Smrg                 register Opaque closure,
944362b94d5Smrg                 register EventPtr event,
945362b94d5Smrg                 Boolean *error _X_UNUSED)
946444c061aSmrg{
947362b94d5Smrg    register unsigned long modval = (unsigned long) closure;
948362b94d5Smrg
949444c061aSmrg    event->event.modifiers |= modval;
950362b94d5Smrg    if (modval != AnyButtonMask)        /* AnyButtonMask is don't-care mask */
951362b94d5Smrg        event->event.modifierMask |= modval;
952444c061aSmrg
953444c061aSmrg    return BROKEN_OPTIMIZER_HACK(str);
954444c061aSmrg}
955444c061aSmrg
956362b94d5Smrgstatic String
957362b94d5SmrgParseKeyAndModifiers(String str,
958362b94d5Smrg                     Opaque closure,
959362b94d5Smrg                     EventPtr event,
960362b94d5Smrg                     Boolean *error)
961444c061aSmrg{
962362b94d5Smrg    str = ParseKeySym(str, closure, event, error);
963444c061aSmrg    if ((unsigned long) closure == 0) {
964362b94d5Smrg        Value metaMask;         /* unused */
965362b94d5Smrg
966362b94d5Smrg        (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
967362b94d5Smrg                                 &metaMask, FALSE);
968362b94d5Smrg    }
969362b94d5Smrg    else {
970362b94d5Smrg        event->event.modifiers |= (unsigned long) closure;
971362b94d5Smrg        event->event.modifierMask |= (unsigned long) closure;
972444c061aSmrg    }
973444c061aSmrg    return str;
974444c061aSmrg}
975444c061aSmrg
976362b94d5Smrgstatic String
977362b94d5SmrgParseKeySym(register String str,
978362b94d5Smrg            Opaque closure _X_UNUSED,
979362b94d5Smrg            EventPtr event,
980362b94d5Smrg            Boolean *error)
981444c061aSmrg{
98272af6995Smrg    String start;
983444c061aSmrg    char keySymNamebuf[100];
984362b94d5Smrg    char *keySymName = NULL;
985444c061aSmrg
986444c061aSmrg    ScanWhitespace(str);
987444c061aSmrg
988444c061aSmrg    if (*str == '\\') {
989362b94d5Smrg        keySymName = keySymNamebuf;
990362b94d5Smrg        str++;
991362b94d5Smrg        keySymName[0] = *str;
992362b94d5Smrg        if (*str != '\0' && !IsNewline(*str))
993362b94d5Smrg            str++;
994362b94d5Smrg        keySymName[1] = '\0';
995362b94d5Smrg        event->event.eventCode = StringToKeySym(keySymName, error);
996362b94d5Smrg        event->event.eventCodeMask = (unsigned long) (~0L);
997362b94d5Smrg    }
998362b94d5Smrg    else if (*str == ',' || *str == ':' ||
999444c061aSmrg             /* allow leftparen to be single char symbol,
1000444c061aSmrg              * for backwards compatibility
1001444c061aSmrg              */
1002362b94d5Smrg             (*str == '(' && *(str + 1) >= '0' && *(str + 1) <= '9')) {
1003362b94d5Smrg        keySymName = keySymNamebuf;     /* just so we can stackfree it later */
1004a773ec55Smrg        keySymName[0] = '\0';
1005362b94d5Smrg        /* no detail */
1006362b94d5Smrg        event->event.eventCode = 0L;
1007444c061aSmrg        event->event.eventCodeMask = 0L;
1008362b94d5Smrg    }
1009362b94d5Smrg    else {
1010362b94d5Smrg        start = str;
1011362b94d5Smrg        while (*str != ','
1012362b94d5Smrg               && *str != ':' && *str != ' ' && *str != '\t' && !IsNewline(*str)
1013362b94d5Smrg               && (*str != '(' || *(str + 1) <= '0' || *(str + 1) >= '9')
1014362b94d5Smrg               && *str != '\0')
1015362b94d5Smrg            str++;
1016362b94d5Smrg        keySymName = XtStackAlloc((size_t) (str - start + 1), keySymNamebuf);
1017a773ec55Smrg        (void) memcpy(keySymName, start, (size_t) (str - start));
1018362b94d5Smrg        keySymName[str - start] = '\0';
1019362b94d5Smrg        event->event.eventCode = StringToKeySym(keySymName, error);
1020362b94d5Smrg        event->event.eventCodeMask = (unsigned long) (~0L);
1021444c061aSmrg    }
102272af6995Smrg    if (*error && keySymName) {
1023362b94d5Smrg        /* We never get here when keySymName hasn't been allocated */
1024362b94d5Smrg        if (keySymName[0] == '<') {
1025362b94d5Smrg            /* special case for common error */
1026362b94d5Smrg            XtWarningMsg(XtNtranslationParseError, "missingComma",
1027362b94d5Smrg                         XtCXtToolkitError,
1028362b94d5Smrg                         "... possibly due to missing ',' in event sequence.",
1029362b94d5Smrg                         (String *) NULL, (Cardinal *) NULL);
1030362b94d5Smrg        }
1031362b94d5Smrg        XtStackFree(keySymName, keySymNamebuf);
1032362b94d5Smrg        return PanicModeRecovery(str);
1033444c061aSmrg    }
1034444c061aSmrg    if (event->event.standard)
1035362b94d5Smrg        event->event.matchEvent = _XtMatchUsingStandardMods;
1036444c061aSmrg    else
1037362b94d5Smrg        event->event.matchEvent = _XtMatchUsingDontCareMods;
1038444c061aSmrg
1039362b94d5Smrg    XtStackFree(keySymName, keySymNamebuf);
1040444c061aSmrg
1041444c061aSmrg    return str;
1042444c061aSmrg}
1043444c061aSmrg
1044362b94d5Smrgstatic String
1045362b94d5SmrgParseTable(register String str, Opaque closure, EventPtr event, Boolean *error)
1046444c061aSmrg{
1047444c061aSmrg    register String start = str;
1048444c061aSmrg    register XrmQuark signature;
1049444c061aSmrg    NameValueTable table = (NameValueTable) closure;
1050444c061aSmrg    char tableSymName[100];
1051444c061aSmrg
1052444c061aSmrg    event->event.eventCode = 0L;
1053444c061aSmrg    ScanAlphanumeric(str);
1054362b94d5Smrg    if (str == start) {
1055362b94d5Smrg        event->event.eventCodeMask = 0L;
1056362b94d5Smrg        return str;
1057362b94d5Smrg    }
1058362b94d5Smrg    if (str - start >= 99) {
1059362b94d5Smrg        Syntax("Invalid Detail Type (string is too long).", "");
1060362b94d5Smrg        *error = TRUE;
1061362b94d5Smrg        return str;
1062362b94d5Smrg    }
1063a773ec55Smrg    (void) memcpy(tableSymName, start, (size_t) (str - start));
1064362b94d5Smrg    tableSymName[str - start] = '\0';
1065444c061aSmrg    signature = StringToQuark(tableSymName);
1066444c061aSmrg    for (; table->signature != NULLQUARK; table++)
1067362b94d5Smrg        if (table->signature == signature) {
1068362b94d5Smrg            event->event.eventCode = table->value;
1069362b94d5Smrg            event->event.eventCodeMask = (unsigned long) (~0L);
1070362b94d5Smrg            return str;
1071362b94d5Smrg        }
1072444c061aSmrg
1073444c061aSmrg    Syntax("Unknown Detail Type:  ", tableSymName);
1074444c061aSmrg    *error = TRUE;
1075444c061aSmrg    return PanicModeRecovery(str);
1076444c061aSmrg}
1077444c061aSmrg
1078a773ec55Smrgstatic String
10797854a16aSmrgParseButton(String str, Opaque closure _X_UNUSED, EventPtr event, Boolean *error)
1080a773ec55Smrg{
1081a773ec55Smrg    String start = str;
1082a773ec55Smrg    char buttonStr[7];
1083a773ec55Smrg    size_t len;
1084a773ec55Smrg    static const char buttonPrefix[] = "Button";
1085a773ec55Smrg    unsigned long button;
1086a773ec55Smrg
1087a773ec55Smrg    event->event.eventCode = 0L;
1088a773ec55Smrg    if (strncmp(str, buttonPrefix, sizeof(buttonPrefix)-1) != 0) {
1089a773ec55Smrg	event->event.eventCodeMask = 0L;
1090a773ec55Smrg	return str;
1091a773ec55Smrg    }
1092a773ec55Smrg    str += sizeof(buttonPrefix)-1;
1093a773ec55Smrg    start = str;
1094a773ec55Smrg    ScanNumeric(str);
1095a773ec55Smrg    if (str == start) {
1096a773ec55Smrg	Syntax("Missing button number", "");
1097a773ec55Smrg	*error = TRUE;
1098a773ec55Smrg	return PanicModeRecovery(str);
1099a773ec55Smrg    }
1100a773ec55Smrg    len = (size_t) (str - start);
1101a773ec55Smrg    if (len >= sizeof buttonStr) {
1102a773ec55Smrg	Syntax("Button number too long", "");
1103a773ec55Smrg	*error = TRUE;
1104a773ec55Smrg	return PanicModeRecovery(str);
1105a773ec55Smrg    }
1106a773ec55Smrg    (void) memcpy(buttonStr, start, len);
1107a773ec55Smrg    buttonStr[len] = '\0';
1108a773ec55Smrg    button = StrToNum(buttonStr);
1109a773ec55Smrg    if (button < 1 || 255 < button) {
1110a773ec55Smrg	Syntax("Invalid button number", buttonStr);
1111a773ec55Smrg	*error = TRUE;
1112a773ec55Smrg	return PanicModeRecovery(str);
1113a773ec55Smrg    }
1114a773ec55Smrg    event->event.eventCode = button;
1115a773ec55Smrg    event->event.eventCodeMask = (unsigned long) (~0L);
1116a773ec55Smrg    return str;
1117a773ec55Smrg}
1118a773ec55Smrg
1119362b94d5Smrgstatic String
1120362b94d5SmrgParseNone(String str,
1121362b94d5Smrg          Opaque closure _X_UNUSED,
1122362b94d5Smrg          EventPtr event,
1123362b94d5Smrg          Boolean *error _X_UNUSED)
1124444c061aSmrg{
1125444c061aSmrg    event->event.eventCode = 0;
1126444c061aSmrg    event->event.eventCodeMask = 0;
1127444c061aSmrg
1128444c061aSmrg    return BROKEN_OPTIMIZER_HACK(str);
1129444c061aSmrg}
1130444c061aSmrg
1131362b94d5Smrgstatic String
1132362b94d5SmrgParseAtom(String str, Opaque closure _X_UNUSED, EventPtr event, Boolean *error)
1133444c061aSmrg{
1134444c061aSmrg    ScanWhitespace(str);
1135444c061aSmrg
1136444c061aSmrg    if (*str == ',' || *str == ':') {
1137362b94d5Smrg        /* no detail */
1138362b94d5Smrg        event->event.eventCode = 0L;
1139444c061aSmrg        event->event.eventCodeMask = 0L;
1140362b94d5Smrg    }
1141362b94d5Smrg    else {
1142362b94d5Smrg        String start;
1143362b94d5Smrg        char atomName[1000];
1144362b94d5Smrg
1145362b94d5Smrg        start = str;
1146362b94d5Smrg        while (*str != ','
1147362b94d5Smrg               && *str != ':' && *str != ' ' && *str != '\t' && !IsNewline(*str)
1148362b94d5Smrg               && *str != '\0')
1149362b94d5Smrg            str++;
1150362b94d5Smrg        if (str - start >= 999) {
1151362b94d5Smrg            Syntax("Atom name must be less than 1000 characters long.", "");
1152362b94d5Smrg            *error = TRUE;
1153362b94d5Smrg            return str;
1154362b94d5Smrg        }
1155a773ec55Smrg        (void) memcpy(atomName, start, (size_t) (str - start));
1156362b94d5Smrg        atomName[str - start] = '\0';
1157362b94d5Smrg        event->event.eventCode = (TMLongCard) XrmStringToQuark(atomName);
1158362b94d5Smrg        event->event.matchEvent = _XtMatchAtom;
1159444c061aSmrg    }
1160444c061aSmrg    return str;
1161444c061aSmrg}
1162444c061aSmrg
1163444c061aSmrgstatic ModifierMask buttonModifierMasks[] = {
1164444c061aSmrg    0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
1165444c061aSmrg};
1166362b94d5Smrg
1167444c061aSmrgstatic String ParseRepeat(String, int *, Boolean *, Boolean *);
1168444c061aSmrg
1169362b94d5Smrgstatic String
1170362b94d5SmrgParseEvent(register String str,
1171362b94d5Smrg           EventPtr event, int *reps,
1172362b94d5Smrg           Boolean *plus,
1173362b94d5Smrg           Boolean *error)
1174444c061aSmrg{
1175362b94d5Smrg    Cardinal tmEvent;
1176444c061aSmrg
1177362b94d5Smrg    str = ParseModifiers(str, event, error);
1178362b94d5Smrg    if (*error)
1179362b94d5Smrg        return str;
1180444c061aSmrg    if (*str != '<') {
1181362b94d5Smrg        Syntax("Missing '<' while parsing event type.", "");
1182362b94d5Smrg        *error = TRUE;
1183362b94d5Smrg        return PanicModeRecovery(str);
1184362b94d5Smrg    }
1185362b94d5Smrg    else
1186362b94d5Smrg        str++;
1187362b94d5Smrg    str = ParseXtEventType(str, event, &tmEvent, error);
1188362b94d5Smrg    if (*error)
1189362b94d5Smrg        return str;
1190362b94d5Smrg    if (*str != '>') {
1191362b94d5Smrg        Syntax("Missing '>' while parsing event type", "");
1192362b94d5Smrg        *error = TRUE;
1193362b94d5Smrg        return PanicModeRecovery(str);
1194362b94d5Smrg    }
1195362b94d5Smrg    else
1196362b94d5Smrg        str++;
1197444c061aSmrg    if (*str == '(') {
1198362b94d5Smrg        str = ParseRepeat(str, reps, plus, error);
1199362b94d5Smrg        if (*error)
1200362b94d5Smrg            return str;
1201444c061aSmrg    }
1202362b94d5Smrg    str =
1203362b94d5Smrg        (*(events[tmEvent].parseDetail)) (str, events[tmEvent].closure, event,
1204362b94d5Smrg                                          error);
1205362b94d5Smrg    if (*error)
1206362b94d5Smrg        return str;
1207444c061aSmrg
1208444c061aSmrg/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t.
1209444c061aSmrg * modifiers in grabs.
1210444c061aSmrg */
1211444c061aSmrg    if ((event->event.eventType == ButtonRelease)
1212362b94d5Smrg        && (event->event.modifiers | event->event.modifierMask) /* any */
1213362b94d5Smrg        &&(event->event.modifiers != AnyModifier)) {
1214362b94d5Smrg        event->event.modifiers = (event->event.modifiers
1215362b94d5Smrg                                  | (TMLongCard) buttonModifierMasks[event->
1216362b94d5Smrg                                                                     event.
1217362b94d5Smrg                                                                     eventCode]);
1218362b94d5Smrg        /* the button that is going up will always be in the modifiers... */
1219444c061aSmrg    }
1220444c061aSmrg
1221444c061aSmrg    return str;
1222444c061aSmrg}
1223444c061aSmrg
1224362b94d5Smrgstatic String
1225362b94d5SmrgParseQuotedStringEvent(register String str,
1226362b94d5Smrg                       register EventPtr event,
1227362b94d5Smrg                       Boolean *error)
1228444c061aSmrg{
1229444c061aSmrg    Value metaMask;
1230362b94d5Smrg    char s[2];
1231444c061aSmrg
1232362b94d5Smrg    if (*str == '^') {
1233362b94d5Smrg        str++;
1234362b94d5Smrg        event->event.modifiers = ControlMask;
1235362b94d5Smrg    }
1236362b94d5Smrg    else if (*str == '$') {
1237362b94d5Smrg        str++;
1238362b94d5Smrg        (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
1239362b94d5Smrg                                 &metaMask, FALSE);
1240444c061aSmrg    }
1241444c061aSmrg    if (*str == '\\')
1242362b94d5Smrg        str++;
1243444c061aSmrg    s[0] = *str;
1244444c061aSmrg    s[1] = '\0';
1245362b94d5Smrg    if (*str != '\0' && !IsNewline(*str))
1246362b94d5Smrg        str++;
1247444c061aSmrg    event->event.eventType = KeyPress;
1248444c061aSmrg    event->event.eventCode = StringToKeySym(s, error);
1249362b94d5Smrg    if (*error)
1250362b94d5Smrg        return PanicModeRecovery(str);
125172af6995Smrg    event->event.eventCodeMask = (unsigned long) (~0L);
1252444c061aSmrg    event->event.matchEvent = _XtMatchUsingStandardMods;
1253444c061aSmrg    event->event.standard = TRUE;
1254444c061aSmrg
1255444c061aSmrg    return str;
1256444c061aSmrg}
1257444c061aSmrg
1258444c061aSmrgstatic EventSeqRec timerEventRec = {
1259444c061aSmrg    {0, 0, NULL, _XtEventTimerEventType, 0L, 0L, NULL, False},
1260444c061aSmrg    /* (StatePtr) -1 */ NULL,
1261444c061aSmrg    NULL,
1262444c061aSmrg    NULL
1263444c061aSmrg};
1264444c061aSmrg
1265362b94d5Smrgstatic void
1266362b94d5SmrgRepeatDown(EventPtr *eventP, int reps, ActionPtr **actionsP)
1267444c061aSmrg{
1268444c061aSmrg    EventRec upEventRec;
1269444c061aSmrg    register EventPtr event, downEvent;
1270444c061aSmrg    EventPtr upEvent = &upEventRec;
1271444c061aSmrg    register int i;
1272444c061aSmrg
1273444c061aSmrg    downEvent = event = *eventP;
1274444c061aSmrg    *upEvent = *downEvent;
1275444c061aSmrg    upEvent->event.eventType = ((event->event.eventType == ButtonPress) ?
1276362b94d5Smrg                                ButtonRelease : KeyRelease);
1277444c061aSmrg    if ((upEvent->event.eventType == ButtonRelease)
1278362b94d5Smrg        && (upEvent->event.modifiers != AnyModifier)
1279444c061aSmrg        && (upEvent->event.modifiers | upEvent->event.modifierMask))
1280362b94d5Smrg        upEvent->event.modifiers = (upEvent->event.modifiers
1281362b94d5Smrg                                    | (TMLongCard) buttonModifierMasks[event->
1282362b94d5Smrg                                                                       event.
1283362b94d5Smrg                                                                       eventCode]);
1284444c061aSmrg
1285444c061aSmrg    if (event->event.lateModifiers)
1286362b94d5Smrg        event->event.lateModifiers->ref_count =
1287362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count +
1288362b94d5Smrg                              (reps - 1) * 2);
1289444c061aSmrg
1290362b94d5Smrg    for (i = 1; i < reps; i++) {
1291444c061aSmrg
1292362b94d5Smrg        /* up */
1293362b94d5Smrg        event->next = XtNew(EventSeqRec);
1294362b94d5Smrg        event = event->next;
1295362b94d5Smrg        *event = *upEvent;
1296444c061aSmrg
1297362b94d5Smrg        /* timer */
1298362b94d5Smrg        event->next = XtNew(EventSeqRec);
1299362b94d5Smrg        event = event->next;
1300362b94d5Smrg        *event = timerEventRec;
1301444c061aSmrg
1302362b94d5Smrg        /* down */
1303362b94d5Smrg        event->next = XtNew(EventSeqRec);
1304362b94d5Smrg        event = event->next;
1305362b94d5Smrg        *event = *downEvent;
1306444c061aSmrg
1307444c061aSmrg    }
1308444c061aSmrg
1309444c061aSmrg    event->next = NULL;
1310444c061aSmrg    *eventP = event;
1311444c061aSmrg    *actionsP = &event->actions;
1312444c061aSmrg}
1313444c061aSmrg
1314362b94d5Smrgstatic void
1315362b94d5SmrgRepeatDownPlus(EventPtr *eventP, int reps, ActionPtr **actionsP)
1316444c061aSmrg{
1317444c061aSmrg    EventRec upEventRec;
1318444c061aSmrg    register EventPtr event, downEvent, lastDownEvent = NULL;
1319444c061aSmrg    EventPtr upEvent = &upEventRec;
1320444c061aSmrg    register int i;
1321444c061aSmrg
1322444c061aSmrg    downEvent = event = *eventP;
1323444c061aSmrg    *upEvent = *downEvent;
1324444c061aSmrg    upEvent->event.eventType = ((event->event.eventType == ButtonPress) ?
1325362b94d5Smrg                                ButtonRelease : KeyRelease);
1326444c061aSmrg    if ((upEvent->event.eventType == ButtonRelease)
1327362b94d5Smrg        && (upEvent->event.modifiers != AnyModifier)
1328444c061aSmrg        && (upEvent->event.modifiers | upEvent->event.modifierMask))
1329362b94d5Smrg        upEvent->event.modifiers = (upEvent->event.modifiers
1330362b94d5Smrg                                    | (TMLongCard) buttonModifierMasks[event->
1331362b94d5Smrg                                                                       event.
1332362b94d5Smrg                                                                       eventCode]);
1333444c061aSmrg
1334444c061aSmrg    if (event->event.lateModifiers)
1335362b94d5Smrg        event->event.lateModifiers->ref_count =
1336362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps * 2 -
1337362b94d5Smrg                              1);
1338444c061aSmrg
1339362b94d5Smrg    for (i = 0; i < reps; i++) {
1340444c061aSmrg
1341362b94d5Smrg        if (i > 0) {
1342362b94d5Smrg            /* down */
1343362b94d5Smrg            event->next = XtNew(EventSeqRec);
1344362b94d5Smrg            event = event->next;
1345362b94d5Smrg            *event = *downEvent;
1346362b94d5Smrg        }
1347362b94d5Smrg        lastDownEvent = event;
1348444c061aSmrg
1349362b94d5Smrg        /* up */
1350362b94d5Smrg        event->next = XtNew(EventSeqRec);
1351362b94d5Smrg        event = event->next;
1352362b94d5Smrg        *event = *upEvent;
1353444c061aSmrg
1354362b94d5Smrg        /* timer */
1355362b94d5Smrg        event->next = XtNew(EventSeqRec);
1356362b94d5Smrg        event = event->next;
1357362b94d5Smrg        *event = timerEventRec;
1358444c061aSmrg
1359444c061aSmrg    }
1360444c061aSmrg
1361444c061aSmrg    event->next = lastDownEvent;
1362444c061aSmrg    *eventP = event;
1363444c061aSmrg    *actionsP = &lastDownEvent->actions;
1364444c061aSmrg}
1365444c061aSmrg
1366362b94d5Smrgstatic void
1367362b94d5SmrgRepeatUp(EventPtr *eventP, int reps, ActionPtr **actionsP)
1368444c061aSmrg{
1369444c061aSmrg    EventRec upEventRec;
1370444c061aSmrg    register EventPtr event, downEvent;
1371444c061aSmrg    EventPtr upEvent = &upEventRec;
1372444c061aSmrg    register int i;
1373444c061aSmrg
1374444c061aSmrg    /* the event currently sitting in *eventP is an "up" event */
1375444c061aSmrg    /* we want to make it a "down" event followed by an "up" event, */
1376444c061aSmrg    /* so that sequence matching on the "state" side works correctly. */
1377444c061aSmrg
1378444c061aSmrg    downEvent = event = *eventP;
1379444c061aSmrg    *upEvent = *downEvent;
1380444c061aSmrg    downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ?
1381362b94d5Smrg                                  ButtonPress : KeyPress);
1382444c061aSmrg    if ((downEvent->event.eventType == ButtonPress)
1383362b94d5Smrg        && (downEvent->event.modifiers != AnyModifier)
1384444c061aSmrg        && (downEvent->event.modifiers | downEvent->event.modifierMask))
1385362b94d5Smrg        downEvent->event.modifiers = (downEvent->event.modifiers
1386362b94d5Smrg                                      &
1387362b94d5Smrg                                      (TMLongCard) (~buttonModifierMasks
1388362b94d5Smrg                                                    [event->event.eventCode]));
1389444c061aSmrg
1390444c061aSmrg    if (event->event.lateModifiers)
1391362b94d5Smrg        event->event.lateModifiers->ref_count =
1392362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps * 2 -
1393362b94d5Smrg                              1);
1394444c061aSmrg
1395444c061aSmrg    /* up */
1396444c061aSmrg    event->next = XtNew(EventSeqRec);
1397444c061aSmrg    event = event->next;
1398444c061aSmrg    *event = *upEvent;
1399444c061aSmrg
1400362b94d5Smrg    for (i = 1; i < reps; i++) {
1401444c061aSmrg
1402362b94d5Smrg        /* timer */
1403362b94d5Smrg        event->next = XtNew(EventSeqRec);
1404362b94d5Smrg        event = event->next;
1405362b94d5Smrg        *event = timerEventRec;
1406444c061aSmrg
1407362b94d5Smrg        /* down */
1408362b94d5Smrg        event->next = XtNew(EventSeqRec);
1409362b94d5Smrg        event = event->next;
1410362b94d5Smrg        *event = *downEvent;
1411444c061aSmrg
1412362b94d5Smrg        /* up */
1413362b94d5Smrg        event->next = XtNew(EventSeqRec);
1414362b94d5Smrg        event = event->next;
1415362b94d5Smrg        *event = *upEvent;
1416444c061aSmrg
1417362b94d5Smrg    }
1418444c061aSmrg
1419444c061aSmrg    event->next = NULL;
1420444c061aSmrg    *eventP = event;
1421444c061aSmrg    *actionsP = &event->actions;
1422444c061aSmrg}
1423444c061aSmrg
1424362b94d5Smrgstatic void
1425362b94d5SmrgRepeatUpPlus(EventPtr *eventP, int reps, ActionPtr **actionsP)
1426444c061aSmrg{
1427444c061aSmrg    EventRec upEventRec;
1428444c061aSmrg    register EventPtr event, downEvent, lastUpEvent = NULL;
1429444c061aSmrg    EventPtr upEvent = &upEventRec;
1430444c061aSmrg    register int i;
1431444c061aSmrg
1432444c061aSmrg    /* the event currently sitting in *eventP is an "up" event */
1433444c061aSmrg    /* we want to make it a "down" event followed by an "up" event, */
1434444c061aSmrg    /* so that sequence matching on the "state" side works correctly. */
1435444c061aSmrg
1436444c061aSmrg    downEvent = event = *eventP;
1437444c061aSmrg    *upEvent = *downEvent;
1438444c061aSmrg    downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ?
1439362b94d5Smrg                                  ButtonPress : KeyPress);
1440444c061aSmrg    if ((downEvent->event.eventType == ButtonPress)
1441362b94d5Smrg        && (downEvent->event.modifiers != AnyModifier)
1442444c061aSmrg        && (downEvent->event.modifiers | downEvent->event.modifierMask))
1443362b94d5Smrg        downEvent->event.modifiers = (downEvent->event.modifiers
1444362b94d5Smrg                                      &
1445362b94d5Smrg                                      (TMLongCard) (~buttonModifierMasks
1446362b94d5Smrg                                                    [event->event.eventCode]));
1447444c061aSmrg
1448444c061aSmrg    if (event->event.lateModifiers)
1449362b94d5Smrg        event->event.lateModifiers->ref_count =
1450362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps * 2);
1451444c061aSmrg
1452362b94d5Smrg    for (i = 0; i < reps; i++) {
1453444c061aSmrg
1454362b94d5Smrg        /* up */
1455362b94d5Smrg        event->next = XtNew(EventSeqRec);
1456362b94d5Smrg        lastUpEvent = event = event->next;
1457362b94d5Smrg        *event = *upEvent;
1458444c061aSmrg
1459362b94d5Smrg        /* timer */
1460362b94d5Smrg        event->next = XtNew(EventSeqRec);
1461362b94d5Smrg        event = event->next;
1462362b94d5Smrg        *event = timerEventRec;
1463444c061aSmrg
1464362b94d5Smrg        /* down */
1465362b94d5Smrg        event->next = XtNew(EventSeqRec);
1466444c061aSmrg        event = event->next;
1467362b94d5Smrg        *event = *downEvent;
1468444c061aSmrg
1469362b94d5Smrg    }
1470444c061aSmrg
1471444c061aSmrg    event->next = lastUpEvent;
1472444c061aSmrg    *eventP = event;
1473444c061aSmrg    *actionsP = &lastUpEvent->actions;
1474444c061aSmrg}
1475444c061aSmrg
1476362b94d5Smrgstatic void
1477362b94d5SmrgRepeatOther(EventPtr *eventP, int reps, ActionPtr **actionsP)
1478444c061aSmrg{
1479444c061aSmrg    register EventPtr event, tempEvent;
1480444c061aSmrg    register int i;
1481444c061aSmrg
1482444c061aSmrg    tempEvent = event = *eventP;
1483444c061aSmrg
1484444c061aSmrg    if (event->event.lateModifiers)
1485362b94d5Smrg        event->event.lateModifiers->ref_count =
1486362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps - 1);
1487444c061aSmrg
1488362b94d5Smrg    for (i = 1; i < reps; i++) {
1489362b94d5Smrg        event->next = XtNew(EventSeqRec);
1490362b94d5Smrg        event = event->next;
1491362b94d5Smrg        *event = *tempEvent;
1492444c061aSmrg    }
1493444c061aSmrg
1494444c061aSmrg    *eventP = event;
1495444c061aSmrg    *actionsP = &event->actions;
1496444c061aSmrg}
1497444c061aSmrg
1498362b94d5Smrgstatic void
1499362b94d5SmrgRepeatOtherPlus(EventPtr *eventP, int reps, ActionPtr **actionsP)
1500444c061aSmrg{
1501444c061aSmrg    register EventPtr event, tempEvent;
1502444c061aSmrg    register int i;
1503444c061aSmrg
1504444c061aSmrg    tempEvent = event = *eventP;
1505444c061aSmrg
1506444c061aSmrg    if (event->event.lateModifiers)
1507362b94d5Smrg        event->event.lateModifiers->ref_count =
1508362b94d5Smrg            (unsigned short) (event->event.lateModifiers->ref_count + reps - 1);
1509444c061aSmrg
1510362b94d5Smrg    for (i = 1; i < reps; i++) {
1511362b94d5Smrg        event->next = XtNew(EventSeqRec);
1512362b94d5Smrg        event = event->next;
1513362b94d5Smrg        *event = *tempEvent;
1514444c061aSmrg    }
1515444c061aSmrg
1516444c061aSmrg    event->next = event;
1517444c061aSmrg    *eventP = event;
1518444c061aSmrg    *actionsP = &event->actions;
1519444c061aSmrg}
1520444c061aSmrg
1521362b94d5Smrgstatic void
1522362b94d5SmrgRepeatEvent(EventPtr *eventP, int reps, Boolean plus, ActionPtr **actionsP)
1523444c061aSmrg{
1524444c061aSmrg    switch ((*eventP)->event.eventType) {
1525444c061aSmrg
1526362b94d5Smrg    case ButtonPress:
1527362b94d5Smrg    case KeyPress:
1528362b94d5Smrg        if (plus)
1529362b94d5Smrg            RepeatDownPlus(eventP, reps, actionsP);
1530362b94d5Smrg        else
1531362b94d5Smrg            RepeatDown(eventP, reps, actionsP);
1532362b94d5Smrg        break;
1533362b94d5Smrg
1534362b94d5Smrg    case ButtonRelease:
1535362b94d5Smrg    case KeyRelease:
1536362b94d5Smrg        if (plus)
1537362b94d5Smrg            RepeatUpPlus(eventP, reps, actionsP);
1538362b94d5Smrg        else
1539362b94d5Smrg            RepeatUp(eventP, reps, actionsP);
1540362b94d5Smrg        break;
1541362b94d5Smrg
1542362b94d5Smrg    default:
1543362b94d5Smrg        if (plus)
1544362b94d5Smrg            RepeatOtherPlus(eventP, reps, actionsP);
1545362b94d5Smrg        else
1546362b94d5Smrg            RepeatOther(eventP, reps, actionsP);
1547444c061aSmrg    }
1548444c061aSmrg}
1549444c061aSmrg
1550362b94d5Smrgstatic String
1551362b94d5SmrgParseRepeat(register String str, int *reps, Boolean *plus, Boolean *error)
1552444c061aSmrg{
1553444c061aSmrg
1554444c061aSmrg    /*** Parse the repetitions, for double click etc... ***/
1555362b94d5Smrg    if (*str != '(' ||
1556362b94d5Smrg        !(isdigit((unsigned char) str[1]) || str[1] == '+' || str[1] == ')'))
1557362b94d5Smrg        return str;
1558444c061aSmrg    str++;
1559362b94d5Smrg    if (isdigit((unsigned char) *str)) {
1560362b94d5Smrg        String start = str;
1561362b94d5Smrg        char repStr[7];
1562362b94d5Smrg        size_t len;
1563362b94d5Smrg
1564362b94d5Smrg        ScanNumeric(str);
1565362b94d5Smrg        len = (size_t) (str - start);
1566362b94d5Smrg        if (len < sizeof repStr) {
1567a773ec55Smrg            (void) memcpy(repStr, start, len);
1568362b94d5Smrg            repStr[len] = '\0';
1569362b94d5Smrg            *reps = (int) StrToNum(repStr);
1570362b94d5Smrg        }
1571362b94d5Smrg        else {
1572362b94d5Smrg            Syntax("Repeat count too large.", "");
1573362b94d5Smrg            *error = TRUE;
1574362b94d5Smrg            return str;
1575362b94d5Smrg        }
1576444c061aSmrg    }
1577444c061aSmrg    if (*reps == 0) {
1578362b94d5Smrg        Syntax("Missing repeat count.", "");
1579362b94d5Smrg        *error = True;
1580362b94d5Smrg        return str;
1581444c061aSmrg    }
1582444c061aSmrg
1583444c061aSmrg    if (*str == '+') {
1584362b94d5Smrg        *plus = TRUE;
1585362b94d5Smrg        str++;
1586444c061aSmrg    }
1587444c061aSmrg    if (*str == ')')
1588362b94d5Smrg        str++;
1589444c061aSmrg    else {
1590362b94d5Smrg        Syntax("Missing ')'.", "");
1591362b94d5Smrg        *error = TRUE;
1592444c061aSmrg    }
1593444c061aSmrg
1594444c061aSmrg    return str;
1595444c061aSmrg}
1596444c061aSmrg
1597444c061aSmrg/***********************************************************************
1598444c061aSmrg * ParseEventSeq
1599444c061aSmrg * Parses the left hand side of a translation table production
1600444c061aSmrg * up to, and consuming the ":".
1601444c061aSmrg * Takes a pointer to a char* (where to start parsing) and returns an
1602444c061aSmrg * event seq (in a passed in variable), having updated the String
1603444c061aSmrg **********************************************************************/
1604444c061aSmrg
1605362b94d5Smrgstatic String
1606362b94d5SmrgParseEventSeq(register String str,
1607362b94d5Smrg              EventSeqPtr *eventSeqP,
1608362b94d5Smrg              ActionPtr ** actionsP,
1609362b94d5Smrg              Boolean *error)
1610444c061aSmrg{
1611444c061aSmrg    EventSeqPtr *nextEvent = eventSeqP;
1612444c061aSmrg
1613444c061aSmrg    *eventSeqP = NULL;
1614444c061aSmrg
1615362b94d5Smrg    while (*str != '\0' && !IsNewline(*str)) {
1616362b94d5Smrg        static Event nullEvent =
1617362b94d5Smrg            { 0, 0, NULL, 0, 0L, 0L, _XtRegularMatch, FALSE };
1618362b94d5Smrg        EventPtr event;
1619444c061aSmrg
1620362b94d5Smrg        ScanWhitespace(str);
1621444c061aSmrg
1622362b94d5Smrg        if (*str == '"') {
1623362b94d5Smrg            str++;
1624362b94d5Smrg            while (*str != '"' && *str != '\0' && !IsNewline(*str)) {
1625444c061aSmrg                event = XtNew(EventRec);
1626444c061aSmrg                event->event = nullEvent;
1627444c061aSmrg                event->state = /* (StatePtr) -1 */ NULL;
1628444c061aSmrg                event->next = NULL;
1629444c061aSmrg                event->actions = NULL;
1630362b94d5Smrg                str = ParseQuotedStringEvent(str, event, error);
1631362b94d5Smrg                if (*error) {
1632362b94d5Smrg                    XtWarningMsg(XtNtranslationParseError, "nonLatin1",
1633362b94d5Smrg                                 XtCXtToolkitError,
1634362b94d5Smrg                                 "... probably due to non-Latin1 character in quoted string",
1635362b94d5Smrg                                 (String *) NULL, (Cardinal *) NULL);
1636362b94d5Smrg                    XtFree((char *) event);
1637362b94d5Smrg                    return PanicModeRecovery(str);
1638362b94d5Smrg                }
1639362b94d5Smrg                *nextEvent = event;
1640362b94d5Smrg                *actionsP = &event->actions;
1641362b94d5Smrg                nextEvent = &event->next;
1642362b94d5Smrg            }
1643362b94d5Smrg            if (*str != '"') {
1644362b94d5Smrg                Syntax("Missing '\"'.", "");
1645444c061aSmrg                *error = TRUE;
1646444c061aSmrg                return PanicModeRecovery(str);
1647362b94d5Smrg            }
1648362b94d5Smrg            else
1649362b94d5Smrg                str++;
1650362b94d5Smrg        }
1651362b94d5Smrg        else {
1652362b94d5Smrg            int reps = 0;
1653362b94d5Smrg            Boolean plus = FALSE;
1654444c061aSmrg
1655444c061aSmrg            event = XtNew(EventRec);
1656444c061aSmrg            event->event = nullEvent;
1657444c061aSmrg            event->state = /* (StatePtr) -1 */ NULL;
1658444c061aSmrg            event->next = NULL;
1659444c061aSmrg            event->actions = NULL;
1660444c061aSmrg
1661362b94d5Smrg            str = ParseEvent(str, event, &reps, &plus, error);
1662362b94d5Smrg            if (*error)
1663362b94d5Smrg                return str;
1664362b94d5Smrg            *nextEvent = event;
1665362b94d5Smrg            *actionsP = &event->actions;
1666362b94d5Smrg            if (reps > 1 || plus)
1667362b94d5Smrg                RepeatEvent(&event, reps, plus, actionsP);
1668362b94d5Smrg            nextEvent = &event->next;
1669362b94d5Smrg        }
1670362b94d5Smrg        ScanWhitespace(str);
1671362b94d5Smrg        if (*str == ':')
1672362b94d5Smrg            break;
1673444c061aSmrg        else {
1674444c061aSmrg            if (*str != ',') {
1675362b94d5Smrg                Syntax("',' or ':' expected while parsing event sequence.", "");
1676444c061aSmrg                *error = TRUE;
1677444c061aSmrg                return PanicModeRecovery(str);
1678362b94d5Smrg            }
1679362b94d5Smrg            else
1680362b94d5Smrg                str++;
1681444c061aSmrg        }
1682444c061aSmrg    }
1683444c061aSmrg
1684444c061aSmrg    if (*str != ':') {
1685362b94d5Smrg        Syntax("Missing ':'after event sequence.", "");
1686444c061aSmrg        *error = TRUE;
1687444c061aSmrg        return PanicModeRecovery(str);
1688362b94d5Smrg    }
1689362b94d5Smrg    else
1690362b94d5Smrg        str++;
1691444c061aSmrg
1692444c061aSmrg    return str;
1693444c061aSmrg}
1694444c061aSmrg
1695362b94d5Smrgstatic String
1696362b94d5SmrgParseActionProc(register String str, XrmQuark *actionProcNameP, Boolean *error)
1697444c061aSmrg{
1698444c061aSmrg    register String start = str;
1699444c061aSmrg    char procName[200];
1700444c061aSmrg
1701444c061aSmrg    str = ScanIdent(str);
1702362b94d5Smrg    if (str - start >= 199) {
1703362b94d5Smrg        Syntax("Action procedure name is longer than 199 chars", "");
1704362b94d5Smrg        *error = TRUE;
1705362b94d5Smrg        return str;
1706362b94d5Smrg    }
1707a773ec55Smrg    (void) memcpy(procName, start, (size_t) (str - start));
1708362b94d5Smrg    procName[str - start] = '\0';
1709362b94d5Smrg    *actionProcNameP = XrmStringToQuark(procName);
1710444c061aSmrg    return str;
1711444c061aSmrg}
1712444c061aSmrg
1713362b94d5Smrgstatic String
1714362b94d5SmrgParseString(register String str, _XtString *strP)
1715444c061aSmrg{
1716444c061aSmrg    register String start;
1717444c061aSmrg
1718444c061aSmrg    if (*str == '"') {
1719362b94d5Smrg        register unsigned prev_len, len;
1720362b94d5Smrg
1721362b94d5Smrg        str++;
1722362b94d5Smrg        start = str;
1723362b94d5Smrg        *strP = NULL;
1724362b94d5Smrg        prev_len = 0;
1725362b94d5Smrg
1726362b94d5Smrg        while (*str != '"' && *str != '\0') {
1727362b94d5Smrg            /* \"  produces double quote embedded in a quoted parameter
1728362b94d5Smrg             * \\" produces backslash as last character of a quoted parameter
1729362b94d5Smrg             */
1730362b94d5Smrg            if (*str == '\\' &&
1731362b94d5Smrg                (*(str + 1) == '"' ||
1732362b94d5Smrg                 (*(str + 1) == '\\' && *(str + 2) == '"'))) {
1733362b94d5Smrg                len = (unsigned) (prev_len + (str - start + 2));
1734362b94d5Smrg                *strP = XtRealloc(*strP, len);
1735a773ec55Smrg                (void) memcpy(*strP + prev_len, start, (size_t) (str - start));
1736362b94d5Smrg                prev_len = len - 1;
1737362b94d5Smrg                str++;
1738362b94d5Smrg                (*strP)[prev_len - 1] = *str;
1739362b94d5Smrg                (*strP)[prev_len] = '\0';
1740362b94d5Smrg                start = str + 1;
1741362b94d5Smrg            }
1742362b94d5Smrg            str++;
1743362b94d5Smrg        }
1744362b94d5Smrg        len = (unsigned) (prev_len + (str - start + 1));
1745362b94d5Smrg        *strP = XtRealloc(*strP, len);
1746a773ec55Smrg        (void) memcpy(*strP + prev_len, start, (size_t) (str - start));
1747362b94d5Smrg        (*strP)[len - 1] = '\0';
1748362b94d5Smrg        if (*str == '"')
1749362b94d5Smrg            str++;
1750362b94d5Smrg        else
1751362b94d5Smrg            XtWarningMsg(XtNtranslationParseError, "parseString",
1752362b94d5Smrg                         XtCXtToolkitError, "Missing '\"'.",
1753362b94d5Smrg                         (String *) NULL, (Cardinal *) NULL);
1754362b94d5Smrg    }
1755362b94d5Smrg    else {
1756362b94d5Smrg        /* scan non-quoted string, stop on whitespace, ',' or ')' */
1757362b94d5Smrg        start = str;
1758362b94d5Smrg        while (*str != ' '
1759362b94d5Smrg               && *str != '\t' && *str != ',' && *str != ')' && !IsNewline(*str)
1760362b94d5Smrg               && *str != '\0')
1761362b94d5Smrg            str++;
1762362b94d5Smrg        *strP = __XtMalloc((unsigned) (str - start + 1));
1763a773ec55Smrg        (void) memcpy(*strP, start, (size_t) (str - start));
1764362b94d5Smrg        (*strP)[str - start] = '\0';
1765444c061aSmrg    }
1766444c061aSmrg    return str;
1767444c061aSmrg}
1768444c061aSmrg
1769362b94d5Smrgstatic String
1770362b94d5SmrgParseParamSeq(register String str, String **paramSeqP, Cardinal *paramNumP)
1771444c061aSmrg{
1772444c061aSmrg    typedef struct _ParamRec *ParamPtr;
1773444c061aSmrg    typedef struct _ParamRec {
1774362b94d5Smrg        ParamPtr next;
1775362b94d5Smrg        String param;
1776444c061aSmrg    } ParamRec;
1777444c061aSmrg
1778444c061aSmrg    ParamPtr params = NULL;
177972af6995Smrg    Cardinal num_params = 0;
1780444c061aSmrg
1781444c061aSmrg    ScanWhitespace(str);
1782444c061aSmrg    while (*str != ')' && *str != '\0' && !IsNewline(*str)) {
1783362b94d5Smrg        _XtString newStr;
1784362b94d5Smrg
1785362b94d5Smrg        str = ParseString(str, &newStr);
1786362b94d5Smrg        if (newStr != NULL) {
1787362b94d5Smrg            ParamPtr temp = (ParamRec *)
1788362b94d5Smrg                ALLOCATE_LOCAL((unsigned) sizeof(ParamRec));
1789362b94d5Smrg
1790362b94d5Smrg            if (temp == NULL)
1791362b94d5Smrg                _XtAllocError(NULL);
1792362b94d5Smrg
1793362b94d5Smrg            num_params++;
1794362b94d5Smrg            temp->next = params;
1795362b94d5Smrg            params = temp;
1796362b94d5Smrg            temp->param = newStr;
1797362b94d5Smrg            ScanWhitespace(str);
1798362b94d5Smrg            if (*str == ',') {
1799362b94d5Smrg                str++;
1800362b94d5Smrg                ScanWhitespace(str);
1801362b94d5Smrg            }
1802362b94d5Smrg        }
1803444c061aSmrg    }
1804444c061aSmrg
1805444c061aSmrg    if (num_params != 0) {
1806a773ec55Smrg        String *paramP = XtMallocArray(num_params + 1, (Cardinal)sizeof(String));
1807362b94d5Smrg        Cardinal i;
1808362b94d5Smrg
1809362b94d5Smrg        *paramSeqP = paramP;
1810362b94d5Smrg        *paramNumP = num_params;
1811362b94d5Smrg        paramP += num_params;   /* list is LIFO right now */
1812362b94d5Smrg        *paramP-- = NULL;
1813362b94d5Smrg        for (i = 0; i < num_params; i++) {
1814362b94d5Smrg            ParamPtr next = params->next;
1815362b94d5Smrg
1816362b94d5Smrg            *paramP-- = params->param;
1817362b94d5Smrg            DEALLOCATE_LOCAL((char *) params);
1818362b94d5Smrg            params = next;
1819362b94d5Smrg        }
1820362b94d5Smrg    }
1821362b94d5Smrg    else {
1822362b94d5Smrg        *paramSeqP = NULL;
1823362b94d5Smrg        *paramNumP = 0;
1824444c061aSmrg    }
1825444c061aSmrg
1826444c061aSmrg    return str;
1827444c061aSmrg}
1828444c061aSmrg
1829362b94d5Smrgstatic String
1830362b94d5SmrgParseAction(String str, ActionPtr actionP, XrmQuark *quarkP, Boolean *error)
1831444c061aSmrg{
1832444c061aSmrg    str = ParseActionProc(str, quarkP, error);
1833362b94d5Smrg    if (*error)
1834362b94d5Smrg        return str;
1835444c061aSmrg
1836444c061aSmrg    if (*str == '(') {
1837362b94d5Smrg        str++;
1838362b94d5Smrg        str = ParseParamSeq(str, &actionP->params, &actionP->num_params);
1839362b94d5Smrg    }
1840362b94d5Smrg    else {
1841362b94d5Smrg        Syntax("Missing '(' while parsing action sequence", "");
1842444c061aSmrg        *error = TRUE;
1843444c061aSmrg        return str;
1844444c061aSmrg    }
1845362b94d5Smrg    if (*str == ')')
1846362b94d5Smrg        str++;
1847362b94d5Smrg    else {
1848362b94d5Smrg        Syntax("Missing ')' while parsing action sequence", "");
1849444c061aSmrg        *error = TRUE;
1850444c061aSmrg        return str;
1851444c061aSmrg    }
1852444c061aSmrg    return str;
1853444c061aSmrg}
1854444c061aSmrg
1855362b94d5Smrgstatic String
1856362b94d5SmrgParseActionSeq(TMParseStateTree parseTree,
1857362b94d5Smrg               String str,
1858362b94d5Smrg               ActionPtr *actionsP,
1859362b94d5Smrg               Boolean *error)
1860444c061aSmrg{
186172af6995Smrg    ActionPtr *nextActionP;
186272af6995Smrg
186372af6995Smrg    if ((nextActionP = actionsP) != NULL)
1864362b94d5Smrg        *actionsP = NULL;
1865444c061aSmrg
1866444c061aSmrg    while (*str != '\0' && !IsNewline(*str)) {
1867362b94d5Smrg        register ActionPtr action;
1868362b94d5Smrg        XrmQuark quark = NULLQUARK;
1869444c061aSmrg
1870362b94d5Smrg        action = XtNew(ActionRec);
1871444c061aSmrg        action->params = NULL;
1872444c061aSmrg        action->num_params = 0;
1873444c061aSmrg        action->next = NULL;
1874444c061aSmrg
1875362b94d5Smrg        str = ParseAction(str, action, &quark, error);
1876362b94d5Smrg        if (*error) {
1877362b94d5Smrg            XtFree((char *) action);
1878362b94d5Smrg            return PanicModeRecovery(str);
1879362b94d5Smrg        }
1880444c061aSmrg
1881362b94d5Smrg        action->idx = _XtGetQuarkIndex(parseTree, quark);
1882362b94d5Smrg        ScanWhitespace(str);
1883362b94d5Smrg        if (nextActionP) {
1884362b94d5Smrg            *nextActionP = action;
1885362b94d5Smrg            nextActionP = &action->next;
1886362b94d5Smrg        }
1887444c061aSmrg    }
1888362b94d5Smrg    if (IsNewline(*str))
1889362b94d5Smrg        str++;
1890444c061aSmrg    ScanWhitespace(str);
1891444c061aSmrg    return str;
1892444c061aSmrg}
1893444c061aSmrg
1894362b94d5Smrgstatic void
1895362b94d5SmrgShowProduction(String currentProduction)
1896444c061aSmrg{
1897444c061aSmrg    Cardinal num_params = 1;
1898444c061aSmrg    String params[1];
1899444c061aSmrg    size_t len;
1900444c061aSmrg    char *eol, *production, productionbuf[500];
1901444c061aSmrg
19028584976cSmrg    eol = strchr(currentProduction, '\n');
1903362b94d5Smrg    if (eol)
1904362b94d5Smrg        len = (size_t) (eol - currentProduction);
1905362b94d5Smrg    else
1906362b94d5Smrg        len = strlen(currentProduction);
1907362b94d5Smrg    production = XtStackAlloc(len + 1, productionbuf);
1908362b94d5Smrg    if (production == NULL)
1909362b94d5Smrg        _XtAllocError(NULL);
1910a773ec55Smrg    (void) memcpy(production, currentProduction, len);
1911444c061aSmrg    production[len] = '\0';
1912444c061aSmrg
1913444c061aSmrg    params[0] = production;
1914444c061aSmrg    XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError,
1915362b94d5Smrg                 "... found while parsing '%s'", params, &num_params);
1916444c061aSmrg
1917362b94d5Smrg    XtStackFree(production, productionbuf);
1918444c061aSmrg}
1919444c061aSmrg
1920444c061aSmrg/***********************************************************************
1921444c061aSmrg * ParseTranslationTableProduction
1922444c061aSmrg * Parses one line of event bindings.
1923444c061aSmrg ***********************************************************************/
1924444c061aSmrg
1925362b94d5Smrgstatic String
1926362b94d5SmrgParseTranslationTableProduction(TMParseStateTree parseTree,
1927362b94d5Smrg                                register String str,
1928362b94d5Smrg                                Boolean *error)
1929444c061aSmrg{
1930362b94d5Smrg    EventSeqPtr eventSeq = NULL;
1931362b94d5Smrg    ActionPtr *actionsP;
1932362b94d5Smrg    String production = str;
1933444c061aSmrg
19342265a131Smrg    actionsP = NULL;
193572af6995Smrg    str = ParseEventSeq(str, &eventSeq, &actionsP, error);
1936444c061aSmrg    if (*error == TRUE) {
1937362b94d5Smrg        ShowProduction(production);
1938362b94d5Smrg    }
1939362b94d5Smrg    else {
1940362b94d5Smrg        ScanWhitespace(str);
1941362b94d5Smrg        str = ParseActionSeq(parseTree, str, actionsP, error);
1942362b94d5Smrg        if (*error == TRUE) {
1943362b94d5Smrg            ShowProduction(production);
1944362b94d5Smrg        }
1945362b94d5Smrg        else {
1946362b94d5Smrg            _XtAddEventSeqToStateTree(eventSeq, parseTree);
1947362b94d5Smrg        }
1948444c061aSmrg    }
1949444c061aSmrg    FreeEventSeq(eventSeq);
1950444c061aSmrg    return (str);
1951444c061aSmrg}
1952444c061aSmrg
1953362b94d5Smrgstatic String
1954362b94d5SmrgCheckForPoundSign(String str,
1955362b94d5Smrg                  _XtTranslateOp defaultOp,
1956362b94d5Smrg                  _XtTranslateOp *actualOpRtn)
1957444c061aSmrg{
1958444c061aSmrg    _XtTranslateOp opType;
1959444c061aSmrg
1960444c061aSmrg    opType = defaultOp;
1961444c061aSmrg    ScanWhitespace(str);
196272af6995Smrg
1963444c061aSmrg    if (*str == '#') {
1964362b94d5Smrg        String start;
1965362b94d5Smrg        char operation[20];
1966362b94d5Smrg        int len;
1967362b94d5Smrg
1968362b94d5Smrg        str++;
1969362b94d5Smrg        start = str;
1970362b94d5Smrg        str = ScanIdent(str);
1971362b94d5Smrg        len = MIN(19, (int) (str - start));
1972a773ec55Smrg        (void) memcpy(operation, start, (size_t) len);
1973362b94d5Smrg        operation[len] = '\0';
1974362b94d5Smrg        if (!strcmp(operation, "replace"))
1975362b94d5Smrg            opType = XtTableReplace;
1976362b94d5Smrg        else if (!strcmp(operation, "augment"))
1977362b94d5Smrg            opType = XtTableAugment;
1978362b94d5Smrg        else if (!strcmp(operation, "override"))
1979362b94d5Smrg            opType = XtTableOverride;
1980362b94d5Smrg        ScanWhitespace(str);
1981362b94d5Smrg        if (IsNewline(*str)) {
1982362b94d5Smrg            str++;
1983362b94d5Smrg            ScanWhitespace(str);
1984362b94d5Smrg        }
1985444c061aSmrg    }
1986444c061aSmrg    *actualOpRtn = opType;
1987444c061aSmrg    return str;
1988444c061aSmrg}
1989444c061aSmrg
1990362b94d5Smrgstatic XtTranslations
1991362b94d5SmrgParseTranslationTable(String source,
1992362b94d5Smrg                      Boolean isAccelerator,
1993362b94d5Smrg                      _XtTranslateOp defaultOp,
1994362b94d5Smrg                      Boolean *error)
1995444c061aSmrg{
1996362b94d5Smrg    XtTranslations xlations;
1997362b94d5Smrg    TMStateTree stateTrees[8];
1998362b94d5Smrg    TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec;
1999362b94d5Smrg    XrmQuark stackQuarks[200];
2000362b94d5Smrg    TMBranchHeadRec stackBranchHeads[200];
2001362b94d5Smrg    StatePtr stackComplexBranchHeads[200];
2002362b94d5Smrg    _XtTranslateOp actualOp;
2003444c061aSmrg
2004444c061aSmrg    if (source == NULL)
2005362b94d5Smrg        return (XtTranslations) NULL;
2006444c061aSmrg
2007444c061aSmrg    source = CheckForPoundSign(source, defaultOp, &actualOp);
2008444c061aSmrg    if (isAccelerator && actualOp == XtTableReplace)
2009362b94d5Smrg        actualOp = defaultOp;
2010444c061aSmrg
2011444c061aSmrg    parseTree->isSimple = TRUE;
2012444c061aSmrg    parseTree->mappingNotifyInterest = FALSE;
201372af6995Smrg    XtSetBit(parseTree->isAccelerator, isAccelerator);
2014444c061aSmrg    parseTree->isStackBranchHeads =
2015362b94d5Smrg        parseTree->isStackQuarks = parseTree->isStackComplexBranchHeads = TRUE;
2016444c061aSmrg
2017444c061aSmrg    parseTree->numQuarks =
2018362b94d5Smrg        parseTree->numBranchHeads = parseTree->numComplexBranchHeads = 0;
2019444c061aSmrg
2020444c061aSmrg    parseTree->quarkTblSize =
2021362b94d5Smrg        parseTree->branchHeadTblSize =
2022362b94d5Smrg        parseTree->complexBranchHeadTblSize = 200;
2023444c061aSmrg
2024444c061aSmrg    parseTree->quarkTbl = stackQuarks;
2025444c061aSmrg    parseTree->branchHeadTbl = stackBranchHeads;
2026444c061aSmrg    parseTree->complexBranchHeadTbl = stackComplexBranchHeads;
2027444c061aSmrg
2028444c061aSmrg    while (source != NULL && *source != '\0') {
2029362b94d5Smrg        source = ParseTranslationTableProduction(parseTree, source, error);
2030362b94d5Smrg        if (*error == TRUE)
2031362b94d5Smrg            break;
2032444c061aSmrg    }
2033444c061aSmrg    stateTrees[0] = _XtParseTreeToStateTree(parseTree);
2034444c061aSmrg
2035444c061aSmrg    if (!parseTree->isStackQuarks)
2036362b94d5Smrg        XtFree((char *) parseTree->quarkTbl);
2037444c061aSmrg    if (!parseTree->isStackBranchHeads)
2038362b94d5Smrg        XtFree((char *) parseTree->branchHeadTbl);
2039444c061aSmrg    if (!parseTree->isStackComplexBranchHeads)
2040362b94d5Smrg        XtFree((char *) parseTree->complexBranchHeadTbl);
2041444c061aSmrg
2042444c061aSmrg    xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL);
204372af6995Smrg    xlations->operation = (unsigned char) actualOp;
2044444c061aSmrg
2045444c061aSmrg#ifdef notdef
2046444c061aSmrg    XtFree(stateTrees);
2047362b94d5Smrg#endif                          /* notdef */
2048444c061aSmrg    return xlations;
2049444c061aSmrg}
2050444c061aSmrg
2051444c061aSmrg/*** public procedures ***/
2052444c061aSmrg
2053362b94d5SmrgBoolean
2054362b94d5SmrgXtCvtStringToAcceleratorTable(Display *dpy,
2055362b94d5Smrg                              XrmValuePtr args _X_UNUSED,
2056362b94d5Smrg                              Cardinal *num_args,
2057362b94d5Smrg                              XrmValuePtr from,
2058362b94d5Smrg                              XrmValuePtr to,
2059362b94d5Smrg                              XtPointer *closure _X_UNUSED)
2060444c061aSmrg{
2061444c061aSmrg    String str;
2062444c061aSmrg    Boolean error = FALSE;
2063444c061aSmrg
2064444c061aSmrg    if (*num_args != 0)
2065444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2066362b94d5Smrg                        "wrongParameters", "cvtStringToAcceleratorTable",
2067362b94d5Smrg                        XtCXtToolkitError,
2068362b94d5Smrg                        "String to AcceleratorTable conversion needs no extra arguments",
2069362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2070362b94d5Smrg    str = (String) (from->addr);
2071444c061aSmrg    if (str == NULL) {
2072444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2073362b94d5Smrg                        "badParameters", "cvtStringToAcceleratorTable",
2074362b94d5Smrg                        XtCXtToolkitError,
2075362b94d5Smrg                        "String to AcceleratorTable conversion needs string",
2076362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2077362b94d5Smrg        return FALSE;
2078444c061aSmrg    }
2079444c061aSmrg    if (to->addr != NULL) {
2080362b94d5Smrg        if (to->size < sizeof(XtAccelerators)) {
2081362b94d5Smrg            to->size = sizeof(XtAccelerators);
2082362b94d5Smrg            return FALSE;
2083362b94d5Smrg        }
2084362b94d5Smrg        *(XtAccelerators *) to->addr =
2085362b94d5Smrg            (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment,
2086362b94d5Smrg                                                   &error);
2087444c061aSmrg    }
2088444c061aSmrg    else {
2089362b94d5Smrg        static XtAccelerators staticStateTable;
2090362b94d5Smrg
2091362b94d5Smrg        staticStateTable =
2092362b94d5Smrg            (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment,
2093362b94d5Smrg                                                   &error);
2094362b94d5Smrg        to->addr = (XPointer) &staticStateTable;
2095362b94d5Smrg        to->size = sizeof(XtAccelerators);
2096444c061aSmrg    }
2097444c061aSmrg    if (error == TRUE)
2098444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2099362b94d5Smrg                        "parseError", "cvtStringToAcceleratorTable",
2100362b94d5Smrg                        XtCXtToolkitError,
2101362b94d5Smrg                        "String to AcceleratorTable conversion encountered errors",
2102362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2103444c061aSmrg    return (error != TRUE);
2104444c061aSmrg}
2105444c061aSmrg
2106444c061aSmrgBoolean
2107362b94d5SmrgXtCvtStringToTranslationTable(Display *dpy,
2108362b94d5Smrg                              XrmValuePtr args _X_UNUSED,
2109362b94d5Smrg                              Cardinal *num_args,
2110362b94d5Smrg                              XrmValuePtr from,
2111362b94d5Smrg                              XrmValuePtr to,
2112362b94d5Smrg                              XtPointer *closure_ret _X_UNUSED)
2113444c061aSmrg{
2114444c061aSmrg    String str;
2115444c061aSmrg    Boolean error = FALSE;
2116444c061aSmrg
2117444c061aSmrg    if (*num_args != 0)
2118362b94d5Smrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2119362b94d5Smrg                        "wrongParameters", "cvtStringToTranslationTable",
2120362b94d5Smrg                        XtCXtToolkitError,
2121362b94d5Smrg                        "String to TranslationTable conversion needs no extra arguments",
2122362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2123362b94d5Smrg    str = (String) (from->addr);
2124444c061aSmrg    if (str == NULL) {
2125444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2126362b94d5Smrg                        "badParameters", "cvtStringToTranslation",
2127362b94d5Smrg                        XtCXtToolkitError,
2128362b94d5Smrg                        "String to TranslationTable conversion needs string",
2129362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2130362b94d5Smrg        return FALSE;
2131444c061aSmrg    }
2132444c061aSmrg    if (to->addr != NULL) {
2133362b94d5Smrg        if (to->size < sizeof(XtTranslations)) {
2134362b94d5Smrg            to->size = sizeof(XtTranslations);
2135362b94d5Smrg            return FALSE;
2136362b94d5Smrg        }
2137362b94d5Smrg        *(XtTranslations *) to->addr =
2138362b94d5Smrg            ParseTranslationTable(str, FALSE, XtTableReplace, &error);
2139444c061aSmrg    }
2140444c061aSmrg    else {
2141362b94d5Smrg        static XtTranslations staticStateTable;
2142362b94d5Smrg
2143362b94d5Smrg        staticStateTable =
2144362b94d5Smrg            ParseTranslationTable(str, FALSE, XtTableReplace, &error);
2145362b94d5Smrg        to->addr = (XPointer) &staticStateTable;
2146362b94d5Smrg        to->size = sizeof(XtTranslations);
2147444c061aSmrg    }
2148444c061aSmrg    if (error == TRUE)
2149444c061aSmrg        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
2150362b94d5Smrg                        "parseError", "cvtStringToTranslationTable",
2151362b94d5Smrg                        XtCXtToolkitError,
2152362b94d5Smrg                        "String to TranslationTable conversion encountered errors",
2153362b94d5Smrg                        (String *) NULL, (Cardinal *) NULL);
2154444c061aSmrg    return (error != TRUE);
2155444c061aSmrg}
2156444c061aSmrg
2157444c061aSmrg/*
2158444c061aSmrg * Parses a user's or applications translation table
2159444c061aSmrg */
2160362b94d5SmrgXtAccelerators
2161362b94d5SmrgXtParseAcceleratorTable(_Xconst char *source)
2162444c061aSmrg{
2163444c061aSmrg    Boolean error = FALSE;
2164444c061aSmrg    XtAccelerators ret =
2165362b94d5Smrg        (XtAccelerators) ParseTranslationTable(source, TRUE, XtTableAugment,
2166362b94d5Smrg                                               &error);
2167362b94d5Smrg
2168444c061aSmrg    if (error == TRUE)
2169362b94d5Smrg        XtWarningMsg("parseError", "cvtStringToAcceleratorTable",
2170362b94d5Smrg                     XtCXtToolkitError,
2171362b94d5Smrg                     "String to AcceleratorTable conversion encountered errors",
2172362b94d5Smrg                     (String *) NULL, (Cardinal *) NULL);
2173444c061aSmrg    return ret;
2174444c061aSmrg}
2175444c061aSmrg
2176362b94d5SmrgXtTranslations
2177362b94d5SmrgXtParseTranslationTable(_Xconst char *source)
2178444c061aSmrg{
2179444c061aSmrg    Boolean error = FALSE;
2180362b94d5Smrg    XtTranslations ret =
2181362b94d5Smrg        ParseTranslationTable(source, FALSE, XtTableReplace, &error);
2182444c061aSmrg    if (error == TRUE)
2183362b94d5Smrg        XtWarningMsg("parseError",
2184362b94d5Smrg                     "cvtStringToTranslationTable", XtCXtToolkitError,
2185362b94d5Smrg                     "String to TranslationTable conversion encountered errors",
2186362b94d5Smrg                     (String *) NULL, (Cardinal *) NULL);
2187444c061aSmrg    return ret;
2188444c061aSmrg}
2189444c061aSmrg
2190362b94d5Smrgvoid
2191362b94d5Smrg_XtTranslateInitialize(void)
2192444c061aSmrg{
2193444c061aSmrg    LOCK_PROCESS;
2194444c061aSmrg    if (initialized) {
2195362b94d5Smrg        XtWarningMsg("translationError", "xtTranslateInitialize",
2196362b94d5Smrg                     XtCXtToolkitError,
2197362b94d5Smrg                     "Initializing Translation manager twice.", (String *) NULL,
2198362b94d5Smrg                     (Cardinal *) NULL);
2199362b94d5Smrg        UNLOCK_PROCESS;
2200362b94d5Smrg        return;
2201444c061aSmrg    }
2202444c061aSmrg
2203444c061aSmrg    initialized = TRUE;
2204444c061aSmrg    UNLOCK_PROCESS;
2205444c061aSmrg    QMeta = XrmPermStringToQuark("Meta");
2206444c061aSmrg    QCtrl = XrmPermStringToQuark("Ctrl");
2207444c061aSmrg    QNone = XrmPermStringToQuark("None");
2208362b94d5Smrg    QAny = XrmPermStringToQuark("Any");
2209444c061aSmrg
2210362b94d5Smrg    Compile_XtEventTable(events, XtNumber(events));
2211362b94d5Smrg    Compile_XtModifierTable(modifiers, XtNumber(modifiers));
2212362b94d5Smrg    CompileNameValueTable(notifyModes);
2213362b94d5Smrg    CompileNameValueTable(motionDetails);
2214444c061aSmrg#if 0
2215362b94d5Smrg    CompileNameValueTable(notifyDetail);
2216362b94d5Smrg    CompileNameValueTable(visibilityNotify);
2217362b94d5Smrg    CompileNameValueTable(circulation);
2218362b94d5Smrg    CompileNameValueTable(propertyChanged);
2219444c061aSmrg#endif
2220362b94d5Smrg    CompileNameValueTable(mappingNotify);
2221444c061aSmrg}
2222444c061aSmrg
2223362b94d5Smrgvoid
2224362b94d5Smrg_XtAddTMConverters(ConverterTable table)
2225444c061aSmrg{
2226362b94d5Smrg    _XtTableAddConverter(table,
2227362b94d5Smrg                         _XtQString,
2228362b94d5Smrg                         XrmPermStringToQuark(XtRTranslationTable),
2229362b94d5Smrg                         XtCvtStringToTranslationTable, (XtConvertArgList) NULL,
2230362b94d5Smrg                         (Cardinal) 0, True, CACHED, _XtFreeTranslations, True);
2231362b94d5Smrg    _XtTableAddConverter(table, _XtQString,
2232362b94d5Smrg                         XrmPermStringToQuark(XtRAcceleratorTable),
2233362b94d5Smrg                         XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL,
2234362b94d5Smrg                         (Cardinal) 0, True, CACHED, _XtFreeTranslations, True);
2235362b94d5Smrg    _XtTableAddConverter(table,
2236362b94d5Smrg                         XrmPermStringToQuark(_XtRStateTablePair),
2237362b94d5Smrg                         XrmPermStringToQuark(XtRTranslationTable),
2238362b94d5Smrg                         _XtCvtMergeTranslations, (XtConvertArgList) NULL,
2239362b94d5Smrg                         (Cardinal) 0, True, CACHED, _XtFreeTranslations, True);
2240444c061aSmrg}
2241