home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1682
/
parse.c
Wrap
C/C++ Source or Header
|
1990-12-28
|
21KB
|
781 lines
/*
* parse.c - Parse event specifications (see Xt manual, appendix B)
*
* George Ferguson, ferguson@cs.rochester.edu, 1 Jun 1990.
*
* $Id: parse.c,v 1.4 90/08/15 11:32:19 ferguson Exp $
*
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include "parse.h"
extern Display *display;
extern Window root;
/*
* Functions defined
*/
char *parseEventList();
void freeEventList();
static char *parseEvent(),*parseMods(),*parseType(),*parseDetail();
static unsigned int lookup();
static void parseError();
#define SKIPWHITE(S) while (isspace(*(S))) (S) += 1
/*
* Text to value mappings
*/
typedef struct {
char *name;
unsigned int value;
} NameValue;
static NameValue booleans[] = {
{"True", True},
{"False", False},
{"On", True},
{"Off", False},
{NULL, 0},
};
static NameValue modifiers[] = {
{"None", None},
{"Shift", ShiftMask},
{"Lock", LockMask},
{"Ctrl", ControlMask},
{"Mod1", Mod1Mask},
{"Mod2", Mod2Mask},
{"Mod3", Mod3Mask},
{"Mod4", Mod4Mask},
{"Mod5", Mod5Mask},
{"Meta", XK_Meta_L},
{"m", XK_Meta_L},
{"h", XK_Hyper_L},
{"su", XK_Super_L},
{"a", XK_Alt_L},
{"Hyper", XK_Hyper_L},
{"Super", XK_Super_L},
{"Alt", XK_Alt_L},
{"Button1", Button1Mask},
{"Button2", Button2Mask},
{"Button3", Button3Mask},
{"Button4", Button4Mask},
{"Button5", Button5Mask},
{"Any", AnyModifier},
{"c", ControlMask},
{"s", ShiftMask},
{"l", LockMask},
{NULL, 0},
};
static NameValue buttonNames[] = {
{"Button1", Button1},
{"Button2", Button2},
{"Button3", Button3},
{"Button4", Button4},
{"Button5", Button5},
{NULL, 0},
};
static NameValue motionDetails[] = {
{"Normal", NotifyNormal},
{"Hint", NotifyHint},
{NULL, 0},
};
static NameValue notifyModes[] = {
{"Normal", NotifyNormal},
{"Grab", NotifyGrab},
{"Ungrab", NotifyUngrab},
{"WhileGrabbed", NotifyWhileGrabbed},
{NULL, 0},
};
static NameValue notifyDetails[] = {
{"Ancestor", NotifyAncestor},
{"Virtual", NotifyVirtual},
{"Inferior", NotifyInferior},
{"Nonlinear", NotifyNonlinear},
{"NonlinearVirtual",NotifyNonlinearVirtual},
{"Pointer", NotifyPointer},
{"PointerRoot", NotifyPointerRoot},
{"DetailNone", NotifyDetailNone},
{NULL, 0},
};
static NameValue circulateDetails[] = {
{"PlaceOnTop", PlaceOnTop},
{"OnTop", PlaceOnTop},
{"PlaceOnBottom", PlaceOnBottom},
{"OnBottom", PlaceOnBottom},
{NULL, 0},
};
static NameValue mappingDetails[] = {
{"Modifier", MappingModifier},
{"Keyboard", MappingKeyboard},
{"Pointer", MappingPointer},
{NULL, 0},
};
static NameValue visibilityDetails[] = {
{"Unobscured", VisibilityUnobscured},
{"PartiallyObscured",VisibilityPartiallyObscured},
{"FullyObscured", VisibilityFullyObscured},
{NULL, 0},
};
static NameValue propertyDetails[] = {
{"NewValue", PropertyNewValue},
{"Delete", PropertyDelete},
{NULL, 0},
};
typedef struct {
char *name;
unsigned int value;
unsigned int mods;
unsigned int detail;
} NameValueModsDetail;
static NameValueModsDetail types[] = {
{"KeyPress", KeyPress, 0, 0},
{"Key", KeyPress, 0, 0},
{"KeyDown", KeyPress, 0, 0},
{"Ctrl", KeyPress, ControlMask, 0},
{"Shift", KeyPress, ShiftMask, 0},
{"Meta", KeyPress, 0, 0},
{"KeyUp", KeyRelease, 0, 0},
{"KeyRelease", KeyRelease, 0, 0},
{"ButtonPress", ButtonPress, 0, 0},
{"BtnDown", ButtonPress, 0, 0},
{"Btn1Down", ButtonPress, 0, Button1},
{"Btn2Down", ButtonPress, 0, Button2},
{"Btn3Down", ButtonPress, 0, Button3},
{"Btn4Down", ButtonPress, 0, Button4},
{"Btn5Down", ButtonPress, 0, Button5},
{"ButtonRelease", ButtonRelease, 0, 0},
{"BtnUp", ButtonRelease, 0, 0},
{"Btn1Up", ButtonRelease, 0, Button1},
{"Btn2Up", ButtonRelease, 0, Button2},
{"Btn3Up", ButtonRelease, 0, Button3},
{"Btn4Up", ButtonRelease, 0, Button4},
{"Btn5Up", ButtonRelease, 0, Button5},
{"MotionNotify", MotionNotify, 0, 0},
{"PtrMoved", MotionNotify, 0, 0},
{"Motion", MotionNotify, 0, 0},
{"MouseMoved", MotionNotify, 0, 0},
{"BtnMotion", MotionNotify, 0, 0},
{"Btn1Motion", MotionNotify, Button1Mask, 0},
{"Btn2Motion", MotionNotify, Button2Mask, 0},
{"Btn3Motion", MotionNotify, Button3Mask, 0},
{"Btn4Motion", MotionNotify, Button4Mask, 0},
{"Btn5Motion", MotionNotify, Button5Mask, 0},
{"EnterNotify", EnterNotify, 0, 0},
{"Enter", EnterNotify, 0, 0},
{"EnterWindow", EnterNotify, 0, 0},
{"LeaveNotify", LeaveNotify, 0, 0},
{"LeaveWindow", LeaveNotify, 0, 0},
{"Leave", LeaveNotify, 0, 0},
{"FocusIn", FocusIn, 0, 0},
{"FocusOut", FocusOut, 0, 0},
{"KeymapNotify", KeymapNotify, 0, 0},
{"Keymap", KeymapNotify, 0, 0},
{"Expose", Expose, 0, 0},
{"GraphicsExpose", GraphicsExpose, 0, 0},
{"GrExp", GraphicsExpose, 0, 0},
{"NoExpose", NoExpose, 0, 0},
{"NoExp", NoExpose, 0, 0},
{"VisibilityNotify", VisibilityNotify, 0, 0},
{"Visible", VisibilityNotify, 0, 0},
{"CreateNotify", CreateNotify, 0, 0},
{"Create", CreateNotify, 0, 0},
{"DestroyNotify", DestroyNotify, 0, 0},
{"Destroy", DestroyNotify, 0, 0},
{"UnmapNotify", UnmapNotify, 0, 0},
{"Unmap", UnmapNotify, 0, 0},
{"MapNotify", MapNotify, 0, 0},
{"Map", MapNotify, 0, 0},
{"MapRequest", MapRequest, 0, 0},
{"MapReq", MapRequest, 0, 0},
{"ReparentNotify", ReparentNotify, 0, 0},
{"Reparent", ReparentNotify, 0, 0},
{"ConfigureNotify", ConfigureNotify, 0, 0},
{"Configure", ConfigureNotify, 0, 0},
{"ConfigureRequest", ConfigureRequest, 0, 0},
{"ConfigureReq", ConfigureRequest, 0, 0},
{"GravityNotify", GravityNotify, 0, 0},
{"Grav", GravityNotify, 0, 0},
{"ResizeRequest", ResizeRequest, 0, 0},
{"ResReq", ResizeRequest, 0, 0},
{"CirculateNotify", CirculateNotify, 0, 0},
{"Circ", CirculateNotify, 0, 0},
{"CirculateRequest", CirculateRequest, 0, 0},
{"CircReq", CirculateRequest, 0, 0},
{"PropertyNotify", PropertyNotify, 0, 0},
{"Prop", PropertyNotify, 0, 0},
{"SelectionClear", SelectionClear, 0, 0},
{"SelClr", SelectionClear, 0, 0},
{"SelectionRequest", SelectionRequest, 0, 0},
{"SelReq", SelectionRequest, 0, 0},
{"SelectionNotify", SelectionNotify, 0, 0},
{"Select", SelectionNotify, 0, 0},
{"ColormapNotify", ColormapNotify, 0, 0},
{"Clrmap", ColormapNotify, 0, 0},
{"ClientMessage", ClientMessage, 0, 0},
{"Message", ClientMessage, 0, 0},
{"MappingNotify", MappingNotify, 0, 0},
{"Mapping", MappingNotify, 0, 0},
{NULL, 0, 0, 0}
};
/* - - - - - - - - */
static unsigned int
lookup(table,name)
NameValue *table;
char *name;
{
while (table->name != NULL && strcasecmp(name,table->name) != 0)
table += 1;
return(table->value);
}
char *
parseEventList(str,evp)
char *str;
EventListPtr *evp;
{
EventListPtr ev,end;
*evp == NULL;
while (*str) {
str = parseEvent(str,&ev);
if (ev != NULL)
if (*evp == NULL)
end = *evp = ev;
else
end = end->next = ev; /* wow! */
else
return(str);
if (*str && *str != ',') {
parseError("',' expected",str);
return(str);
} else if (*str)
str += 1; /* skip comma */
}
return(str);
}
static char *
parseEvent(str,evp)
char *str;
EventListPtr *evp;
{
unsigned int mods;
int type,count;
unsigned int detail;
str = parseMods(str,&mods);
SKIPWHITE(str);
if (*str != '<') {
parseError("'<' expected",str);
return(str);
} else
str += 1;
str = parseType(str,&type,&mods,&detail);
if (*str != '>') {
parseError("'>' expected",str);
return(str);
} else
str += 1;
SKIPWHITE(str);
count = 1; /* default */
if (*str == '(') {
str += 1;
count = (int)strtol(str,&str,0);
if (count == 0) {
parseError("count expected",str);
return(str);
}
if (*str != ')') {
parseError("')' expected",str);
return(str);
} else
str += 1;
}
SKIPWHITE(str);
*evp = (EventListElem *)malloc(sizeof(EventListElem));
(*evp)->count = count;
(*evp)->next = NULL;
str = parseDetail(str,&((*evp)->event),type,mods,detail);
return(str);
}
static char *
parseMods(str,modsp)
char *str;
unsigned int *modsp;
{
char modstr[32];
int i;
unsigned int m;
*modsp = (unsigned int)0;
while (*str && *str != '<') {
SKIPWHITE(str);
i = 0;
while (isalnum(*str) && i < 30)
modstr[i++] = *str++;
if (i == 31)
parseError("modifier name too long",str);
modstr[i] = '\0';
if ((m=lookup(modifiers,modstr)) == 0)
parseError("unknown modifier",modstr);
else
*modsp |= m;
}
return(str);
}
static char *
parseType(str,typep,modsp,detailp)
char *str;
int *typep;
unsigned int *modsp,*detailp;
{
char typestr[32];
int i;
i = 0;
while (isalnum(*str) && i < 30)
typestr[i++] = *str++;
if (i == 31)
parseError("event type too long",str);
typestr[i] = '\0';
for (i=0; types[i].name!=NULL && strcasecmp(types[i].name,typestr)!=0; i++);
if (types[i].name == NULL) {
parseError("unknown event type",typestr);
*typep = 0;
} else {
*typep = types[i].value;
*detailp = types[i].detail;
*modsp |= types[i].mods;
}
return(str);
}
static char *
parseDetail(str,xevp,type,mods,detail)
char *str;
XEvent *xevp;
int type;
unsigned int mods,detail;
{
char detailstr[256];
int i;
i = 0;
while (*str && !(i > 0 && *str == ',') && i < 255)
detailstr[i++] = *str++;
if (i == 255)
parseError("detail too long (truncated)",str);
detailstr[i] = '\0';
xevp->type = type;
switch (type) {
case KeyPress:
case KeyRelease: {
XKeyEvent *xkevp = (XKeyEvent *)xevp;
KeyCode k;
char *s = strchr(detailstr,' ');
if (s != NULL)
*s++ = '\0';
k = XKeysymToKeycode(display,XStringToKeysym(detailstr));
if (detail != 0 && k != 0) {
parseError("key detail conflict",detailstr);
xkevp->type = -1;
break;
} else if (detail == 0)
xkevp->keycode = k;
else
xkevp->keycode = detail;
if (s != NULL) {
xkevp->x = (int)strtol(s,&s,0);
xkevp->y = (int)strtol(s,&s,0);
xkevp->x_root = (int)strtol(s,&s,0);
xkevp->y_root = (int)strtol(s,&s,0);
}
xkevp->state = mods;
xkevp->root = root;
xkevp->same_screen = True;
break;
}
case ButtonPress:
case ButtonRelease: {
XButtonEvent *xbevp = (XButtonEvent *)xevp;
unsigned b = lookup(buttonNames,detailstr);
if (*detailstr && b == 0) {
parseError("bad button detail",detailstr);
xbevp->type = -1;
break;
}
if (detail != 0 && b != 0) {
parseError("button detail conflict",detailstr);
xbevp->button = 0;
} else if (detail == 0)
xbevp->button = b;
else
xbevp->button = detail;
xbevp->state = mods;
xbevp->root = root;
xbevp->same_screen = True;
break;
}
case MotionNotify: {
XMotionEvent *xmevp = (XMotionEvent *)xevp;
xmevp->is_hint = lookup(motionDetails,detailstr);
if (*detailstr && xmevp->is_hint == 0) {
parseError("bad motion detail",detailstr);
xmevp->type = -1;
}
xmevp->state = mods;
xmevp->root = root;
xmevp->same_screen = True;
break;
}
case EnterNotify:
case LeaveNotify: {
XCrossingEvent *xcevp = (XCrossingEvent *)xevp;
char *s = strchr(detailstr,' ');
if (s != NULL)
*s++ = '\0';
xcevp->mode = lookup(notifyModes,detailstr);
if (s != NULL)
xcevp->detail = lookup(notifyDetails,s);
xcevp->state = mods;
xcevp->root = root;
xcevp->same_screen = True;
break;
}
case FocusIn:
case FocusOut: {
XFocusChangeEvent *xfcevp = (XFocusChangeEvent *)xevp;
char *s = strchr(detailstr,' ');
if (s != NULL)
*s++ = '\0';
xfcevp->mode = lookup(notifyModes,detailstr);
if (s != NULL)
xfcevp->detail = lookup(notifyDetails,s);
if (*detailstr && xfcevp->mode == 0 && xfcevp->detail == 0) {
parseError("bad focus mode or detail",detailstr);
xfcevp->type = -1;
}
break;
}
case KeymapNotify: {
XKeymapEvent *xkevp = (XKeymapEvent *)xevp;
int i;
char *s = detailstr;
for (i=0; i < 32; i++)
xkevp->key_vector[i] = (char)strtol(s,&s,0);
break;
}
case Expose: {
XExposeEvent *xeevp = (XExposeEvent *)xevp;
char *s = detailstr;
xeevp->x = (int)strtol(s,&s,0);
xeevp->y = (int)strtol(s,&s,0);
xeevp->width = (int)strtol(s,&s,0);
xeevp->height = (int)strtol(s,&s,0);
xeevp->count = (int)strtol(s,&s,0);
break;
}
case GraphicsExpose: {
XGraphicsExposeEvent *xgevp = (XGraphicsExposeEvent *)xevp;
char *s = detailstr;
xgevp->x = (int)strtol(s,&s,0);
xgevp->y = (int)strtol(s,&s,0);
xgevp->width = (int)strtol(s,&s,0);
xgevp->height = (int)strtol(s,&s,0);
xgevp->count = (int)strtol(s,&s,0);
xgevp->major_code = (int)strtol(s,&s,0);
xgevp->minor_code = (int)strtol(s,&s,0);
break;
}
case NoExpose: {
XNoExposeEvent *xnevp = (XNoExposeEvent *)xevp;
char *s = detailstr;
xnevp->major_code = (int)strtol(s,&s,0);
xnevp->minor_code = (int)strtol(s,&s,0);
break;
}
case CirculateNotify:
case CirculateRequest: {
XCirculateEvent *xcevp = (XCirculateEvent *)xevp;
if ((xcevp->place=lookup(circulateDetails,detailstr)) == 99) {
parseError("bad circulate detail",detailstr);
xcevp->type = -1;
}
break;
}
case ConfigureNotify:
case ConfigureRequest: {
XConfigureEvent *xcevp = (XConfigureEvent *)xevp;
char *s = detailstr;
xcevp->x = (int)strtol(s,&s,0);
xcevp->y = (int)strtol(s,&s,0);
xcevp->width = (int)strtol(s,&s,0);
xcevp->height = (int)strtol(s,&s,0);
xcevp->border_width = (int)strtol(s,&s,0);
xcevp->above = (Window)strtol(s,&s,0);
SKIPWHITE(s);
xcevp->override_redirect=lookup(booleans,s);
break;
}
case CreateNotify: {
XCreateWindowEvent *xcevp = (XCreateWindowEvent *)xevp;
char *s = detailstr;
xcevp->x = (int)strtol(s,&s,0);
xcevp->y = (int)strtol(s,&s,0);
xcevp->width = (int)strtol(s,&s,0);
xcevp->height = (int)strtol(s,&s,0);
xcevp->border_width = (int)strtol(s,&s,0);
SKIPWHITE(s);
xcevp->override_redirect=lookup(booleans,s);
break;
}
case DestroyNotify: {
XDestroyWindowEvent *xdevp = (XDestroyWindowEvent *)xevp;
xdevp->window = (Window)strtol(detailstr,NULL,0);
break;
}
case GravityNotify: {
XGravityEvent *xgevp = (XGravityEvent *)xevp;
char *s = detailstr;
xgevp->x = (int)strtol(s,&s,0);
xgevp->y = (int)strtol(s,&s,0);
break;
}
case MapNotify:
case MapRequest: {
XMapEvent *xmevp = (XMapEvent *)xevp;
xmevp->override_redirect = lookup(booleans,detailstr);
break;
}
case MappingNotify: {
XMappingEvent *xmevp = (XMappingEvent *)xevp;
char *s=strchr(detailstr,' ');
if (s != NULL)
*s++ = '\0';
if ((xmevp->request=lookup(mappingDetails,detailstr)) == 0) {
parseError("bad mapping detail",detailstr);
xmevp->type = -1;
}
if (xmevp->request == MappingKeyboard && s != NULL) {
SKIPWHITE(s);
xmevp->first_keycode = (int)strtol(s,&s,0);
xmevp->count = (int)strtol(s,&s,0);
}
break;
}
case ReparentNotify: {
XReparentEvent *xrevp = (XReparentEvent *)xevp;
char *s = strchr(detailstr,' ');
if (s != NULL)
*s++ = '\0';
xrevp->parent = (Window)strtol(detailstr,NULL,0);
if (s != NULL) {
SKIPWHITE(s);
xrevp->x = (int)strtol(s,&s,0);
xrevp->y = (int)strtol(s,&s,0);
SKIPWHITE(s);
xrevp->override_redirect = lookup(booleans,s);
}
break;
}
case UnmapNotify: {
XUnmapEvent *xuevp = (XUnmapEvent *)xevp;
xuevp->from_configure = lookup(booleans,detailstr);
break;
}
case VisibilityNotify: {
XVisibilityEvent *xvevp = (XVisibilityEvent *)xevp;
xvevp->state = lookup(visibilityDetails,detailstr);
break;
}
case ResizeRequest: {
XResizeRequestEvent *xrevp = (XResizeRequestEvent *)xevp;
char *s = detailstr;
xrevp->width = (int)strtol(s,&s,0);
xrevp->height = (int)strtol(s,&s,0);
break;
}
case ColormapNotify:
parseError("can't handle ColormapNotify events","");
xevp->type = -1;
break;
case ClientMessage: {
XClientMessageEvent *xcevp = (XClientMessageEvent *)xevp;
char *s = strchr(detailstr,' ');
int i;
if (*detailstr == '\0') {
parseError("missing atom for client message","");
xcevp->type = -1;
break;
}
if (s != NULL)
*s++ = '\0';
xcevp->message_type = XInternAtom(display,detailstr,True);
if (s != NULL) {
SKIPWHITE(s);
if (*s == 'b') {
xcevp->format = 8;
SKIPWHITE(s);
for (i=0; i < 20; i++)
xcevp->data.b[i] = (char)strtol(s,&s,0);
} else if (*s == 'c') {
xcevp->format = 8;
SKIPWHITE(s);
for (i=0; i < 20; i++)
xcevp->data.b[i] = *s++;
} else if (*s == 's') {
xcevp->format = 16;
SKIPWHITE(s);
for (i=0; i < 10; i++)
xcevp->data.s[i] = (short)strtol(s,&s,0);
} else if (*s == 'l') {
xcevp->format = 32;
SKIPWHITE(s);
for (i=0; i < 5; i++)
xcevp->data.l[i] = strtol(s,&s,0);
}
}
}
case PropertyNotify: {
XPropertyEvent *xpevp = (XPropertyEvent *)xevp;
char *s = strchr(detailstr,' ');
if (*detailstr == '\0') {
parseError("missing atom for property notify","");
xpevp->type = -1;
break;
}
if (s != NULL)
*s++ = '\0';
xpevp->atom = XInternAtom(display,detailstr,True);
if (s != NULL) {
SKIPWHITE(s);
xpevp->state = lookup(propertyDetails,s);
}
xpevp->time = CurrentTime;
break;
}
case SelectionClear: {
XSelectionClearEvent *xsevp = (XSelectionClearEvent *)xevp;
if (*detailstr == '\0') {
parseError("missing atom for selection clear","");
xsevp->type = -1;
break;
}
xsevp->selection = XInternAtom(display,detailstr,True);
xsevp->time = CurrentTime;
break;
}
/* Note SelectionRequest and Selection are identical except the
event types have different structures (and different errors). */
case SelectionRequest: {
XSelectionRequestEvent *xsevp = (XSelectionRequestEvent *)xevp;
char *s1 = detailstr;
char *s2,*s3;
if (*s1 == '\0') {
parseError("missing atom for selection request (selection)","");
xsevp->type = -1;
break;
}
if ((s2=strchr(s1,' ')) == NULL) {
parseError("missing atom for selection request (target)","");
xsevp->type = -1;
break;
}
*s2++ = '\0';
SKIPWHITE(s2);
if ((s3=strchr(s2,' ')) == NULL) {
parseError("missing atom for selection request (property)","");
xsevp->type = -1;
break;
}
*s3++ = '\0';
SKIPWHITE(s3);
xsevp->selection = XInternAtom(display,s1,True);
xsevp->target = XInternAtom(display,s2,True);
if (*s3 == '\0' || strcasecmp(s3,"None") == 0)
xsevp->property = None;
else
xsevp->property = XInternAtom(display,s3,True);
xsevp->time = CurrentTime;
}
case SelectionNotify: {
XSelectionEvent *xsevp = (XSelectionEvent *)xevp;
char *s1 = detailstr;
char *s2,*s3;
if (*s1 == '\0') {
parseError("missing atom for selection notify (selection)","");
xsevp->type = -1;
break;
}
if ((s2=strchr(s1,' ')) == NULL) {
parseError("missing atom for selection notify (target)","");
xsevp->type = -1;
break;
}
*s2++ = '\0';
SKIPWHITE(s2);
if ((s3=strchr(s2,' ')) == NULL) {
parseError("missing atom for selection notify (property)","");
xsevp->type = -1;
break;
}
*s3++ = '\0';
SKIPWHITE(s3);
xsevp->selection = XInternAtom(display,s1,True);
xsevp->target = XInternAtom(display,s2,True);
if (*s3 == '\0' || strcasecmp(s3,"None") == 0)
xsevp->property = None;
else
xsevp->property = XInternAtom(display,s3,True);
xsevp->time = CurrentTime;
}
default:
parseError("don't understand event type\n","");
xevp->type = -1;
}
return(str);
}
static void
parseError(s1,s2)
char *s1,*s2;
{
if (*s2 == '\0')
fprintf(stderr,"xse: %s\n",s1);
else
fprintf(stderr,"xse: %s: \"%s\"\n",s1,s2);
}
void
freeEventList(p)
EventListPtr p;
{
EventListPtr q;
while (p != NULL) {
q = p;
p = p->next;
free(q);
}
}