summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
commit9f1e6d353042f462da0a3a2264a115eca2c859a5 (patch)
tree8cc8dd18f9a2b02506042d3be020e9fec7f3131c
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
-rw-r--r--cfgparse.y224
-rw-r--r--cfgscan.c386
-rw-r--r--evargs.c190
-rw-r--r--example.cf53
-rw-r--r--printev.c656
-rw-r--r--tokens.h67
-rw-r--r--utils.c368
-rw-r--r--utils.h307
-rw-r--r--xkbevd.c555
-rw-r--r--xkbevd.h102
-rw-r--r--xkbevd.man96
11 files changed, 3004 insertions, 0 deletions
diff --git a/cfgparse.y b/cfgparse.y
new file mode 100644
index 0000000..16a02ca
--- /dev/null
+++ b/cfgparse.y
@@ -0,0 +1,224 @@
+/* $Xorg: cfgparse.y,v 1.3 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+%token
+ END_OF_FILE 0
+ ERROR 255
+ BELL 1
+ ACCESSX 2
+ MESSAGE 3
+
+ NONE 20
+ IGNORE 21
+ ECHO 22
+ PRINT_EV 23
+ SHELL 24
+ SOUND 25
+
+ EQUALS 40
+ PLUS 41
+ MINUS 42
+ DIVIDE 43
+ TIMES 44
+ OBRACE 45
+ CBRACE 46
+ OPAREN 47
+ CPAREN 48
+ OBRACKET 49
+ CBRACKET 50
+ DOT 51
+ COMMA 52
+ SEMI 53
+ EXCLAM 54
+ INVERT 55
+ STRING 60
+ INTEGER 61
+ FLOAT 62
+ IDENT 63
+ KEYNAME 64
+%{
+#ifdef DEBUG
+#define YYDEBUG 1
+#endif
+#define DEBUG_VAR parseDebug
+#include "xkbevd.h"
+%}
+%right EQUALS
+%left PLUS MINUS
+%left TIMES DIVIDE
+%left EXCLAM INVERT
+%left OPAREN
+%start CfgFile
+%union {
+ char * str;
+ int ival;
+ CfgEntryPtr entry;
+ ActDefPtr act;
+}
+%type <str> Ident String OptString NameSpec OptNameSpec
+%type <ival> ActionType EventType
+%type <act> ActionDef
+%type <entry> CfgFile CfgEntryList CfgEntry EventDef VarDef
+%%
+CfgFile : CfgEntryList
+ { InterpretConfigs($1); }
+ ;
+
+CfgEntryList : CfgEntryList CfgEntry
+ {
+ CfgEntryPtr tmp;
+ if ($1!=NULL) {
+ for (tmp=$1;tmp->next!=NULL;tmp=tmp->next) {
+ /* conditional does the work */
+ }
+ tmp->next= $2;
+ $$= $1;
+ }
+ else $$= $2;
+ }
+ | CfgEntry { $$= $1; }
+ ;
+
+CfgEntry : EventDef ActionDef
+ {
+ if (($1)&&($2))
+ $1->action= *($2);
+ if ($2)
+ uFree($2);
+ $$= $1;
+ }
+ | VarDef { $$= $1; }
+ ;
+
+VarDef : Ident EQUALS NameSpec
+ {
+ CfgEntryPtr cfg;
+ cfg= uTypedCalloc(1,CfgEntryRec);
+ if (cfg) {
+ cfg->entry_type= VariableDef;
+ cfg->event_type= 0;
+ cfg->name.str= $1;
+ cfg->action.type= UnknownAction;
+ cfg->action.text= $3;
+ cfg->action.priv= 0;
+ cfg->next= NULL;
+ }
+ $$= cfg;
+ }
+ ;
+
+EventDef : EventType OPAREN OptNameSpec CPAREN
+ {
+ CfgEntryPtr cfg;
+ cfg= uTypedCalloc(1,CfgEntryRec);
+ if (cfg) {
+ cfg->entry_type= EventDef;
+ cfg->event_type= $1;
+ cfg->name.str= $3;
+ cfg->action.type= UnknownAction;
+ cfg->action.text= NULL;
+ cfg->action.priv= 0;
+ cfg->next= NULL;
+ }
+ $$= cfg;
+ }
+ ;
+
+EventType : BELL { $$= XkbBellNotify; }
+ | ACCESSX { $$= XkbAccessXNotify; }
+ | MESSAGE { $$= XkbActionMessage; }
+ ;
+
+ActionDef : ActionType OptString
+ {
+ ActDefPtr act;
+ act= uTypedCalloc(1,ActDefRec);
+ if (act) {
+ act->type= $1;
+ act->text= $2;
+ }
+ $$= act;
+ }
+ ;
+
+ActionType : NONE { $$ = NoAction; }
+ | IGNORE { $$ = NoAction; }
+ | ECHO { $$ = EchoAction; }
+ | PRINT_EV { $$ = PrintEvAction; }
+ | SHELL { $$ = ShellAction; }
+ | SOUND { $$ = SoundAction; }
+ | { $$ = UnknownAction; }
+
+OptNameSpec : NameSpec { $$= $1; }
+ | { $$= NULL; }
+ ;
+
+NameSpec : Ident { $$= $1; }
+ | String { $$= $1; }
+ ;
+
+Ident : IDENT { $$= scanStr; scanStr= NULL; }
+ ;
+
+OptString : String { $$= $1; }
+ | { $$= NULL; }
+ ;
+
+String : STRING { $$= scanStr; scanStr= NULL; }
+ ;
+%%
+int
+yyerror(s)
+char *s;
+{
+ (void)fprintf(stderr,"%s: line %d of %s\n",s,lineNum,
+ (scanFile?scanFile:"(unknown)"));
+ if (scanStr)
+ (void)fprintf(stderr,"last scanned symbol is: %s\n",scanStr);
+ return 1;
+}
+
+
+int
+yywrap()
+{
+ return 1;
+}
+
+int
+CFGParseFile(file)
+FILE *file;
+{
+ if (file) {
+ extern FILE *yyin;
+ yyin= file;
+ if (yyparse()==0) {
+ return 1;
+ }
+ return 0;
+ }
+ return 1;
+}
diff --git a/cfgscan.c b/cfgscan.c
new file mode 100644
index 0000000..c99c53d
--- /dev/null
+++ b/cfgscan.c
@@ -0,0 +1,386 @@
+/* $Xorg: cfgscan.c,v 1.3 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <X11/Xos.h>
+#include <X11/X.h>
+#include <X11/extensions/XKB.h>
+
+#include "tokens.h"
+
+FILE *yyin = stdin;
+
+static char scanFileBuf[1024];
+char * scanFile= scanFileBuf;
+int lineNum= 0;
+
+int scanInt;
+char *scanIntStr;
+int scanIntClass;
+
+char *scanStr = NULL;
+int scanStrLine= 0;
+
+#define BUFSIZE 512
+static int nInBuf = 0;
+static char buf[BUFSIZE];
+
+#ifdef DEBUG
+
+extern unsigned debugFlags;
+
+static char *
+tokText(tok)
+ int tok;
+{
+static char buf[32];
+
+ switch (tok) {
+ case END_OF_FILE: sprintf(buf, "END_OF_FILE");break;
+ case ERROR: sprintf(buf, "ERROR"); break;
+
+ case BELL: sprintf(buf, "BELL"); break;
+ case ACCESSX: sprintf(buf, "ACCESSX"); break;
+ case MESSAGE: sprintf(buf, "MESSAGE"); break;
+
+ case NONE: sprintf(buf, "NONE"); break;
+ case IGNORE: sprintf(buf, "IGNORE"); break;
+ case ECHO: sprintf(buf, "ECHO"); break;
+ case PRINT_EV: sprintf(buf, "PRINT_EV"); break;
+ case SHELL: sprintf(buf, "SHELL"); break;
+ case SOUND: sprintf(buf, "SOUND"); break;
+
+ case EQUALS: sprintf(buf, "EQUALS"); break;
+ case PLUS: sprintf(buf, "PLUS"); break;
+ case MINUS: sprintf(buf, "MINUS"); break;
+ case DIVIDE: sprintf(buf, "DIVIDE"); break;
+ case TIMES: sprintf(buf, "TIMES"); break;
+ case OBRACE: sprintf(buf, "OBRACE"); break;
+ case CBRACE: sprintf(buf, "CBRACE"); break;
+ case OPAREN: sprintf(buf, "OPAREN"); break;
+ case CPAREN: sprintf(buf, "CPAREN"); break;
+ case OBRACKET: sprintf(buf, "OBRACKET");break;
+ case CBRACKET: sprintf(buf, "CBRACKET");break;
+ case DOT: sprintf(buf, "DOT"); break;
+ case COMMA: sprintf(buf, "COMMA"); break;
+ case SEMI: sprintf(buf, "SEMI"); break;
+ case EXCLAM: sprintf(buf, "EXCLAM"); break;
+ case INVERT: sprintf(buf, "INVERT"); break;
+
+ case STRING: sprintf(buf, "STRING (%s)",scanStr); break;
+ case INTEGER: sprintf(buf, "INTEGER (0x%x)",scanInt); break;
+ case FLOAT: sprintf(buf, "FLOAT (%d.%d)",
+ scanInt/XkbGeomPtsPerMM,
+ scanInt%XkbGeomPtsPerMM);break;
+ case IDENT: sprintf(buf, "IDENT (%s)",scanStr); break;
+ case KEYNAME: sprintf(buf, "KEYNAME (%s)",scanStr); break;
+ default: sprintf(buf, "UNKNOWN"); break;
+ }
+ return buf;
+}
+#endif
+
+int
+setScanState(file,line)
+ char * file;
+ int line;
+{
+ if (file!=NULL)
+ strncpy(scanFile,file,1024);
+ if (line>=0)
+ lineNum= line;
+ return 1;
+}
+
+int
+yyGetString()
+{
+int ch;
+
+ nInBuf = 0;
+ while ( ((ch=getc(yyin))!=EOF) && (ch!='"') ) {
+ if ( ch == '\\' ) {
+ if ((ch = getc(yyin))!=EOF) {
+ if ( ch=='n' ) ch = '\n';
+ else if ( ch == 't' ) ch = '\t';
+ else if ( ch == 'v' ) ch = '\v';
+ else if ( ch == 'b' ) ch = '\b';
+ else if ( ch == 'r' ) ch = '\r';
+ else if ( ch == 'f' ) ch = '\f';
+ else if ( ch == 'e' ) ch = '\033';
+ else if ( ch == '0' ) {
+ int tmp,stop;
+ ch = stop = 0;
+ if (((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ }
+ }
+ else return ERROR;
+ }
+
+ if ( nInBuf < BUFSIZE-1 )
+ buf[nInBuf++] = ch;
+ }
+ if ( ch == '"' ) {
+ buf[nInBuf++] = '\0';
+ if ( scanStr )
+ free( scanStr );
+ scanStr = (char *)uStringDup(buf);
+ scanStrLine = lineNum;
+ return STRING;
+ }
+ return ERROR;
+}
+
+int
+yyGetKeyName()
+{
+int ch;
+
+ nInBuf = 0;
+ while ( ((ch=getc(yyin))!=EOF) && (ch!='>') ) {
+ if ( ch == '\\' ) {
+ if ((ch = getc(yyin))!=EOF) {
+ if ( ch=='n' ) ch = '\n';
+ else if ( ch == 't' ) ch = '\t';
+ else if ( ch == 'v' ) ch = '\v';
+ else if ( ch == 'b' ) ch = '\b';
+ else if ( ch == 'r' ) ch = '\r';
+ else if ( ch == 'f' ) ch = '\f';
+ else if ( ch == 'e' ) ch = '\033';
+ else if ( ch == '0' ) {
+ int tmp,stop;
+ ch = stop = 0;
+ if (((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ if ((!stop) && ((tmp=getc(yyin))!=EOF) && (isdigit(tmp)) &&
+ (tmp!='8') && (tmp!='9')) {
+ ch= (ch*8)+(tmp-'0');
+ }
+ else {
+ stop= 1;
+ ungetc(tmp,yyin);
+ }
+ }
+ }
+ else return ERROR;
+ }
+
+ if ( nInBuf < BUFSIZE-1 )
+ buf[nInBuf++] = ch;
+ }
+ if (( ch == '>' )&&(nInBuf<5)) {
+ buf[nInBuf++] = '\0';
+ if ( scanStr )
+ free( scanStr );
+ scanStr = (char *)uStringDup(buf);
+ scanStrLine = lineNum;
+ return KEYNAME;
+ }
+ return ERROR;
+}
+
+struct _Keyword {
+ char *keyword;
+ int token;
+} keywords[] = {
+ { "bell", BELL },
+ { "accessx", ACCESSX },
+ { "message", MESSAGE },
+ { "none", NONE },
+ { "ignore", IGNORE },
+ { "echo", ECHO },
+ { "printevent", PRINT_EV },
+ { "shell", SHELL },
+ { "sound", SOUND }
+};
+int numKeywords = sizeof(keywords)/sizeof(struct _Keyword);
+
+int
+yyGetIdent(first)
+ int first;
+{
+int ch,i,found;
+int rtrn;
+
+ buf[0] = first; nInBuf = 1;
+ while ( ((ch=getc(yyin))!=EOF) && (isalnum(ch)||(ch=='_')) ) {
+ if ( nInBuf < BUFSIZE - 1 )
+ buf[nInBuf++] = ch;
+ }
+ buf[nInBuf++] = '\0';
+ found= 0;
+
+ for (i=0;(!found)&&(i<numKeywords);i++) {
+ if (uStrCaseCmp(buf,keywords[i].keyword)==0) {
+ rtrn= keywords[i].token;
+ found= 1;
+ }
+ }
+ if (!found) {
+ if ( scanStr )
+ free( scanStr );
+ scanStr = (char *)uStringDup(buf);
+ scanStrLine = lineNum;
+ rtrn = IDENT;
+ }
+
+ if ( (ch!=EOF) && (!isspace(ch)) )
+ ungetc( ch, yyin );
+ else if ( ch=='\n' )
+ lineNum++;
+
+ return rtrn;
+}
+
+int
+yyGetNumber(ch)
+ int ch;
+{
+int isFloat= 0;
+
+ buf[0]= ch;
+ nInBuf= 1;
+ while (((ch=getc(yyin))!=EOF)&&(isxdigit(ch)||((nInBuf==1)&&(ch=='x')))) {
+ buf[nInBuf++]= ch;
+ }
+ if (ch=='.') {
+ isFloat= 1;
+ buf[nInBuf++]= ch;
+ while (((ch=getc(yyin))!=EOF)&&(isxdigit(ch))) {
+ buf[nInBuf++]= ch;
+ }
+ }
+ buf[nInBuf++]= '\0';
+ if ((ch!=EOF)&&(!isspace(ch)))
+ ungetc( ch, yyin );
+
+ if (isFloat) {
+ float tmp;
+ if (sscanf(buf,"%g",&tmp)==1) {
+ scanInt= tmp*XkbGeomPtsPerMM;
+ return FLOAT;
+ }
+ }
+ else if ( sscanf(buf,"%i",&scanInt)==1 )
+ return INTEGER;
+ fprintf(stderr,"Malformed number %s\n",buf);
+ return ERROR;
+}
+
+int
+yylex()
+{
+int ch;
+int rtrn;
+
+ do {
+ ch = getc(yyin);
+ if ( ch == '\n' ) {
+ lineNum++;
+ }
+ else if ( ch=='/' ) { /* handle C++ style double-/ comments */
+ int newch= getc(yyin);
+ if (newch=='/') {
+ do {
+ ch= getc(yyin);
+ } while ((ch!='\n')&&(ch!=EOF));
+ lineNum++;
+ }
+ else if (newch!=EOF) {
+ ungetc(newch,yyin);
+ }
+ }
+ } while ((ch!=EOF)&&(isspace(ch)));
+ if ( ch == '=' ) rtrn = EQUALS;
+ else if ( ch == '+' ) rtrn = PLUS;
+ else if ( ch == '-' ) rtrn = MINUS;
+ else if ( ch == '/' ) rtrn = DIVIDE;
+ else if ( ch == '*' ) rtrn = TIMES;
+ else if ( ch == '{' ) rtrn = OBRACE;
+ else if ( ch == '}' ) rtrn = CBRACE;
+ else if ( ch == '(' ) rtrn = OPAREN;
+ else if ( ch == ')' ) rtrn = CPAREN;
+ else if ( ch == '[' ) rtrn = OBRACKET;
+ else if ( ch == ']' ) rtrn = CBRACKET;
+ else if ( ch == '.' ) rtrn = DOT;
+ else if ( ch == ',' ) rtrn = COMMA;
+ else if ( ch == ';' ) rtrn = SEMI;
+ else if ( ch == '!' ) rtrn = EXCLAM;
+ else if ( ch == '~' ) rtrn = INVERT;
+ else if ( ch == '"' ) rtrn = yyGetString();
+ else if ( ch == '<' ) rtrn = yyGetKeyName();
+ else if ( isalpha(ch) || (ch=='_')) rtrn = yyGetIdent(ch);
+ else if ( isdigit(ch) ) rtrn = yyGetNumber(ch);
+ else if ( ch == EOF ) rtrn = END_OF_FILE;
+ else {
+ fprintf(stderr,"Unexpected character %c (%d) in input stream\n",ch,ch);
+ rtrn = ERROR;
+ }
+#ifdef DEBUG
+ if (debugFlags&0x2)
+ fprintf(stderr,"scan: %s\n",tokText(rtrn));
+#endif
+ return rtrn;
+}
diff --git a/evargs.c b/evargs.c
new file mode 100644
index 0000000..94876db
--- /dev/null
+++ b/evargs.c
@@ -0,0 +1,190 @@
+/* $Xorg: evargs.c,v 1.3 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+
+#define DEBUG_VAR evargsDebug
+#include "xkbevd.h"
+
+/***====================================================================***/
+
+static char *
+AppendBellNotifyArg(sink,arg,ev)
+ char * sink;
+ char * arg;
+ XkbEvent * ev;
+{
+ if (uStringEqual(arg,"device")||uStringEqual(arg,"D"))
+ sprintf(sink,"%d",ev->bell.device);
+ else if (uStringEqual(arg,"volume")||uStringEqual(arg,"v"))
+ sprintf(sink,"%d",ev->bell.percent);
+ else if (uStringEqual(arg,"pitch")||uStringEqual(arg,"p"))
+ sprintf(sink,"%d",ev->bell.pitch);
+ else if (uStringEqual(arg,"duration")||uStringEqual(arg,"d"))
+ sprintf(sink,"%d",ev->bell.duration);
+ else if (uStringEqual(arg,"class")||uStringEqual(arg,"c"))
+ sprintf(sink,"%d",ev->bell.bell_class);
+ else if (uStringEqual(arg,"id")||uStringEqual(arg,"i"))
+ sprintf(sink,"%d",ev->bell.bell_id);
+ else if (uStringEqual(arg,"window")||uStringEqual(arg,"w"))
+ sprintf(sink,"0x%x",ev->bell.window);
+ else if (uStringEqual(arg,"name")||uStringEqual(arg,"n"))
+ sprintf(sink,"%s",XkbAtomText(dpy,ev->bell.name,XkbMessage));
+ return sink;
+}
+
+static char *
+AppendAccessXNotifyArg(sink,arg,ev)
+ char * sink;
+ char * arg;
+ XkbEvent * ev;
+{
+ if (uStringEqual(arg,"device")||uStringEqual(arg,"D"))
+ sprintf(sink,"%d",ev->accessx.device);
+ else if (uStringEqual(arg,"detail")||uStringEqual(arg,"d")) {
+ sprintf(sink,"%s",XkbAccessXDetailText(ev->accessx.detail,XkbMessage));
+ }
+ else if (uStringEqual(arg,"keycode")||uStringEqual(arg,"key")||
+ uStringEqual(arg,"k"))
+ sprintf(sink,"%d",ev->accessx.keycode);
+ else if (uStringEqual(arg,"skdelay")||uStringEqual(arg,"s"))
+ sprintf(sink,"%d",ev->accessx.sk_delay);
+ else if (uStringEqual(arg,"bkdelay")||uStringEqual(arg,"b"))
+ sprintf(sink,"%d",ev->accessx.debounce_delay);
+ return sink;
+}
+
+static char *
+AppendActionMessageArg(sink,arg,ev)
+ char * sink;
+ char * arg;
+ XkbEvent * ev;
+{
+ if (uStringEqual(arg,"device")||uStringEqual(arg,"D"))
+ sprintf(sink,"%d",ev->message.device);
+ else if (uStringEqual(arg,"message")||uStringEqual(arg,"m"))
+ sprintf(sink,"%s",ev->message.message);
+ else if (uStringEqual(arg,"keycode")||uStringEqual(arg,"key")||
+ uStringEqual(arg,"k"))
+ sprintf(sink,"%d",ev->message.keycode);
+ else if (uStringEqual(arg,"press")||uStringEqual(arg,"p"))
+ sprintf(sink,"%s",(ev->message.press?"press":"release"));
+ else if (uStringEqual(arg,"event")||uStringEqual(arg,"e"))
+ sprintf(sink,"%s",(ev->message.key_event_follows?"event":"no_event"));
+ return sink;
+}
+
+static char *
+AppendEventArg(sink,arg,ev)
+ char * sink;
+ char * arg;
+ XkbEvent * ev;
+{
+ switch (ev->any.xkb_type) {
+ case XkbBellNotify:
+ sink= AppendBellNotifyArg(sink,arg,ev);
+ break;
+ case XkbAccessXNotify:
+ sink= AppendAccessXNotifyArg(sink,arg,ev);
+ break;
+ case XkbActionMessage:
+ sink= AppendActionMessageArg(sink,arg,ev);
+ break;
+ default:
+ return sink;
+ }
+ sink+= strlen(sink);
+ return sink;
+}
+
+static void
+CopyEventArg(sink_inout,source_inout,ev)
+ char ** sink_inout;
+ char ** source_inout;
+ XkbEvent * ev;
+{
+char buf[1024];
+char *source,*sink;
+char *arg;
+
+ arg= buf;
+ source= *source_inout;
+ sink= *sink_inout;
+ if (*source=='$') {
+ *sink++= '$';
+ source++;
+ *sink++= '\0';
+ *sink_inout= sink;
+ *source_inout= source;
+ return;
+ }
+ else if (*source=='(') {
+ source++;
+ while ((*source!=')')&&(*source!='\0')) {
+ *arg++= *source++;
+ }
+ if (*source=='\0') {
+ *sink++= '$';
+ *sink++= '\0';
+ *sink_inout= sink;
+ return;
+ }
+ source++;
+ *arg++= '\0';
+ arg= buf;
+ }
+ else {
+ arg[0]= *source++;
+ arg[1]= '\0';
+ }
+ sink= AppendEventArg(sink,arg,ev);
+ *sink_inout= sink;
+ *source_inout= source;
+ return;
+}
+
+char *
+SubstituteEventArgs(cmd,ev)
+ char * cmd;
+ XkbEvent * ev;
+{
+static char buf[1024];
+char *source,*sink;
+
+ if (index(cmd,'$')==NULL)
+ return cmd;
+ buf[0]= '\0';
+ sink= buf;
+ source= cmd;
+ while (*source!='\0') {
+ if (*source=='$') {
+ source++;
+ CopyEventArg(&sink,&source,ev);
+ }
+ *sink++= *source++;
+ }
+ return buf;
+}
+
diff --git a/example.cf b/example.cf
new file mode 100644
index 0000000..7e73f15
--- /dev/null
+++ b/example.cf
@@ -0,0 +1,53 @@
+//$Xorg: example.cf,v 1.3 2000/08/17 19:54:49 cpqbld Exp $
+soundDirectory = "/space/erik/.xkb/sounds/"
+
+Bell() "ss/08.ting.aifc"
+
+Bell(Info) "sfx/cricket.aiff"
+Bell(Warning) "ss/02.xylo.pong.aifc" // bogus
+Bell(MinorError) "ss/02.xylo.pong.aifc"
+Bell(MajorError) "instr/crash16_hrd.aiff"
+Bell(Question) echo "xkbevd: ignoring $(name) bell\n"
+Bell(Start) "ss/searchBegin.44.aifc"
+Bell(End) "ss/searchEnd.44.aifc"
+Bell(Success) "musictags/harp_glis.Cmj.aiff"
+Bell(Failure) "sfx/cannon.aiff"
+Bell(Wait) "ss/searchBegin.44.aifc"
+Bell(Proceed) "ss/searchEnd.44.aifc"
+Bell("Ignore") echo "xkbevd: ignoring $(name) bell\n"
+Bell(Iconify) echo "xkbevd: ignoring $(name) bell\n"
+Bell(Deiconify) echo "xkbevd: ignoring $(name) bell\n"
+Bell(Open) echo "xkbevd: ignoring $(name) bell\n"
+Bell(Close) echo "xkbevd: ignoring $(name) bell\n"
+Bell(TerminalBell) "ss/ss2.aifc"
+Bell(MarginBell) "sfx/bell.aiff"
+Bell(CursorStuck) "ss/02.chick.aifc"
+Bell(NewMail) "sfx/doorchime.aiff"
+Bell(LaunchApp) "ss/05.kerchick.echo.aifc"
+Bell(AppDeath) "ss/20.zikik.aifc"
+Bell(ImAlive) "ss/ss6.aifc"
+Bell(RepeatingLastBell) ignore
+Bell(ClockChimeHour) "musictags/harp_glis.Cmj.aiff"
+Bell(ClockChimeHalf) "musictags/belltree_up2.aiff"
+Bell(ClockChimeQuarter) "ss/ss6.aifc"
+Bell(AX_FeatureOn) "instr/drm_clave.aiff"
+Bell(AX_FeatureOff) "instr/drm_cowbell.aiff"
+Bell(AX_FeatureChange) "instr/warped_harm.aiff"
+
+Bell(AX_IndicatorOn) "ss/01.african.thumb.inst.aifc"
+Bell(AX_IndicatorOff) "ss/07.bzz.organ.aifc"
+Bell(AX_IndicatorChange) "ss/01.buzz.kerchick.aifc"
+
+Bell(AX_SlowKeysWarning) "sfx/alarm_clock.aiff"
+
+Bell(AX_SlowKeyPress) "instr/drm_stick_mid.aiff"
+Bell(AX_SlowKeyAccept) "instr/drm_cowbell.aiff"
+Bell(AX_SlowKeyReject) "instr/drm_snare.aiff"
+Bell(AX_SlowKeyRelease) "instr/drm_cowbell.aiff"
+
+Bell(AX_BounceKeyReject) "instr/drm_snare.aiff"
+
+Bell(AX_StickyLatch) "sfx/click2.aiff"
+Bell(AX_StickyLock) "sfx/click3.aiff"
+Bell(AX_StickyUnlock) "ss/searchEnd.44.aifc"
+SlowKey() printEvent
diff --git a/printev.c b/printev.c
new file mode 100644
index 0000000..c889af0
--- /dev/null
+++ b/printev.c
@@ -0,0 +1,656 @@
+/* $Xorg: printev.c,v 1.3 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+
+#define DEBUG_VAR printevDebug
+#include "xkbevd.h"
+#include <X11/Xutil.h>
+
+#define Yes "yes"
+#define No "no"
+#define Unknown "unknown"
+#define ynText(v) ((v)?Yes:No)
+
+static char *
+eventTypeToString(evType)
+ int evType;
+{
+static char name[20];
+ switch (evType) {
+ case KeyPress: strcpy(name,"KeyPress"); break;
+ case KeyRelease:strcpy(name,"KeyRelease"); break;
+ default: strcpy(name,"unknown"); break;
+ }
+ return name;
+}
+
+static void
+xkb_prologue (file, ev, name)
+ FILE * file;
+ XkbEvent * ev;
+ char * name;
+{
+ XkbAnyEvent *e = &ev->any;
+
+ fprintf(file,"\n%s event, serial %ld, synthetic %s, device %d, time %ld,\n",
+ name, e->serial, ynText(e->send_event), e->device,e->time);
+ return;
+}
+
+static void
+do_XkbStateNotify(file,xkbev)
+ FILE * file;
+ XkbEvent * xkbev;
+{
+ XkbStateNotifyEvent *state= &xkbev->state;
+
+ if (state->keycode!=0)
+ fprintf(file," keycode %d, eventType %s,\n",
+ state->keycode,eventTypeToString(state->event_type));
+ else fprintf(file," request %d/%d,\n",state->req_minor,state->req_minor);
+ fprintf(file," group= %d%s, base= %d%s, latched= %d%s, locked= %d%s,\n",
+ state->group, (state->changed&XkbGroupStateMask?"*":""),
+ state->base_group,(state->changed&XkbGroupBaseMask?"*":""),
+ state->latched_group,(state->changed&XkbGroupLatchMask?"*":""),
+ state->locked_group,(state->changed&XkbGroupLockMask?"*":""));
+ fprintf(file,
+ " mods= 0x%02x%s, base= 0x%02x%s, latched= 0x%02x%s, locked= 0x%02x%s\n",
+ state->mods, (state->changed&XkbModifierStateMask?"*":""),
+ state->base_mods,(state->changed&XkbModifierBaseMask?"*":""),
+ state->latched_mods,(state->changed&XkbModifierLatchMask?"*":""),
+ state->locked_mods,(state->changed&XkbModifierLockMask?"*":""));
+ fprintf(file," grab mods= 0x%02x%s, compat grab mods= 0x%02x%s\n",
+ state->grab_mods, (state->changed&XkbGrabModsMask?"*":""),
+ state->compat_grab_mods,
+ (state->changed&XkbCompatGrabModsMask?"*":""));
+ fprintf(file," lookup mods= 0x%02x%s, compat lookup mods= 0x%02x%s\n",
+ state->lookup_mods, (state->changed&XkbLookupModsMask?"*":""),
+ state->compat_lookup_mods,
+ (state->changed&XkbCompatLookupModsMask?"*":""));
+ fprintf(file," compatState = 0x%02x%s, ",
+ state->compat_state,(state->changed&XkbCompatStateMask?"*":""));
+ fprintf(file,"ptr_buttons= 0x%04x%s\n",state->ptr_buttons,
+ (state->changed&XkbPointerButtonMask?"*":""));
+ return;
+}
+
+static void
+do_map_message(what,first,num,eol)
+ char * what;
+ int first;
+ int num;
+ int eol;
+{
+ if (num>1)
+ printf("%ss %d..%d changed%s",what,first,first+num-1,(eol?"\n":""));
+ else printf("%s %d changed%s",what,first,(eol?"\n":""));
+}
+
+void
+do_XkbMapNotify(file,xkbev)
+ FILE * file;
+ XkbEvent * xkbev;
+{
+ XkbMapNotifyEvent *map = &xkbev->map;
+ if (map->changed&XkbKeyTypesMask) {
+ do_map_message("key type",map->first_type,map->num_types,0);
+ }
+ if (map->changed&XkbKeySymsMask) {
+ do_map_message("symbols for key",map->first_key_sym,map->num_key_syms,
+ 1);
+ }
+ if (map->changed&XkbKeyActionsMask) {
+ do_map_message("acts for key",map->first_key_act,
+ map->num_key_acts,1);
+ }
+ if (map->changed&XkbKeyBehaviorsMask) {
+ do_map_message("behavior for key",map->first_key_behavior,
+ map->num_key_behaviors,1);
+ }
+ if (map->changed&XkbVirtualModsMask) {
+ fprintf(file," virtual modifiers changed (0x%04x)\n",map->vmods);
+ }
+ if (map->changed&XkbExplicitComponentsMask) {
+ do_map_message("explicit components for key",map->first_key_explicit,
+ map->num_key_explicit,1);
+ }
+ if (map->changed&XkbModifierMapMask) {
+ do_map_message("modifier map for key",map->first_modmap_key,
+ map->num_modmap_keys,1);
+ }
+ return;
+}
+
+void
+do_XkbControlsNotify(file,xkbev)
+ FILE * file;
+ XkbEvent * xkbev;
+{
+ XkbControlsNotifyEvent *ctrls = &xkbev->ctrls;
+ fprintf(file," changed= 0x%x, enabled= 0x%x, enabledChanges= 0x%x\n",
+ ctrls->changed_ctrls,ctrls->enabled_ctrls,
+ ctrls->enabled_ctrl_changes);
+ fprintf(file," num_groups= %d\n",ctrls->num_groups);
+ if (ctrls->keycode!=0)
+ fprintf(file," keycode %d, eventType %s,",
+ ctrls->keycode,eventTypeToString(ctrls->event_type));
+ else fprintf(file," request %d/%d%s\n",ctrls->req_major,ctrls->req_minor,
+ (ctrls->req_major!=xkbOpcode?" (NON-XKB)":""));
+ return;
+}
+
+void
+do_XkbIndicatorNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbIndicatorNotifyEvent *leds = &xkbev->indicators;
+ if (leds->xkb_type==XkbIndicatorStateNotify)
+ fprintf(file," state changes= 0x%08x, new state= 0x%08x\n",
+ leds->changed,leds->state);
+ else fprintf(file," map changes= 0x%08x, state= 0x%08x\n",
+ leds->changed,leds->state);
+ return;
+}
+
+void
+do_XkbBellNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbBellNotifyEvent *bell = &xkbev->bell;
+ fprintf(file," bell class= %d, id= %d\n",bell->bell_class,bell->bell_id);
+ fprintf(file," percent= %d, pitch= %d, duration= %d",
+ bell->percent,bell->pitch,bell->duration);
+ if (bell->name!=None) {
+ char *name = XGetAtomName (dpy, bell->name);
+ fprintf(file,"\n name= \"%s\"\n",(name?name:""));
+ if (name)
+ XFree(name);
+ }
+ else fprintf(file,", no name\n");
+ fprintf(file," window= 0x%x, %sevent_only\n",bell->window,
+ (bell->event_only?"":"!"));
+ return;
+}
+
+void
+do_XkbAccessXNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbAccessXNotifyEvent *sk = &xkbev->accessx;
+ char *detail;
+ switch (sk->detail) {
+ case XkbAXN_SKPress: detail= "skpress"; break;
+ case XkbAXN_SKAccept: detail= "skaccept"; break;
+ case XkbAXN_SKReject: detail= "skreject"; break;
+ case XkbAXN_SKRelease: detail= "skrelease"; break;
+ case XkbAXN_BKAccept: detail= "bkaccept"; break;
+ case XkbAXN_BKReject: detail= "bkreject"; break;
+ case XkbAXN_AXKWarning: detail= "warning"; break;
+ default: {
+ static char buf[20];
+ sprintf(buf,"unknown(%d)",sk->detail);
+ detail= buf;
+ break;
+ }
+ }
+ fprintf(file,
+ " keycode= %d,detail= %s,slow keys delay= %d,debounce delay= %d\n",
+ sk->keycode,detail,sk->sk_delay,sk->debounce_delay);
+ return;
+}
+
+do_XkbNamesNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbNamesNotifyEvent *names = &xkbev->names;
+
+ if (names->changed&
+ (XkbKeycodesNameMask|XkbGeometryNameMask|XkbSymbolsNameMask)) {
+ int needComma= 0;
+ fprintf(file," ");
+ if (names->changed&XkbKeycodesNameMask) {
+ fprintf(file,"keycodes");
+ needComma++;
+ }
+ if (names->changed&XkbGeometryNameMask) {
+ fprintf(file,"%sgeometry",(needComma?", ":""));
+ needComma++;
+ }
+ if (names->changed&XkbSymbolsNameMask) {
+ fprintf(file,"%ssymbols",(needComma?", ":""));
+ needComma++;
+ }
+ if (names->changed&XkbPhysSymbolsNameMask) {
+ fprintf(file,"%sphysical symbols",(needComma?", ":""));
+ needComma++;
+ }
+ fprintf(file," name%s changed\n",(needComma>1?"s":""));
+ }
+ if (names->changed&XkbKeyTypeNamesMask) {
+ do_map_message("key type name",names->first_type,names->num_types,1);
+ }
+ if (names->changed&XkbKTLevelNamesMask) {
+ do_map_message("level names for key type",
+ names->first_lvl,names->num_lvls,1);
+ }
+ if (names->changed&XkbIndicatorNamesMask) {
+ fprintf(file," names of indicators in 0x%08x changed\n",
+ names->changed_indicators);
+ }
+ if (names->changed&XkbVirtualModNamesMask) {
+ fprintf(file," names of virtual modifiers in 0x%04x changed\n",
+ names->changed_vmods);
+ }
+ if (names->changed&XkbGroupNamesMask) {
+ fprintf(file," names of groups in 0x%x changed\n",
+ names->changed_groups);
+ }
+ if (names->changed&XkbKeyNamesMask) {
+ do_map_message("names for key",names->first_key,names->num_keys,1);
+ }
+ if (names->changed&XkbKeyAliasesMask) {
+ fprintf(file,"key aliases changed (%d aliases total)\n",
+ names->num_aliases);
+ }
+ if (names->changed&XkbRGNamesMask) {
+ fprintf(file,"radio group names changed (%d radio groups total)\n",
+ names->num_radio_groups);
+ }
+ return;
+}
+
+void
+do_XkbCompatMapNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbCompatMapNotifyEvent *map = &xkbev->compat;
+
+ if (map->changed_groups)
+ fprintf(file," compat maps for groups in 0x%02x changed\n",
+ map->changed_groups);
+ if (map->num_si>0) {
+ fprintf(file," symbol interpretations %d..%d (of %d) changed\n",
+ map->first_si,map->first_si+map->num_si-1,
+ map->num_total_si);
+ }
+ else fprintf(file," keyboard has %d symbol interpretations\n",
+ map->num_total_si);
+ return;
+}
+
+void
+do_XkbActionMessage(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbActionMessageEvent *msg= &xkbev->message;
+ fprintf(file," message: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ msg->message[0],msg->message[1],
+ msg->message[2],msg->message[3],
+ msg->message[4],msg->message[5]);
+ fprintf(file," key %d, event: %s, follows: %s\n",msg->keycode,
+ (msg->press?"press":"release"),
+ (msg->key_event_follows?"yes":"no"));
+ return;
+}
+
+void
+do_XkbNewKeyboardNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbNewKeyboardNotifyEvent *nk= &xkbev->new_kbd;
+ fprintf(file," new device: %d min_keycode: %d, max_keycode %d\n",
+ nk->device,nk->min_key_code,nk->max_key_code);
+ fprintf(file," old device: %d min_keycode: %d, max_keycode %d\n",
+ nk->old_device,
+ nk->old_min_key_code,nk->old_max_key_code);
+ return;
+}
+
+void
+do_XkbExtensionDeviceNotify(file,xkbev)
+ FILE * file;
+ XkbEvent *xkbev;
+{
+ XkbExtensionDeviceNotifyEvent *edn= &xkbev->device;
+ fprintf(file," device= %d, class= %d, id= %d\n",edn->device,
+ edn->led_class,edn->led_id);
+ fprintf(file," reason= 0x%0x\n",edn->reason);
+ fprintf(file," supported= 0x%0x, unsupported= 0x%0x\n",edn->supported,
+ edn->unsupported);
+ fprintf(file," first button= %d, num buttons= %d\n",edn->first_btn,
+ edn->num_btns);
+ fprintf(file," leds defined= 0x%08x, led state= 0x%08x\n",
+ edn->leds_defined,edn->led_state);
+ return;
+}
+
+static char keyState[XkbMaxLegalKeyCode];
+
+do_KeyEvent (eventp,compose,repeat)
+ XkbEvent *eventp;
+{
+ XKeyEvent *e = &eventp->core.xkey;
+ KeySym ks;
+ char *ksname,*kname;
+ int nbytes;
+ char str[256+1];
+ static XComposeStatus status;
+
+ nbytes = XLookupString (e, str, 256, &ks, (compose?&status:NULL));
+ if (ks == NoSymbol)
+ ksname = "NoSymbol";
+ else if (!(ksname = XKeysymToString (ks)))
+ ksname = "(no name)";
+ printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
+ e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
+
+ if (xkb && xkb->names && xkb->names->keys)
+ kname= XkbKeyNameText(xkb->names->keys[e->keycode].name,XkbMessage);
+ else kname= "<????>";
+
+ printf (" state 0x%x, group= %d, key %s (keycode %u, keysym 0x%x, %s)\n",
+ e->state&0x1FFF, (e->state>>13)&0x7, kname,
+ e->keycode, ks, ksname);
+ printf (" same_screen %s, autorepeat %s,\n",ynText(e->same_screen),
+ (detectableRepeat ? ynText(repeat) : "UNKNOWN"));
+ if (nbytes < 0) nbytes = 0;
+ if (nbytes > 256) nbytes = 256;
+ str[nbytes] = '\0';
+ printf (" XLookupString gives %d characters: \"%s\"\n", nbytes, str);
+
+ return;
+}
+
+
+do_KeyPress (eventp)
+ XkbEvent *eventp;
+{
+int repeat;
+
+ repeat= keyState[eventp->core.xkey.keycode]!=0;
+ keyState[eventp->core.xkey.keycode]= 1;
+ do_KeyEvent (eventp, 1,repeat);
+ return;
+}
+
+do_KeyRelease (eventp)
+ XkbEvent *eventp;
+{
+ keyState[eventp->core.xkey.keycode]= 0;
+ do_KeyEvent (eventp,0,False);
+ return;
+}
+
+do_ButtonPress (eventp)
+ XkbEvent *eventp;
+{
+ XButtonEvent *e = &eventp->core.xbutton;
+
+ printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
+ e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
+ printf (" state 0x%x, group= %d, button %u, same_screen %s\n",
+ e->state&0x1FFF, (e->state>>13)&0x7, e->button,
+ ynText(e->same_screen));
+
+ return;
+}
+
+do_ButtonRelease (eventp)
+ XkbEvent *eventp;
+{
+ do_ButtonPress (eventp); /* since it has the same info */
+ return;
+}
+
+do_MotionNotify (eventp)
+ XkbEvent *eventp;
+{
+ XMotionEvent *e = &eventp->core.xmotion;
+
+ printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
+ e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
+ printf (" state 0x%x, group= %d, is_hint %u, same_screen %s\n",
+ e->state&0x1FFF, (e->state>>13)&0x7, e->is_hint,
+ ynText(e->same_screen));
+
+ return;
+}
+
+do_EnterNotify (eventp)
+ XkbEvent *eventp;
+{
+ XCrossingEvent *e = &eventp->core.xcrossing;
+ char *mode, *detail;
+ char dmode[10], ddetail[10];
+
+ switch (e->mode) {
+ case NotifyNormal: mode = "NotifyNormal"; break;
+ case NotifyGrab: mode = "NotifyGrab"; break;
+ case NotifyUngrab: mode = "NotifyUngrab"; break;
+ case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
+ default: mode = dmode, sprintf (dmode, "%u", e->mode); break;
+ }
+
+ switch (e->detail) {
+ case NotifyAncestor: detail = "NotifyAncestor"; break;
+ case NotifyVirtual: detail = "NotifyVirtual"; break;
+ case NotifyInferior: detail = "NotifyInferior"; break;
+ case NotifyNonlinear: detail = "NotifyNonlinear"; break;
+ case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+ case NotifyPointer: detail = "NotifyPointer"; break;
+ case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+ case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+ default: detail = ddetail; sprintf (ddetail, "%u", e->detail); break;
+ }
+
+ printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
+ e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
+ printf (" mode %s, detail %s, same_screen %s,\n",
+ mode, detail, ynText(e->same_screen));
+ printf (" focus %s, state %u, group= %d\n", ynText(e->focus),
+ e->state&0x1FFF, (e->state>>13)&7 );
+
+ return;
+}
+
+do_LeaveNotify (eventp)
+ XkbEvent *eventp;
+{
+ do_EnterNotify (eventp); /* since it has same information */
+ return;
+}
+
+do_KeymapNotify (eventp)
+ XkbEvent *eventp;
+{
+ XKeymapEvent *e = &eventp->core.xkeymap;
+ int i;
+
+ printf (" keys: ");
+ for (i = 0; i < 32; i++) {
+ if (i == 16) printf ("\n ");
+ printf ("%-3u ", (unsigned int) e->key_vector[i]);
+ }
+ printf ("\n");
+ return;
+}
+
+do_ClientMessage (eventp)
+ XkbEvent *eventp;
+{
+ XClientMessageEvent *e = &eventp->core.xclient;
+ char *mname = XGetAtomName (dpy, e->message_type);
+
+ printf (" message_type 0x%lx (%s), format %d\n",
+ e->message_type, mname ? mname : Unknown, e->format);
+
+ if (mname) XFree (mname);
+ return;
+}
+
+do_MappingNotify (eventp)
+ XkbEvent *eventp;
+{
+ XMappingEvent *e = &eventp->core.xmapping;
+ char *r;
+ char rdummy[10];
+
+ switch (e->request) {
+ case MappingModifier: r = "MappingModifier"; break;
+ case MappingKeyboard: r = "MappingKeyboard"; break;
+ case MappingPointer: r = "MappingPointer"; break;
+ default: r = rdummy; sprintf (rdummy, "%d", e->request); break;
+ }
+
+ printf (" request %s, first_keycode %d, count %d\n",
+ r, e->first_keycode, e->count);
+ XRefreshKeyboardMapping(e);
+ return;
+}
+
+
+
+set_sizehints (hintp, min_width, min_height,
+ defwidth, defheight, defx, defy, geom)
+ XSizeHints *hintp;
+ int min_width, min_height, defwidth, defheight, defx, defy;
+ char *geom;
+{
+ int geom_result;
+
+ /* set the size hints, algorithm from xlib xbiff */
+
+ hintp->width = hintp->min_width = min_width;
+ hintp->height = hintp->min_height = min_height;
+ hintp->flags = PMinSize;
+ hintp->x = hintp->y = 0;
+ geom_result = NoValue;
+ if (geom != NULL) {
+ geom_result = XParseGeometry (geom, &hintp->x, &hintp->y,
+ (unsigned int *)&hintp->width,
+ (unsigned int *)&hintp->height);
+ if ((geom_result & WidthValue) && (geom_result & HeightValue)) {
+#define max(a,b) ((a) > (b) ? (a) : (b))
+ hintp->width = max (hintp->width, hintp->min_width);
+ hintp->height = max (hintp->height, hintp->min_height);
+ hintp->flags |= USSize;
+ }
+ if ((geom_result & XValue) && (geom_result & YValue)) {
+ hintp->flags += USPosition;
+ }
+ }
+ if (!(hintp->flags & USSize)) {
+ hintp->width = defwidth;
+ hintp->height = defheight;
+ hintp->flags |= PSize;
+ }
+/*
+ if (!(hintp->flags & USPosition)) {
+ hintp->x = defx;
+ hintp->y = defy;
+ hintp->flags |= PPosition;
+ }
+ */
+ if (geom_result & XNegative) {
+ hintp->x = DisplayWidth (dpy, DefaultScreen (dpy)) + hintp->x -
+ hintp->width;
+ }
+ if (geom_result & YNegative) {
+ hintp->y = DisplayHeight (dpy, DefaultScreen (dpy)) + hintp->y -
+ hintp->height;
+ }
+ return;
+}
+
+Bool
+PrintXkbEvent(file,ev)
+ FILE * file;
+ XkbEvent * ev;
+{
+ if (ev->type==xkbEventCode) {
+ switch (ev->any.xkb_type) {
+ case XkbStateNotify:
+ xkb_prologue(file, ev, "XkbStateNotify" );
+ do_XkbStateNotify(file,ev);
+ break;
+ case XkbMapNotify:
+ xkb_prologue(file, ev, "XkbMapNotify" );
+ do_XkbMapNotify(file,ev);
+ break;
+ case XkbControlsNotify:
+ xkb_prologue(file, ev, "XkbControlsNotify" );
+ do_XkbControlsNotify(file,ev);
+ break;
+ case XkbIndicatorMapNotify:
+ xkb_prologue(file, ev, "XkbIndicatorMapNotify" );
+ do_XkbIndicatorNotify(file,ev);
+ break;
+ case XkbIndicatorStateNotify:
+ xkb_prologue(file, ev, "XkbIndicatorStateNotify" );
+ do_XkbIndicatorNotify(file,ev);
+ break;
+ case XkbBellNotify:
+ xkb_prologue(file, ev, "XkbBellNotify" );
+ do_XkbBellNotify(file,ev);
+ break;
+ case XkbAccessXNotify:
+ xkb_prologue(file, ev, "XkbAccessXNotify" );
+ do_XkbAccessXNotify(file,ev);
+ break;
+ case XkbNamesNotify:
+ xkb_prologue(file, ev, "XkbNamesNotify" );
+ do_XkbNamesNotify(file,ev);
+ break;
+ case XkbCompatMapNotify:
+ xkb_prologue(file, ev, "XkbCompatMapNotify" );
+ do_XkbCompatMapNotify(file,ev);
+ break;
+ case XkbActionMessage:
+ xkb_prologue(file, ev, "XkbActionMessage" );
+ do_XkbActionMessage(file,ev);
+ break;
+ case XkbNewKeyboardNotify:
+ xkb_prologue(file, ev, "XkbNewKeyboard" );
+ do_XkbNewKeyboardNotify(file,ev);
+ break;
+ case XkbExtensionDeviceNotify:
+ xkb_prologue(file, ev, "XkbExtensionDeviceNotify" );
+ do_XkbExtensionDeviceNotify(file,ev);
+ break;
+ default:
+ xkb_prologue(file, ev, "XKB_UNKNOWN!!!" );
+ break;
+ }
+ }
+ return;
+}
diff --git a/tokens.h b/tokens.h
new file mode 100644
index 0000000..c0b9d97
--- /dev/null
+++ b/tokens.h
@@ -0,0 +1,67 @@
+/* $Xorg: tokens.h,v 1.3 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+#ifndef TOKENS_H
+#define TOKENS_H 1
+
+#define END_OF_FILE 0
+#define ERROR 255
+
+#define BELL 1
+#define ACCESSX 2
+#define MESSAGE 3
+
+#define NONE 20
+#define IGNORE 21
+#define ECHO 22
+#define PRINT_EV 23
+#define SHELL 24
+#define SOUND 25
+
+#define EQUALS 40
+#define PLUS 41
+#define MINUS 42
+#define DIVIDE 43
+#define TIMES 44
+#define OBRACE 45
+#define CBRACE 46
+#define OPAREN 47
+#define CPAREN 48
+#define OBRACKET 49
+#define CBRACKET 50
+#define DOT 51
+#define COMMA 52
+#define SEMI 53
+#define EXCLAM 54
+#define INVERT 55
+
+#define STRING 60
+#define INTEGER 61
+#define FLOAT 62
+#define IDENT 63
+#define KEYNAME 64
+
+#endif
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..8d331df
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,368 @@
+
+ /*\
+ * $Xorg: utils.c,v 1.5 2000/08/17 19:54:49 cpqbld Exp $
+ *
+ * COPYRIGHT 1990
+ * DIGITAL EQUIPMENT CORPORATION
+ * MAYNARD, MASSACHUSETTS
+ * ALL RIGHTS RESERVED.
+ *
+ * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
+ * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
+ * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE
+ * FOR ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED
+ * WARRANTY.
+ *
+ * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
+ * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
+ * ADDITION TO THAT SET FORTH ABOVE.
+ *
+ * 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 Equipment Corporation not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ \*/
+
+#include "utils.h"
+#include <ctype.h>
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc();
+#endif
+
+/***====================================================================***/
+
+Opaque
+uAlloc(size)
+ unsigned size;
+{
+ return((Opaque)malloc(size));
+}
+
+/***====================================================================***/
+
+Opaque
+uCalloc(n,size)
+ unsigned n;
+ unsigned size;
+{
+ return((Opaque)calloc(n,size));
+}
+
+/***====================================================================***/
+
+Opaque
+uRealloc(old,newSize)
+ Opaque old;
+ unsigned newSize;
+{
+ if (old==NULL)
+ return((Opaque)malloc(newSize));
+ else return((Opaque)realloc((char *)old,newSize));
+}
+
+/***====================================================================***/
+
+Opaque
+uRecalloc(old,nOld,nNew,itemSize)
+ Opaque old;
+ unsigned nOld;
+ unsigned nNew;
+ unsigned itemSize;
+{
+char *rtrn;
+
+ if (old==NULL)
+ rtrn= (char *)calloc(nNew,itemSize);
+ else {
+ rtrn= (char *)realloc((char *)old,nNew*itemSize);
+ if ((rtrn)&&(nNew>nOld)) {
+ bzero(&rtrn[nOld*itemSize],(nNew-nOld)*itemSize);
+ }
+ }
+ return (Opaque)rtrn;
+}
+
+/***====================================================================***/
+
+void
+uFree(ptr)
+ Opaque ptr;
+{
+ if (ptr!=(Opaque)NULL)
+ free((char *)ptr);
+ return;
+}
+
+/***====================================================================***/
+/*** FUNCTION ENTRY TRACKING ***/
+/***====================================================================***/
+
+static FILE *entryFile= stderr;
+ int uEntryLevel;
+
+Boolean
+uSetEntryFile(name)
+ char *name;
+{
+ if ((entryFile!=NULL)&&(entryFile!=stderr)) {
+ fprintf(entryFile,"switching to %s\n",name?name:"stderr");
+ fclose(entryFile);
+ }
+ if (name!=NullString) entryFile= fopen(name,"w");
+ else entryFile= stderr;
+ if (entryFile==NULL) {
+ entryFile= stderr;
+ return(False);
+ }
+ return(True);
+}
+
+void
+uEntry(l,s,a1,a2,a3,a4,a5,a6,a7,a8)
+int l;
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+int i;
+
+ for (i=0;i<uEntryLevel;i++) {
+ putc(' ',entryFile);
+ }
+ fprintf(entryFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ uEntryLevel+= l;
+ return;
+}
+
+void
+uExit(l,rtVal)
+ int l;
+ char * rtVal;
+{
+int i;
+
+ uEntryLevel-= l;
+ if (uEntryLevel<0) uEntryLevel= 0;
+ for (i=0;i<uEntryLevel;i++) {
+ putc(' ',entryFile);
+ }
+ fprintf(entryFile,"---> 0x%p\n",rtVal);
+ return;
+}
+
+/***====================================================================***/
+/*** PRINT FUNCTIONS ***/
+/***====================================================================***/
+
+ FILE *uDebugFile= stderr;
+ int uDebugIndentLevel= 0;
+ int uDebugIndentSize= 4;
+
+Boolean
+uSetDebugFile(name)
+ char *name;
+{
+ if ((uDebugFile!=NULL)&&(uDebugFile!=stderr)) {
+ fprintf(uDebugFile,"switching to %s\n",name?name:"stderr");
+ fclose(uDebugFile);
+ }
+ if (name!=NullString) uDebugFile= fopen(name,"w");
+ else uDebugFile= stderr;
+ if (uDebugFile==NULL) {
+ uDebugFile= stderr;
+ return(False);
+ }
+ return(True);
+}
+
+void
+uDebug(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+int i;
+
+ for (i=(uDebugIndentLevel*uDebugIndentSize);i>0;i--) {
+ putc(' ',uDebugFile);
+ }
+ fprintf(uDebugFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(uDebugFile);
+ return;
+}
+
+void
+uDebugNOI(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(uDebugFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(uDebugFile);
+ return;
+}
+
+/***====================================================================***/
+
+static FILE *errorFile= stderr;
+
+Boolean
+uSetErrorFile(name)
+ char *name;
+{
+ if ((errorFile!=NULL)&&(errorFile!=stderr)) {
+ fprintf(errorFile,"switching to %s\n",name?name:"stderr");
+ fclose(errorFile);
+ }
+ if (name!=NullString) errorFile= fopen(name,"w");
+ else errorFile= stderr;
+ if (errorFile==NULL) {
+ errorFile= stderr;
+ return(False);
+ }
+ return(True);
+}
+
+void
+uInformation(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+void
+uAction(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(errorFile," ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+void
+uWarning(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(errorFile,"Warning: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+void
+uError(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(errorFile,"Error: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+void
+uFatalError(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(errorFile,"Fatal Error: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fprintf(errorFile," Exiting\n");
+ fflush(errorFile);
+ exit(1);
+ /* NOTREACHED */
+}
+
+/***====================================================================***/
+
+void
+uInternalError(s,a1,a2,a3,a4,a5,a6,a7,a8)
+char *s;
+Opaque a1,a2,a3,a4,a5,a6,a7,a8;
+{
+ fprintf(errorFile,"Internal error: ");
+ fprintf(errorFile,s,a1,a2,a3,a4,a5,a6,a7,a8);
+ fflush(errorFile);
+ return;
+}
+
+/***====================================================================***/
+
+#ifndef HAVE_STRDUP
+char *
+uStringDup(str)
+ char *str;
+{
+char *rtrn;
+
+ if (str==NULL)
+ return NULL;
+ rtrn= (char *)uAlloc(strlen(str)+1);
+ strcpy(rtrn,str);
+ return rtrn;
+}
+#endif
+
+#ifndef HAVE_STRCASECMP
+int
+uStrCaseCmp(str1, str2)
+ char *str1, *str2;
+{
+ char buf1[512],buf2[512];
+ char c, *s;
+ register int n;
+
+ for (n=0, s = buf1; (c = *str1++); n++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (n>510)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ for (n=0, s = buf2; (c = *str2++); n++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (n>510)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ return (strcmp(buf1, buf2));
+}
+
+int
+uStrCasePrefix(prefix, str)
+ char *prefix, *str;
+{
+ char c1;
+ char c2;
+ while (((c1=*prefix)!='\0')&&((c2=*str)!='\0')) {
+ if (isupper(c1)) c1= tolower(c1);
+ if (isupper(c2)) c2= tolower(c2);
+ if (c1!=c2)
+ return 0;
+ prefix++; str++;
+ }
+ if (c1!='\0')
+ return 0;
+ return 1;
+}
+
+#endif
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..448099f
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,307 @@
+#ifndef UTILS_H
+#define UTILS_H 1
+
+ /*\
+ * $Xorg: utils.h,v 1.3 2000/08/17 19:54:49 cpqbld Exp $
+ *
+ * COPYRIGHT 1990
+ * DIGITAL EQUIPMENT CORPORATION
+ * MAYNARD, MASSACHUSETTS
+ * ALL RIGHTS RESERVED.
+ *
+ * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
+ * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
+ * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE
+ * FOR ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED
+ * WARRANTY.
+ *
+ * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
+ * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
+ * ADDITION TO THAT SET FORTH ABOVE.
+ *
+ * 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 Equipment Corporation not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ \*/
+
+/***====================================================================***/
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <X11/Xfuncproto.h>
+#include <X11/Xfuncs.h>
+
+_XFUNCPROTOBEGIN
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef NUL
+#define NUL '\0'
+#endif
+
+/***====================================================================***/
+
+#ifndef OPAQUE_DEFINED
+typedef void *Opaque;
+#endif
+#ifndef NullOpaque
+#define NullOpaque ((Opaque)NULL)
+#endif
+
+#ifndef BOOLEAN_DEFINED
+typedef char Boolean;
+#endif
+
+#ifndef True
+#define True ((Boolean)1)
+#define False ((Boolean)0)
+#endif /* ndef True */
+#define booleanText(b) ((b)?"True":"False")
+
+#ifndef COMPARISON_DEFINED
+typedef int Comparison;
+
+#define Greater ((Comparison)1)
+#define Equal ((Comparison)0)
+#define Less ((Comparison)-1)
+#define CannotCompare ((Comparison)-37)
+#define comparisonText(c) ((c)?((c)<0?"Less":"Greater"):"Equal")
+#endif
+
+typedef union {
+ int i;
+ unsigned u;
+ void *p;
+ void *(*fp)();
+} Union;
+
+/***====================================================================***/
+
+extern Opaque uAlloc(
+#if NeedFunctionPrototypes
+ unsigned /* size */
+#endif
+);
+extern Opaque uCalloc(
+#if NeedFunctionPrototypes
+ unsigned /* n */,
+ unsigned /* size */
+#endif
+);
+extern Opaque uRealloc(
+#if NeedFunctionPrototypes
+ Opaque /* old */,
+ unsigned /* newSize */
+#endif
+);
+extern Opaque uRecalloc(
+#if NeedFunctionPrototypes
+ Opaque /* old */,
+ unsigned /* nOld */,
+ unsigned /* nNew */,
+ unsigned /* newSize */
+#endif
+);
+extern void uFree(
+#if NeedFunctionPrototypes
+ Opaque /* ptr */
+#endif
+);
+
+#define uTypedAlloc(t) ((t *)uAlloc((unsigned)sizeof(t)))
+#define uTypedCalloc(n,t) ((t *)uCalloc((unsigned)n,(unsigned)sizeof(t)))
+#define uTypedRealloc(pO,n,t) ((t *)uRealloc((Opaque)pO,((unsigned)n)*sizeof(t)))
+#define uTypedRecalloc(pO,o,n,t) ((t *)uRecalloc((Opaque)pO,((unsigned)o),((unsigned)n),sizeof(t)))
+#if (defined mdHasAlloca) && (mdHasAlloca)
+#define uTmpAlloc(n) ((Opaque)alloca((unsigned)n))
+#define uTmpFree(p)
+#else
+#define uTmpAlloc(n) uAlloc(n)
+#define uTmpFree(p) uFree(p)
+#endif
+
+/***====================================================================***/
+
+extern Boolean uSetErrorFile(
+#if NeedFunctionPrototypes
+ char * /* name */
+#endif
+);
+extern void uInformation();
+extern void uAction();
+extern void uWarning();
+extern void uError();
+extern void uFatalError();
+extern void uInternalError();
+
+/***====================================================================***/
+
+#define NullString ((char *)NULL)
+
+#define uStringText(s) ((s)==NullString?"<NullString>":(s))
+#define uStringEqual(s1,s2) (uStringCompare(s1,s2)==Equal)
+#define uStringPrefix(p,s) (strncmp(p,s,strlen(p))==0)
+#define uStringCompare(s1,s2) (strcmp(s1,s2))
+#define uStrCaseEqual(s1,s2) (uStrCaseCmp(s1,s2)==0)
+#ifdef HAVE_STRCASECMP
+#define uStrCaseCmp(s1,s2) (strcasecmp(s1,s2))
+#define uStrCasePrefix(p,s) (strncasecmp(p,s,strlen(p))==0)
+#else
+extern int uStrCaseCmp(
+#if NeedFunctionPrototypes
+ char * /* s1 */,
+ char * /* s2 */
+#endif
+);
+extern int uStrCasePrefix(
+#if NeedFunctionPrototypes
+ char * /* p */,
+ char * /* str */
+#endif
+);
+#endif
+#ifdef HAVE_STRDUP
+#define uStringDup(s1) (strdup(s1))
+#else
+extern char *uStringDup(
+#if NeedFunctionPrototypes
+ char * /* s1 */
+#endif
+);
+#endif
+
+/***====================================================================***/
+
+#ifdef ASSERTIONS_ON
+#define uASSERT(where,why) \
+ {if (!(why)) uFatalError("assertion botched in %s ( why )\n",where);}
+#else
+#define uASSERT(where,why)
+#endif
+
+/***====================================================================***/
+
+#ifndef DEBUG_VAR
+#define DEBUG_VAR debugFlags
+#endif
+
+#ifdef DEBUG_VAR_NOT_LOCAL
+extern
+#endif
+unsigned int DEBUG_VAR;
+
+extern void uDebug();
+extern void uDebugNOI(); /* no indent */
+extern Boolean uSetDebugFile(
+#if NeedFunctionPrototypes
+ char *name
+#endif
+);
+extern FILE *uDebugFile;
+extern int uDebugIndentLevel;
+extern int uDebugIndentSize;
+#define uDebugIndent(l) (uDebugIndentLevel+=(l))
+#define uDebugOutdent(l) (uDebugIndentLevel-=(l))
+#ifdef DEBUG_ON
+#define uDEBUG(f,s) { if (DEBUG_VAR&(f)) uDebug(s);}
+#define uDEBUG1(f,s,a) { if (DEBUG_VAR&(f)) uDebug(s,a);}
+#define uDEBUG2(f,s,a,b) { if (DEBUG_VAR&(f)) uDebug(s,a,b);}
+#define uDEBUG3(f,s,a,b,c) { if (DEBUG_VAR&(f)) uDebug(s,a,b,c);}
+#define uDEBUG4(f,s,a,b,c,d) { if (DEBUG_VAR&(f)) uDebug(s,a,b,c,d);}
+#define uDEBUG5(f,s,a,b,c,d,e) { if (DEBUG_VAR&(f)) uDebug(s,a,b,c,d,e);}
+#define uDEBUG_NOI(f,s) { if (DEBUG_VAR&(f)) uDebug(s);}
+#define uDEBUG_NOI1(f,s,a) { if (DEBUG_VAR&(f)) uDebugNOI(s,a);}
+#define uDEBUG_NOI2(f,s,a,b) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b);}
+#define uDEBUG_NOI3(f,s,a,b,c) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b,c);}
+#define uDEBUG_NOI4(f,s,a,b,c,d) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b,c,d);}
+#define uDEBUG_NOI5(f,s,a,b,c,d,e) { if (DEBUG_VAR&(f)) uDebugNOI(s,a,b,c,d,e);}
+#else
+#define uDEBUG(f,s)
+#define uDEBUG1(f,s,a)
+#define uDEBUG2(f,s,a,b)
+#define uDEBUG3(f,s,a,b,c)
+#define uDEBUG4(f,s,a,b,c,d)
+#define uDEBUG5(f,s,a,b,c,d,e)
+#define uDEBUG_NOI(f,s)
+#define uDEBUG_NOI1(f,s,a)
+#define uDEBUG_NOI2(f,s,a,b)
+#define uDEBUG_NOI3(f,s,a,b,c)
+#define uDEBUG_NOI4(f,s,a,b,c,d)
+#define uDEBUG_NOI5(f,s,a,b,c,d,e)
+#endif
+
+extern Boolean uSetEntryFile(
+#if NeedFunctionPrototypes
+ char *name
+#endif
+);
+extern void uEntry();
+extern void uExit(
+#if NeedFunctionPrototypes
+ int l,char *rtVal
+#endif
+);
+#ifdef ENTRY_TRACKING_ON
+#define ENTRY_BIT 0x10
+#define LOW_ENTRY_BIT 0x1000
+#define ENTER (DEBUG_VAR&ENTRY_BIT)
+#define FLAG(fLag) (DEBUG_VAR&(fLag))
+
+extern int uEntryLevel;
+
+#define uENTRY(s) { if (ENTER) uEntry(1,s);}
+#define uENTRY1(s,a) { if (ENTER) uEntry(1,s,a);}
+#define uENTRY2(s,a,b) { if (ENTER) uEntry(1,s,a,b);}
+#define uENTRY3(s,a,b,c) { if (ENTER) uEntry(1,s,a,b,c);}
+#define uENTRY4(s,a,b,c,d) { if (ENTER) uEntry(1,s,a,b,c,d);}
+#define uENTRY5(s,a,b,c,d,e) { if (ENTER) uEntry(1,s,a,b,c,d,e);}
+#define uENTRY6(s,a,b,c,d,e,f) { if (ENTER) uEntry(1,s,a,b,c,d,e,f);}
+#define uENTRY7(s,a,b,c,d,e,f,g) { if (ENTER) uEntry(1,s,a,b,c,d,e,f,g);}
+#define uRETURN(v) { if (ENTER) uEntryLevel--; return(v); }
+#define uVOIDRETURN { if (ENTER) uEntryLevel--; return; }
+
+#define uFLAG_ENTRY(w,s) { if (FLAG(w)) uEntry(0,s);}
+#define uFLAG_ENTRY1(w,s,a) { if (FLAG(w)) uEntry(0,s,a);}
+#define uFLAG_ENTRY2(w,s,a,b) { if (FLAG(w)) uEntry(0,s,a,b);}
+#define uFLAG_ENTRY3(w,s,a,b,c) { if (FLAG(w)) uEntry(0,s,a,b,c);}
+#define uFLAG_ENTRY4(w,s,a,b,c,d) { if (FLAG(w)) uEntry(0,s,a,b,c,d);}
+#define uFLAG_ENTRY5(w,s,a,b,c,d,e) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e);}
+#define uFLAG_ENTRY6(w,s,a,b,c,d,e,f) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e,f);}
+#define uFLAG_ENTRY7(w,s,a,b,c,d,e,f,g) { if(FLAG(w))uEntry(0,s,a,b,c,d,e,f,g);}
+#define uFLAG_RETURN(v) { return(v);}
+#define uFLAG_VOIDRETURN { return; }
+#else
+#define uENTRY(s)
+#define uENTRY1(s,a)
+#define uENTRY2(s,a1,a2)
+#define uENTRY3(s,a1,a2,a3)
+#define uENTRY4(s,a1,a2,a3,a4)
+#define uENTRY5(s,a1,a2,a3,a4,a5)
+#define uENTRY6(s,a1,a2,a3,a4,a5,a6)
+#define uENTRY7(s,a1,a2,a3,a4,a5,a6,a7)
+#define uRETURN(v) { return(v); }
+#define uVOIDRETURN { return; }
+
+#define uFLAG_ENTRY(f,s)
+#define uFLAG_ENTRY1(f,s,a)
+#define uFLAG_ENTRY2(f,s,a,b)
+#define uFLAG_ENTRY3(f,s,a,b,c)
+#define uFLAG_ENTRY4(f,s,a,b,c,d)
+#define uFLAG_ENTRY5(f,s,a,b,c,d,e)
+#define uFLAG_ENTRY6(f,s,a,b,c,d,e,g)
+#define uFLAG_ENTRY7(f,s,a,b,c,d,e,g,h)
+#define uFLAG_RETURN(v) { return(v);}
+#define uFLAG_VOIDRETURN { return; }
+#endif
+
+_XFUNCPROTOEND
+
+#endif /* UTILS_H */
+
+
diff --git a/xkbevd.c b/xkbevd.c
new file mode 100644
index 0000000..6f9787f
--- /dev/null
+++ b/xkbevd.c
@@ -0,0 +1,555 @@
+/* $Xorg: xkbevd.c,v 1.4 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+
+#define DEBUG_VAR xkbevdDebug
+#include "xkbevd.h"
+
+#define lowbit(x) ((x) & (-(x)))
+
+/***====================================================================***/
+
+#ifndef DFLT_XKBEVD_CONFIG
+#define DFLT_XKBEVD_CONFIG "%s/.xkb/xkbevd.cf"
+#endif /* DFLT_XKBEVD_CONFIG */
+
+#ifndef DFLT_XKB_CONFIG_ROOT
+#define DFLT_XKB_CONFIG_ROOT "/usr/X11R6/lib/xkb"
+#endif
+
+#ifndef DFLT_SYS_XKBEVD_CONFIG
+#define DFLT_SYS_XKBEVD_CONFIG "%s/xkbevd.cf"
+#endif /* DFLT_SYS_XKBEVD_CONFIG */
+
+#ifndef DFLT_SOUND_CMD
+#define DFLT_SOUND_CMD "/usr/sbin/sfplay -q"
+#endif /* DFLT_SOUND_CMD */
+
+#ifndef DFLT_SOUND_DIR
+#define DFLT_SOUND_DIR "/usr/share/data/sounds/prosonus/"
+#endif /* DFLT_SOUND_DIR */
+
+/***====================================================================***/
+
+char * dpyName= NULL;
+Display * dpy= NULL;
+char * cfgFileName= NULL;
+int xkbOpcode= 0;
+int xkbEventCode= 0;
+Bool detectableRepeat= False;
+
+CfgEntryPtr config= NULL;
+unsigned long eventMask= 0;
+
+Bool synch= False;
+int verbose= 0;
+Bool background= False;
+
+char * soundCmd= NULL;
+char * soundDir= NULL;
+
+XkbDescPtr xkb= NULL;
+
+/***====================================================================***/
+
+#define M(m) fprintf(stderr,(m))
+#define M1(m,a) fprintf(stderr,(m),(a))
+
+void
+Usage(argc,argv)
+ int argc;
+ char * argv[];
+{
+ M1("Usage: %s [options]...\n",argv[0]);
+ M("Legal options:\n");
+ M("-?,-help Print this message\n");
+ M("-cfg <file> Specify a config file\n");
+ M("-sc <cmd> Specify the command to play sounds\n");
+ M("-sd <dir> Specify the root directory for sound files\n");
+ M("-d[isplay] <dpy> Specify the display to watch\n");
+ M("-bg Run in background\n");
+ M("-synch Force synchronization\n");
+ M("-v Print verbose messages\n");
+ return;
+}
+
+/***====================================================================***/
+
+Bool
+parseArgs(argc,argv)
+ int argc;
+ char * argv[];
+{
+register int i;
+
+ for (i=1;i<argc;i++) {
+ if (strcmp(argv[i],"-bg")==0) {
+ background= True;
+ }
+ else if (strcmp(argv[i],"-cfg")==0) {
+ if (i>=(argc-1)) {
+ uError("No configuration file specified on command line\n");
+ uAction("Trailing %s argument ignored\n",argv[i]);
+ }
+ else {
+ char *name= argv[++i];
+ if (cfgFileName!=NULL) {
+ if (uStringEqual(cfgFileName,name))
+ uWarning("Config file \"%s\" specified twice!\n");
+ else {
+ uWarning("Multiple config files on command line\n");
+ uAction("Using \"%s\", ignoring \"%s\"\n",name,
+ cfgFileName);
+ }
+ }
+ cfgFileName= name;
+ }
+ }
+ else if ((strcmp(argv[i],"-d")==0)||(strcmp(argv[i],"-display")==0)) {
+ if (i>=(argc-1)) {
+ uError("No display specified on command line\n");
+ uAction("Trailing %s argument ignored\n",argv[i]);
+ }
+ else {
+ char *name= argv[++i];
+ if (dpyName!=NULL) {
+ if (uStringEqual(dpyName,name))
+ uWarning("Display \"%s\" specified twice!\n");
+ else {
+ uWarning("Multiple displays on command line\n");
+ uAction("Using \"%s\", ignoring \"%s\"\n",name,
+ dpyName);
+ }
+ }
+ dpyName= name;
+ }
+ }
+ else if (strcmp(argv[i],"-sc")==0) {
+ if (i>=(argc-1)) {
+ uError("No sound command specified on command line\n");
+ uAction("Trailing %s argument ignored\n",argv[i]);
+ }
+ else {
+ char *name= argv[++i];
+ if (soundCmd!=NULL) {
+ if (uStringEqual(soundCmd,name))
+ uWarning("Sound command \"%s\" specified twice!\n");
+ else {
+ uWarning("Multiple sound commands on command line\n");
+ uAction("Using \"%s\", ignoring \"%s\"\n",name,
+ soundCmd);
+ }
+ }
+ soundCmd= name;
+ }
+ }
+ else if (strcmp(argv[i],"-sd")==0) {
+ if (i>=(argc-1)) {
+ uError("No sound directory specified on command line\n");
+ uAction("Trailing %s argument ignored\n",argv[i]);
+ }
+ else {
+ char *name= argv[++i];
+ if (soundDir!=NULL) {
+ if (uStringEqual(soundDir,name))
+ uWarning("Sound directory \"%s\" specified twice!\n");
+ else {
+ uWarning("Multiple sound dirs on command line\n");
+ uAction("Using \"%s\", ignoring \"%s\"\n",name,
+ soundDir);
+ }
+ }
+ soundDir= name;
+ }
+ }
+ else if ((strcmp(argv[i],"-synch")==0)||(strcmp(argv[i],"-s")==0)) {
+ synch= True;
+ }
+ else if (strcmp(argv[i],"-v")==0) {
+ verbose++;
+ }
+ else if ((strcmp(argv[i],"-?")==0)||(strcmp(argv[i],"-help")==0)) {
+ Usage(argc,argv);
+ exit(0);
+ }
+ else {
+ uError("Unknown flag \"%s\" on command line\n",argv[i]);
+ Usage(argc,argv);
+ return False;
+ }
+ }
+ return True;
+}
+
+Display *
+GetDisplay(program,dpyName,opcodeRtrn,evBaseRtrn)
+ char * program;
+ char * dpyName;
+ int * opcodeRtrn;
+ int * evBaseRtrn;
+{
+int mjr,mnr,error;
+Display *dpy;
+
+ mjr= XkbMajorVersion;
+ mnr= XkbMinorVersion;
+ dpy= XkbOpenDisplay(dpyName,evBaseRtrn,NULL,&mjr,&mnr,&error);
+ if (dpy==NULL) {
+ switch (error) {
+ case XkbOD_BadLibraryVersion:
+ uInformation("%s was compiled with XKB version %d.%02d\n",
+ program,XkbMajorVersion,XkbMinorVersion);
+ uError("X library supports incompatible version %d.%02d\n",
+ mjr,mnr);
+ break;
+ case XkbOD_ConnectionRefused:
+ uError("Cannot open display \"%s\"\n",dpyName);
+ break;
+ case XkbOD_NonXkbServer:
+ uError("XKB extension not present on %s\n",dpyName);
+ break;
+ case XkbOD_BadServerVersion:
+ uInformation("%s was compiled with XKB version %d.%02d\n",
+ program,XkbMajorVersion,XkbMinorVersion);
+ uError("Server %s uses incompatible version %d.%02d\n",
+ dpyName,mjr,mnr);
+ break;
+ default:
+ uInternalError("Unknown error %d from XkbOpenDisplay\n",error);
+ }
+ }
+ else if (synch)
+ XSynchronize(dpy,True);
+ if (opcodeRtrn)
+ XkbQueryExtension(dpy,opcodeRtrn,evBaseRtrn,NULL,&mjr,&mnr);
+ return dpy;
+}
+
+/***====================================================================***/
+
+void
+InterpretConfigs(cfg)
+ CfgEntryPtr cfg;
+{
+char * name;
+unsigned priv= 0;
+
+ config= cfg;
+ while (cfg!=NULL) {
+ name= cfg->name.str;
+ if (cfg->entry_type==VariableDef) {
+ if (uStrCaseEqual(name,"sounddirectory")||
+ uStrCaseEqual(name,"sounddir")) {
+ if (soundDir==NULL) {
+ soundDir= cfg->action.text;
+ cfg->name.str= NULL;
+ cfg->action.text= NULL;
+ }
+ }
+ else if (uStrCaseEqual(name,"soundcommand")||
+ uStrCaseEqual(name,"soundcmd")) {
+ if (soundCmd==NULL) {
+ soundCmd= cfg->action.text;
+ cfg->name.str= NULL;
+ cfg->action.text= NULL;
+ }
+ }
+ else {
+ uWarning("Assignment to unknown variable \"%s\"\n",cfg->name);
+ uAction("Ignored\n");
+ }
+ }
+ else if (cfg->entry_type==EventDef) switch (cfg->event_type) {
+ case XkbBellNotify:
+ if (name!=NULL) cfg->name.atom= XInternAtom(dpy,name,False);
+ else cfg->name.atom= None;
+ if (name) uFree(name);
+ break;
+ case XkbAccessXNotify:
+ priv= 0;
+ if (name==NULL)
+ priv= XkbAllNewKeyboardEventsMask;
+ else if (uStrCaseEqual(name,"skpress"))
+ priv= XkbAXN_SKPressMask;
+ else if (uStrCaseEqual(name,"skaccept"))
+ priv= XkbAXN_SKAcceptMask;
+ else if (uStrCaseEqual(name,"skreject"))
+ priv= XkbAXN_SKRejectMask;
+ else if (uStrCaseEqual(name,"skrelease"))
+ priv= XkbAXN_SKReleaseMask;
+ else if (uStrCaseEqual(name,"bkaccept"))
+ priv= XkbAXN_BKAcceptMask;
+ else if (uStrCaseEqual(name,"bkreject"))
+ priv= XkbAXN_BKRejectMask;
+ else if (uStrCaseEqual(name,"warning"))
+ priv= XkbAXN_AXKWarningMask;
+ if (name) uFree(name);
+ cfg->name.priv= priv;
+ break;
+ case XkbActionMessage:
+ /* nothing to do */
+ break;
+ }
+ eventMask|= (1L<<cfg->event_type);
+ cfg= cfg->next;
+ }
+ while ((config)&&(config->entry_type!=EventDef)) {
+ CfgEntryPtr next;
+ if (config->name.str) uFree(config->name.str);
+ if (config->action.text) uFree(config->action.text);
+ config->name.str= NULL;
+ config->action.text= NULL;
+ next= config->next;
+ uFree(config);
+ config= next;
+ }
+ cfg= config;
+ while ((cfg!=NULL)&&(cfg->next!=NULL)) {
+ CfgEntryPtr next;
+ next= cfg->next;
+ if (next->entry_type!=EventDef) {
+ if (next->name.str) uFree(config->name.str);
+ if (next->action.text) uFree(config->action.text);
+ next->name.str= NULL;
+ next->action.text= NULL;
+ cfg->next= next->next;
+ next->next= NULL;
+ uFree(next);
+ }
+ else cfg= next;
+ }
+ return;
+}
+
+CfgEntryPtr
+FindMatchingConfig(ev)
+ XkbEvent * ev;
+{
+CfgEntryPtr cfg,dflt;
+
+ dflt= NULL;
+ for (cfg= config;(cfg!=NULL);cfg=cfg->next) {
+ if ((ev->type!=xkbEventCode)||(cfg->event_type!=ev->any.xkb_type))
+ continue;
+ switch (ev->any.xkb_type) {
+ case XkbBellNotify:
+ if (ev->bell.name==cfg->name.atom)
+ return cfg;
+ else if ((cfg->name.atom==None)&&(dflt==NULL))
+ dflt= cfg;
+ break;
+ case XkbAccessXNotify:
+ if (cfg->name.priv&(1L<<ev->accessx.detail))
+ return cfg;
+ break;
+ case XkbActionMessage:
+ if (cfg->name.str==NULL)
+ dflt= cfg;
+ else if (strncmp(cfg->name.str,ev->message.message,
+ XkbActionMessageLength)==0)
+ return cfg;
+ break;
+ default:
+ uInternalError("Can't handle type %d XKB events yet, Sorry.\n");
+ break;
+ }
+ }
+ return dflt;
+}
+
+Bool
+ProcessMatchingConfig(ev)
+ XkbEvent * ev;
+{
+CfgEntryPtr cfg;
+char buf[1024],*cmd;
+int ok;
+
+ cfg= FindMatchingConfig(ev);
+ if (!cfg)
+ return False;
+ if (cfg->action.type==UnknownAction) {
+ if (cfg->action.text==NULL)
+ cfg->action.type= NoAction;
+ else if (cfg->action.text[0]=='!') {
+ char *tmp;
+ cfg->action.type= ShellAction;
+ tmp= uStringDup(&cfg->action.text[1]);
+ uFree(cfg->action.text);
+ cfg->action.text= tmp;
+ }
+ else cfg->action.type= SoundAction;
+ }
+ switch (cfg->action.type) {
+ case NoAction:
+ return True;
+ case EchoAction:
+ if (cfg->action.text!=NULL) {
+ sprintf(buf,cfg->action.text);
+ cmd= SubstituteEventArgs(buf,ev);
+ printf("%s",cmd);
+ }
+ return True;
+ case PrintEvAction:
+ PrintXkbEvent(stdout,ev);
+ return True;
+ case ShellAction:
+ if (cfg->action.text==NULL) {
+ uWarning("Empty shell command!\n");
+ uAction("Ignored\n");
+ return True;
+ }
+ cmd= cfg->action.text;
+ break;
+ case SoundAction:
+ if (cfg->action.text==NULL) {
+ uWarning("Empty sound command!\n");
+ uAction("Ignored\n");
+ return True;
+ }
+ sprintf(buf,"%s %s%s",soundCmd,soundDir,cfg->action.text);
+ cmd= buf;
+ break;
+ default:
+ uInternalError("Unknown error action type %d\n",cfg->action.type);
+ return False;
+ }
+ cmd= SubstituteEventArgs(cmd,ev);
+ if (verbose)
+ uInformation("Executing shell command \"%s\"\n",cmd);
+ ok= (system(cmd)==0);
+ return ok;
+}
+
+/***====================================================================***/
+
+int
+main(argc,argv)
+ int argc;
+ char * argv[];
+{
+FILE * file;
+static char buf[1024];
+XkbEvent ev;
+Bool ok;
+
+ if (!parseArgs(argc,argv))
+ exit(1);
+ file= NULL;
+ XkbInitAtoms(NULL);
+ if (cfgFileName==NULL) {
+ char *home;
+ home= (char *)getenv("HOME");
+ sprintf(buf,DFLT_XKBEVD_CONFIG,(home?home:""));
+ cfgFileName= buf;
+ }
+ if (uStringEqual(cfgFileName,"-")) {
+ static char *in= "stdin";
+ file= stdin;
+ cfgFileName= in;
+ }
+ else {
+ file= fopen(cfgFileName,"r");
+ if (file==NULL) { /* no personal config, try for a system one */
+ if (cfgFileName!=buf) { /* user specified a file. bail */
+ uError("Can't open config file \"%s\n",cfgFileName);
+ uAction("Exiting\n");
+ exit(1);
+ }
+ sprintf(buf,DFLT_SYS_XKBEVD_CONFIG,DFLT_XKB_CONFIG_ROOT);
+ file= fopen(cfgFileName,"r");
+ if (file==NULL) {
+ if (verbose) {
+ uError("Couldn't find a config file anywhere\n");
+ uAction("Exiting\n");
+ exit(1);
+ }
+ exit(0);
+ }
+ }
+ }
+
+ if (background) {
+ if (fork()!=0) {
+ if (verbose)
+ uInformation("Running in the background\n");
+ exit(0);
+ }
+ }
+ dpy= GetDisplay(argv[0],dpyName,&xkbOpcode,&xkbEventCode);
+ if (!dpy)
+ goto BAILOUT;
+ ok= True;
+ setScanState(cfgFileName,1);
+ CFGParseFile(file);
+ if (!config) {
+ uError("No configuration specified in \"%s\"\n",cfgFileName);
+ goto BAILOUT;
+ }
+ if (eventMask==0) {
+ uError("No events to watch in \"%s\"\n",cfgFileName);
+ goto BAILOUT;
+ }
+ if (!XkbSelectEvents(dpy,XkbUseCoreKbd,eventMask,eventMask)) {
+ uError("Couldn't select desired XKB events\n");
+ goto BAILOUT;
+ }
+ xkb= XkbGetKeyboard(dpy,XkbGBN_AllComponentsMask,XkbUseCoreKbd);
+ if (eventMask&XkbBellNotifyMask) {
+ unsigned ctrls,vals;
+ if (verbose)
+ uInformation("Temporarily disabling the audible bell\n");
+ if (!XkbChangeEnabledControls(dpy,XkbUseCoreKbd,XkbAudibleBellMask,0)) {
+ uError("Couldn't disable audible bell\n");
+ goto BAILOUT;
+ }
+ ctrls= vals= XkbAudibleBellMask;
+ if (!XkbSetAutoResetControls(dpy,XkbAudibleBellMask,&ctrls,&vals)) {
+ uWarning("Couldn't configure audible bell to reset on exit\n");
+ uAction("Audible bell might remain off\n");
+ }
+ }
+ if (soundCmd==NULL) soundCmd= DFLT_SOUND_CMD;
+ if (soundDir==NULL) soundDir= DFLT_SOUND_DIR;
+ XkbStdBellEvent(dpy,None,0,XkbBI_ImAlive);
+ while (1) {
+ XNextEvent(dpy,&ev.core);
+ if ((!ProcessMatchingConfig(&ev))&&(ev.type==xkbEventCode)&&
+ (ev.any.xkb_type==XkbBellNotify)) {
+ XkbForceDeviceBell(dpy,ev.bell.device,
+ ev.bell.bell_class,ev.bell.bell_id,
+ ev.bell.percent);
+ }
+ }
+
+ XCloseDisplay(dpy);
+ return (ok==0);
+BAILOUT:
+ uAction("Exiting\n");
+ if (dpy!=NULL)
+ XCloseDisplay(dpy);
+ exit(1);
+}
diff --git a/xkbevd.h b/xkbevd.h
new file mode 100644
index 0000000..d415389
--- /dev/null
+++ b/xkbevd.h
@@ -0,0 +1,102 @@
+/* $Xorg: xkbevd.h,v 1.3 2000/08/17 19:54:49 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ 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 Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS 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.
+
+ ********************************************************/
+#ifndef XKBEVD_H
+#define XKBEVD_H 1
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBfile.h>
+#include <X11/extensions/XKBbells.h>
+
+#include "utils.h"
+
+extern FILE * yyin;
+extern char * scanFile;
+extern int lineNum;
+extern int scanInt;
+extern char * scanIntStr;
+extern int scanIntClass;
+extern char * scanStr;
+extern int scanStrLine;
+
+extern Display * dpy;
+extern int xkbOpcode;
+extern int xkbEventCode;
+extern Bool detectableRepeat;
+
+extern XkbDescPtr xkb;
+
+#define UnknownAction 0
+#define NoAction 1
+#define EchoAction 2
+#define PrintEvAction 3
+#define ShellAction 4
+#define SoundAction 5
+
+typedef struct _ActDef {
+ int type;
+ char * text;
+ unsigned priv;
+} ActDefRec,*ActDefPtr;
+
+#define EventDef 0
+#define VariableDef 1
+
+typedef struct _CfgEntry {
+ unsigned char entry_type;
+ unsigned char event_type;
+ union {
+ char * str;
+ Atom atom;
+ unsigned priv;
+ } name;
+ ActDefRec action;
+ struct _CfgEntry * next;
+} CfgEntryRec,*CfgEntryPtr;
+
+extern void InterpretConfigs(
+#if NeedFunctionPrototypes
+ CfgEntryPtr /* cfgs */
+#endif
+);
+
+extern char *SubstituteEventArgs(
+#if NeedFunctionPrototypes
+ char * /* cmd */,
+ XkbEvent * /* ev */
+#endif
+);
+
+extern Bool PrintXkbEvent(
+#if NeedFunctionPrototypes
+ FILE * /* file */,
+ XkbEvent * /* ev */
+#endif
+);
+
+#endif /* XKBEVD_H */
diff --git a/xkbevd.man b/xkbevd.man
new file mode 100644
index 0000000..f66277d
--- /dev/null
+++ b/xkbevd.man
@@ -0,0 +1,96 @@
+.\" $Xorg: xkbevd.man,v 1.3 2000/08/17 19:54:49 cpqbld Exp $
+.TH XKBCOMP 1 "Release 6.4" "X Version 11"
+.SH NAME
+xkbevd \- XKB event daemon
+.SH SYNOPSIS
+.B xkbevd
+[ options ]
+.SH DESCRIPTION
+.PP
+This command is very raw and is therefore only partially implemented; we
+present it here as a rough prototype for developers, not as a general purpose
+tool for end users. Something like this might make a suitable replacement
+for xev; I'm not signing up, mind you, but it's an interesting idea.
+.PP
+The
+.I xkbevd
+event daemon listens for specified XKB events and executes requested commands
+if they occur. The configuration file consists of a list of event
+specification/action pairs and/or variable definitions.
+.PP
+An event specification consists of a short XKB event name followed by a
+string or identifier which serves as a qualifier in parentheses; empty
+parentesis indicate no qualification and serve to specify the default
+command which is applied to events which do not match any of the other
+specifications. The interpretation of the qualifier depends on the type
+of the event: Bell events match using the name of the bell, message events
+match on the contents of the message string and slow key events accept
+any of \fIpress\fP, \fIrelease\fP, \fIaccept\fP, or \fIreject\fP. No
+other events are currently recognized.
+.PP
+An action consists of an optional keyword followed by an optional string
+argument. Currently, \fIxkbev\fP recognizes the actions: \fInone\fP,
+\fIignore\fP, \fIecho\fP, \fIprintEvent\fP, \fIsound\fP, and \fIshell\fP.
+If the action is not specified, the string is taken as the name of a sound
+file to be played unless it begins with an exclamation point, in which case
+it is taken as a shell command.
+.PP
+Variable definitions in the argument string are expanded with fields from
+the event in question before the argument string is passed to the action
+processor. The general syntax for a variable is
+either $\fIc\P or $(\fIstr\fP), where \fIc\fP is a single character and
+\fIstr\fP is a string of arbitrary length. All parameters have both
+single-character and long names.
+.PP
+The list of recognized parameters varies from event to event and is too long
+to list here right now. This is a developer release anyway, so you can
+be expected to look at the source code (evargs.c is of particular interest).
+.PP
+The \fIignore\fP, \fIecho\fP, \fIprintEvent\fP, \fIsound\fP,and \fIshell\fP
+actions do what you would expect commands named \fIignore\fP, \fIecho\fP,
+\fIprintEvent\fP, \fIsound\fP, and \fIshell\fP to do, except that the sound
+command has only been implemented and tested for SGI machines. It launches
+an external program right now, so it should be pretty easy to adapt,
+especially if you like audio cues that arrive about a half-second after you
+expect them.
+.PP
+The only currently recognized variables are \fIsoundDirectory\fP and
+\fIsoundCmd\fP. I'm sure you can figure out what they do.
+.SH OPTIONS
+.TP 8
+.B \-help
+Prints a usage message that is far more up-to-date than anything in this
+man page.
+.TP 8
+.B \-cfg \fIfile\fP
+Specifies the configuration file to read. If no configuration file is
+specified, \fIxkbevd\fP looks for ~/.xkb/xkbevd.cf and $(LIBDIR)/xkb/xkbevd.cf
+in that order.
+.TP 8
+.B \-sc\ \fIcmd\fP
+Specifies the command used to play sounds.
+.TP 8
+.B \-sd\ \fIdirectory\fP
+Specifies a top-level directory for sound files.
+.TP 8
+.B \-display\ \fIdisplay\fP
+Specifies the display to use. If not present, \fIxkbevd\fP uses $DISPLAY.
+.TP 8
+.B \-bg
+Tells \fIxkbevd\fP to fork itself (and run in the background).
+.TP 8
+.B \-synch
+Forces synchronization of all X requests. Slow.
+.TP 8
+.B \-v
+Print more information, including debugging messages. Multiple
+specifications of \fI-v\fP cause more output, to a point.
+.SH "SEE ALSO"
+X(1)
+.SH COPYRIGHT
+Copyright 1995, Silicon Graphics Computer Systems
+Copyright 1995, 1998 The Open Group
+.br
+See \fIX(1)\fP for a full statement of rights and permissions.
+.SH AUTHOR
+Erik Fortune, Silicon Graphics