mark@sunquest.UUCP (Mark Langley) (09/24/88)
Better to curse the darkness than go around lighting small candles... Not having anything better to do on a Friday afternoon I wrote the function that I requested. Namely, I think an application program should be able to invoke actions in the same way the translation manager can. Thus to invoke an XtActionProc called foo, it should take no more than the following XtCallActionProc( "foo(abc,def)" ); The code to do this was not quite as easy as I had hoped, but straightforward nonetheless. The context diff was short enough (under 150 lines) that I post it here. It's just two functions that must go in TMstate.c. Unfortunately they can't be isolated because they need to access one private static variable called globalActionList... BTW kudos to Charles Haynes @Dec who (I think) built the translation routines. They are well done. Have Fun Mark Langley mark@sunquest.com ------ Cut Here ------ *** /usr/src/local/x11r2/lib/Xt/TMstate.c Sat Sep 24 07:30:04 1988 --- TMstate.c Sat Sep 24 08:16:49 1988 *************** *** 641,660 **** --- 641,783 ---- } typedef struct _ActionListRec *ActionList; typedef struct _ActionListRec { ActionList next; CompiledActionTable table; } ActionListRec; static ActionList globalActionList = NULL; + #define OPAREN '(' + #define CPAREN ')' + #define COMMA ',' + + /* + * sParseAction - Ad Hoc function to parse an action and return strings. + * function returns 0 on ok, and a string on error. + * + * Note that there are no strings malloced if an error occurs, + * *size XtMalloced otherwise. *size holds the max number + * to allocate on input. + * + * donated + * Mark Langley + * mark@sunquest.com + */ + static char *sParseAction(s, name, strings, size) + char *s; + char *name; + char **strings; + int *size; + {int i, j, len, args, cparen, max; + char *tmp; + + max = *size; + *size = 0; + for (i=0; s[i]; i++) + if (s[i] == OPAREN) + break; + if (s[i] != OPAREN) + return "Missing '('"; + + strncpy(name, s, i); + name[i] = '\0'; + i++; + for (cparen=args=0; s[i] && !cparen; i++) { + for (j=i; s[i] && (s[i] != COMMA) && (s[i] != CPAREN); i++) + ; + if (s[i] == CPAREN) + cparen = 1; + len = 1 + i - j; + if (len <= 1) + break; + strncpy(tmp=XtMalloc(len), &s[j], len); + tmp[len-1] = '\0'; + if (args < max) + strings[args++] = tmp; + } + if (!cparen) { + for (i=0; i<args;i++) + XtFree(strings[i]); + *size = 0; + return "Missing ')'"; + } + strings[args] = 0; + *size = args; + return 0; + } + + /* + * XtCallActionProc - invoke an ActionProc with an arglist + * donated by + * Mark Langley + * mark@sunquest.com + */ + XtCallActionProc(w, s) + Widget w; + char *s; + {ActionList al; + CompiledActionTable t; + char *strings[32], *msg; + char name[256]; + int i, size=32; + XtActionProc f=0; + register XrmQuark q; + register WidgetClass class=w->core.widget_class; + + msg = sParseAction(s, name, strings, &size); + if (msg) { + XtWarning(msg); + return; + } + q = XrmStringToQuark(name); + /* + * First search the widget's superclass chain + */ + for (;class != NULL && !f; class=class->core_class.superclass) + if (class->core_class.actions != NULL) { + t=(CompiledActionTable) class->core_class.actions; + for (i=0; t[i].name; i++) + if (t[i].signature == q) { + f = (XtActionProc) t[i].value; + break; + } + } + + /* + * search the global action procs + */ + for (al=globalActionList; al && !f; al = al->next) + for (t=al->table; t->name; t++) + if (t->signature == q) { + f = (XtActionProc) t->value; + break; + } + + if (f) { + XEvent event; + event.type=0; /* What else? */ + (*f)(w, &event, strings, &size); + } + else { + char message[256]; + sprintf(message, "Action not found: %s ", name); + XtWarning(message); + } + /* + * free up strings allocated by sParse + */ + for (i=0; i<size; i++) + XtFree(strings[i]); + } + static void ReportUnboundActions(tm, stateTable) TMRec* tm; XtTranslations stateTable; { Cardinal num_unbound; char message[10000]; register Cardinal num_chars; register Cardinal i; num_unbound = 0;