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 */ 64typedef 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 */ 76typedef struct _XawActionRes { 77 XrmQuark qname; 78 XrmQuark qtype; 79 Cardinal size; 80} XawActionRes; 81 82struct _XawActionResList { 83 WidgetClass widget_class; 84 XawActionRes **resources; 85 Cardinal num_common_resources; 86 Cardinal num_constraint_resources; 87}; 88 89/* variables */ 90typedef struct _XawActionVar { 91 XrmQuark qname; 92 XrmQuark qvalue; 93} XawActionVar; 94 95struct _XawActionVarList { 96 Widget widget; 97 Cardinal num_variables; 98 XawActionVar **variables; 99}; 100 101/* 102 * Private methods 103 */ 104/* expressions */ 105static int get_token(XawEvalInfo*); 106static Bool expr(XawEvalInfo*); 107static Bool and(XawEvalInfo*); 108static Bool prim(XawEvalInfo*); 109 110/* resources */ 111static String XawConvertActionRes(XawActionResList*, Widget w, String); 112 113static char * _XawEscapeActionVarValue(String); 114static char * _XawUnescapeActionVarValue(String); 115static XawActionResList *_XawCreateActionResList(WidgetClass); 116static XawActionResList *_XawFindActionResList(WidgetClass); 117static void _XawBindActionResList(XawActionResList*); 118static XawActionRes *_XawFindActionRes(XawActionResList*, Widget, String); 119static int qcmp_action_resource_list(_Xconst void*, _Xconst void*); 120static int bcmp_action_resource_list(_Xconst void*, _Xconst void*); 121static int qcmp_action_resource(_Xconst void*, _Xconst void*); 122static int bcmp_action_resource(_Xconst void*, _Xconst void*); 123 124/* variables */ 125static String XawConvertActionVar(XawActionVarList*, String); 126static void XawDeclareActionVar(XawActionVarList*, String, String); 127 128static XawActionVarList *_XawCreateActionVarList(Widget); 129static XawActionVarList *_XawFindActionVarList(Widget); 130static XawActionVar *_XawCreateActionVar(XawActionVarList*, String); 131static XawActionVar *_XawFindActionVar(XawActionVarList*, String); 132static void _XawDestroyActionVarList(Widget, XtPointer, XtPointer); 133 134/* 135 * Initialization 136 */ 137/* resources */ 138static XawActionResList **resource_list; 139static Cardinal num_resource_list; 140 141/* variables */ 142static XawActionVarList **variable_list; 143static Cardinal num_variable_list; 144 145/* 146 * Implementation 147 */ 148/* 149 * Start of Boolean Expression Evaluation Implementation Code 150 */ 151Bool 152XawParseBoolean(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 189Bool 190XawBooleanExpression(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 227static int 228get_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 312static Bool 313expr(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 334static Bool 335and(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 352static Bool 353prim(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 */ 399void 400XawSetValuesAction(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 503void 504XawGetValuesAction(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 531void 532XawDeclareAction(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 552void 553XawCallProcAction(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 582static String 583XawConvertActionRes(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 649void 650XawPrintActionErrorMsg(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 672XawActionResList * 673XawGetActionResList(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 685static int 686qcmp_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 693static 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 725static int 726bcmp_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 733static 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 749static int 750qcmp_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 757static 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 833static int 834bcmp_action_resource(register _Xconst void *string, 835 register _Xconst void *resource) 836{ 837 return (strcmp((String)string, 838 XrmQuarkToString((*(XawActionRes **)resource)->qname))); 839} 840 841static 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 */ 872static 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 */ 886static 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 898static void 899XawDeclareActionVar(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 937static String 938XawConvertActionVar(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 962XawActionVarList * 963XawGetActionVarList(Widget w) 964{ 965 XawActionVarList *list; 966 967 list = _XawFindActionVarList(w); 968 if (!list) 969 list = _XawCreateActionVarList(w); 970 971 return (list); 972} 973 974static int 975qcmp_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 982static 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 1020static int 1021bcmp_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 1028static 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 1043static int 1044qcmp_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 1051static 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 1084static int 1085bcmp_action_variable(register _Xconst void *string, 1086 register _Xconst void *variable) 1087{ 1088 return (strcmp((String)string, 1089 XrmQuarkToString((*(XawActionVar **)variable)->qname))); 1090} 1091 1092static 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*/ 1107static 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