#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)();
typedef void (*ModifierProc)();
typedef TMShortCard 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();
static void ParseModSym();
static String PanicModeRecovery();
static String CheckForPoundSign();
static KeySym StringToKeySym();
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
static NameValueRec mappingNotify[] = {
{"Modifier", 0, MappingModifier},
{"Keyboard", 0, MappingKeyboard},
{"Pointer", 0, MappingPointer},
{NULL, NULLQUARK, 0},
};
static String ParseKeySym();
static String ParseKeyAndModifiers();
static String ParseTable();
static String ParseImmed();
static String ParseAddModifier();
static String ParseNone();
static String ParseAtom();
static EventKey events[] = {
{"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},
{"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},
{"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},
{"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},
{"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},
{"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
{"EventTimer", NULLQUARK, _XtEventTimerEventType,ParseNone,NULL},
#endif
};
#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(eventSeq)
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(table)
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(table, count)
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(table, count)
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(str)
String str;
{
ScanFor(str,'\n');
if (*str == '\n') str++;
return str;
}
static void Syntax(str0,str1)
String str0,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(eventStr,error)
String eventStr;
Boolean *error;
{
register int i, 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(keysymL,notL,keysymR,notR,lateBindings)
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++){}
}
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(name,lateBindings,notFlag,valueP,error)
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(signature, lateBindings, notFlag, valueP,
constMask)
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
(*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
(*modifiers[i].modifierParseProc)
(modifiers[i].value, lateBindings, notFlag, valueP);
UNLOCK_PROCESS;
return TRUE;
}
}
UNLOCK_PROCESS;
return FALSE;
}
static String ScanIdent(str)
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(str, token_return)
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 (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(str, event,error)
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) {
event->event.modifierMask = 0;
event->event.modifiers = AnyModifier;
ScanWhitespace(str);
return str;
}
str = start;
}
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(str, event, tmEventP,error)
register String str;
EventPtr event;
Cardinal *tmEventP;
Boolean* error;
{
String start = str;
char eventTypeStrbuf[100];
char* eventTypeStr;
ScanAlphanumeric(str);
eventTypeStr = XtStackAlloc (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(str)
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(str)
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(str)
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(str, error)
String str;
Boolean *error;
{
KeySym k;
if (str == NULL || *str == '\0') return (KeySym) 0;
#ifndef NOTASCII
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
if (*(str+1) == '\0') return (KeySym) *str;
#endif
Syntax("Unknown keysym name: ", str);
*error = TRUE;
return NoSymbol;
}
static void ParseModImmed(value, lateBindings, notFlag, valueP)
Value value;
LateBindingsPtr* lateBindings;
Boolean notFlag;
Value* valueP;
{
*valueP = value;
}
static void ParseModSym(value, lateBindings, notFlag, valueP)
Value value;
LateBindingsPtr* lateBindings;
Boolean notFlag;
Value* valueP;
{
register KeySym keysymL = (KeySym)value;
register KeySym keysymR = keysymL + 1;
StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings);
*valueP = 0;
}
#ifdef sparc
static String stupid_optimizer_kludge;
#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val)
#else
#define BROKEN_OPTIMIZER_HACK(val) val
#endif
static String ParseImmed(str, closure, event,error)
register String str;
register Opaque closure;
register EventPtr event;
Boolean* error;
{
event->event.eventCode = (unsigned long)closure;
event->event.eventCodeMask = (unsigned long)~0L;
return BROKEN_OPTIMIZER_HACK(str);
}
static String ParseAddModifier(str, closure, event, error)
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)
event->event.modifierMask |= modval;
return BROKEN_OPTIMIZER_HACK(str);
}
static String ParseKeyAndModifiers(str, closure, event,error)
String str;
Opaque closure;
EventPtr event;
Boolean* error;
{
str = ParseKeySym(str, closure, event,error);
if ((unsigned long) closure == 0) {
Value metaMask;
(void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE,
&metaMask, FALSE);
} else {
event->event.modifiers |= (unsigned long) closure;
event->event.modifierMask |= (unsigned long) closure;
}
return str;
}
static String ParseKeySym(str, closure, event,error)
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 == ':' ||
(*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) {
keySymName = keySymNamebuf;
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 (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) {
if (keySymName[0] == '<') {
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(str, closure, event,error)
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);
}
static String ParseNone(str, closure, event,error)
String str;
Opaque closure;
EventPtr event;
Boolean* error;
{
event->event.eventCode = 0;
event->event.eventCodeMask = 0;
return BROKEN_OPTIMIZER_HACK(str);
}
static String ParseAtom(str, closure, event,error)
String str;
Opaque closure;
EventPtr event;
Boolean* error;
{
ScanWhitespace(str);
if (*str == ',' || *str == ':') {
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();
static String ParseEvent(str, event, reps, plus, error)
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;
if ((event->event.eventType == ButtonRelease)
&& (event->event.modifiers | event->event.modifierMask)
&& (event->event.modifiers != AnyModifier))
{
event->event.modifiers
|= buttonModifierMasks[event->event.eventCode];
}
return str;
}
static String ParseQuotedStringEvent(str, event,error)
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},
NULL,
NULL,
NULL
};
static void RepeatDown(eventP, reps, actionsP)
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++) {
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *upEvent;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = timerEventRec;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *downEvent;
}
event->next = NULL;
*eventP = event;
*actionsP = &event->actions;
}
static void RepeatDownPlus(eventP, reps, actionsP)
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) {
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *downEvent;
}
lastDownEvent = event;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *upEvent;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = timerEventRec;
}
event->next = lastDownEvent;
*eventP = event;
*actionsP = &lastDownEvent->actions;
}
static void RepeatUp(eventP, reps, actionsP)
EventPtr *eventP;
int reps;
ActionPtr **actionsP;
{
EventRec upEventRec;
register EventPtr event, downEvent;
EventPtr upEvent = &upEventRec;
register int i;
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;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *upEvent;
for (i=1; i<reps; i++) {
event->next = XtNew(EventSeqRec);
event = event->next;
*event = timerEventRec;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *downEvent;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *upEvent;
}
event->next = NULL;
*eventP = event;
*actionsP = &event->actions;
}
static void RepeatUpPlus(eventP, reps, actionsP)
EventPtr *eventP;
int reps;
ActionPtr **actionsP;
{
EventRec upEventRec;
register EventPtr event, downEvent, lastUpEvent = NULL;
EventPtr upEvent = &upEventRec;
register int i;
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++) {
event->next = XtNew(EventSeqRec);
lastUpEvent = event = event->next;
*event = *upEvent;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = timerEventRec;
event->next = XtNew(EventSeqRec);
event = event->next;
*event = *downEvent;
}
event->next = lastUpEvent;
*eventP = event;
*actionsP = &lastUpEvent->actions;
}
static void RepeatOther(eventP, reps, actionsP)
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(eventP, reps, actionsP)
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(eventP, reps, plus, actionsP)
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(str, reps, plus, error)
register String str;
int *reps;
Boolean *plus, *error;
{
if (*str != '(' || !(isdigit(str[1]) || str[1] == '+' || str[1] == ')'))
return str;
str++;
if (isdigit(*str)) {
String start = str;
char repStr[7];
int 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;
}
static String ParseEventSeq(str, eventSeqP, actionsP,error)
register String str;
EventSeqPtr *eventSeqP;
ActionPtr **actionsP;
Boolean *error;
{
EventSeqPtr *nextEvent = eventSeqP;
*eventSeqP = NULL;
while ( *str != '\0' && !IsNewline(*str)) {
static Event nullEvent =
{0, 0,0L, 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 = 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 = 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(str, actionProcNameP, error)
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(str, strP)
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') {
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 {
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(str, paramSeqP, paramNumP)
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;
*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(str, actionP, quarkP, error)
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(parseTree, str, actionsP, error)
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(currentProduction)
String currentProduction;
{
Cardinal num_params = 1;
String params[1];
int len;
char *eol, *production, productionbuf[500];
#ifdef __UNIXOS2__
eol = strchr(currentProduction, '\r');
if (!eol)
#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);
}
static String ParseTranslationTableProduction(parseTree, str, error)
TMParseStateTree parseTree;
register String str;
Boolean* error;
{
EventSeqPtr eventSeq = NULL;
ActionPtr *actionsP;
String production = str;
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(str, defaultOp, actualOpRtn)
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(source, isAccelerator, defaultOp, error)
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
return xlations;
}
Boolean XtCvtStringToAcceleratorTable(dpy, args, num_args, from, to, closure)
Display* dpy;
XrmValuePtr args;
Cardinal *num_args;
XrmValuePtr from,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);
}
Boolean
XtCvtStringToTranslationTable(dpy, args, num_args, from, to, closure_ret)
Display *dpy;
XrmValuePtr args;
Cardinal *num_args;
XrmValuePtr from,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);
}
XtAccelerators XtParseAcceleratorTable(
_Xconst char* source)
{
Boolean error = FALSE;
XtAccelerators ret =
(XtAccelerators) ParseTranslationTable (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(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(table)
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);
}