diff options
Diffstat (limited to 'libXt/src/TMparse.c')
-rw-r--r-- | libXt/src/TMparse.c | 4288 |
1 files changed, 2144 insertions, 2144 deletions
diff --git a/libXt/src/TMparse.c b/libXt/src/TMparse.c index 14bb4593f..5fddb8230 100644 --- a/libXt/src/TMparse.c +++ b/libXt/src/TMparse.c @@ -1,2144 +1,2144 @@ -/***********************************************************
-Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
-
-Copyright 1987, 1988, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "IntrinsicI.h"
-#include "StringDefs.h"
-#include <ctype.h>
-#include <stdlib.h>
-#ifndef NOTASCII
-#define XK_LATIN1
-#endif
-#define XK_MISCELLANY
-#include <X11/keysymdef.h>
-
-#ifdef CACHE_TRANSLATIONS
-# ifdef REFCNT_TRANSLATIONS
-# define CACHED XtCacheAll | XtCacheRefCount
-# else
-# define CACHED XtCacheAll
-# endif
-#else
-# define CACHED XtCacheNone
-#endif
-
-#ifndef MAX
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-#endif
-
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-static String XtNtranslationParseError = "translationParseError";
-
-typedef int EventType;
-
-typedef String (*ParseProc)(
- String /* str; */,
- Opaque /* closure; */,
- EventPtr /* event; */,
- Boolean* /* error */);
-
-typedef TMShortCard Value;
-typedef void (*ModifierProc)(Value, LateBindingsPtr*, Boolean, Value*);
-
-typedef struct _ModifierRec {
- char* name;
- XrmQuark signature;
- ModifierProc modifierParseProc;
- Value value;
-} ModifierRec, *ModifierKeys;
-
-typedef struct _EventKey {
- char *event;
- XrmQuark signature;
- EventType eventType;
- ParseProc parseDetail;
- Opaque closure;
-}EventKey, *EventKeys;
-
-typedef struct {
- char *name;
- XrmQuark signature;
- Value value;
-} NameValueRec, *NameValueTable;
-
-static void ParseModImmed(Value, LateBindingsPtr*, Boolean, Value*);
-static void ParseModSym(Value, LateBindingsPtr*, Boolean, Value*);
-static String PanicModeRecovery(String);
-static String CheckForPoundSign(String, _XtTranslateOp, _XtTranslateOp *);
-static KeySym StringToKeySym(String, Boolean *);
-static ModifierRec modifiers[] = {
- {"Shift", 0, ParseModImmed,ShiftMask},
- {"Lock", 0, ParseModImmed,LockMask},
- {"Ctrl", 0, ParseModImmed,ControlMask},
- {"Mod1", 0, ParseModImmed,Mod1Mask},
- {"Mod2", 0, ParseModImmed,Mod2Mask},
- {"Mod3", 0, ParseModImmed,Mod3Mask},
- {"Mod4", 0, ParseModImmed,Mod4Mask},
- {"Mod5", 0, ParseModImmed,Mod5Mask},
- {"Meta", 0, ParseModSym, XK_Meta_L},
- {"m", 0, ParseModSym, XK_Meta_L},
- {"h", 0, ParseModSym, XK_Hyper_L},
- {"su", 0, ParseModSym, XK_Super_L},
- {"a", 0, ParseModSym, XK_Alt_L},
- {"Hyper", 0, ParseModSym, XK_Hyper_L},
- {"Super", 0, ParseModSym, XK_Super_L},
- {"Alt", 0, ParseModSym, XK_Alt_L},
- {"Button1", 0, ParseModImmed,Button1Mask},
- {"Button2", 0, ParseModImmed,Button2Mask},
- {"Button3", 0, ParseModImmed,Button3Mask},
- {"Button4", 0, ParseModImmed,Button4Mask},
- {"Button5", 0, ParseModImmed,Button5Mask},
- {"c", 0, ParseModImmed,ControlMask},
- {"s", 0, ParseModImmed,ShiftMask},
- {"l", 0, ParseModImmed,LockMask},
-};
-
-static NameValueRec buttonNames[] = {
- {"Button1", 0, Button1},
- {"Button2", 0, Button2},
- {"Button3", 0, Button3},
- {"Button4", 0, Button4},
- {"Button5", 0, Button5},
- {NULL, NULLQUARK, 0},
-};
-
-static NameValueRec motionDetails[] = {
- {"Normal", 0, NotifyNormal},
- {"Hint", 0, NotifyHint},
- {NULL, NULLQUARK, 0},
-};
-
-static NameValueRec notifyModes[] = {
- {"Normal", 0, NotifyNormal},
- {"Grab", 0, NotifyGrab},
- {"Ungrab", 0, NotifyUngrab},
- {"WhileGrabbed", 0, NotifyWhileGrabbed},
- {NULL, NULLQUARK, 0},
-};
-
-#if 0
-static NameValueRec notifyDetail[] = {
- {"Ancestor", 0, NotifyAncestor},
- {"Virtual", 0, NotifyVirtual},
- {"Inferior", 0, NotifyInferior},
- {"Nonlinear", 0, NotifyNonlinear},
- {"NonlinearVirtual", 0, NotifyNonlinearVirtual},
- {"Pointer", 0, NotifyPointer},
- {"PointerRoot", 0, NotifyPointerRoot},
- {"DetailNone", 0, NotifyDetailNone},
- {NULL, NULLQUARK, 0},
-};
-
-static NameValueRec visibilityNotify[] = {
- {"Unobscured", 0, VisibilityUnobscured},
- {"PartiallyObscured", 0, VisibilityPartiallyObscured},
- {"FullyObscured", 0, VisibilityFullyObscured},
- {NULL, NULLQUARK, 0},
-};
-
-static NameValueRec circulation[] = {
- {"OnTop", 0, PlaceOnTop},
- {"OnBottom", 0, PlaceOnBottom},
- {NULL, NULLQUARK, 0},
-};
-
-static NameValueRec propertyChanged[] = {
- {"NewValue", 0, PropertyNewValue},
- {"Delete", 0, PropertyDelete},
- {NULL, NULLQUARK, 0},
-};
-#endif /*0*/
-
-static NameValueRec mappingNotify[] = {
- {"Modifier", 0, MappingModifier},
- {"Keyboard", 0, MappingKeyboard},
- {"Pointer", 0, MappingPointer},
- {NULL, NULLQUARK, 0},
-};
-
-static String ParseKeySym(String, Opaque, EventPtr, Boolean*);
-static String ParseKeyAndModifiers(String, Opaque, EventPtr, Boolean*);
-static String ParseTable(String, Opaque, EventPtr, Boolean*);
-static String ParseImmed(String, Opaque, EventPtr, Boolean*);
-static String ParseAddModifier(String, Opaque, EventPtr, Boolean*);
-static String ParseNone(String, Opaque, EventPtr, Boolean*);
-static String ParseAtom(String, Opaque, EventPtr, Boolean*);
-
-static EventKey events[] = {
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-{"KeyPress", NULLQUARK, KeyPress, ParseKeySym, NULL},
-{"Key", NULLQUARK, KeyPress, ParseKeySym, NULL},
-{"KeyDown", NULLQUARK, KeyPress, ParseKeySym, NULL},
-{"Ctrl", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)ControlMask},
-{"Shift", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)ShiftMask},
-{"Meta", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)NULL},
-{"KeyUp", NULLQUARK, KeyRelease, ParseKeySym, NULL},
-{"KeyRelease", NULLQUARK, KeyRelease, ParseKeySym, NULL},
-
-{"ButtonPress", NULLQUARK, ButtonPress, ParseTable,(Opaque)buttonNames},
-{"BtnDown", NULLQUARK, ButtonPress, ParseTable,(Opaque)buttonNames},
-{"Btn1Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button1},
-{"Btn2Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button2},
-{"Btn3Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button3},
-{"Btn4Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button4},
-{"Btn5Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button5},
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-{"ButtonRelease", NULLQUARK, ButtonRelease, ParseTable,(Opaque)buttonNames},
-{"BtnUp", NULLQUARK, ButtonRelease, ParseTable,(Opaque)buttonNames},
-{"Btn1Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button1},
-{"Btn2Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button2},
-{"Btn3Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button3},
-{"Btn4Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button4},
-{"Btn5Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button5},
-
-{"MotionNotify", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails},
-{"PtrMoved", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails},
-{"Motion", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails},
-{"MouseMoved", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails},
-{"BtnMotion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)AnyButtonMask},
-{"Btn1Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button1Mask},
-{"Btn2Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button2Mask},
-{"Btn3Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button3Mask},
-{"Btn4Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button4Mask},
-{"Btn5Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button5Mask},
-
-{"EnterNotify", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes},
-{"Enter", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes},
-{"EnterWindow", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes},
-
-{"LeaveNotify", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes},
-{"LeaveWindow", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes},
-{"Leave", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes},
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-{"FocusIn", NULLQUARK, FocusIn, ParseTable,(Opaque)notifyModes},
-
-{"FocusOut", NULLQUARK, FocusOut, ParseTable,(Opaque)notifyModes},
-
-{"KeymapNotify", NULLQUARK, KeymapNotify, ParseNone, NULL},
-{"Keymap", NULLQUARK, KeymapNotify, ParseNone, NULL},
-
-{"Expose", NULLQUARK, Expose, ParseNone, NULL},
-
-{"GraphicsExpose", NULLQUARK, GraphicsExpose, ParseNone, NULL},
-{"GrExp", NULLQUARK, GraphicsExpose, ParseNone, NULL},
-
-{"NoExpose", NULLQUARK, NoExpose, ParseNone, NULL},
-{"NoExp", NULLQUARK, NoExpose, ParseNone, NULL},
-
-{"VisibilityNotify",NULLQUARK, VisibilityNotify,ParseNone, NULL},
-{"Visible", NULLQUARK, VisibilityNotify,ParseNone, NULL},
-
-{"CreateNotify", NULLQUARK, CreateNotify, ParseNone, NULL},
-{"Create", NULLQUARK, CreateNotify, ParseNone, NULL},
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-{"DestroyNotify", NULLQUARK, DestroyNotify, ParseNone, NULL},
-{"Destroy", NULLQUARK, DestroyNotify, ParseNone, NULL},
-
-{"UnmapNotify", NULLQUARK, UnmapNotify, ParseNone, NULL},
-{"Unmap", NULLQUARK, UnmapNotify, ParseNone, NULL},
-
-{"MapNotify", NULLQUARK, MapNotify, ParseNone, NULL},
-{"Map", NULLQUARK, MapNotify, ParseNone, NULL},
-
-{"MapRequest", NULLQUARK, MapRequest, ParseNone, NULL},
-{"MapReq", NULLQUARK, MapRequest, ParseNone, NULL},
-
-{"ReparentNotify", NULLQUARK, ReparentNotify, ParseNone, NULL},
-{"Reparent", NULLQUARK, ReparentNotify, ParseNone, NULL},
-
-{"ConfigureNotify", NULLQUARK, ConfigureNotify, ParseNone, NULL},
-{"Configure", NULLQUARK, ConfigureNotify, ParseNone, NULL},
-
-{"ConfigureRequest",NULLQUARK, ConfigureRequest,ParseNone, NULL},
-{"ConfigureReq", NULLQUARK, ConfigureRequest,ParseNone, NULL},
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-{"GravityNotify", NULLQUARK, GravityNotify, ParseNone, NULL},
-{"Grav", NULLQUARK, GravityNotify, ParseNone, NULL},
-
-{"ResizeRequest", NULLQUARK, ResizeRequest, ParseNone, NULL},
-{"ResReq", NULLQUARK, ResizeRequest, ParseNone, NULL},
-
-{"CirculateNotify", NULLQUARK, CirculateNotify, ParseNone, NULL},
-{"Circ", NULLQUARK, CirculateNotify, ParseNone, NULL},
-
-{"CirculateRequest",NULLQUARK, CirculateRequest,ParseNone, NULL},
-{"CircReq", NULLQUARK, CirculateRequest,ParseNone, NULL},
-
-{"PropertyNotify", NULLQUARK, PropertyNotify, ParseAtom, NULL},
-{"Prop", NULLQUARK, PropertyNotify, ParseAtom, NULL},
-
-{"SelectionClear", NULLQUARK, SelectionClear, ParseAtom, NULL},
-{"SelClr", NULLQUARK, SelectionClear, ParseAtom, NULL},
-
-{"SelectionRequest",NULLQUARK, SelectionRequest,ParseAtom, NULL},
-{"SelReq", NULLQUARK, SelectionRequest,ParseAtom, NULL},
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-{"SelectionNotify", NULLQUARK, SelectionNotify, ParseAtom, NULL},
-{"Select", NULLQUARK, SelectionNotify, ParseAtom, NULL},
-
-{"ColormapNotify", NULLQUARK, ColormapNotify, ParseNone, NULL},
-{"Clrmap", NULLQUARK, ColormapNotify, ParseNone, NULL},
-
-{"ClientMessage", NULLQUARK, ClientMessage, ParseAtom, NULL},
-{"Message", NULLQUARK, ClientMessage, ParseAtom, NULL},
-
-{"MappingNotify", NULLQUARK, MappingNotify, ParseTable, (Opaque)mappingNotify},
-{"Mapping", NULLQUARK, MappingNotify, ParseTable, (Opaque)mappingNotify},
-
-#ifdef DEBUG
-# ifdef notdef
-{"Timer", NULLQUARK, _XtTimerEventType,ParseNone, NULL},
-# endif /* notdef */
-{"EventTimer", NULLQUARK, _XtEventTimerEventType,ParseNone,NULL},
-#endif /* DEBUG */
-
-/* Event Name, Quark, Event Type, Detail Parser, Closure */
-
-};
-
-#ifndef __UNIXOS2__
-#define IsNewline(str) ((str) == '\n')
-#else
-#define IsNewline(str) ((str) == '\n' || (str) == '\r')
-#endif
-
-#define ScanFor(str, ch) \
- while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))) (str)++
-
-#define ScanNumeric(str) while ('0' <= *(str) && *(str) <= '9') (str)++
-
-#define ScanAlphanumeric(str) \
- while (('A' <= *(str) && *(str) <= 'Z') || \
- ('a' <= *(str) && *(str) <= 'z') || \
- ('0' <= *(str) && *(str) <= '9')) (str)++
-
-#ifndef __UNIXOS2__
-#define ScanWhitespace(str) \
- while (*(str) == ' ' || *(str) == '\t') (str)++
-#else
-#define ScanWhitespace(str) \
- while (*(str) == ' ' || *(str) == '\t' || *(str) == '\r') (str)++
-#endif
-
-static Boolean initialized = FALSE;
-static XrmQuark QMeta;
-static XrmQuark QCtrl;
-static XrmQuark QNone;
-static XrmQuark QAny;
-
-static void FreeEventSeq(
- EventSeqPtr eventSeq)
-{
- register EventSeqPtr evs = eventSeq;
-
- while (evs != NULL) {
- evs->state = (StatePtr) evs;
- if (evs->next != NULL
- && evs->next->state == (StatePtr) evs->next)
- evs->next = NULL;
- evs = evs->next;
- }
-
- evs = eventSeq;
- while (evs != NULL) {
- register EventPtr event = evs;
- evs = evs->next;
- if (evs == event) evs = NULL;
- XtFree((char *)event);
- }
-}
-
-static void CompileNameValueTable(
- NameValueTable table)
-{
- register int i;
-
- for (i=0; table[i].name; i++)
- table[i].signature = XrmPermStringToQuark(table[i].name);
-}
-
-static int OrderEvents(_Xconst void *a, _Xconst void *b)
-{
- return ((((_Xconst EventKey *)a)->signature <
- ((_Xconst EventKey *)b)->signature) ? -1 : 1);
-}
-
-static void Compile_XtEventTable(
- EventKeys table,
- Cardinal count)
-{
- register int i;
- register EventKeys entry = table;
-
- for (i=count; --i >= 0; entry++)
- entry->signature = XrmPermStringToQuark(entry->event);
- qsort(table, count, sizeof(EventKey), OrderEvents);
-}
-
-static int OrderModifiers(_Xconst void *a, _Xconst void *b)
-{
- return ((((_Xconst ModifierRec *)a)->signature <
- ((_Xconst ModifierRec *)b)->signature) ? -1 : 1);
-}
-
-static void Compile_XtModifierTable(
- ModifierKeys table,
- Cardinal count)
-{
- register int i;
- register ModifierKeys entry = table;
-
- for (i=count; --i >= 0; entry++)
- entry->signature = XrmPermStringToQuark(entry->name);
- qsort(table, count, sizeof(ModifierRec), OrderModifiers);
-}
-
-static String PanicModeRecovery(
- String str)
-{
- ScanFor(str,'\n');
- if (*str == '\n') str++;
- return str;
-
-}
-
-
-static void Syntax(
- String str0,String str1)
-{
- Cardinal num_params = 2;
- String params[2];
-
- params[0] = str0;
- params[1] = str1;
- XtWarningMsg(XtNtranslationParseError,"parseError",XtCXtToolkitError,
- "translation table syntax error: %s %s",params,&num_params);
-}
-
-
-
-static Cardinal LookupTMEventType(
- String eventStr,
- Boolean *error)
-{
- register int i = 0, left, right;
- register XrmQuark signature;
- static int previous = 0;
-
- LOCK_PROCESS;
- if ((signature = StringToQuark(eventStr)) == events[previous].signature) {
- UNLOCK_PROCESS;
- return (Cardinal) previous;
- }
-
- left = 0;
- right = XtNumber(events) - 1;
- while (left <= right) {
- i = (left + right) >> 1;
- if (signature < events[i].signature)
- right = i - 1;
- else if (signature > events[i].signature)
- left = i + 1;
- else {
- previous = i;
- UNLOCK_PROCESS;
- return (Cardinal) i;
- }
- }
-
- Syntax("Unknown event type : ",eventStr);
- *error = TRUE;
- UNLOCK_PROCESS;
- return (Cardinal) i;
-}
-
-static void StoreLateBindings(
- KeySym keysymL,
- Boolean notL,
- KeySym keysymR,
- Boolean notR,
- LateBindingsPtr* lateBindings)
-{
- LateBindingsPtr temp;
- Boolean pair = FALSE;
- unsigned long count,number;
- if (lateBindings != NULL){
- temp = *lateBindings;
- if (temp != NULL) {
- for (count = 0; temp[count].keysym; count++){/*EMPTY*/}
- }
- else count = 0;
- if (! keysymR){
- number = 1;pair = FALSE;
- } else{
- number = 2;pair = TRUE;
- }
-
- temp = (LateBindingsPtr)XtRealloc((char *)temp,
- (unsigned)((count+number+1) * sizeof(LateBindings)) );
- *lateBindings = temp;
- temp[count].knot = notL;
- temp[count].pair = pair;
- if (count == 0)
- temp[count].ref_count = 1;
- temp[count++].keysym = keysymL;
- if (keysymR){
- temp[count].knot = notR;
- temp[count].pair = FALSE;
- temp[count].ref_count = 0;
- temp[count++].keysym = keysymR;
- }
- temp[count].knot = temp[count].pair = FALSE;
- temp[count].ref_count = 0;
- temp[count].keysym = 0;
- }
-}
-
-static void _XtParseKeysymMod(
- String name,
- LateBindingsPtr* lateBindings,
- Boolean notFlag,
- Value *valueP,
- Boolean *error)
-{
- KeySym keySym;
- keySym = StringToKeySym(name, error);
- *valueP = 0;
- if (keySym != NoSymbol) {
- StoreLateBindings(keySym,notFlag,(KeySym) NULL,FALSE,lateBindings);
- }
-}
-
-static Boolean _XtLookupModifier(
- XrmQuark signature,
- LateBindingsPtr* lateBindings,
- Boolean notFlag,
- Value *valueP,
- Bool constMask)
-{
- register int i, left, right;
- static int previous = 0;
-
- LOCK_PROCESS;
- if (signature == modifiers[previous].signature) {
- if (constMask) *valueP = modifiers[previous].value;
- else /* if (modifiers[previous].modifierParseProc) always true */
- (*modifiers[previous].modifierParseProc)
- (modifiers[previous].value, lateBindings, notFlag, valueP);
- UNLOCK_PROCESS;
- return TRUE;
- }
-
- left = 0;
- right = XtNumber(modifiers) - 1;
- while (left <= right) {
- i = (left + right) >> 1;
- if (signature < modifiers[i].signature)
- right = i - 1;
- else if (signature > modifiers[i].signature)
- left = i + 1;
- else {
- previous = i;
- if (constMask) *valueP = modifiers[i].value;
- else /* if (modifiers[i].modifierParseProc) always true */
- (*modifiers[i].modifierParseProc)
- (modifiers[i].value, lateBindings, notFlag, valueP);
- UNLOCK_PROCESS;
- return TRUE;
- }
- }
- UNLOCK_PROCESS;
- return FALSE;
-}
-
-
-static String ScanIdent(
- register String str)
-{
- ScanAlphanumeric(str);
- while (
- ('A' <= *str && *str <= 'Z')
- || ('a' <= *str && *str <= 'z')
- || ('0' <= *str && *str <= '9')
- || (*str == '-')
- || (*str == '_')
- || (*str == '$')
- ) str++;
- return str;
-}
-
-static String FetchModifierToken(
- String str,
- XrmQuark *token_return)
-{
- String start = str;
-
- if (*str == '$') {
- *token_return = QMeta;
- str++;
- return str;
- }
- if (*str == '^') {
- *token_return = QCtrl;
- str++;
- return str;
- }
- str = ScanIdent(str);
- if (start != str) {
- char modStrbuf[100];
- char* modStr;
-
- modStr = XtStackAlloc ((size_t)(str - start + 1), modStrbuf);
- if (modStr == NULL) _XtAllocError (NULL);
- (void) memmove(modStr, start, str-start);
- modStr[str-start] = '\0';
- *token_return = XrmStringToQuark(modStr);
- XtStackFree (modStr, modStrbuf);
- return str;
- }
- return str;
-}
-
-static String ParseModifiers(
- register String str,
- EventPtr event,
- Boolean* error)
-{
- register String start;
- Boolean notFlag, exclusive, keysymAsMod;
- Value maskBit;
- XrmQuark Qmod;
-
- ScanWhitespace(str);
- start = str;
- str = FetchModifierToken(str, &Qmod);
- exclusive = FALSE;
- if (start != str) {
- if (Qmod == QNone) {
- event->event.modifierMask = ~0;
- event->event.modifiers = 0;
- ScanWhitespace(str);
- return str;
- } else if (Qmod == QAny) { /*backward compatability*/
- event->event.modifierMask = 0;
- event->event.modifiers = AnyModifier;
- ScanWhitespace(str);
- return str;
- }
- str = start; /*if plain modifier, reset to beginning */
- }
- else while (*str == '!' || *str == ':') {
- if (*str == '!') {
- exclusive = TRUE;
- str++;
- ScanWhitespace(str);
- }
- if (*str == ':') {
- event->event.standard = TRUE;
- str++;
- ScanWhitespace(str);
- }
- }
-
- while (*str != '<') {
- if (*str == '~') {
- notFlag = TRUE;
- str++;
- } else
- notFlag = FALSE;
- if (*str == '@') {
- keysymAsMod = TRUE;
- str++;
- }
- else keysymAsMod = FALSE;
- start = str;
- str = FetchModifierToken(str, &Qmod);
- if (start == str) {
- Syntax("Modifier or '<' expected","");
- *error = TRUE;
- return PanicModeRecovery(str);
- }
- if (keysymAsMod) {
- _XtParseKeysymMod(XrmQuarkToString(Qmod),
- &event->event.lateModifiers,
- notFlag,&maskBit, error);
- if (*error)
- return PanicModeRecovery(str);
-
- } else
- if (!_XtLookupModifier(Qmod, &event->event.lateModifiers,
- notFlag, &maskBit, FALSE)) {
- Syntax("Unknown modifier name: ", XrmQuarkToString(Qmod));
- *error = TRUE;
- return PanicModeRecovery(str);
- }
- event->event.modifierMask |= maskBit;
- if (notFlag) event->event.modifiers &= ~maskBit;
- else event->event.modifiers |= maskBit;
- ScanWhitespace(str);
- }
- if (exclusive) event->event.modifierMask = ~0;
- return str;
-}
-
-static String ParseXtEventType(
- register String str,
- EventPtr event,
- Cardinal *tmEventP,
- Boolean* error)
-{
- String start = str;
- char eventTypeStrbuf[100];
- char* eventTypeStr;
-
- ScanAlphanumeric(str);
- eventTypeStr = XtStackAlloc ((size_t)(str - start + 1), eventTypeStrbuf);
- if (eventTypeStr == NULL) _XtAllocError (NULL);
- (void) memmove(eventTypeStr, start, str-start);
- eventTypeStr[str-start] = '\0';
- *tmEventP = LookupTMEventType(eventTypeStr,error);
- XtStackFree (eventTypeStr, eventTypeStrbuf);
- if (*error)
- return PanicModeRecovery(str);
- event->event.eventType = events[*tmEventP].eventType;
- return str;
-}
-
-static unsigned long StrToHex(
- String str)
-{
- register char c;
- register unsigned long val = 0;
-
- while ((c = *str)) {
- if ('0' <= c && c <= '9') val = val*16+c-'0';
- else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10;
- else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10;
- else return 0;
- str++;
- }
-
- return val;
-}
-
-static unsigned long StrToOct(
- String str)
-{
- register char c;
- register unsigned long val = 0;
-
- while ((c = *str)) {
- if ('0' <= c && c <= '7') val = val*8+c-'0'; else return 0;
- str++;
- }
-
- return val;
-}
-
-static unsigned long StrToNum(
- String str)
-{
- register char c;
- register unsigned long val = 0;
-
- if (*str == '0') {
- str++;
- if (*str == 'x' || *str == 'X') return StrToHex(++str);
- else return StrToOct(str);
- }
-
- while ((c = *str)) {
- if ('0' <= c && c <= '9') val = val*10+c-'0';
- else return 0;
- str++;
- }
-
- return val;
-}
-
-static KeySym StringToKeySym(
- String str,
- Boolean *error)
-{
- KeySym k;
-
- if (str == NULL || *str == '\0') return (KeySym) 0;
-
-#ifndef NOTASCII
- /* special case single character ASCII, for speed */
- if (*(str+1) == '\0') {
- if (' ' <= *str && *str <= '~') return XK_space + (*str - ' ');
- }
-#endif
-
- if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str);
- k = XStringToKeysym(str);
- if (k != NoSymbol) return k;
-
-#ifdef NOTASCII
- /* fall-back case to preserve backwards compatibility; no-one
- * should be relying upon this!
- */
- if (*(str+1) == '\0') return (KeySym) *str;
-#endif
-
- Syntax("Unknown keysym name: ", str);
- *error = TRUE;
- return NoSymbol;
-}
-/* ARGSUSED */
-static void ParseModImmed(
- Value value,
- LateBindingsPtr* lateBindings,
- Boolean notFlag,
- Value* valueP)
-{
- *valueP = value;
-}
-
- /* is only valid with keysyms that have an _L and _R in their name;
- * and ignores keysym lookup errors (i.e. assumes only valid keysyms)
- */
-static void ParseModSym(
- Value value,
- LateBindingsPtr* lateBindings,
- Boolean notFlag,
- Value* valueP)
-{
- register KeySym keysymL = (KeySym)value;
- register KeySym keysymR = keysymL + 1; /* valid for supported keysyms */
- StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings);
- *valueP = 0;
-}
-
-#ifdef sparc
-/*
- * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that
- * causes the value of the most recently used variable to be returned instead
- * of the value passed in.
- */
-static String stupid_optimizer_kludge;
-#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val)
-#else
-#define BROKEN_OPTIMIZER_HACK(val) val
-#endif
-
-/* ARGSUSED */
-static String ParseImmed(
- register String str,
- register Opaque closure,
- register EventPtr event,
- Boolean* error)
-{
- event->event.eventCode = (unsigned long)closure;
- event->event.eventCodeMask = ~0UL;
-
- return BROKEN_OPTIMIZER_HACK(str);
-}
-
-/* ARGSUSED */
-static String ParseAddModifier(
- register String str,
- register Opaque closure,
- register EventPtr event,
- Boolean* error)
-{
- register unsigned long modval = (unsigned long)closure;
- event->event.modifiers |= modval;
- if (modval != AnyButtonMask) /* AnyButtonMask is don't-care mask */
- event->event.modifierMask |= modval;
-
- return BROKEN_OPTIMIZER_HACK(str);
-}
-
-
-static String ParseKeyAndModifiers(
- String str,
- Opaque closure,
- EventPtr event,
- Boolean* error)
-{
- str = ParseKeySym(str, closure, event,error);
- if ((unsigned long) closure == 0) {
- Value metaMask; /* unused */
- (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
- &metaMask, FALSE);
- } else {
- event->event.modifiers |= (unsigned long) closure;
- event->event.modifierMask |= (unsigned long) closure;
- }
- return str;
-}
-
-/*ARGSUSED*/
-static String ParseKeySym(
- register String str,
- Opaque closure,
- EventPtr event,
- Boolean* error)
-{
- char *start;
- char keySymNamebuf[100];
- char* keySymName;
-
- ScanWhitespace(str);
-
- if (*str == '\\') {
- keySymName = keySymNamebuf;
- str++;
- keySymName[0] = *str;
- if (*str != '\0' && !IsNewline(*str)) str++;
- keySymName[1] = '\0';
- event->event.eventCode = StringToKeySym(keySymName, error);
- event->event.eventCodeMask = ~0L;
- } else if (*str == ',' || *str == ':' ||
- /* allow leftparen to be single char symbol,
- * for backwards compatibility
- */
- (*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) {
- keySymName = keySymNamebuf; /* just so we can stackfree it later */
- /* no detail */
- event->event.eventCode = 0L;
- event->event.eventCodeMask = 0L;
- } else {
- start = str;
- while (
- *str != ','
- && *str != ':'
- && *str != ' '
- && *str != '\t'
- && !IsNewline(*str)
- && (*str != '(' || *(str+1) <= '0' || *(str+1) >= '9')
- && *str != '\0') str++;
- keySymName = XtStackAlloc ((size_t)(str - start + 1), keySymNamebuf);
- (void) memmove(keySymName, start, str-start);
- keySymName[str-start] = '\0';
- event->event.eventCode = StringToKeySym(keySymName, error);
- event->event.eventCodeMask = ~0L;
- }
- if (*error) {
- /* We never get here when keySymName hasn't been allocated */
- if (keySymName[0] == '<') {
- /* special case for common error */
- XtWarningMsg(XtNtranslationParseError, "missingComma",
- XtCXtToolkitError,
- "... possibly due to missing ',' in event sequence.",
- (String*)NULL, (Cardinal*)NULL);
- }
- XtStackFree (keySymName, keySymNamebuf);
- return PanicModeRecovery(str);
- }
- if (event->event.standard)
- event->event.matchEvent = _XtMatchUsingStandardMods;
- else
- event->event.matchEvent = _XtMatchUsingDontCareMods;
-
- XtStackFree (keySymName, keySymNamebuf);
-
- return str;
-}
-
-static String ParseTable(
- register String str,
- Opaque closure,
- EventPtr event,
- Boolean* error)
-{
- register String start = str;
- register XrmQuark signature;
- NameValueTable table = (NameValueTable) closure;
- char tableSymName[100];
-
- event->event.eventCode = 0L;
- ScanAlphanumeric(str);
- if (str == start) {event->event.eventCodeMask = 0L; return str; }
- if (str-start >= 99) {
- Syntax("Invalid Detail Type (string is too long).", "");
- *error = TRUE;
- return str;
- }
- (void) memmove(tableSymName, start, str-start);
- tableSymName[str-start] = '\0';
- signature = StringToQuark(tableSymName);
- for (; table->signature != NULLQUARK; table++)
- if (table->signature == signature) {
- event->event.eventCode = table->value;
- event->event.eventCodeMask = ~0L;
- return str;
- }
-
- Syntax("Unknown Detail Type: ", tableSymName);
- *error = TRUE;
- return PanicModeRecovery(str);
-}
-
-/*ARGSUSED*/
-static String ParseNone(
- String str,
- Opaque closure,
- EventPtr event,
- Boolean* error)
-{
- event->event.eventCode = 0;
- event->event.eventCodeMask = 0;
-
- return BROKEN_OPTIMIZER_HACK(str);
-}
-
-/*ARGSUSED*/
-static String ParseAtom(
- String str,
- Opaque closure,
- EventPtr event,
- Boolean* error)
-{
- ScanWhitespace(str);
-
- if (*str == ',' || *str == ':') {
- /* no detail */
- event->event.eventCode = 0L;
- event->event.eventCodeMask = 0L;
- } else {
- char *start, atomName[1000];
- start = str;
- while (
- *str != ','
- && *str != ':'
- && *str != ' '
- && *str != '\t'
- && !IsNewline(*str)
- && *str != '\0') str++;
- if (str-start >= 999) {
- Syntax( "Atom name must be less than 1000 characters long.", "" );
- *error = TRUE;
- return str;
- }
- (void) memmove(atomName, start, str-start);
- atomName[str-start] = '\0';
- event->event.eventCode = XrmStringToQuark(atomName);
- event->event.matchEvent = _XtMatchAtom;
- }
- return str;
-}
-
-static ModifierMask buttonModifierMasks[] = {
- 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
-};
-static String ParseRepeat(String, int *, Boolean *, Boolean *);
-
-static String ParseEvent(
- register String str,
- EventPtr event,
- int* reps,
- Boolean* plus,
- Boolean* error)
-{
- Cardinal tmEvent;
-
- str = ParseModifiers(str, event,error);
- if (*error) return str;
- if (*str != '<') {
- Syntax("Missing '<' while parsing event type.","");
- *error = TRUE;
- return PanicModeRecovery(str);
- }
- else str++;
- str = ParseXtEventType(str, event, &tmEvent,error);
- if (*error) return str;
- if (*str != '>'){
- Syntax("Missing '>' while parsing event type","");
- *error = TRUE;
- return PanicModeRecovery(str);
- }
- else str++;
- if (*str == '(') {
- str = ParseRepeat(str, reps, plus, error);
- if (*error) return str;
- }
- str = (*(events[tmEvent].parseDetail))(
- str, events[tmEvent].closure, event,error);
- if (*error) return str;
-
-/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t.
- * modifiers in grabs.
- */
- if ((event->event.eventType == ButtonRelease)
- && (event->event.modifiers | event->event.modifierMask) /* any */
- && (event->event.modifiers != AnyModifier))
- {
- event->event.modifiers
- |= buttonModifierMasks[event->event.eventCode];
- /* the button that is going up will always be in the modifiers... */
- }
-
- return str;
-}
-
-static String ParseQuotedStringEvent(
- register String str,
- register EventPtr event,
- Boolean *error)
-{
- Value metaMask;
- char s[2];
-
- if (*str=='^') {
- str++;
- event->event.modifiers = ControlMask;
- } else if (*str == '$') {
- str++;
- (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
- &metaMask, FALSE);
- }
- if (*str == '\\')
- str++;
- s[0] = *str;
- s[1] = '\0';
- if (*str != '\0' && !IsNewline(*str)) str++;
- event->event.eventType = KeyPress;
- event->event.eventCode = StringToKeySym(s, error);
- if (*error) return PanicModeRecovery(str);
- event->event.eventCodeMask = ~0L;
- event->event.matchEvent = _XtMatchUsingStandardMods;
- event->event.standard = TRUE;
-
- return str;
-}
-
-
-static EventSeqRec timerEventRec = {
- {0, 0, NULL, _XtEventTimerEventType, 0L, 0L, NULL, False},
- /* (StatePtr) -1 */ NULL,
- NULL,
- NULL
-};
-
-static void RepeatDown(
- EventPtr *eventP,
- int reps,
- ActionPtr **actionsP)
-{
- EventRec upEventRec;
- register EventPtr event, downEvent;
- EventPtr upEvent = &upEventRec;
- register int i;
-
- downEvent = event = *eventP;
- *upEvent = *downEvent;
- upEvent->event.eventType = ((event->event.eventType == ButtonPress) ?
- ButtonRelease : KeyRelease);
- if ((upEvent->event.eventType == ButtonRelease)
- && (upEvent->event.modifiers != AnyModifier)
- && (upEvent->event.modifiers | upEvent->event.modifierMask))
- upEvent->event.modifiers
- |= buttonModifierMasks[event->event.eventCode];
-
- if (event->event.lateModifiers)
- event->event.lateModifiers->ref_count += (reps - 1) * 2;
-
- for (i=1; i<reps; i++) {
-
- /* up */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *upEvent;
-
- /* timer */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = timerEventRec;
-
- /* down */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *downEvent;
-
- }
-
- event->next = NULL;
- *eventP = event;
- *actionsP = &event->actions;
-}
-
-static void RepeatDownPlus(
- EventPtr *eventP,
- int reps,
- ActionPtr **actionsP)
-{
- EventRec upEventRec;
- register EventPtr event, downEvent, lastDownEvent = NULL;
- EventPtr upEvent = &upEventRec;
- register int i;
-
- downEvent = event = *eventP;
- *upEvent = *downEvent;
- upEvent->event.eventType = ((event->event.eventType == ButtonPress) ?
- ButtonRelease : KeyRelease);
- if ((upEvent->event.eventType == ButtonRelease)
- && (upEvent->event.modifiers != AnyModifier)
- && (upEvent->event.modifiers | upEvent->event.modifierMask))
- upEvent->event.modifiers
- |= buttonModifierMasks[event->event.eventCode];
-
- if (event->event.lateModifiers)
- event->event.lateModifiers->ref_count += reps * 2 - 1;
-
- for (i=0; i<reps; i++) {
-
- if (i > 0) {
- /* down */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *downEvent;
- }
- lastDownEvent = event;
-
- /* up */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *upEvent;
-
- /* timer */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = timerEventRec;
-
- }
-
- event->next = lastDownEvent;
- *eventP = event;
- *actionsP = &lastDownEvent->actions;
-}
-
-static void RepeatUp(
- EventPtr *eventP,
- int reps,
- ActionPtr **actionsP)
-{
- EventRec upEventRec;
- register EventPtr event, downEvent;
- EventPtr upEvent = &upEventRec;
- register int i;
-
- /* the event currently sitting in *eventP is an "up" event */
- /* we want to make it a "down" event followed by an "up" event, */
- /* so that sequence matching on the "state" side works correctly. */
-
- downEvent = event = *eventP;
- *upEvent = *downEvent;
- downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ?
- ButtonPress : KeyPress);
- if ((downEvent->event.eventType == ButtonPress)
- && (downEvent->event.modifiers != AnyModifier)
- && (downEvent->event.modifiers | downEvent->event.modifierMask))
- downEvent->event.modifiers
- &= ~buttonModifierMasks[event->event.eventCode];
-
- if (event->event.lateModifiers)
- event->event.lateModifiers->ref_count += reps * 2 - 1;
-
- /* up */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *upEvent;
-
- for (i=1; i<reps; i++) {
-
- /* timer */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = timerEventRec;
-
- /* down */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *downEvent;
-
- /* up */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *upEvent;
-
- }
-
- event->next = NULL;
- *eventP = event;
- *actionsP = &event->actions;
-}
-
-static void RepeatUpPlus(
- EventPtr *eventP,
- int reps,
- ActionPtr **actionsP)
-{
- EventRec upEventRec;
- register EventPtr event, downEvent, lastUpEvent = NULL;
- EventPtr upEvent = &upEventRec;
- register int i;
-
- /* the event currently sitting in *eventP is an "up" event */
- /* we want to make it a "down" event followed by an "up" event, */
- /* so that sequence matching on the "state" side works correctly. */
-
- downEvent = event = *eventP;
- *upEvent = *downEvent;
- downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ?
- ButtonPress : KeyPress);
- if ((downEvent->event.eventType == ButtonPress)
- && (downEvent->event.modifiers != AnyModifier)
- && (downEvent->event.modifiers | downEvent->event.modifierMask))
- downEvent->event.modifiers
- &= ~buttonModifierMasks[event->event.eventCode];
-
- if (event->event.lateModifiers)
- event->event.lateModifiers->ref_count += reps * 2;
-
- for (i=0; i<reps; i++) {
-
- /* up */
- event->next = XtNew(EventSeqRec);
- lastUpEvent = event = event->next;
- *event = *upEvent;
-
- /* timer */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = timerEventRec;
-
- /* down */
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *downEvent;
-
- }
-
- event->next = lastUpEvent;
- *eventP = event;
- *actionsP = &lastUpEvent->actions;
-}
-
-static void RepeatOther(
- EventPtr *eventP,
- int reps,
- ActionPtr **actionsP)
-{
- register EventPtr event, tempEvent;
- register int i;
-
- tempEvent = event = *eventP;
-
- if (event->event.lateModifiers)
- event->event.lateModifiers->ref_count += reps - 1;
-
- for (i=1; i<reps; i++) {
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *tempEvent;
- }
-
- *eventP = event;
- *actionsP = &event->actions;
-}
-
-static void RepeatOtherPlus(
- EventPtr *eventP,
- int reps,
- ActionPtr **actionsP)
-{
- register EventPtr event, tempEvent;
- register int i;
-
- tempEvent = event = *eventP;
-
- if (event->event.lateModifiers)
- event->event.lateModifiers->ref_count += reps - 1;
-
- for (i=1; i<reps; i++) {
- event->next = XtNew(EventSeqRec);
- event = event->next;
- *event = *tempEvent;
- }
-
- event->next = event;
- *eventP = event;
- *actionsP = &event->actions;
-}
-
-static void RepeatEvent(
- EventPtr *eventP,
- int reps,
- Boolean plus,
- ActionPtr **actionsP)
-{
- switch ((*eventP)->event.eventType) {
-
- case ButtonPress:
- case KeyPress:
- if (plus) RepeatDownPlus(eventP, reps, actionsP);
- else RepeatDown(eventP, reps, actionsP);
- break;
-
- case ButtonRelease:
- case KeyRelease:
- if (plus) RepeatUpPlus(eventP, reps, actionsP);
- else RepeatUp(eventP, reps, actionsP);
- break;
-
- default:
- if (plus) RepeatOtherPlus(eventP, reps, actionsP);
- else RepeatOther(eventP, reps, actionsP);
- }
-}
-
-static String ParseRepeat(
- register String str,
- int *reps,
- Boolean *plus, Boolean *error)
-{
-
- /*** Parse the repetitions, for double click etc... ***/
- if (*str != '(' || !(isdigit(str[1]) || str[1] == '+' || str[1] == ')'))
- return str;
- str++;
- if (isdigit(*str)) {
- String start = str;
- char repStr[7];
- size_t len;
-
- ScanNumeric(str);
- len = (str - start);
- if (len < sizeof repStr) {
- (void) memmove(repStr, start, len);
- repStr[len] = '\0';
- *reps = StrToNum(repStr);
- } else {
- Syntax("Repeat count too large.", "");
- *error = TRUE;
- return str;
- }
- }
- if (*reps == 0) {
- Syntax("Missing repeat count.","");
- *error = True;
- return str;
- }
-
- if (*str == '+') {
- *plus = TRUE;
- str++;
- }
- if (*str == ')')
- str++;
- else {
- Syntax("Missing ')'.","");
- *error = TRUE;
- }
-
- return str;
-}
-
-/***********************************************************************
- * ParseEventSeq
- * Parses the left hand side of a translation table production
- * up to, and consuming the ":".
- * Takes a pointer to a char* (where to start parsing) and returns an
- * event seq (in a passed in variable), having updated the String
- **********************************************************************/
-
-static String ParseEventSeq(
- register String str,
- EventSeqPtr *eventSeqP,
- ActionPtr **actionsP,
- Boolean *error)
-{
- EventSeqPtr *nextEvent = eventSeqP;
-
- *eventSeqP = NULL;
-
- while ( *str != '\0' && !IsNewline(*str)) {
- static Event nullEvent =
- {0, 0,NULL, 0, 0L, 0L,_XtRegularMatch,FALSE};
- EventPtr event;
-
- ScanWhitespace(str);
-
- if (*str == '"') {
- str++;
- while (*str != '"' && *str != '\0' && !IsNewline(*str)) {
- event = XtNew(EventRec);
- event->event = nullEvent;
- event->state = /* (StatePtr) -1 */ NULL;
- event->next = NULL;
- event->actions = NULL;
- str = ParseQuotedStringEvent(str, event,error);
- if (*error) {
- XtWarningMsg(XtNtranslationParseError, "nonLatin1",
- XtCXtToolkitError,
- "... probably due to non-Latin1 character in quoted string",
- (String*)NULL, (Cardinal*)NULL);
- return PanicModeRecovery(str);
- }
- *nextEvent = event;
- *actionsP = &event->actions;
- nextEvent = &event->next;
- }
- if (*str != '"') {
- Syntax("Missing '\"'.","");
- *error = TRUE;
- return PanicModeRecovery(str);
- }
- else str++;
- } else {
- int reps = 0;
- Boolean plus = FALSE;
-
- event = XtNew(EventRec);
- event->event = nullEvent;
- event->state = /* (StatePtr) -1 */ NULL;
- event->next = NULL;
- event->actions = NULL;
-
- str = ParseEvent(str, event, &reps, &plus, error);
- if (*error) return str;
- *nextEvent = event;
- *actionsP = &event->actions;
- if (reps > 1 || plus)
- RepeatEvent(&event, reps, plus, actionsP);
- nextEvent = &event->next;
- }
- ScanWhitespace(str);
- if (*str == ':') break;
- else {
- if (*str != ',') {
- Syntax("',' or ':' expected while parsing event sequence.","");
- *error = TRUE;
- return PanicModeRecovery(str);
- } else str++;
- }
- }
-
- if (*str != ':') {
- Syntax("Missing ':'after event sequence.","");
- *error = TRUE;
- return PanicModeRecovery(str);
- } else str++;
-
- return str;
-}
-
-
-static String ParseActionProc(
- register String str,
- XrmQuark *actionProcNameP,
- Boolean *error)
-{
- register String start = str;
- char procName[200];
-
- str = ScanIdent(str);
- if (str-start >= 199) {
- Syntax("Action procedure name is longer than 199 chars","");
- *error = TRUE;
- return str;
- }
- (void) memmove(procName, start, str-start);
- procName[str-start] = '\0';
- *actionProcNameP = XrmStringToQuark( procName );
- return str;
-}
-
-
-static String ParseString(
- register String str,
- String *strP)
-{
- register String start;
-
- if (*str == '"') {
- register unsigned prev_len, len;
- str++;
- start = str;
- *strP = NULL;
- prev_len = 0;
-
- while (*str != '"' && *str != '\0') {
- /* \" produces double quote embedded in a quoted parameter
- * \\" produces backslash as last character of a quoted parameter
- */
- if (*str == '\\' &&
- (*(str+1) == '"' || (*(str+1) == '\\' && *(str+2) == '"'))) {
- len = prev_len + (str-start+2);
- *strP = XtRealloc(*strP, len);
- (void) memmove(*strP + prev_len, start, str-start);
- prev_len = len-1;
- str++;
- (*strP)[prev_len-1] = *str;
- (*strP)[prev_len] = '\0';
- start = str+1;
- }
- str++;
- }
- len = prev_len + (str-start+1);
- *strP = XtRealloc(*strP, len);
- (void) memmove( *strP + prev_len, start, str-start);
- (*strP)[len-1] = '\0';
- if (*str == '"') str++; else
- XtWarningMsg(XtNtranslationParseError,"parseString",
- XtCXtToolkitError,"Missing '\"'.",
- (String *)NULL, (Cardinal *)NULL);
- } else {
- /* scan non-quoted string, stop on whitespace, ',' or ')' */
- start = str;
- while (*str != ' '
- && *str != '\t'
- && *str != ','
- && *str != ')'
- && !IsNewline(*str)
- && *str != '\0') str++;
- *strP = __XtMalloc((unsigned)(str-start+1));
- (void) memmove(*strP, start, str-start);
- (*strP)[str-start] = '\0';
- }
- return str;
-}
-
-
-static String ParseParamSeq(
- register String str,
- String **paramSeqP,
- Cardinal *paramNumP)
-{
- typedef struct _ParamRec *ParamPtr;
- typedef struct _ParamRec {
- ParamPtr next;
- String param;
- } ParamRec;
-
- ParamPtr params = NULL;
- register Cardinal num_params = 0;
- register Cardinal i;
-
- ScanWhitespace(str);
- while (*str != ')' && *str != '\0' && !IsNewline(*str)) {
- String newStr;
- str = ParseString(str, &newStr);
- if (newStr != NULL) {
- ParamPtr temp = (ParamRec*)
- ALLOCATE_LOCAL( (unsigned)sizeof(ParamRec) );
- if (temp == NULL) _XtAllocError (NULL);
-
- num_params++;
- temp->next = params;
- params = temp;
- temp->param = newStr;
- ScanWhitespace(str);
- if (*str == ',') {
- str++;
- ScanWhitespace(str);
- }
- }
- }
-
- if (num_params != 0) {
- String *paramP = (String *)
- __XtMalloc( (unsigned)(num_params+1) * sizeof(String) );
- *paramSeqP = paramP;
- *paramNumP = num_params;
- paramP += num_params; /* list is LIFO right now */
- *paramP-- = NULL;
- for (i=0; i < num_params; i++) {
- ParamPtr next = params->next;
- *paramP-- = params->param;
- DEALLOCATE_LOCAL( (char *)params );
- params = next;
- }
- } else {
- *paramSeqP = NULL;
- *paramNumP = 0;
- }
-
- return str;
-}
-
-static String ParseAction(
- String str,
- ActionPtr actionP,
- XrmQuark* quarkP,
- Boolean* error)
-{
- str = ParseActionProc(str, quarkP, error);
- if (*error) return str;
-
- if (*str == '(') {
- str++;
- str = ParseParamSeq(str, &actionP->params, &actionP->num_params);
- } else {
- Syntax("Missing '(' while parsing action sequence","");
- *error = TRUE;
- return str;
- }
- if (*str == ')') str++;
- else{
- Syntax("Missing ')' while parsing action sequence","");
- *error = TRUE;
- return str;
- }
- return str;
-}
-
-
-static String ParseActionSeq(
- TMParseStateTree parseTree,
- String str,
- ActionPtr *actionsP,
- Boolean *error)
-{
- ActionPtr *nextActionP = actionsP;
-
- *actionsP = NULL;
- while (*str != '\0' && !IsNewline(*str)) {
- register ActionPtr action;
- XrmQuark quark;
-
- action = XtNew(ActionRec);
- action->params = NULL;
- action->num_params = 0;
- action->next = NULL;
-
- str = ParseAction(str, action, &quark, error);
- if (*error) return PanicModeRecovery(str);
-
- action->idx = _XtGetQuarkIndex(parseTree, quark);
- ScanWhitespace(str);
- *nextActionP = action;
- nextActionP = &action->next;
- }
- if (IsNewline(*str)) str++;
- ScanWhitespace(str);
- return str;
-}
-
-
-static void ShowProduction(
- String currentProduction)
-{
- Cardinal num_params = 1;
- String params[1];
- size_t len;
- char *eol, *production, productionbuf[500];
-
-#ifdef __UNIXOS2__
- eol = strchr(currentProduction, '\r');
- if (!eol) /* try '\n' as well below */
-#endif
- eol = strchr(currentProduction, '\n');
- if (eol) len = eol - currentProduction;
- else len = strlen (currentProduction);
- production = XtStackAlloc (len + 1, productionbuf);
- if (production == NULL) _XtAllocError (NULL);
- (void) memmove(production, currentProduction, len);
- production[len] = '\0';
-
- params[0] = production;
- XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError,
- "... found while parsing '%s'", params, &num_params);
-
- XtStackFree (production, productionbuf);
-}
-
-/***********************************************************************
- * ParseTranslationTableProduction
- * Parses one line of event bindings.
- ***********************************************************************/
-
-static String ParseTranslationTableProduction(
- TMParseStateTree parseTree,
- register String str,
- Boolean* error)
-{
- EventSeqPtr eventSeq = NULL;
- ActionPtr *actionsP;
- String production = str;
-
- actionsP = NULL;
- str = ParseEventSeq(str, &eventSeq, &actionsP,error);
- if (*error == TRUE) {
- ShowProduction(production);
- FreeEventSeq(eventSeq);
- return (str);
- }
- ScanWhitespace(str);
- str = ParseActionSeq(parseTree, str, actionsP, error);
- if (*error == TRUE) {
- ShowProduction(production);
- FreeEventSeq(eventSeq);
- return (str);
- }
-
- _XtAddEventSeqToStateTree(eventSeq, parseTree);
- FreeEventSeq(eventSeq);
- return (str);
-}
-
-static String CheckForPoundSign(
- String str,
- _XtTranslateOp defaultOp,
- _XtTranslateOp *actualOpRtn)
-{
- String start;
- char operation[20];
- _XtTranslateOp opType;
-
- opType = defaultOp;
- ScanWhitespace(str);
- if (*str == '#') {
- int len;
- str++;
- start = str;
- str = ScanIdent(str);
- len = MIN(19, str-start);
- (void) memmove(operation, start, len);
- operation[len] = '\0';
- if (!strcmp(operation,"replace"))
- opType = XtTableReplace;
- else if (!strcmp(operation,"augment"))
- opType = XtTableAugment;
- else if (!strcmp(operation,"override"))
- opType = XtTableOverride;
- ScanWhitespace(str);
- if (IsNewline(*str)) {
- str++;
- ScanWhitespace(str);
- }
- }
- *actualOpRtn = opType;
- return str;
-}
-
-static XtTranslations ParseTranslationTable(
- String source,
- Boolean isAccelerator,
- _XtTranslateOp defaultOp,
- Boolean* error)
-{
- XtTranslations xlations;
- TMStateTree stateTrees[8];
- TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec;
- XrmQuark stackQuarks[200];
- TMBranchHeadRec stackBranchHeads[200];
- StatePtr stackComplexBranchHeads[200];
- _XtTranslateOp actualOp;
-
- if (source == NULL)
- return (XtTranslations)NULL;
-
- source = CheckForPoundSign(source, defaultOp, &actualOp);
- if (isAccelerator && actualOp == XtTableReplace)
- actualOp = defaultOp;
-
- parseTree->isSimple = TRUE;
- parseTree->mappingNotifyInterest = FALSE;
- parseTree->isAccelerator = isAccelerator;
- parseTree->isStackBranchHeads =
- parseTree->isStackQuarks =
- parseTree->isStackComplexBranchHeads = TRUE;
-
- parseTree->numQuarks =
- parseTree->numBranchHeads =
- parseTree->numComplexBranchHeads = 0;
-
- parseTree->quarkTblSize =
- parseTree->branchHeadTblSize =
- parseTree->complexBranchHeadTblSize = 200;
-
- parseTree->quarkTbl = stackQuarks;
- parseTree->branchHeadTbl = stackBranchHeads;
- parseTree->complexBranchHeadTbl = stackComplexBranchHeads;
-
- while (source != NULL && *source != '\0') {
- source = ParseTranslationTableProduction(parseTree, source, error);
- if (*error == TRUE) break;
- }
- stateTrees[0] = _XtParseTreeToStateTree(parseTree);
-
- if (!parseTree->isStackQuarks)
- XtFree((char *)parseTree->quarkTbl);
- if (!parseTree->isStackBranchHeads)
- XtFree((char *)parseTree->branchHeadTbl);
- if (!parseTree->isStackComplexBranchHeads)
- XtFree((char *)parseTree->complexBranchHeadTbl);
-
- xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL);
- xlations->operation = actualOp;
-
-#ifdef notdef
- XtFree(stateTrees);
-#endif /* notdef */
- return xlations;
-}
-
-/*** public procedures ***/
-
-/*ARGSUSED*/
-Boolean XtCvtStringToAcceleratorTable(
- Display* dpy,
- XrmValuePtr args,
- Cardinal *num_args,
- XrmValuePtr from,
- XrmValuePtr to,
- XtPointer *closure)
-{
- String str;
- Boolean error = FALSE;
-
- if (*num_args != 0)
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError,
- "String to AcceleratorTable conversion needs no extra arguments",
- (String *)NULL, (Cardinal *)NULL);
- str = (String)(from->addr);
- if (str == NULL) {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError,
- "String to AcceleratorTable conversion needs string",
- (String *)NULL, (Cardinal *)NULL);
- return FALSE;
- }
- if (to->addr != NULL) {
- if (to->size < sizeof(XtAccelerators)) {
- to->size = sizeof(XtAccelerators);
- return FALSE;
- }
- *(XtAccelerators*)to->addr =
- (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error);
- }
- else {
- static XtAccelerators staticStateTable;
- staticStateTable =
- (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error);
- to->addr = (XPointer) &staticStateTable;
- to->size = sizeof(XtAccelerators);
- }
- if (error == TRUE)
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError,
- "String to AcceleratorTable conversion encountered errors",
- (String *)NULL, (Cardinal *)NULL);
- return (error != TRUE);
-}
-
-
-/*ARGSUSED*/
-Boolean
-XtCvtStringToTranslationTable(
- Display *dpy,
- XrmValuePtr args,
- Cardinal *num_args,
- XrmValuePtr from,
- XrmValuePtr to,
- XtPointer *closure_ret)
-{
- String str;
- Boolean error = FALSE;
-
- if (*num_args != 0)
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError,
- "String to TranslationTable conversion needs no extra arguments",
- (String *)NULL, (Cardinal *)NULL);
- str = (String)(from->addr);
- if (str == NULL) {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "badParameters","cvtStringToTranslation",XtCXtToolkitError,
- "String to TranslationTable conversion needs string",
- (String *)NULL, (Cardinal *)NULL);
- return FALSE;
- }
- if (to->addr != NULL) {
- if (to->size < sizeof(XtTranslations)) {
- to->size = sizeof(XtTranslations);
- return FALSE;
- }
- *(XtTranslations*)to->addr =
- ParseTranslationTable(str, FALSE, XtTableReplace, &error);
- }
- else {
- static XtTranslations staticStateTable;
- staticStateTable =
- ParseTranslationTable(str, FALSE, XtTableReplace, &error);
- to->addr = (XPointer) &staticStateTable;
- to->size = sizeof(XtTranslations);
- }
- if (error == TRUE)
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "parseError","cvtStringToTranslationTable",XtCXtToolkitError,
- "String to TranslationTable conversion encountered errors",
- (String *)NULL, (Cardinal *)NULL);
- return (error != TRUE);
-}
-
-
-/*
- * Parses a user's or applications translation table
- */
-XtAccelerators XtParseAcceleratorTable(
- _Xconst char* source)
-{
- Boolean error = FALSE;
- XtAccelerators ret =
- (XtAccelerators) ParseTranslationTable ((char *)source, TRUE, XtTableAugment, &error);
- if (error == TRUE)
- XtWarningMsg ("parseError", "cvtStringToAcceleratorTable",
- XtCXtToolkitError,
- "String to AcceleratorTable conversion encountered errors",
- (String *)NULL, (Cardinal *)NULL);
- return ret;
-}
-
-XtTranslations XtParseTranslationTable(
- _Xconst char* source)
-{
- Boolean error = FALSE;
- XtTranslations ret = ParseTranslationTable((char *)source, FALSE, XtTableReplace, &error);
- if (error == TRUE)
- XtWarningMsg ("parseError",
- "cvtStringToTranslationTable", XtCXtToolkitError,
- "String to TranslationTable conversion encountered errors",
- (String *)NULL, (Cardinal *)NULL);
- return ret;
-}
-
-void _XtTranslateInitialize(void)
-{
- LOCK_PROCESS;
- if (initialized) {
- XtWarningMsg("translationError","xtTranslateInitialize",
- XtCXtToolkitError,"Initializing Translation manager twice.",
- (String *)NULL, (Cardinal *)NULL);
- UNLOCK_PROCESS;
- return;
- }
-
- initialized = TRUE;
- UNLOCK_PROCESS;
- QMeta = XrmPermStringToQuark("Meta");
- QCtrl = XrmPermStringToQuark("Ctrl");
- QNone = XrmPermStringToQuark("None");
- QAny = XrmPermStringToQuark("Any");
-
- Compile_XtEventTable( events, XtNumber(events) );
- Compile_XtModifierTable( modifiers, XtNumber(modifiers) );
- CompileNameValueTable( buttonNames );
- CompileNameValueTable( notifyModes );
- CompileNameValueTable( motionDetails );
-#if 0
- CompileNameValueTable( notifyDetail );
- CompileNameValueTable( visibilityNotify );
- CompileNameValueTable( circulation );
- CompileNameValueTable( propertyChanged );
-#endif
- CompileNameValueTable( mappingNotify );
-}
-
-void _XtAddTMConverters(
- ConverterTable table)
-{
- _XtTableAddConverter(table,
- _XtQString,
- XrmPermStringToQuark(XtRTranslationTable),
- XtCvtStringToTranslationTable, (XtConvertArgList) NULL,
- (Cardinal)0, True, CACHED, _XtFreeTranslations, True);
- _XtTableAddConverter(table, _XtQString,
- XrmPermStringToQuark(XtRAcceleratorTable),
- XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL,
- (Cardinal)0, True, CACHED, _XtFreeTranslations, True);
- _XtTableAddConverter(table,
- XrmPermStringToQuark( _XtRStateTablePair ),
- XrmPermStringToQuark(XtRTranslationTable),
- _XtCvtMergeTranslations, (XtConvertArgList) NULL,
- (Cardinal)0, True, CACHED, _XtFreeTranslations, True);
-}
+/*********************************************************** +Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + +Copyright 1987, 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "IntrinsicI.h" +#include "StringDefs.h" +#include <ctype.h> +#include <stdlib.h> +#ifndef NOTASCII +#define XK_LATIN1 +#endif +#define XK_MISCELLANY +#include <X11/keysymdef.h> + +#ifdef CACHE_TRANSLATIONS +# ifdef REFCNT_TRANSLATIONS +# define CACHED XtCacheAll | XtCacheRefCount +# else +# define CACHED XtCacheAll +# endif +#else +# define CACHED XtCacheNone +#endif + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +static String XtNtranslationParseError = "translationParseError"; + +typedef int EventType; + +typedef String (*ParseProc)( + String /* str; */, + Opaque /* closure; */, + EventPtr /* event; */, + Boolean* /* error */); + +typedef TMShortCard Value; +typedef void (*ModifierProc)(Value, LateBindingsPtr*, Boolean, Value*); + +typedef struct _ModifierRec { + char* name; + XrmQuark signature; + ModifierProc modifierParseProc; + Value value; +} ModifierRec, *ModifierKeys; + +typedef struct _EventKey { + char *event; + XrmQuark signature; + EventType eventType; + ParseProc parseDetail; + Opaque closure; +}EventKey, *EventKeys; + +typedef struct { + char *name; + XrmQuark signature; + Value value; +} NameValueRec, *NameValueTable; + +static void ParseModImmed(Value, LateBindingsPtr*, Boolean, Value*); +static void ParseModSym(Value, LateBindingsPtr*, Boolean, Value*); +static String PanicModeRecovery(String); +static String CheckForPoundSign(String, _XtTranslateOp, _XtTranslateOp *); +static KeySym StringToKeySym(String, Boolean *); +static ModifierRec modifiers[] = { + {"Shift", 0, ParseModImmed,ShiftMask}, + {"Lock", 0, ParseModImmed,LockMask}, + {"Ctrl", 0, ParseModImmed,ControlMask}, + {"Mod1", 0, ParseModImmed,Mod1Mask}, + {"Mod2", 0, ParseModImmed,Mod2Mask}, + {"Mod3", 0, ParseModImmed,Mod3Mask}, + {"Mod4", 0, ParseModImmed,Mod4Mask}, + {"Mod5", 0, ParseModImmed,Mod5Mask}, + {"Meta", 0, ParseModSym, XK_Meta_L}, + {"m", 0, ParseModSym, XK_Meta_L}, + {"h", 0, ParseModSym, XK_Hyper_L}, + {"su", 0, ParseModSym, XK_Super_L}, + {"a", 0, ParseModSym, XK_Alt_L}, + {"Hyper", 0, ParseModSym, XK_Hyper_L}, + {"Super", 0, ParseModSym, XK_Super_L}, + {"Alt", 0, ParseModSym, XK_Alt_L}, + {"Button1", 0, ParseModImmed,Button1Mask}, + {"Button2", 0, ParseModImmed,Button2Mask}, + {"Button3", 0, ParseModImmed,Button3Mask}, + {"Button4", 0, ParseModImmed,Button4Mask}, + {"Button5", 0, ParseModImmed,Button5Mask}, + {"c", 0, ParseModImmed,ControlMask}, + {"s", 0, ParseModImmed,ShiftMask}, + {"l", 0, ParseModImmed,LockMask}, +}; + +static NameValueRec buttonNames[] = { + {"Button1", 0, Button1}, + {"Button2", 0, Button2}, + {"Button3", 0, Button3}, + {"Button4", 0, Button4}, + {"Button5", 0, Button5}, + {NULL, NULLQUARK, 0}, +}; + +static NameValueRec motionDetails[] = { + {"Normal", 0, NotifyNormal}, + {"Hint", 0, NotifyHint}, + {NULL, NULLQUARK, 0}, +}; + +static NameValueRec notifyModes[] = { + {"Normal", 0, NotifyNormal}, + {"Grab", 0, NotifyGrab}, + {"Ungrab", 0, NotifyUngrab}, + {"WhileGrabbed", 0, NotifyWhileGrabbed}, + {NULL, NULLQUARK, 0}, +}; + +#if 0 +static NameValueRec notifyDetail[] = { + {"Ancestor", 0, NotifyAncestor}, + {"Virtual", 0, NotifyVirtual}, + {"Inferior", 0, NotifyInferior}, + {"Nonlinear", 0, NotifyNonlinear}, + {"NonlinearVirtual", 0, NotifyNonlinearVirtual}, + {"Pointer", 0, NotifyPointer}, + {"PointerRoot", 0, NotifyPointerRoot}, + {"DetailNone", 0, NotifyDetailNone}, + {NULL, NULLQUARK, 0}, +}; + +static NameValueRec visibilityNotify[] = { + {"Unobscured", 0, VisibilityUnobscured}, + {"PartiallyObscured", 0, VisibilityPartiallyObscured}, + {"FullyObscured", 0, VisibilityFullyObscured}, + {NULL, NULLQUARK, 0}, +}; + +static NameValueRec circulation[] = { + {"OnTop", 0, PlaceOnTop}, + {"OnBottom", 0, PlaceOnBottom}, + {NULL, NULLQUARK, 0}, +}; + +static NameValueRec propertyChanged[] = { + {"NewValue", 0, PropertyNewValue}, + {"Delete", 0, PropertyDelete}, + {NULL, NULLQUARK, 0}, +}; +#endif /*0*/ + +static NameValueRec mappingNotify[] = { + {"Modifier", 0, MappingModifier}, + {"Keyboard", 0, MappingKeyboard}, + {"Pointer", 0, MappingPointer}, + {NULL, NULLQUARK, 0}, +}; + +static String ParseKeySym(String, Opaque, EventPtr, Boolean*); +static String ParseKeyAndModifiers(String, Opaque, EventPtr, Boolean*); +static String ParseTable(String, Opaque, EventPtr, Boolean*); +static String ParseImmed(String, Opaque, EventPtr, Boolean*); +static String ParseAddModifier(String, Opaque, EventPtr, Boolean*); +static String ParseNone(String, Opaque, EventPtr, Boolean*); +static String ParseAtom(String, Opaque, EventPtr, Boolean*); + +static EventKey events[] = { + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +{"KeyPress", NULLQUARK, KeyPress, ParseKeySym, NULL}, +{"Key", NULLQUARK, KeyPress, ParseKeySym, NULL}, +{"KeyDown", NULLQUARK, KeyPress, ParseKeySym, NULL}, +{"Ctrl", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)ControlMask}, +{"Shift", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)ShiftMask}, +{"Meta", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)NULL}, +{"KeyUp", NULLQUARK, KeyRelease, ParseKeySym, NULL}, +{"KeyRelease", NULLQUARK, KeyRelease, ParseKeySym, NULL}, + +{"ButtonPress", NULLQUARK, ButtonPress, ParseTable,(Opaque)buttonNames}, +{"BtnDown", NULLQUARK, ButtonPress, ParseTable,(Opaque)buttonNames}, +{"Btn1Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button1}, +{"Btn2Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button2}, +{"Btn3Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button3}, +{"Btn4Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button4}, +{"Btn5Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button5}, + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +{"ButtonRelease", NULLQUARK, ButtonRelease, ParseTable,(Opaque)buttonNames}, +{"BtnUp", NULLQUARK, ButtonRelease, ParseTable,(Opaque)buttonNames}, +{"Btn1Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button1}, +{"Btn2Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button2}, +{"Btn3Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button3}, +{"Btn4Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button4}, +{"Btn5Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button5}, + +{"MotionNotify", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, +{"PtrMoved", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, +{"Motion", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, +{"MouseMoved", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, +{"BtnMotion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)AnyButtonMask}, +{"Btn1Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button1Mask}, +{"Btn2Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button2Mask}, +{"Btn3Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button3Mask}, +{"Btn4Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button4Mask}, +{"Btn5Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button5Mask}, + +{"EnterNotify", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes}, +{"Enter", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes}, +{"EnterWindow", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes}, + +{"LeaveNotify", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes}, +{"LeaveWindow", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes}, +{"Leave", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes}, + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +{"FocusIn", NULLQUARK, FocusIn, ParseTable,(Opaque)notifyModes}, + +{"FocusOut", NULLQUARK, FocusOut, ParseTable,(Opaque)notifyModes}, + +{"KeymapNotify", NULLQUARK, KeymapNotify, ParseNone, NULL}, +{"Keymap", NULLQUARK, KeymapNotify, ParseNone, NULL}, + +{"Expose", NULLQUARK, Expose, ParseNone, NULL}, + +{"GraphicsExpose", NULLQUARK, GraphicsExpose, ParseNone, NULL}, +{"GrExp", NULLQUARK, GraphicsExpose, ParseNone, NULL}, + +{"NoExpose", NULLQUARK, NoExpose, ParseNone, NULL}, +{"NoExp", NULLQUARK, NoExpose, ParseNone, NULL}, + +{"VisibilityNotify",NULLQUARK, VisibilityNotify,ParseNone, NULL}, +{"Visible", NULLQUARK, VisibilityNotify,ParseNone, NULL}, + +{"CreateNotify", NULLQUARK, CreateNotify, ParseNone, NULL}, +{"Create", NULLQUARK, CreateNotify, ParseNone, NULL}, + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +{"DestroyNotify", NULLQUARK, DestroyNotify, ParseNone, NULL}, +{"Destroy", NULLQUARK, DestroyNotify, ParseNone, NULL}, + +{"UnmapNotify", NULLQUARK, UnmapNotify, ParseNone, NULL}, +{"Unmap", NULLQUARK, UnmapNotify, ParseNone, NULL}, + +{"MapNotify", NULLQUARK, MapNotify, ParseNone, NULL}, +{"Map", NULLQUARK, MapNotify, ParseNone, NULL}, + +{"MapRequest", NULLQUARK, MapRequest, ParseNone, NULL}, +{"MapReq", NULLQUARK, MapRequest, ParseNone, NULL}, + +{"ReparentNotify", NULLQUARK, ReparentNotify, ParseNone, NULL}, +{"Reparent", NULLQUARK, ReparentNotify, ParseNone, NULL}, + +{"ConfigureNotify", NULLQUARK, ConfigureNotify, ParseNone, NULL}, +{"Configure", NULLQUARK, ConfigureNotify, ParseNone, NULL}, + +{"ConfigureRequest",NULLQUARK, ConfigureRequest,ParseNone, NULL}, +{"ConfigureReq", NULLQUARK, ConfigureRequest,ParseNone, NULL}, + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +{"GravityNotify", NULLQUARK, GravityNotify, ParseNone, NULL}, +{"Grav", NULLQUARK, GravityNotify, ParseNone, NULL}, + +{"ResizeRequest", NULLQUARK, ResizeRequest, ParseNone, NULL}, +{"ResReq", NULLQUARK, ResizeRequest, ParseNone, NULL}, + +{"CirculateNotify", NULLQUARK, CirculateNotify, ParseNone, NULL}, +{"Circ", NULLQUARK, CirculateNotify, ParseNone, NULL}, + +{"CirculateRequest",NULLQUARK, CirculateRequest,ParseNone, NULL}, +{"CircReq", NULLQUARK, CirculateRequest,ParseNone, NULL}, + +{"PropertyNotify", NULLQUARK, PropertyNotify, ParseAtom, NULL}, +{"Prop", NULLQUARK, PropertyNotify, ParseAtom, NULL}, + +{"SelectionClear", NULLQUARK, SelectionClear, ParseAtom, NULL}, +{"SelClr", NULLQUARK, SelectionClear, ParseAtom, NULL}, + +{"SelectionRequest",NULLQUARK, SelectionRequest,ParseAtom, NULL}, +{"SelReq", NULLQUARK, SelectionRequest,ParseAtom, NULL}, + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +{"SelectionNotify", NULLQUARK, SelectionNotify, ParseAtom, NULL}, +{"Select", NULLQUARK, SelectionNotify, ParseAtom, NULL}, + +{"ColormapNotify", NULLQUARK, ColormapNotify, ParseNone, NULL}, +{"Clrmap", NULLQUARK, ColormapNotify, ParseNone, NULL}, + +{"ClientMessage", NULLQUARK, ClientMessage, ParseAtom, NULL}, +{"Message", NULLQUARK, ClientMessage, ParseAtom, NULL}, + +{"MappingNotify", NULLQUARK, MappingNotify, ParseTable, (Opaque)mappingNotify}, +{"Mapping", NULLQUARK, MappingNotify, ParseTable, (Opaque)mappingNotify}, + +#ifdef DEBUG +# ifdef notdef +{"Timer", NULLQUARK, _XtTimerEventType,ParseNone, NULL}, +# endif /* notdef */ +{"EventTimer", NULLQUARK, _XtEventTimerEventType,ParseNone,NULL}, +#endif /* DEBUG */ + +/* Event Name, Quark, Event Type, Detail Parser, Closure */ + +}; + +#ifndef __UNIXOS2__ +#define IsNewline(str) ((str) == '\n') +#else +#define IsNewline(str) ((str) == '\n' || (str) == '\r') +#endif + +#define ScanFor(str, ch) \ + while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))) (str)++ + +#define ScanNumeric(str) while ('0' <= *(str) && *(str) <= '9') (str)++ + +#define ScanAlphanumeric(str) \ + while (('A' <= *(str) && *(str) <= 'Z') || \ + ('a' <= *(str) && *(str) <= 'z') || \ + ('0' <= *(str) && *(str) <= '9')) (str)++ + +#ifndef __UNIXOS2__ +#define ScanWhitespace(str) \ + while (*(str) == ' ' || *(str) == '\t') (str)++ +#else +#define ScanWhitespace(str) \ + while (*(str) == ' ' || *(str) == '\t' || *(str) == '\r') (str)++ +#endif + +static Boolean initialized = FALSE; +static XrmQuark QMeta; +static XrmQuark QCtrl; +static XrmQuark QNone; +static XrmQuark QAny; + +static void FreeEventSeq( + EventSeqPtr eventSeq) +{ + register EventSeqPtr evs = eventSeq; + + while (evs != NULL) { + evs->state = (StatePtr) evs; + if (evs->next != NULL + && evs->next->state == (StatePtr) evs->next) + evs->next = NULL; + evs = evs->next; + } + + evs = eventSeq; + while (evs != NULL) { + register EventPtr event = evs; + evs = evs->next; + if (evs == event) evs = NULL; + XtFree((char *)event); + } +} + +static void CompileNameValueTable( + NameValueTable table) +{ + register int i; + + for (i=0; table[i].name; i++) + table[i].signature = XrmPermStringToQuark(table[i].name); +} + +static int OrderEvents(_Xconst void *a, _Xconst void *b) +{ + return ((((_Xconst EventKey *)a)->signature < + ((_Xconst EventKey *)b)->signature) ? -1 : 1); +} + +static void Compile_XtEventTable( + EventKeys table, + Cardinal count) +{ + register int i; + register EventKeys entry = table; + + for (i=count; --i >= 0; entry++) + entry->signature = XrmPermStringToQuark(entry->event); + qsort(table, count, sizeof(EventKey), OrderEvents); +} + +static int OrderModifiers(_Xconst void *a, _Xconst void *b) +{ + return ((((_Xconst ModifierRec *)a)->signature < + ((_Xconst ModifierRec *)b)->signature) ? -1 : 1); +} + +static void Compile_XtModifierTable( + ModifierKeys table, + Cardinal count) +{ + register int i; + register ModifierKeys entry = table; + + for (i=count; --i >= 0; entry++) + entry->signature = XrmPermStringToQuark(entry->name); + qsort(table, count, sizeof(ModifierRec), OrderModifiers); +} + +static String PanicModeRecovery( + String str) +{ + ScanFor(str,'\n'); + if (*str == '\n') str++; + return str; + +} + + +static void Syntax( + String str0,String str1) +{ + Cardinal num_params = 2; + String params[2]; + + params[0] = str0; + params[1] = str1; + XtWarningMsg(XtNtranslationParseError,"parseError",XtCXtToolkitError, + "translation table syntax error: %s %s",params,&num_params); +} + + + +static Cardinal LookupTMEventType( + String eventStr, + Boolean *error) +{ + register int i = 0, left, right; + register XrmQuark signature; + static int previous = 0; + + LOCK_PROCESS; + if ((signature = StringToQuark(eventStr)) == events[previous].signature) { + UNLOCK_PROCESS; + return (Cardinal) previous; + } + + left = 0; + right = XtNumber(events) - 1; + while (left <= right) { + i = (left + right) >> 1; + if (signature < events[i].signature) + right = i - 1; + else if (signature > events[i].signature) + left = i + 1; + else { + previous = i; + UNLOCK_PROCESS; + return (Cardinal) i; + } + } + + Syntax("Unknown event type : ",eventStr); + *error = TRUE; + UNLOCK_PROCESS; + return (Cardinal) i; +} + +static void StoreLateBindings( + KeySym keysymL, + Boolean notL, + KeySym keysymR, + Boolean notR, + LateBindingsPtr* lateBindings) +{ + LateBindingsPtr temp; + Boolean pair = FALSE; + unsigned long count,number; + if (lateBindings != NULL){ + temp = *lateBindings; + if (temp != NULL) { + for (count = 0; temp[count].keysym; count++){/*EMPTY*/} + } + else count = 0; + if (! keysymR){ + number = 1;pair = FALSE; + } else{ + number = 2;pair = TRUE; + } + + temp = (LateBindingsPtr)XtRealloc((char *)temp, + (unsigned)((count+number+1) * sizeof(LateBindings)) ); + *lateBindings = temp; + temp[count].knot = notL; + temp[count].pair = pair; + if (count == 0) + temp[count].ref_count = 1; + temp[count++].keysym = keysymL; + if (keysymR){ + temp[count].knot = notR; + temp[count].pair = FALSE; + temp[count].ref_count = 0; + temp[count++].keysym = keysymR; + } + temp[count].knot = temp[count].pair = FALSE; + temp[count].ref_count = 0; + temp[count].keysym = 0; + } +} + +static void _XtParseKeysymMod( + String name, + LateBindingsPtr* lateBindings, + Boolean notFlag, + Value *valueP, + Boolean *error) +{ + KeySym keySym; + keySym = StringToKeySym(name, error); + *valueP = 0; + if (keySym != NoSymbol) { + StoreLateBindings(keySym,notFlag,(KeySym) NULL,FALSE,lateBindings); + } +} + +static Boolean _XtLookupModifier( + XrmQuark signature, + LateBindingsPtr* lateBindings, + Boolean notFlag, + Value *valueP, + Bool constMask) +{ + register int i, left, right; + static int previous = 0; + + LOCK_PROCESS; + if (signature == modifiers[previous].signature) { + if (constMask) *valueP = modifiers[previous].value; + else /* if (modifiers[previous].modifierParseProc) always true */ + (*modifiers[previous].modifierParseProc) + (modifiers[previous].value, lateBindings, notFlag, valueP); + UNLOCK_PROCESS; + return TRUE; + } + + left = 0; + right = XtNumber(modifiers) - 1; + while (left <= right) { + i = (left + right) >> 1; + if (signature < modifiers[i].signature) + right = i - 1; + else if (signature > modifiers[i].signature) + left = i + 1; + else { + previous = i; + if (constMask) *valueP = modifiers[i].value; + else /* if (modifiers[i].modifierParseProc) always true */ + (*modifiers[i].modifierParseProc) + (modifiers[i].value, lateBindings, notFlag, valueP); + UNLOCK_PROCESS; + return TRUE; + } + } + UNLOCK_PROCESS; + return FALSE; +} + + +static String ScanIdent( + register String str) +{ + ScanAlphanumeric(str); + while ( + ('A' <= *str && *str <= 'Z') + || ('a' <= *str && *str <= 'z') + || ('0' <= *str && *str <= '9') + || (*str == '-') + || (*str == '_') + || (*str == '$') + ) str++; + return str; +} + +static String FetchModifierToken( + String str, + XrmQuark *token_return) +{ + String start = str; + + if (*str == '$') { + *token_return = QMeta; + str++; + return str; + } + if (*str == '^') { + *token_return = QCtrl; + str++; + return str; + } + str = ScanIdent(str); + if (start != str) { + char modStrbuf[100]; + char* modStr; + + modStr = XtStackAlloc ((size_t)(str - start + 1), modStrbuf); + if (modStr == NULL) _XtAllocError (NULL); + (void) memmove(modStr, start, str-start); + modStr[str-start] = '\0'; + *token_return = XrmStringToQuark(modStr); + XtStackFree (modStr, modStrbuf); + return str; + } + return str; +} + +static String ParseModifiers( + register String str, + EventPtr event, + Boolean* error) +{ + register String start; + Boolean notFlag, exclusive, keysymAsMod; + Value maskBit; + XrmQuark Qmod; + + ScanWhitespace(str); + start = str; + str = FetchModifierToken(str, &Qmod); + exclusive = FALSE; + if (start != str) { + if (Qmod == QNone) { + event->event.modifierMask = ~0; + event->event.modifiers = 0; + ScanWhitespace(str); + return str; + } else if (Qmod == QAny) { /*backward compatability*/ + event->event.modifierMask = 0; + event->event.modifiers = AnyModifier; + ScanWhitespace(str); + return str; + } + str = start; /*if plain modifier, reset to beginning */ + } + else while (*str == '!' || *str == ':') { + if (*str == '!') { + exclusive = TRUE; + str++; + ScanWhitespace(str); + } + if (*str == ':') { + event->event.standard = TRUE; + str++; + ScanWhitespace(str); + } + } + + while (*str != '<') { + if (*str == '~') { + notFlag = TRUE; + str++; + } else + notFlag = FALSE; + if (*str == '@') { + keysymAsMod = TRUE; + str++; + } + else keysymAsMod = FALSE; + start = str; + str = FetchModifierToken(str, &Qmod); + if (start == str) { + Syntax("Modifier or '<' expected",""); + *error = TRUE; + return PanicModeRecovery(str); + } + if (keysymAsMod) { + _XtParseKeysymMod(XrmQuarkToString(Qmod), + &event->event.lateModifiers, + notFlag,&maskBit, error); + if (*error) + return PanicModeRecovery(str); + + } else + if (!_XtLookupModifier(Qmod, &event->event.lateModifiers, + notFlag, &maskBit, FALSE)) { + Syntax("Unknown modifier name: ", XrmQuarkToString(Qmod)); + *error = TRUE; + return PanicModeRecovery(str); + } + event->event.modifierMask |= maskBit; + if (notFlag) event->event.modifiers &= ~maskBit; + else event->event.modifiers |= maskBit; + ScanWhitespace(str); + } + if (exclusive) event->event.modifierMask = ~0; + return str; +} + +static String ParseXtEventType( + register String str, + EventPtr event, + Cardinal *tmEventP, + Boolean* error) +{ + String start = str; + char eventTypeStrbuf[100]; + char* eventTypeStr; + + ScanAlphanumeric(str); + eventTypeStr = XtStackAlloc ((size_t)(str - start + 1), eventTypeStrbuf); + if (eventTypeStr == NULL) _XtAllocError (NULL); + (void) memmove(eventTypeStr, start, str-start); + eventTypeStr[str-start] = '\0'; + *tmEventP = LookupTMEventType(eventTypeStr,error); + XtStackFree (eventTypeStr, eventTypeStrbuf); + if (*error) + return PanicModeRecovery(str); + event->event.eventType = events[*tmEventP].eventType; + return str; +} + +static unsigned long StrToHex( + String str) +{ + register char c; + register unsigned long val = 0; + + while ((c = *str)) { + if ('0' <= c && c <= '9') val = val*16+c-'0'; + else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10; + else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10; + else return 0; + str++; + } + + return val; +} + +static unsigned long StrToOct( + String str) +{ + register char c; + register unsigned long val = 0; + + while ((c = *str)) { + if ('0' <= c && c <= '7') val = val*8+c-'0'; else return 0; + str++; + } + + return val; +} + +static unsigned long StrToNum( + String str) +{ + register char c; + register unsigned long val = 0; + + if (*str == '0') { + str++; + if (*str == 'x' || *str == 'X') return StrToHex(++str); + else return StrToOct(str); + } + + while ((c = *str)) { + if ('0' <= c && c <= '9') val = val*10+c-'0'; + else return 0; + str++; + } + + return val; +} + +static KeySym StringToKeySym( + String str, + Boolean *error) +{ + KeySym k; + + if (str == NULL || *str == '\0') return (KeySym) 0; + +#ifndef NOTASCII + /* special case single character ASCII, for speed */ + if (*(str+1) == '\0') { + if (' ' <= *str && *str <= '~') return XK_space + (*str - ' '); + } +#endif + + if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str); + k = XStringToKeysym(str); + if (k != NoSymbol) return k; + +#ifdef NOTASCII + /* fall-back case to preserve backwards compatibility; no-one + * should be relying upon this! + */ + if (*(str+1) == '\0') return (KeySym) *str; +#endif + + Syntax("Unknown keysym name: ", str); + *error = TRUE; + return NoSymbol; +} +/* ARGSUSED */ +static void ParseModImmed( + Value value, + LateBindingsPtr* lateBindings, + Boolean notFlag, + Value* valueP) +{ + *valueP = value; +} + + /* is only valid with keysyms that have an _L and _R in their name; + * and ignores keysym lookup errors (i.e. assumes only valid keysyms) + */ +static void ParseModSym( + Value value, + LateBindingsPtr* lateBindings, + Boolean notFlag, + Value* valueP) +{ + register KeySym keysymL = (KeySym)value; + register KeySym keysymR = keysymL + 1; /* valid for supported keysyms */ + StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings); + *valueP = 0; +} + +#ifdef sparc +/* + * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that + * causes the value of the most recently used variable to be returned instead + * of the value passed in. + */ +static String stupid_optimizer_kludge; +#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val) +#else +#define BROKEN_OPTIMIZER_HACK(val) val +#endif + +/* ARGSUSED */ +static String ParseImmed( + register String str, + register Opaque closure, + register EventPtr event, + Boolean* error) +{ + event->event.eventCode = (unsigned long)closure; + event->event.eventCodeMask = ~0UL; + + return BROKEN_OPTIMIZER_HACK(str); +} + +/* ARGSUSED */ +static String ParseAddModifier( + register String str, + register Opaque closure, + register EventPtr event, + Boolean* error) +{ + register unsigned long modval = (unsigned long)closure; + event->event.modifiers |= modval; + if (modval != AnyButtonMask) /* AnyButtonMask is don't-care mask */ + event->event.modifierMask |= modval; + + return BROKEN_OPTIMIZER_HACK(str); +} + + +static String ParseKeyAndModifiers( + String str, + Opaque closure, + EventPtr event, + Boolean* error) +{ + str = ParseKeySym(str, closure, event,error); + if ((unsigned long) closure == 0) { + Value metaMask; /* unused */ + (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE, + &metaMask, FALSE); + } else { + event->event.modifiers |= (unsigned long) closure; + event->event.modifierMask |= (unsigned long) closure; + } + return str; +} + +/*ARGSUSED*/ +static String ParseKeySym( + register String str, + Opaque closure, + EventPtr event, + Boolean* error) +{ + char *start; + char keySymNamebuf[100]; + char* keySymName; + + ScanWhitespace(str); + + if (*str == '\\') { + keySymName = keySymNamebuf; + str++; + keySymName[0] = *str; + if (*str != '\0' && !IsNewline(*str)) str++; + keySymName[1] = '\0'; + event->event.eventCode = StringToKeySym(keySymName, error); + event->event.eventCodeMask = ~0L; + } else if (*str == ',' || *str == ':' || + /* allow leftparen to be single char symbol, + * for backwards compatibility + */ + (*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) { + keySymName = keySymNamebuf; /* just so we can stackfree it later */ + /* no detail */ + event->event.eventCode = 0L; + event->event.eventCodeMask = 0L; + } else { + start = str; + while ( + *str != ',' + && *str != ':' + && *str != ' ' + && *str != '\t' + && !IsNewline(*str) + && (*str != '(' || *(str+1) <= '0' || *(str+1) >= '9') + && *str != '\0') str++; + keySymName = XtStackAlloc ((size_t)(str - start + 1), keySymNamebuf); + (void) memmove(keySymName, start, str-start); + keySymName[str-start] = '\0'; + event->event.eventCode = StringToKeySym(keySymName, error); + event->event.eventCodeMask = ~0L; + } + if (*error) { + /* We never get here when keySymName hasn't been allocated */ + if (keySymName[0] == '<') { + /* special case for common error */ + XtWarningMsg(XtNtranslationParseError, "missingComma", + XtCXtToolkitError, + "... possibly due to missing ',' in event sequence.", + (String*)NULL, (Cardinal*)NULL); + } + XtStackFree (keySymName, keySymNamebuf); + return PanicModeRecovery(str); + } + if (event->event.standard) + event->event.matchEvent = _XtMatchUsingStandardMods; + else + event->event.matchEvent = _XtMatchUsingDontCareMods; + + XtStackFree (keySymName, keySymNamebuf); + + return str; +} + +static String ParseTable( + register String str, + Opaque closure, + EventPtr event, + Boolean* error) +{ + register String start = str; + register XrmQuark signature; + NameValueTable table = (NameValueTable) closure; + char tableSymName[100]; + + event->event.eventCode = 0L; + ScanAlphanumeric(str); + if (str == start) {event->event.eventCodeMask = 0L; return str; } + if (str-start >= 99) { + Syntax("Invalid Detail Type (string is too long).", ""); + *error = TRUE; + return str; + } + (void) memmove(tableSymName, start, str-start); + tableSymName[str-start] = '\0'; + signature = StringToQuark(tableSymName); + for (; table->signature != NULLQUARK; table++) + if (table->signature == signature) { + event->event.eventCode = table->value; + event->event.eventCodeMask = ~0L; + return str; + } + + Syntax("Unknown Detail Type: ", tableSymName); + *error = TRUE; + return PanicModeRecovery(str); +} + +/*ARGSUSED*/ +static String ParseNone( + String str, + Opaque closure, + EventPtr event, + Boolean* error) +{ + event->event.eventCode = 0; + event->event.eventCodeMask = 0; + + return BROKEN_OPTIMIZER_HACK(str); +} + +/*ARGSUSED*/ +static String ParseAtom( + String str, + Opaque closure, + EventPtr event, + Boolean* error) +{ + ScanWhitespace(str); + + if (*str == ',' || *str == ':') { + /* no detail */ + event->event.eventCode = 0L; + event->event.eventCodeMask = 0L; + } else { + char *start, atomName[1000]; + start = str; + while ( + *str != ',' + && *str != ':' + && *str != ' ' + && *str != '\t' + && !IsNewline(*str) + && *str != '\0') str++; + if (str-start >= 999) { + Syntax( "Atom name must be less than 1000 characters long.", "" ); + *error = TRUE; + return str; + } + (void) memmove(atomName, start, str-start); + atomName[str-start] = '\0'; + event->event.eventCode = XrmStringToQuark(atomName); + event->event.matchEvent = _XtMatchAtom; + } + return str; +} + +static ModifierMask buttonModifierMasks[] = { + 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask +}; +static String ParseRepeat(String, int *, Boolean *, Boolean *); + +static String ParseEvent( + register String str, + EventPtr event, + int* reps, + Boolean* plus, + Boolean* error) +{ + Cardinal tmEvent; + + str = ParseModifiers(str, event,error); + if (*error) return str; + if (*str != '<') { + Syntax("Missing '<' while parsing event type.",""); + *error = TRUE; + return PanicModeRecovery(str); + } + else str++; + str = ParseXtEventType(str, event, &tmEvent,error); + if (*error) return str; + if (*str != '>'){ + Syntax("Missing '>' while parsing event type",""); + *error = TRUE; + return PanicModeRecovery(str); + } + else str++; + if (*str == '(') { + str = ParseRepeat(str, reps, plus, error); + if (*error) return str; + } + str = (*(events[tmEvent].parseDetail))( + str, events[tmEvent].closure, event,error); + if (*error) return str; + +/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t. + * modifiers in grabs. + */ + if ((event->event.eventType == ButtonRelease) + && (event->event.modifiers | event->event.modifierMask) /* any */ + && (event->event.modifiers != AnyModifier)) + { + event->event.modifiers + |= buttonModifierMasks[event->event.eventCode]; + /* the button that is going up will always be in the modifiers... */ + } + + return str; +} + +static String ParseQuotedStringEvent( + register String str, + register EventPtr event, + Boolean *error) +{ + Value metaMask; + char s[2]; + + if (*str=='^') { + str++; + event->event.modifiers = ControlMask; + } else if (*str == '$') { + str++; + (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE, + &metaMask, FALSE); + } + if (*str == '\\') + str++; + s[0] = *str; + s[1] = '\0'; + if (*str != '\0' && !IsNewline(*str)) str++; + event->event.eventType = KeyPress; + event->event.eventCode = StringToKeySym(s, error); + if (*error) return PanicModeRecovery(str); + event->event.eventCodeMask = ~0L; + event->event.matchEvent = _XtMatchUsingStandardMods; + event->event.standard = TRUE; + + return str; +} + + +static EventSeqRec timerEventRec = { + {0, 0, NULL, _XtEventTimerEventType, 0L, 0L, NULL, False}, + /* (StatePtr) -1 */ NULL, + NULL, + NULL +}; + +static void RepeatDown( + EventPtr *eventP, + int reps, + ActionPtr **actionsP) +{ + EventRec upEventRec; + register EventPtr event, downEvent; + EventPtr upEvent = &upEventRec; + register int i; + + downEvent = event = *eventP; + *upEvent = *downEvent; + upEvent->event.eventType = ((event->event.eventType == ButtonPress) ? + ButtonRelease : KeyRelease); + if ((upEvent->event.eventType == ButtonRelease) + && (upEvent->event.modifiers != AnyModifier) + && (upEvent->event.modifiers | upEvent->event.modifierMask)) + upEvent->event.modifiers + |= buttonModifierMasks[event->event.eventCode]; + + if (event->event.lateModifiers) + event->event.lateModifiers->ref_count += (reps - 1) * 2; + + for (i=1; i<reps; i++) { + + /* up */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *upEvent; + + /* timer */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = timerEventRec; + + /* down */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *downEvent; + + } + + event->next = NULL; + *eventP = event; + *actionsP = &event->actions; +} + +static void RepeatDownPlus( + EventPtr *eventP, + int reps, + ActionPtr **actionsP) +{ + EventRec upEventRec; + register EventPtr event, downEvent, lastDownEvent = NULL; + EventPtr upEvent = &upEventRec; + register int i; + + downEvent = event = *eventP; + *upEvent = *downEvent; + upEvent->event.eventType = ((event->event.eventType == ButtonPress) ? + ButtonRelease : KeyRelease); + if ((upEvent->event.eventType == ButtonRelease) + && (upEvent->event.modifiers != AnyModifier) + && (upEvent->event.modifiers | upEvent->event.modifierMask)) + upEvent->event.modifiers + |= buttonModifierMasks[event->event.eventCode]; + + if (event->event.lateModifiers) + event->event.lateModifiers->ref_count += reps * 2 - 1; + + for (i=0; i<reps; i++) { + + if (i > 0) { + /* down */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *downEvent; + } + lastDownEvent = event; + + /* up */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *upEvent; + + /* timer */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = timerEventRec; + + } + + event->next = lastDownEvent; + *eventP = event; + *actionsP = &lastDownEvent->actions; +} + +static void RepeatUp( + EventPtr *eventP, + int reps, + ActionPtr **actionsP) +{ + EventRec upEventRec; + register EventPtr event, downEvent; + EventPtr upEvent = &upEventRec; + register int i; + + /* the event currently sitting in *eventP is an "up" event */ + /* we want to make it a "down" event followed by an "up" event, */ + /* so that sequence matching on the "state" side works correctly. */ + + downEvent = event = *eventP; + *upEvent = *downEvent; + downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ? + ButtonPress : KeyPress); + if ((downEvent->event.eventType == ButtonPress) + && (downEvent->event.modifiers != AnyModifier) + && (downEvent->event.modifiers | downEvent->event.modifierMask)) + downEvent->event.modifiers + &= ~buttonModifierMasks[event->event.eventCode]; + + if (event->event.lateModifiers) + event->event.lateModifiers->ref_count += reps * 2 - 1; + + /* up */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *upEvent; + + for (i=1; i<reps; i++) { + + /* timer */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = timerEventRec; + + /* down */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *downEvent; + + /* up */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *upEvent; + + } + + event->next = NULL; + *eventP = event; + *actionsP = &event->actions; +} + +static void RepeatUpPlus( + EventPtr *eventP, + int reps, + ActionPtr **actionsP) +{ + EventRec upEventRec; + register EventPtr event, downEvent, lastUpEvent = NULL; + EventPtr upEvent = &upEventRec; + register int i; + + /* the event currently sitting in *eventP is an "up" event */ + /* we want to make it a "down" event followed by an "up" event, */ + /* so that sequence matching on the "state" side works correctly. */ + + downEvent = event = *eventP; + *upEvent = *downEvent; + downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ? + ButtonPress : KeyPress); + if ((downEvent->event.eventType == ButtonPress) + && (downEvent->event.modifiers != AnyModifier) + && (downEvent->event.modifiers | downEvent->event.modifierMask)) + downEvent->event.modifiers + &= ~buttonModifierMasks[event->event.eventCode]; + + if (event->event.lateModifiers) + event->event.lateModifiers->ref_count += reps * 2; + + for (i=0; i<reps; i++) { + + /* up */ + event->next = XtNew(EventSeqRec); + lastUpEvent = event = event->next; + *event = *upEvent; + + /* timer */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = timerEventRec; + + /* down */ + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *downEvent; + + } + + event->next = lastUpEvent; + *eventP = event; + *actionsP = &lastUpEvent->actions; +} + +static void RepeatOther( + EventPtr *eventP, + int reps, + ActionPtr **actionsP) +{ + register EventPtr event, tempEvent; + register int i; + + tempEvent = event = *eventP; + + if (event->event.lateModifiers) + event->event.lateModifiers->ref_count += reps - 1; + + for (i=1; i<reps; i++) { + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *tempEvent; + } + + *eventP = event; + *actionsP = &event->actions; +} + +static void RepeatOtherPlus( + EventPtr *eventP, + int reps, + ActionPtr **actionsP) +{ + register EventPtr event, tempEvent; + register int i; + + tempEvent = event = *eventP; + + if (event->event.lateModifiers) + event->event.lateModifiers->ref_count += reps - 1; + + for (i=1; i<reps; i++) { + event->next = XtNew(EventSeqRec); + event = event->next; + *event = *tempEvent; + } + + event->next = event; + *eventP = event; + *actionsP = &event->actions; +} + +static void RepeatEvent( + EventPtr *eventP, + int reps, + Boolean plus, + ActionPtr **actionsP) +{ + switch ((*eventP)->event.eventType) { + + case ButtonPress: + case KeyPress: + if (plus) RepeatDownPlus(eventP, reps, actionsP); + else RepeatDown(eventP, reps, actionsP); + break; + + case ButtonRelease: + case KeyRelease: + if (plus) RepeatUpPlus(eventP, reps, actionsP); + else RepeatUp(eventP, reps, actionsP); + break; + + default: + if (plus) RepeatOtherPlus(eventP, reps, actionsP); + else RepeatOther(eventP, reps, actionsP); + } +} + +static String ParseRepeat( + register String str, + int *reps, + Boolean *plus, Boolean *error) +{ + + /*** Parse the repetitions, for double click etc... ***/ + if (*str != '(' || !(isdigit(str[1]) || str[1] == '+' || str[1] == ')')) + return str; + str++; + if (isdigit(*str)) { + String start = str; + char repStr[7]; + size_t len; + + ScanNumeric(str); + len = (str - start); + if (len < sizeof repStr) { + (void) memmove(repStr, start, len); + repStr[len] = '\0'; + *reps = StrToNum(repStr); + } else { + Syntax("Repeat count too large.", ""); + *error = TRUE; + return str; + } + } + if (*reps == 0) { + Syntax("Missing repeat count.",""); + *error = True; + return str; + } + + if (*str == '+') { + *plus = TRUE; + str++; + } + if (*str == ')') + str++; + else { + Syntax("Missing ')'.",""); + *error = TRUE; + } + + return str; +} + +/*********************************************************************** + * ParseEventSeq + * Parses the left hand side of a translation table production + * up to, and consuming the ":". + * Takes a pointer to a char* (where to start parsing) and returns an + * event seq (in a passed in variable), having updated the String + **********************************************************************/ + +static String ParseEventSeq( + register String str, + EventSeqPtr *eventSeqP, + ActionPtr **actionsP, + Boolean *error) +{ + EventSeqPtr *nextEvent = eventSeqP; + + *eventSeqP = NULL; + + while ( *str != '\0' && !IsNewline(*str)) { + static Event nullEvent = + {0, 0,NULL, 0, 0L, 0L,_XtRegularMatch,FALSE}; + EventPtr event; + + ScanWhitespace(str); + + if (*str == '"') { + str++; + while (*str != '"' && *str != '\0' && !IsNewline(*str)) { + event = XtNew(EventRec); + event->event = nullEvent; + event->state = /* (StatePtr) -1 */ NULL; + event->next = NULL; + event->actions = NULL; + str = ParseQuotedStringEvent(str, event,error); + if (*error) { + XtWarningMsg(XtNtranslationParseError, "nonLatin1", + XtCXtToolkitError, + "... probably due to non-Latin1 character in quoted string", + (String*)NULL, (Cardinal*)NULL); + return PanicModeRecovery(str); + } + *nextEvent = event; + *actionsP = &event->actions; + nextEvent = &event->next; + } + if (*str != '"') { + Syntax("Missing '\"'.",""); + *error = TRUE; + return PanicModeRecovery(str); + } + else str++; + } else { + int reps = 0; + Boolean plus = FALSE; + + event = XtNew(EventRec); + event->event = nullEvent; + event->state = /* (StatePtr) -1 */ NULL; + event->next = NULL; + event->actions = NULL; + + str = ParseEvent(str, event, &reps, &plus, error); + if (*error) return str; + *nextEvent = event; + *actionsP = &event->actions; + if (reps > 1 || plus) + RepeatEvent(&event, reps, plus, actionsP); + nextEvent = &event->next; + } + ScanWhitespace(str); + if (*str == ':') break; + else { + if (*str != ',') { + Syntax("',' or ':' expected while parsing event sequence.",""); + *error = TRUE; + return PanicModeRecovery(str); + } else str++; + } + } + + if (*str != ':') { + Syntax("Missing ':'after event sequence.",""); + *error = TRUE; + return PanicModeRecovery(str); + } else str++; + + return str; +} + + +static String ParseActionProc( + register String str, + XrmQuark *actionProcNameP, + Boolean *error) +{ + register String start = str; + char procName[200]; + + str = ScanIdent(str); + if (str-start >= 199) { + Syntax("Action procedure name is longer than 199 chars",""); + *error = TRUE; + return str; + } + (void) memmove(procName, start, str-start); + procName[str-start] = '\0'; + *actionProcNameP = XrmStringToQuark( procName ); + return str; +} + + +static String ParseString( + register String str, + String *strP) +{ + register String start; + + if (*str == '"') { + register unsigned prev_len, len; + str++; + start = str; + *strP = NULL; + prev_len = 0; + + while (*str != '"' && *str != '\0') { + /* \" produces double quote embedded in a quoted parameter + * \\" produces backslash as last character of a quoted parameter + */ + if (*str == '\\' && + (*(str+1) == '"' || (*(str+1) == '\\' && *(str+2) == '"'))) { + len = prev_len + (str-start+2); + *strP = XtRealloc(*strP, len); + (void) memmove(*strP + prev_len, start, str-start); + prev_len = len-1; + str++; + (*strP)[prev_len-1] = *str; + (*strP)[prev_len] = '\0'; + start = str+1; + } + str++; + } + len = prev_len + (str-start+1); + *strP = XtRealloc(*strP, len); + (void) memmove( *strP + prev_len, start, str-start); + (*strP)[len-1] = '\0'; + if (*str == '"') str++; else + XtWarningMsg(XtNtranslationParseError,"parseString", + XtCXtToolkitError,"Missing '\"'.", + (String *)NULL, (Cardinal *)NULL); + } else { + /* scan non-quoted string, stop on whitespace, ',' or ')' */ + start = str; + while (*str != ' ' + && *str != '\t' + && *str != ',' + && *str != ')' + && !IsNewline(*str) + && *str != '\0') str++; + *strP = __XtMalloc((unsigned)(str-start+1)); + (void) memmove(*strP, start, str-start); + (*strP)[str-start] = '\0'; + } + return str; +} + + +static String ParseParamSeq( + register String str, + String **paramSeqP, + Cardinal *paramNumP) +{ + typedef struct _ParamRec *ParamPtr; + typedef struct _ParamRec { + ParamPtr next; + String param; + } ParamRec; + + ParamPtr params = NULL; + register Cardinal num_params = 0; + register Cardinal i; + + ScanWhitespace(str); + while (*str != ')' && *str != '\0' && !IsNewline(*str)) { + String newStr; + str = ParseString(str, &newStr); + if (newStr != NULL) { + ParamPtr temp = (ParamRec*) + ALLOCATE_LOCAL( (unsigned)sizeof(ParamRec) ); + if (temp == NULL) _XtAllocError (NULL); + + num_params++; + temp->next = params; + params = temp; + temp->param = newStr; + ScanWhitespace(str); + if (*str == ',') { + str++; + ScanWhitespace(str); + } + } + } + + if (num_params != 0) { + String *paramP = (String *) + __XtMalloc( (unsigned)(num_params+1) * sizeof(String) ); + *paramSeqP = paramP; + *paramNumP = num_params; + paramP += num_params; /* list is LIFO right now */ + *paramP-- = NULL; + for (i=0; i < num_params; i++) { + ParamPtr next = params->next; + *paramP-- = params->param; + DEALLOCATE_LOCAL( (char *)params ); + params = next; + } + } else { + *paramSeqP = NULL; + *paramNumP = 0; + } + + return str; +} + +static String ParseAction( + String str, + ActionPtr actionP, + XrmQuark* quarkP, + Boolean* error) +{ + str = ParseActionProc(str, quarkP, error); + if (*error) return str; + + if (*str == '(') { + str++; + str = ParseParamSeq(str, &actionP->params, &actionP->num_params); + } else { + Syntax("Missing '(' while parsing action sequence",""); + *error = TRUE; + return str; + } + if (*str == ')') str++; + else{ + Syntax("Missing ')' while parsing action sequence",""); + *error = TRUE; + return str; + } + return str; +} + + +static String ParseActionSeq( + TMParseStateTree parseTree, + String str, + ActionPtr *actionsP, + Boolean *error) +{ + ActionPtr *nextActionP = actionsP; + + *actionsP = NULL; + while (*str != '\0' && !IsNewline(*str)) { + register ActionPtr action; + XrmQuark quark; + + action = XtNew(ActionRec); + action->params = NULL; + action->num_params = 0; + action->next = NULL; + + str = ParseAction(str, action, &quark, error); + if (*error) return PanicModeRecovery(str); + + action->idx = _XtGetQuarkIndex(parseTree, quark); + ScanWhitespace(str); + *nextActionP = action; + nextActionP = &action->next; + } + if (IsNewline(*str)) str++; + ScanWhitespace(str); + return str; +} + + +static void ShowProduction( + String currentProduction) +{ + Cardinal num_params = 1; + String params[1]; + size_t len; + char *eol, *production, productionbuf[500]; + +#ifdef __UNIXOS2__ + eol = strchr(currentProduction, '\r'); + if (!eol) /* try '\n' as well below */ +#endif + eol = strchr(currentProduction, '\n'); + if (eol) len = eol - currentProduction; + else len = strlen (currentProduction); + production = XtStackAlloc (len + 1, productionbuf); + if (production == NULL) _XtAllocError (NULL); + (void) memmove(production, currentProduction, len); + production[len] = '\0'; + + params[0] = production; + XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError, + "... found while parsing '%s'", params, &num_params); + + XtStackFree (production, productionbuf); +} + +/*********************************************************************** + * ParseTranslationTableProduction + * Parses one line of event bindings. + ***********************************************************************/ + +static String ParseTranslationTableProduction( + TMParseStateTree parseTree, + register String str, + Boolean* error) +{ + EventSeqPtr eventSeq = NULL; + ActionPtr *actionsP; + String production = str; + + actionsP = NULL; + str = ParseEventSeq(str, &eventSeq, &actionsP,error); + if (*error == TRUE) { + ShowProduction(production); + FreeEventSeq(eventSeq); + return (str); + } + ScanWhitespace(str); + str = ParseActionSeq(parseTree, str, actionsP, error); + if (*error == TRUE) { + ShowProduction(production); + FreeEventSeq(eventSeq); + return (str); + } + + _XtAddEventSeqToStateTree(eventSeq, parseTree); + FreeEventSeq(eventSeq); + return (str); +} + +static String CheckForPoundSign( + String str, + _XtTranslateOp defaultOp, + _XtTranslateOp *actualOpRtn) +{ + String start; + char operation[20]; + _XtTranslateOp opType; + + opType = defaultOp; + ScanWhitespace(str); + if (*str == '#') { + int len; + str++; + start = str; + str = ScanIdent(str); + len = MIN(19, str-start); + (void) memmove(operation, start, len); + operation[len] = '\0'; + if (!strcmp(operation,"replace")) + opType = XtTableReplace; + else if (!strcmp(operation,"augment")) + opType = XtTableAugment; + else if (!strcmp(operation,"override")) + opType = XtTableOverride; + ScanWhitespace(str); + if (IsNewline(*str)) { + str++; + ScanWhitespace(str); + } + } + *actualOpRtn = opType; + return str; +} + +static XtTranslations ParseTranslationTable( + String source, + Boolean isAccelerator, + _XtTranslateOp defaultOp, + Boolean* error) +{ + XtTranslations xlations; + TMStateTree stateTrees[8]; + TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec; + XrmQuark stackQuarks[200]; + TMBranchHeadRec stackBranchHeads[200]; + StatePtr stackComplexBranchHeads[200]; + _XtTranslateOp actualOp; + + if (source == NULL) + return (XtTranslations)NULL; + + source = CheckForPoundSign(source, defaultOp, &actualOp); + if (isAccelerator && actualOp == XtTableReplace) + actualOp = defaultOp; + + parseTree->isSimple = TRUE; + parseTree->mappingNotifyInterest = FALSE; + parseTree->isAccelerator = isAccelerator; + parseTree->isStackBranchHeads = + parseTree->isStackQuarks = + parseTree->isStackComplexBranchHeads = TRUE; + + parseTree->numQuarks = + parseTree->numBranchHeads = + parseTree->numComplexBranchHeads = 0; + + parseTree->quarkTblSize = + parseTree->branchHeadTblSize = + parseTree->complexBranchHeadTblSize = 200; + + parseTree->quarkTbl = stackQuarks; + parseTree->branchHeadTbl = stackBranchHeads; + parseTree->complexBranchHeadTbl = stackComplexBranchHeads; + + while (source != NULL && *source != '\0') { + source = ParseTranslationTableProduction(parseTree, source, error); + if (*error == TRUE) break; + } + stateTrees[0] = _XtParseTreeToStateTree(parseTree); + + if (!parseTree->isStackQuarks) + XtFree((char *)parseTree->quarkTbl); + if (!parseTree->isStackBranchHeads) + XtFree((char *)parseTree->branchHeadTbl); + if (!parseTree->isStackComplexBranchHeads) + XtFree((char *)parseTree->complexBranchHeadTbl); + + xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL); + xlations->operation = actualOp; + +#ifdef notdef + XtFree(stateTrees); +#endif /* notdef */ + return xlations; +} + +/*** public procedures ***/ + +/*ARGSUSED*/ +Boolean XtCvtStringToAcceleratorTable( + Display* dpy, + XrmValuePtr args, + Cardinal *num_args, + XrmValuePtr from, + XrmValuePtr to, + XtPointer *closure) +{ + String str; + Boolean error = FALSE; + + if (*num_args != 0) + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, + "String to AcceleratorTable conversion needs no extra arguments", + (String *)NULL, (Cardinal *)NULL); + str = (String)(from->addr); + if (str == NULL) { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, + "String to AcceleratorTable conversion needs string", + (String *)NULL, (Cardinal *)NULL); + return FALSE; + } + if (to->addr != NULL) { + if (to->size < sizeof(XtAccelerators)) { + to->size = sizeof(XtAccelerators); + return FALSE; + } + *(XtAccelerators*)to->addr = + (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); + } + else { + static XtAccelerators staticStateTable; + staticStateTable = + (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); + to->addr = (XPointer) &staticStateTable; + to->size = sizeof(XtAccelerators); + } + if (error == TRUE) + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError, + "String to AcceleratorTable conversion encountered errors", + (String *)NULL, (Cardinal *)NULL); + return (error != TRUE); +} + + +/*ARGSUSED*/ +Boolean +XtCvtStringToTranslationTable( + Display *dpy, + XrmValuePtr args, + Cardinal *num_args, + XrmValuePtr from, + XrmValuePtr to, + XtPointer *closure_ret) +{ + String str; + Boolean error = FALSE; + + if (*num_args != 0) + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError, + "String to TranslationTable conversion needs no extra arguments", + (String *)NULL, (Cardinal *)NULL); + str = (String)(from->addr); + if (str == NULL) { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "badParameters","cvtStringToTranslation",XtCXtToolkitError, + "String to TranslationTable conversion needs string", + (String *)NULL, (Cardinal *)NULL); + return FALSE; + } + if (to->addr != NULL) { + if (to->size < sizeof(XtTranslations)) { + to->size = sizeof(XtTranslations); + return FALSE; + } + *(XtTranslations*)to->addr = + ParseTranslationTable(str, FALSE, XtTableReplace, &error); + } + else { + static XtTranslations staticStateTable; + staticStateTable = + ParseTranslationTable(str, FALSE, XtTableReplace, &error); + to->addr = (XPointer) &staticStateTable; + to->size = sizeof(XtTranslations); + } + if (error == TRUE) + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "parseError","cvtStringToTranslationTable",XtCXtToolkitError, + "String to TranslationTable conversion encountered errors", + (String *)NULL, (Cardinal *)NULL); + return (error != TRUE); +} + + +/* + * Parses a user's or applications translation table + */ +XtAccelerators XtParseAcceleratorTable( + _Xconst char* source) +{ + Boolean error = FALSE; + XtAccelerators ret = + (XtAccelerators) ParseTranslationTable ((char *)source, TRUE, XtTableAugment, &error); + if (error == TRUE) + XtWarningMsg ("parseError", "cvtStringToAcceleratorTable", + XtCXtToolkitError, + "String to AcceleratorTable conversion encountered errors", + (String *)NULL, (Cardinal *)NULL); + return ret; +} + +XtTranslations XtParseTranslationTable( + _Xconst char* source) +{ + Boolean error = FALSE; + XtTranslations ret = ParseTranslationTable((char *)source, FALSE, XtTableReplace, &error); + if (error == TRUE) + XtWarningMsg ("parseError", + "cvtStringToTranslationTable", XtCXtToolkitError, + "String to TranslationTable conversion encountered errors", + (String *)NULL, (Cardinal *)NULL); + return ret; +} + +void _XtTranslateInitialize(void) +{ + LOCK_PROCESS; + if (initialized) { + XtWarningMsg("translationError","xtTranslateInitialize", + XtCXtToolkitError,"Initializing Translation manager twice.", + (String *)NULL, (Cardinal *)NULL); + UNLOCK_PROCESS; + return; + } + + initialized = TRUE; + UNLOCK_PROCESS; + QMeta = XrmPermStringToQuark("Meta"); + QCtrl = XrmPermStringToQuark("Ctrl"); + QNone = XrmPermStringToQuark("None"); + QAny = XrmPermStringToQuark("Any"); + + Compile_XtEventTable( events, XtNumber(events) ); + Compile_XtModifierTable( modifiers, XtNumber(modifiers) ); + CompileNameValueTable( buttonNames ); + CompileNameValueTable( notifyModes ); + CompileNameValueTable( motionDetails ); +#if 0 + CompileNameValueTable( notifyDetail ); + CompileNameValueTable( visibilityNotify ); + CompileNameValueTable( circulation ); + CompileNameValueTable( propertyChanged ); +#endif + CompileNameValueTable( mappingNotify ); +} + +void _XtAddTMConverters( + ConverterTable table) +{ + _XtTableAddConverter(table, + _XtQString, + XrmPermStringToQuark(XtRTranslationTable), + XtCvtStringToTranslationTable, (XtConvertArgList) NULL, + (Cardinal)0, True, CACHED, _XtFreeTranslations, True); + _XtTableAddConverter(table, _XtQString, + XrmPermStringToQuark(XtRAcceleratorTable), + XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL, + (Cardinal)0, True, CACHED, _XtFreeTranslations, True); + _XtTableAddConverter(table, + XrmPermStringToQuark( _XtRStateTablePair ), + XrmPermStringToQuark(XtRTranslationTable), + _XtCvtMergeTranslations, (XtConvertArgList) NULL, + (Cardinal)0, True, CACHED, _XtFreeTranslations, True); +} |