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