1 /*
2  * Copyright (c) 1998 by The XFree86 Project, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  * Except as contained in this notice, the name of the XFree86 Project shall
23  * not be used in advertising or otherwise to promote the sale, use or other
24  * dealings in this Software without prior written authorization from the
25  * XFree86 Project.
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <X11/Xmd.h>
36 #include <X11/IntrinsicP.h>
37 #include <X11/StringDefs.h>
38 #include <X11/CoreP.h>
39 #include <X11/Constraint.h>
40 #include <X11/Xmu/CharSet.h>
41 #include <X11/Xfuncs.h>
42 #include "Private.h"
43 
44 
45 #ifndef OLDXAW
46 
47 /*
48  * Definitions
49  */
50 #define ERROR   -2
51 #define END     -1
52 #define BOOLEAN 0
53 #define AND     '&'
54 #define OR      '|'
55 #define XOR     '^'
56 #define NOT     '~'
57 #define LP      '('
58 #define RP      ')'
59 
60 /*
61  * Types
62  */
63 /* boolean expressions */
64 typedef struct _XawEvalInfo {
65   Widget widget;
66   XawActionResList *rlist;
67   XawActionVarList *vlist;
68   XawParseBooleanProc parse_proc;
69   XEvent *event;
70   char *cp, *lp;
71   int token;
72   Bool value;
73 } XawEvalInfo;
74 
75 /* resources */
76 typedef struct _XawActionRes {
77   XrmQuark qname;
78   XrmQuark qtype;
79   Cardinal size;
80 } XawActionRes;
81 
82 struct _XawActionResList {
83   WidgetClass widget_class;
84   XawActionRes **resources;
85   Cardinal num_common_resources;
86   Cardinal num_constraint_resources;
87 };
88 
89 /* variables */
90 typedef struct _XawActionVar {
91   XrmQuark qname;
92   XrmQuark qvalue;
93 } XawActionVar;
94 
95 struct _XawActionVarList {
96   Widget widget;
97   Cardinal num_variables;
98   XawActionVar **variables;
99 };
100 
101 /*
102  * Private methods
103  */
104 /* expressions */
105 static int get_token(XawEvalInfo*);
106 static Bool expr(XawEvalInfo*);
107 static Bool and(XawEvalInfo*);
108 static Bool prim(XawEvalInfo*);
109 
110 /* resources */
111 static String XawConvertActionRes(XawActionResList*, Widget w, String);
112 
113 static char * _XawEscapeActionVarValue(String);
114 static char * _XawUnescapeActionVarValue(String);
115 static XawActionResList *_XawCreateActionResList(WidgetClass);
116 static XawActionResList *_XawFindActionResList(WidgetClass);
117 static void _XawBindActionResList(XawActionResList*);
118 static XawActionRes *_XawFindActionRes(XawActionResList*, Widget, String);
119 static int qcmp_action_resource_list(_Xconst void*, _Xconst void*);
120 static int bcmp_action_resource_list(_Xconst void*, _Xconst void*);
121 static int qcmp_action_resource(_Xconst void*, _Xconst void*);
122 static int bcmp_action_resource(_Xconst void*, _Xconst void*);
123 
124 /* variables */
125 static String XawConvertActionVar(XawActionVarList*, String);
126 static void XawDeclareActionVar(XawActionVarList*, String, String);
127 
128 static XawActionVarList *_XawCreateActionVarList(Widget);
129 static XawActionVarList *_XawFindActionVarList(Widget);
130 static XawActionVar *_XawCreateActionVar(XawActionVarList*, String);
131 static XawActionVar *_XawFindActionVar(XawActionVarList*, String);
132 static void _XawDestroyActionVarList(Widget, XtPointer, XtPointer);
133 
134 /*
135  * Initialization
136  */
137 /* resources */
138 static XawActionResList **resource_list;
139 static Cardinal num_resource_list;
140 
141 /* variables */
142 static XawActionVarList **variable_list;
143 static Cardinal num_variable_list;
144 
145 /*
146  * Implementation
147  */
148 /*
149  * Start of Boolean Expression Evaluation Implementation Code
150  */
151 Bool
XawParseBoolean(Widget w,String param,XEvent * event,Bool * succed)152 XawParseBoolean(Widget w, String param, XEvent *event, Bool *succed)
153 {
154   char *tmp = (char *)param;
155   int value;
156 
157   if (!param)
158     return (False);
159 
160   value = (int)strtod(param, &tmp);
161   if (*tmp == '\0')
162     return (value);
163 
164   if (XmuCompareISOLatin1(param, "true") == 0
165       || XmuCompareISOLatin1(param, "yes") == 0
166       || XmuCompareISOLatin1(param, "on") == 0
167       || XmuCompareISOLatin1(param, "in") == 0
168       || XmuCompareISOLatin1(param, "up") == 0)
169     return (True);
170   else if (XmuCompareISOLatin1(param, "false") == 0
171 	  || XmuCompareISOLatin1(param, "no") == 0
172 	  || XmuCompareISOLatin1(param, "off") == 0
173 	  || XmuCompareISOLatin1(param, "out") == 0
174 	  || XmuCompareISOLatin1(param, "down") == 0)
175       ;
176   else if (XmuCompareISOLatin1(param, "my") == 0
177 	   || XmuCompareISOLatin1(param, "mine") == 0)
178     return (event->xany.window == XtWindow(w));
179   else if (XmuCompareISOLatin1(param, "faked") == 0)
180     return (event->xany.send_event != 0);
181   else
182     *succed = False;
183 
184   return (False);
185 }
186 
187 Bool
XawBooleanExpression(Widget w,String param,XEvent * event)188 XawBooleanExpression(Widget w, String param, XEvent *event)
189 {
190   XawEvalInfo info;
191   Bool retval;
192 
193   if (!param)
194     return (False);
195 
196   info.widget = w;
197 
198   info.rlist = XawGetActionResList(XtClass(w));
199   info.vlist = XawGetActionVarList(w);
200 
201   /*
202    * Verify widget class, in case we will allow the parse proc procedure
203    * as a widget class element, or if we allow overriding the default
204    * parse boolean proc.
205    */
206   info.parse_proc = XawParseBoolean;
207 
208   info.event = event;
209   info.cp = info.lp = (char *)param;
210 
211 #ifdef DIAGNOSTIC
212   fprintf(stderr, "(*) Parsing expression \"%s\"\n", param);
213 #endif
214 
215   (void)get_token(&info);
216   if (info.token == ERROR)
217     return (False);
218   retval = expr(&info);
219 
220   return (info.token != ERROR ? retval : False);
221 }
222 
223 static int
get_token(XawEvalInfo * info)224 get_token(XawEvalInfo *info)
225 {
226   int ch;
227   char *p, name[256];
228 
229   info->lp = info->cp;
230 
231   /*COSTCOND*/
232   while (1)	/* eat white spaces */
233     {
234       ch = *info->cp++;
235       if (isspace(ch))
236 	continue;
237       break;
238     }
239 
240   switch (ch)
241     {
242     case AND: case OR: case XOR: case NOT: case LP: case RP:
243       return (info->token = ch);
244     }
245 
246   /* It's a symbol name, resolve it. */
247   if (ch == XAW_PRIV_VAR_PREFIX || isalnum(ch) || ch == '_' || ch == '\\')
248     {
249       Bool succed = True;
250 
251       p = info->cp - 1;
252 
253       while ((ch = *info->cp) && (isalnum(ch) || ch == '_'))
254 	++info->cp;
255 
256       strncpy(name, p, XawMin((int)sizeof(name) - 1,
257 			      (unsigned)(info->cp - p)));
258       name[XawMin((int)sizeof(name) -1, info->cp - p)] = '\0';
259 
260       if (name[0] == XAW_PRIV_VAR_PREFIX)
261 	{
262 	  String value = XawConvertActionVar(info->vlist, name);
263 
264 	  info->value = info->parse_proc(info->widget, value, info->event,
265 					 &succed) & 1;
266 	}
267       else
268 	{
269 	  info->value = info->parse_proc(info->widget, name, info->event,
270 					 &succed) & 1;
271 	  if (!succed)
272 	    {
273 	      String value =
274 		XawConvertActionRes(info->rlist, info->widget,
275 				    name[0] == '\\' ? &name[1] : name);
276 	      /* '\\' may have been used to escape a resource name.
277 	       */
278 
279 	      succed = True;
280 	      info->value = info->parse_proc(info->widget, value, info->event,
281 					     &succed) & 1;
282 	      if (!succed)
283 		{
284 		  /* not a numeric value or boolean string */
285 		  info->value = True;
286 		  succed = True;
287 		}
288 	    }
289 	}
290       if (succed)
291 	return (info->token = BOOLEAN);
292     }
293   else if (ch == '\0')
294     return (info->token = END);
295 
296   {
297     char msg[256];
298 
299     snprintf(msg, sizeof(msg), "evaluate(): bad token \"%c\" at \"%s\"",
300 	     ch, info->cp - 1);
301 
302     XtAppWarning(XtWidgetToApplicationContext(info->widget), msg);
303   }
304 
305   return (info->token = ERROR);
306 }
307 
308 static Bool
expr(XawEvalInfo * info)309 expr(XawEvalInfo *info)
310 {
311   Bool left = and(info);
312 
313   for (;;)
314     switch (info->token)
315       {
316       case OR:
317 	(void)get_token(info);
318 	left |= and(info);
319 	break;
320       case XOR:
321 	(void)get_token(info);
322 	left ^= and(info);
323 	break;
324       default:
325 	return (left);
326       }
327   /* NOTREACHED */
328 }
329 
330 static Bool
and(XawEvalInfo * info)331 and(XawEvalInfo *info)
332 {
333   Bool left = prim(info);
334 
335   for (;;)
336     switch (info->token)
337       {
338       case AND:
339 	(void)get_token(info);
340 	left &= prim(info);
341 	break;
342       default:
343 	return (left);
344       }
345   /* NOTREACHED */
346 }
347 
348 static Bool
prim(XawEvalInfo * info)349 prim(XawEvalInfo *info)
350 {
351   Bool e;
352 
353   switch (info->token)
354     {
355     case BOOLEAN:
356       e = info->value;
357       (void)get_token(info);
358       return (e);
359     case NOT:
360       (void)get_token(info);
361       return (!prim(info));
362     case LP:
363       (void)get_token(info);
364       e = expr(info);
365       if (info->token != RP)
366 	{
367 	  char msg[256];
368 
369 	  info->token = ERROR;
370 	  snprintf(msg, sizeof(msg), "evaluate(): expecting ), at \"%s\"",
371 		   info->lp);
372 	  XtAppWarning(XtWidgetToApplicationContext(info->widget), msg);
373 	  return (False);
374 	}
375       (void)get_token(info);
376       return (e);
377     case END:
378       return (True);
379     default:
380       {
381 	char msg[256];
382 
383 	info->token = ERROR;
384 	snprintf(msg, sizeof(msg), "evaluate(): syntax error, at \"%s\"",
385 		 info->lp);
386 	XtAppWarning(XtWidgetToApplicationContext(info->widget), msg);
387       } return (False);
388     }
389   /* NOTREACHED */
390 }
391 
392 /*
393  * Start of Resources Implementation Code
394  */
395 void
XawSetValuesAction(Widget w,XEvent * event,String * params,Cardinal * num_params)396 XawSetValuesAction(Widget w, XEvent *event,
397 		   String *params, Cardinal *num_params)
398 {
399   Arg *arglist;
400   Cardinal num_args, count;
401   XawActionResList *rlist;
402   XawActionVarList *vlist;
403   XawActionRes *resource;
404   XrmValue from, to;
405   String value;
406   char  c_1;
407   short c_2;
408   int   c_4;
409 #ifdef LONG64
410   long  c_8;
411 #endif
412 
413   if (!(*num_params & 1))
414     {
415       XawPrintActionErrorMsg("set-values", w, params, num_params);
416       return;
417     }
418 
419   if (!XawBooleanExpression(w, params[0], event))
420     return;
421 
422   rlist = XawGetActionResList(XtClass(w));
423   vlist = XawGetActionVarList(w);
424 
425   num_args = 0;
426   arglist = (Arg *)XtMalloc((Cardinal)sizeof(Arg) * ((*num_params) >> 1));
427 
428   for (count = 1; count < *num_params; count += 2)
429     {
430       if ((resource = _XawFindActionRes(rlist, w, params[count])) == NULL)
431 	{
432 	  char msg[256];
433 
434 	  snprintf(msg, sizeof(msg), "set-values(): bad resource name \"%s\"",
435 		   params[count]);
436 	  XtAppWarning(XtWidgetToApplicationContext(w), msg);
437           continue;
438 	}
439       value = XawConvertActionVar(vlist, params[count + 1]);
440       from.size = (Cardinal) strlen(value) + 1;
441       from.addr = (char *)value;
442       to.size = resource->size;
443       switch (to.size)
444 	{
445 	case 1: to.addr = (XPointer)&c_1; break;
446 	case 2: to.addr = (XPointer)&c_2; break;
447 	case 4: to.addr = (XPointer)&c_4; break;
448 #ifdef LONG64
449 	case 8: to.addr = (XPointer)&c_8; break;
450 #endif
451 	default:
452 	  {
453 	    char msg[256];
454 
455 	    snprintf(msg, sizeof(msg),
456 		     "set-values(): bad resource size for \"%s\"",
457 		     params[count]);
458 	    XtAppWarning(XtWidgetToApplicationContext(w), msg);
459 	  } continue;
460 	}
461 
462       if (strcmp(XtRString, XrmQuarkToString(resource->qtype)) == 0)
463 #ifdef LONG64
464 	c_8 = (long)from.addr;
465 #else
466 	c_4 = (int)from.addr;
467 #endif
468       else if (!XtConvertAndStore(w, XtRString, &from,
469 				  XrmQuarkToString(resource->qtype), &to))
470 	continue;
471 
472       switch (to.size)
473 	{
474 	case 1:
475 	  XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_1);
476 	  break;
477 	case 2:
478 	  XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_2);
479 	  break;
480 	case 4:
481 	  XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_4);
482 	  break;
483 #ifdef LONG64
484 	case 8:
485 	  XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_8);
486 	  break;
487 #endif
488 	}
489       ++num_args;
490     }
491 
492   XtSetValues(w, arglist, num_args);
493   XtFree((char *)arglist);
494 }
495 
496 void
XawGetValuesAction(Widget w,XEvent * event,String * params,Cardinal * num_params)497 XawGetValuesAction(Widget w, XEvent *event,
498 		   String *params, Cardinal *num_params)
499 {
500   XawActionResList *rlist;
501   XawActionVarList *vlist;
502   String value;
503   Cardinal count;
504 
505   if (!(*num_params & 1))
506     {
507       XawPrintActionErrorMsg("get-values", w, params, num_params);
508       return;
509     }
510   if (!XawBooleanExpression(w, params[0], event))
511     return;
512 
513   rlist = XawGetActionResList(XtClass(w));
514   vlist = XawGetActionVarList(w);
515 
516   for (count = 1; count < *num_params; count += 2)
517     {
518       if ((value = XawConvertActionRes(rlist, w, params[count + 1])) == NULL)
519 	continue;
520       XawDeclareActionVar(vlist, params[count], value);
521     }
522 }
523 
524 void
XawDeclareAction(Widget w,XEvent * event,String * params,Cardinal * num_params)525 XawDeclareAction(Widget w, XEvent *event,
526 		 String *params, Cardinal *num_params)
527 {
528   XawActionVarList *vlist;
529   Cardinal count;
530 
531   if (!(*num_params & 1))
532     {
533       XawPrintActionErrorMsg("declare", w, params, num_params);
534       return;
535     }
536   if (!XawBooleanExpression(w, params[0], event))
537     return;
538 
539   vlist = XawGetActionVarList(w);
540 
541   for (count = 1; count < *num_params; count += 2)
542     XawDeclareActionVar(vlist, params[count], params[count + 1]);
543 }
544 
545 void
XawCallProcAction(Widget w,XEvent * event,String * params,Cardinal * num_params)546 XawCallProcAction(Widget w, XEvent *event,
547 		  String *params, Cardinal *num_params)
548 {
549   String *args;
550   Cardinal num_args;
551 
552   if (*num_params < 2)
553     {
554       XawPrintActionErrorMsg("call-proc", w, params, num_params);
555       return;
556     }
557 
558   if (*num_params && !XawBooleanExpression(w, params[0], event))
559     return;
560 
561   if (*num_params > 2)
562     {
563       args = &params[2];
564       num_args = *num_params - 2;
565     }
566   else
567     {
568       args = NULL;
569       num_args = 0;
570     }
571 
572   XtCallActionProc(w, params[1], event, args, num_args);
573 }
574 
575 static String
XawConvertActionRes(XawActionResList * list,Widget w,String name)576 XawConvertActionRes(XawActionResList *list, Widget w, String name)
577 {
578   XawActionRes *resource;
579   XrmValue from, to;
580   Arg arg;
581   char  c_1;
582   short c_2;
583   int   c_4;
584 #ifdef LONG64
585   long  c_8;
586 #endif
587 
588   if ((resource = _XawFindActionRes(list, w, name)) == NULL)
589     {
590       char msg[256];
591 
592       snprintf(msg, sizeof(msg), "convert(): bad resource name \"%s\"",
593 	       name);
594       XtAppWarning(XtWidgetToApplicationContext(w), msg);
595       return (NULL);
596     }
597 
598   from.size = resource->size;
599   switch (from.size)
600     {
601     case 1:
602       XtSetArg(arg, XrmQuarkToString(resource->qname),
603 	       from.addr = (XPointer)&c_1);
604       break;
605     case 2:
606       XtSetArg(arg, XrmQuarkToString(resource->qname),
607                from.addr = (XPointer)&c_2);
608       break;
609     case 4:
610       XtSetArg(arg, XrmQuarkToString(resource->qname),
611                from.addr = (XPointer)&c_4);
612       break;
613 #ifdef LONG64
614     case 8:
615       XtSetArg(arg, XrmQuarkToString(resource->qname),
616 	       from.addr = (XPointer)&c_8);
617       break;
618 #endif
619     default:
620       {
621         char msg[256];
622 
623         snprintf(msg, sizeof(msg), "convert(): bad resource size for \"%s\"",
624 		 name);
625 	XtAppWarning(XtWidgetToApplicationContext(w), name);
626       } return (NULL);
627     }
628 
629   XtGetValues(w, &arg, 1);
630   to.size = sizeof(String);
631   to.addr = NULL;
632 
633   if (strcmp(XtRString, XrmQuarkToString(resource->qtype)) == 0)
634     to.addr = *(char **)from.addr;
635   else if (!XtConvertAndStore(w, XrmQuarkToString(resource->qtype),
636 			      &from, XtRString, &to))
637     return (NULL);
638 
639   return ((String)to.addr);
640 }
641 
642 void
XawPrintActionErrorMsg(String action_name,Widget w,String * params,Cardinal * num_params)643 XawPrintActionErrorMsg(String action_name, Widget w,
644 		       String *params, Cardinal *num_params)
645 {
646   char msg[1024];
647   unsigned int size, idx;
648 
649   size = (unsigned)snprintf(msg,
650 			    sizeof(msg),
651 			    "%s(): bad number of parameters.\n\t(",
652 			    action_name);
653 
654   idx = 0;
655   while (idx < *num_params - 1 && size < sizeof(msg))
656     size += (unsigned)snprintf(&msg[size], sizeof(msg) - size, "%s, ",
657 			       params[idx++]);
658   if (*num_params)
659     snprintf(&msg[size], sizeof(msg) - size, "%s)", params[idx]);
660   else
661     snprintf(&msg[size], sizeof(msg) - size, ")");
662   XtAppWarning(XtWidgetToApplicationContext(w), msg);
663 }
664 
665 XawActionResList *
XawGetActionResList(WidgetClass wc)666 XawGetActionResList(WidgetClass wc)
667 {
668   XawActionResList *list;
669 
670   list = _XawFindActionResList(wc);
671 
672   if (!list)
673     list = _XawCreateActionResList(wc);
674 
675   return (list);
676 }
677 
678 static int
qcmp_action_resource_list(register _Xconst void * left,register _Xconst void * right)679 qcmp_action_resource_list(register _Xconst void *left,
680 			  register _Xconst void *right)
681 {
682   return (int)((char *)((*(XawActionResList **)left)->widget_class) -
683 	       (char *)((*(XawActionResList **)right)->widget_class));
684 }
685 
686 static XawActionResList *
_XawCreateActionResList(WidgetClass wc)687 _XawCreateActionResList(WidgetClass wc)
688 {
689   XawActionResList *list;
690 
691   list = (XawActionResList *)XtMalloc((Cardinal)sizeof(XawActionResList));
692   list->widget_class = wc;
693   list->num_common_resources = list->num_constraint_resources = 0;
694   list->resources = NULL;
695 
696   if (!resource_list)
697     {
698       num_resource_list = 1;
699       resource_list = (XawActionResList **)XtMalloc((Cardinal)sizeof(XawActionResList*));
700       resource_list[0] = list;
701     }
702   else
703     {
704       ++num_resource_list;
705       resource_list = (XawActionResList **)XtRealloc((char *)resource_list,
706 						     (Cardinal) sizeof(XawActionResList*)
707 						     * num_resource_list);
708       resource_list[num_resource_list - 1] = list;
709       qsort(resource_list, num_resource_list, sizeof(XawActionResList*),
710 	    qcmp_action_resource_list);
711     }
712 
713   _XawBindActionResList(list);
714 
715   return (list);
716 }
717 
718 static int
bcmp_action_resource_list(register _Xconst void * wc,register _Xconst void * list)719 bcmp_action_resource_list(register _Xconst void *wc,
720 			  register _Xconst void *list)
721 {
722   return (int)((char *)wc
723              - (char *)((*(XawActionResList **)list)->widget_class));
724 }
725 
726 static XawActionResList *
_XawFindActionResList(WidgetClass wc)727 _XawFindActionResList(WidgetClass wc)
728 {
729   XawActionResList **list;
730 
731   if (!resource_list)
732     return (NULL);
733 
734   list = (XawActionResList **)bsearch(wc, resource_list,
735 				      num_resource_list,
736 				      sizeof(XawActionResList*),
737 				      bcmp_action_resource_list);
738 
739   return (list ? *list : NULL);
740 }
741 
742 static int
qcmp_action_resource(register _Xconst void * left,register _Xconst void * right)743 qcmp_action_resource(register _Xconst void *left,
744 		     register _Xconst void *right)
745 {
746   return (strcmp(XrmQuarkToString((*(XawActionRes **)left)->qname),
747 		 XrmQuarkToString((*(XawActionRes **)right)->qname)));
748 }
749 
750 static void
_XawBindActionResList(XawActionResList * list)751 _XawBindActionResList(XawActionResList *list)
752 {
753   XtResourceList xt_list, cons_list;
754   Cardinal i, num_xt, num_cons;
755 
756 #ifdef DIAGNOSTIC
757   fprintf(stderr, "(*) Creating resource list for class \'%s\'\n---------\n",
758 	  list->widget_class->core_class.class_name);
759 #endif
760 
761   XtGetResourceList(list->widget_class, &xt_list, &num_xt);
762   XtGetConstraintResourceList(list->widget_class, &cons_list, &num_cons);
763   list->num_common_resources = num_xt;
764   list->num_constraint_resources = num_cons;
765 
766   list->resources = (XawActionRes **)
767     XtMalloc((Cardinal)sizeof(XawActionRes*) * (num_xt + num_cons));
768 
769 #ifdef DIAGNOSTIC
770   fprintf(stderr, "Common resources\n---\n");
771 #endif
772 
773   for (i = 0; i < num_xt; i++)
774     {
775       list->resources[i] = (XawActionRes *)XtMalloc((Cardinal)sizeof(XawActionRes));
776       list->resources[i]->qname =
777 	XrmPermStringToQuark(xt_list[i].resource_name);
778       list->resources[i]->qtype =
779 	XrmPermStringToQuark(xt_list[i].resource_type);
780       list->resources[i]->size = xt_list[i].resource_size;
781 
782 #ifdef DIAGNOSTIC
783       fprintf(stderr, "%-20s\t%-20s\t(%d)\n",
784 	      xt_list[i].resource_name,
785 	      xt_list[i].resource_type,
786 	      xt_list[i].resource_size);
787 #endif
788     }
789 
790 #ifdef DIAGNOSTIC
791   fprintf(stderr, "---\nContraint resources\n---");
792 #endif
793 
794   for (; i < num_xt + num_cons; i++)
795     {
796       list->resources[i] = (XawActionRes *)XtMalloc((Cardinal)sizeof(XawActionRes));
797       list->resources[i]->qname =
798 	XrmPermStringToQuark(cons_list[i - num_xt].resource_name);
799       list->resources[i]->qtype =
800 	XrmPermStringToQuark(cons_list[i - num_xt].resource_type);
801       list->resources[i]->size = cons_list[i - num_xt].resource_size;
802 
803 #ifdef DIAGNOSTIC
804       fprintf(stderr, "%-20s\t%-20s\t(%d)\n",
805 	      cons_list[i - num_xt].resource_name,
806 	      cons_list[i - num_xt].resource_type,
807 	      cons_list[i - num_xt].resource_size);
808 #endif
809     }
810 
811 #ifdef DIAGNOSTIC
812   fprintf(stderr, "---\n");
813 #endif
814 
815   XtFree((char *)xt_list);
816   if (cons_list)
817     XtFree((char *)cons_list);
818 
819   qsort(list->resources, list->num_common_resources, sizeof(XawActionRes*),
820 	qcmp_action_resource);
821   if (num_cons)
822     qsort(&list->resources[num_xt], list->num_constraint_resources,
823 	  sizeof(XawActionRes*), qcmp_action_resource);
824 }
825 
826 static int
bcmp_action_resource(register _Xconst void * string,register _Xconst void * resource)827 bcmp_action_resource(register _Xconst void *string,
828 		     register _Xconst void *resource)
829 {
830   return (strcmp((String)string,
831 		 XrmQuarkToString((*(XawActionRes **)resource)->qname)));
832 }
833 
834 static XawActionRes *
_XawFindActionRes(XawActionResList * list,Widget detail,String name)835 _XawFindActionRes(XawActionResList *list, Widget detail, String name)
836 {
837   XawActionRes **res;
838 
839   if (!list->resources)
840     return (NULL);
841 
842   res = (XawActionRes **)bsearch(name, list->resources,
843 				 list->num_common_resources,
844 				 sizeof(XawActionRes*), bcmp_action_resource);
845 
846   if (!res && XtParent(detail)
847       && XtIsSubclass(XtParent(detail), constraintWidgetClass))
848     {
849       XawActionResList *cons = XawGetActionResList(XtClass(XtParent(detail)));
850 
851       if (cons)
852 	res = (XawActionRes **)
853 	  bsearch(name, &cons->resources[cons->num_common_resources],
854 		  cons->num_constraint_resources,
855 		  sizeof(XawActionRes*), bcmp_action_resource);
856     }
857 
858   return (res ? *res : NULL);
859 }
860 
861 /*
862  * Start of Variables Implementation Code
863  */
864 /* For speed, only does memory allocation when really required */
865 static char *
_XawEscapeActionVarValue(String value)866 _XawEscapeActionVarValue(String value)
867 {
868   char * escape;
869 
870   if (value[0] == '$' || value[0] == '\\')
871     {
872       escape = XtMalloc((Cardinal)strlen(value) + 2);
873       escape[0] = '\\';
874       strcpy(escape + 1, value);
875       return (escape);
876     }
877   return (NULL);
878 }
879 
880 /* For speed, only does memory allocation when really required */
881 static char *
_XawUnescapeActionVarValue(String value)882 _XawUnescapeActionVarValue(String value)
883 {
884   char * unescape;
885 
886   if (value[0] == '\\')
887     {
888       unescape = XtMalloc((Cardinal)strlen(value));
889       strcpy(unescape, value + 1);
890       return (unescape);
891     }
892   return (NULL);
893 }
894 
895 static void
XawDeclareActionVar(XawActionVarList * list,String name,String value)896 XawDeclareActionVar(XawActionVarList *list, String name, String value)
897 {
898   XawActionVar *variable;
899   char * escape = NULL;
900 
901   if (name[0] != XAW_PRIV_VAR_PREFIX)
902     {
903       char msg[256];
904 
905       snprintf(msg, sizeof(msg),
906 	       "declare(): variable name must begin with \'%c\', at %s = %s",
907 	       XAW_PRIV_VAR_PREFIX, name, value);
908       XtAppWarning(XtWidgetToApplicationContext(list->widget), msg);
909       return;
910     }
911   variable = _XawFindActionVar(list, name);
912   if (!variable)
913     variable = _XawCreateActionVar(list, name);
914   if (value)
915     escape = _XawEscapeActionVarValue(value);
916 
917   if (variable->qvalue)
918     {
919       String val = escape ? escape : value;
920 
921       if (strcmp(XrmQuarkToString(variable->qvalue), val) == 0)
922 	{
923 	  if (escape)
924 	    XtFree(escape);
925 	  return;
926 	}
927     }
928   variable->qvalue = (escape ? XrmStringToQuark(escape) :
929 		      (value ? XrmStringToQuark(value) : NULLQUARK));
930   if (escape)
931     XtFree(escape);
932 }
933 
934 static String
XawConvertActionVar(XawActionVarList * list,String name)935 XawConvertActionVar(XawActionVarList *list, String name)
936 {
937   XawActionVar *variable;
938   char * unescape;
939   XrmQuark quark;
940 
941   if (name[0] != XAW_PRIV_VAR_PREFIX)
942     return (name);
943 
944   variable = _XawFindActionVar(list, name);
945   if (!variable || variable->qvalue == NULLQUARK)
946     return (name);
947   unescape = _XawUnescapeActionVarValue(XrmQuarkToString(variable->qvalue));
948   if (unescape)
949     {
950       quark = XrmStringToQuark(unescape);
951       XtFree(unescape);
952     }
953   else
954     quark = variable->qvalue;
955 
956   return (XrmQuarkToString(quark));
957 }
958 
959 XawActionVarList *
XawGetActionVarList(Widget w)960 XawGetActionVarList(Widget w)
961 {
962   XawActionVarList *list;
963 
964   list = _XawFindActionVarList(w);
965   if (!list)
966     list = _XawCreateActionVarList(w);
967 
968   return (list);
969 }
970 
971 static int
qcmp_action_variable_list(register _Xconst void * left,register _Xconst void * right)972 qcmp_action_variable_list(register _Xconst void *left,
973 			  register _Xconst void *right)
974 {
975   return (int)((char *)((*(XawActionVarList **)left)->widget) -
976 	       (char *)((*(XawActionVarList **)right)->widget));
977 }
978 
979 static XawActionVarList *
_XawCreateActionVarList(Widget w)980 _XawCreateActionVarList(Widget w)
981 {
982   XawActionVarList *list;
983 
984 #ifdef DIAGNOSTIC
985   fprintf(stderr, "(*) Creating action variable list for widget %s (%p)\n",
986 	  XtName(w), w);
987 #endif
988 
989   list = (XawActionVarList *)XtMalloc((Cardinal)sizeof(XawActionVarList));
990   list->widget = w;
991   list->num_variables = 0;
992   list->variables = NULL;
993 
994   if (!variable_list)
995     {
996       num_variable_list = 1;
997       variable_list = (XawActionVarList **)XtMalloc((Cardinal)sizeof(XawActionVarList*));
998       variable_list[0] = list;
999     }
1000   else
1001     {
1002       ++num_variable_list;
1003       variable_list = (XawActionVarList **)
1004 	XtRealloc((char *)variable_list,
1005 		  (Cardinal)sizeof(XawActionVarList *) * num_variable_list);
1006       variable_list[num_variable_list - 1] = list;
1007       qsort(variable_list, num_variable_list, sizeof(XawActionVarList*),
1008 	    qcmp_action_variable_list);
1009     }
1010 
1011   XtAddCallback(w, XtNdestroyCallback, _XawDestroyActionVarList,
1012 		(XtPointer)list);
1013 
1014   return (list);
1015 }
1016 
1017 static int
bcmp_action_variable_list(register _Xconst void * widget,register _Xconst void * list)1018 bcmp_action_variable_list(register _Xconst void *widget,
1019 			  register _Xconst void *list)
1020 {
1021   return (int)((char *)widget
1022              - (char *)((*(XawActionVarList **)list)->widget));
1023 }
1024 
1025 static XawActionVarList *
_XawFindActionVarList(Widget w)1026 _XawFindActionVarList(Widget w)
1027 {
1028   XawActionVarList **list;
1029 
1030   if (!num_variable_list)
1031     return (NULL);
1032 
1033   list = (XawActionVarList **)bsearch(w, variable_list, num_variable_list,
1034 				      sizeof(XawActionVarList*),
1035 				      bcmp_action_variable_list);
1036 
1037   return (list ? *list : NULL);
1038 }
1039 
1040 static int
qcmp_action_variable(register _Xconst void * left,register _Xconst void * right)1041 qcmp_action_variable(register _Xconst void *left,
1042 		     register _Xconst void *right)
1043 {
1044   return (strcmp(XrmQuarkToString((*(XawActionVar **)left)->qname),
1045 		 XrmQuarkToString((*(XawActionVar **)right)->qname)));
1046 }
1047 
1048 static XawActionVar *
_XawCreateActionVar(XawActionVarList * list,String name)1049 _XawCreateActionVar(XawActionVarList *list, String name)
1050 {
1051   XawActionVar *variable;
1052 
1053 #ifdef DIAGNOSTIC
1054   fprintf(stderr, "(*) Creating action variable '%s' for widget %s (%p)\n",
1055 	  name, XtName(list->widget), list->widget);
1056 #endif
1057 
1058   variable = (XawActionVar *)XtMalloc((Cardinal)sizeof(XawActionVar));
1059   variable->qname = XrmStringToQuark(name);
1060   variable->qvalue = NULLQUARK;
1061 
1062   if (!list->variables)
1063     {
1064       list->num_variables = 1;
1065       list->variables = (XawActionVar **)XtMalloc((Cardinal)sizeof(XawActionVar*));
1066       list->variables[0] = variable;
1067     }
1068   else
1069     {
1070       ++list->num_variables;
1071       list->variables = (XawActionVar **)XtRealloc((char *)list->variables,
1072 						   (Cardinal) sizeof(XawActionVar *) *
1073 						   list->num_variables);
1074       list->variables[list->num_variables - 1] = variable;
1075       qsort(list->variables, list->num_variables, sizeof(XawActionVar*),
1076 	    qcmp_action_variable);
1077     }
1078   return (variable);
1079 }
1080 
1081 static int
bcmp_action_variable(register _Xconst void * string,register _Xconst void * variable)1082 bcmp_action_variable(register _Xconst void *string,
1083 		     register _Xconst void *variable)
1084 {
1085   return (strcmp((String)string,
1086 		 XrmQuarkToString((*(XawActionVar **)variable)->qname)));
1087 }
1088 
1089 static XawActionVar *
_XawFindActionVar(XawActionVarList * list,String name)1090 _XawFindActionVar(XawActionVarList *list, String name)
1091 {
1092   XawActionVar **var;
1093 
1094   if (!list->variables)
1095     return (NULL);
1096 
1097   var = (XawActionVar **)bsearch(name, list->variables, list->num_variables,
1098 				 sizeof(XawActionVar*), bcmp_action_variable);
1099 
1100   return (var ? *var : NULL);
1101 }
1102 
1103 /*ARGSUSED*/
1104 static void
_XawDestroyActionVarList(Widget w,XtPointer client_data,XtPointer call_data _X_UNUSED)1105 _XawDestroyActionVarList(Widget w, XtPointer client_data, XtPointer call_data _X_UNUSED)
1106 {
1107   XawActionVarList *list = (XawActionVarList *)client_data;
1108   Cardinal i;
1109 
1110   for (i = 0; i < num_variable_list; i++)
1111     if (variable_list[i] == list)
1112       break;
1113   if (i >= num_variable_list || list->widget != w
1114       || variable_list[i]->widget != w)
1115     {
1116       XtWarning("destroy-variable-list(): Bad widget argument.");
1117       return;
1118     }
1119   if (--num_variable_list > 0)
1120     {
1121       memmove(&variable_list[i], &variable_list[i + 1],
1122 	    (num_variable_list - i) * sizeof(XawActionVarList *));
1123       variable_list = (XawActionVarList **)
1124 	XtRealloc((char *)variable_list, (Cardinal) sizeof(XawActionVarList *) *
1125 		  num_variable_list);
1126     }
1127   else
1128     {
1129       XtFree((char *)variable_list);
1130       variable_list = NULL;
1131     }
1132 
1133   XtFree((char *)list->variables);
1134   XtFree((char *)list);
1135 }
1136 
1137 #endif /* OLDXAW */
1138