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 = ¶ms[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