viewres.c revision 2464907f
1/* 2 * $XConsortium: viewres.c,v 1.74 94/04/17 20:43:24 converse Exp $ 3 * 4 * 5Copyright (c) 1989 X Consortium 6 7Permission is hereby granted, free of charge, to any person obtaining a copy 8of this software and associated documentation files (the "Software"), to deal 9in the Software without restriction, including without limitation the rights 10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11copies of the Software, and to permit persons to whom the Software is 12furnished to do so, subject to the following conditions: 13 14The above copyright notice and this permission notice shall be included in 15all copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24Except as contained in this notice, the name of the X Consortium shall not be 25used in advertising or otherwise to promote the sale, use or other dealings 26in this Software without prior written authorization from the X Consortium. 27 * * 28 * Author: Jim Fulton, MIT X Consortium 29 */ 30/* $XFree86: xc/programs/viewres/viewres.c,v 1.6 2003/05/27 22:26:58 tsi Exp $ */ 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <X11/StringDefs.h> 35#include <X11/IntrinsicP.h> 36#include <X11/Xaw/Cardinals.h> 37#include <X11/Xaw/Box.h> 38#include <X11/Xaw/Form.h> 39#include <X11/Xaw/Command.h> 40#include <X11/Xaw/MenuButton.h> 41#include <X11/Xaw/SimpleMenu.h> 42#include <X11/Xaw/Sme.h> 43#include <X11/Xaw/SmeBSB.h> 44#include <X11/Xaw/SmeLine.h> 45#include <X11/Xaw/Paned.h> 46#include <X11/Xaw/Porthole.h> 47#include <X11/Xaw/Toggle.h> 48#include <X11/Xaw/Text.h> 49#include <X11/Xaw/List.h> 50#include <X11/Xaw/Scrollbar.h> 51#include <X11/Xaw/Panner.h> 52#include <X11/Xaw/Tree.h> 53#include <X11/Xmu/Converters.h> 54#include <X11/Xmu/CharSet.h> 55#include <X11/Xmu/WidgetNode.h> 56#include <X11/Xaw/AllWidgets.h> 57 58#define widget_list XawWidgetArray /* or motif or ol or ... */ 59#define nwidgets XawWidgetCount 60 61typedef struct { 62 const char **resource_labels; /* names of res added by widget */ 63 Cardinal nnewresources; /* number res added by widget */ 64 Cardinal nnewconstraints; /* number res added by widget */ 65 Cardinal nnew; /* number new */ 66 Widget instance; /* Label widget in box in tree */ 67 Widget resource_lw; /* List widget showing resources */ 68 int selection_index; /* -1 or index into selection_list */ 69} ViewresData; 70 71#define VData(node) ((ViewresData *) (node)->data) 72 73 74#define IsShowing(node) (VData(node)->resource_lw && \ 75 XtIsManaged(VData(node)->resource_lw)) 76 77 78struct WidgetList { 79 int n_elements; 80 int max_elements; 81 XmuWidgetNode **elements; 82}; 83 84static struct WidgetList selected_list = { 0, 0, (XmuWidgetNode **) NULL }; 85 86#define INSERT_NODE(node,i) \ 87 selected_list.elements[VData(node)->selection_index = (i)] = (node) 88 89#define REMOVE_NODE(node) \ 90 selected_list.elements[VData(node)->selection_index] = \ 91 (XmuWidgetNode *) NULL; VData(node)->selection_index = (-1) 92 93static const char *ProgramName; 94static int NumberShowing = 0; 95 96static Arg sensitiveargs[2] = {{ XtNsensitive, (XtArgVal) FALSE }, 97 { XtNsensitive, (XtArgVal) TRUE }}; 98 99static const char *help_message[] = { 100 "-top name object to be top of tree", 101 "-variable show variable name instead of class name", 102 "-vertical list the tree vertically", 103 NULL 104}; 105 106static XrmOptionDescRec Options[] = { 107 { "-top", "*topObject", XrmoptionSepArg, (XPointer) NULL }, 108 { "-variable", "*showVariable", XrmoptionNoArg, (XPointer) "on" }, 109 { "-vertical", "*Tree.Gravity", XrmoptionNoArg, (XPointer) "north" } 110}; 111 112 113typedef struct { 114 char *top_object; 115 Boolean show_variable; 116} OptionsRec; 117 118static OptionsRec options; 119 120#define Offset(field) XtOffsetOf(OptionsRec, field) 121 122static XtResource Resources[] = { 123 { "topObject", "TopObject", XtRString, sizeof(char *), 124 Offset(top_object), XtRString, (XtPointer) "object" }, 125 { "showVariable", "ShowVariable", XtRBoolean, sizeof(Boolean), 126 Offset(show_variable), XtRImmediate, (XtPointer) FALSE }, 127}; 128 129#undef Offset 130 131static const char *fallback_resources[] = { 132 "*allowShellResize: true", 133 "*Porthole.top: ChainTop", 134 "*Porthole.left: ChainLeft", 135 "*Porthole.bottom: ChainBottom", 136 "*Porthole.right: ChainRight", 137 "*Porthole.resizable: on", 138 "*Panner.top: ChainTop", 139 "*Panner.left: ChainLeft", 140 "*Panner.bottom: ChainTop", 141 "*Panner.right: ChainLeft", 142 "*Panner.resizable: on", 143 "*Tree*ShapeStyle: rectangle", 144 "*Tree*Toggle*BorderWidth: 0", 145 "*Porthole*Box.BorderWidth: 0", 146 "*Porthole*Box.HSpace: 0", 147 "*Porthole*Box.VSpace: 0", 148 "*Paned*allowResize: true", 149 "*buttonbox.quit.Translations: #override \\n <Btn1Down>,<Btn1Up>: Quit() unset()", 150 "*Toggle.Translations: #augment \\n <Btn2Down>,<Btn2Up>: set() notify() Resources(toggle)", 151 NULL 152}; 153 154static void ActionQuit(Widget, XEvent *, String *, Cardinal *); 155static void ActionSetLableType(Widget, XEvent *, String *, Cardinal *); 156static void ActionSetOrientation(Widget, XEvent *, String *, Cardinal *); 157static void ActionSelect(Widget, XEvent *, String *, Cardinal *); 158static void ActionResources(Widget, XEvent *, String *, Cardinal *); 159static void set_labeltype_menu(Boolean, Boolean); 160static void set_orientation_menu(XtGravity, Boolean); 161static void build_tree(XmuWidgetNode *, Widget, Widget); 162static void set_node_labels(XmuWidgetNode *, int); 163 164static XtActionsRec viewres_actions[] = { 165 { "Quit", ActionQuit }, 166 { "SetLabelType", ActionSetLableType }, 167 { "SetOrientation", ActionSetOrientation }, 168 { "Select", ActionSelect }, 169 { "Resources", ActionResources }, 170}; 171 172static Atom wm_delete_window; 173 174#define BOOL_OFF 0 175#define BOOL_ON 1 176#define BOOL_TOGGLE 2 177 178#define VIEW_HORIZONTAL 0 179#define VIEW_VERTICAL 1 180#define VIEW_VARIABLES 2 181#define VIEW_CLASSES 3 182#define VIEW_SHOW_RESOURCES 4 183#define VIEW_HIDE_RESOURCES 5 184#define VIEW_number 6 185 186#define SELECT_NOTHING 0 187#define SELECT_ALL 1 188#define SELECT_INVERT 2 189#define SELECT_PARENT 3 190#define SELECT_ANCESTORS 4 191#define SELECT_CHILDREN 5 192#define SELECT_DESCENDANTS 6 193#define SELECT_HAS_RESOURCES 7 194#define SELECT_SHOWN_RESOURCES 8 195#define SELECT_number 9 196 197static struct _nametable { 198 const char *name; 199 int value; 200} select_nametable[] = { 201 { "nothing", SELECT_NOTHING }, 202 { "all", SELECT_ALL }, 203 { "invert", SELECT_INVERT }, 204 { "parent", SELECT_PARENT }, 205 { "ancestors", SELECT_ANCESTORS }, 206 { "children", SELECT_CHILDREN }, 207 { "descendants", SELECT_DESCENDANTS }, 208 { "resources", SELECT_HAS_RESOURCES }, 209 { "shown", SELECT_SHOWN_RESOURCES }, 210}, boolean_nametable[] = { 211 { "off", BOOL_OFF }, 212 { "false", BOOL_OFF }, 213 { "no", BOOL_OFF }, 214 { "on", BOOL_ON }, 215 { "true", BOOL_ON }, 216 { "yes", BOOL_ON }, 217 { "toggle", BOOL_TOGGLE }, 218}; 219 220static Widget treeWidget; 221static Widget viewButton, viewMenu, selectButton, selectMenu; 222static Widget view_widgets[VIEW_number]; 223static Widget select_widgets[SELECT_number]; 224static XmuWidgetNode *topnode; 225 226static Arg false_args[1] = {{ XtNstate, (XtArgVal) FALSE }}; 227static Arg true_args[1] = {{ XtNstate, (XtArgVal) TRUE }}; 228 229 230/* 231 * routines 232 */ 233static void 234usage (void) 235{ 236 const char **cpp; 237 fprintf (stderr, "usage: %s [-options...]\n", ProgramName); 238 fprintf(stderr, "\nwhere options include:\n"); 239 for (cpp = help_message; *cpp; cpp++) { 240 fprintf (stderr, " %s\n", *cpp); 241 } 242 fprintf(stderr, "\n"); 243 exit (1); 244} 245 246 247static XmuWidgetNode * 248widget_to_node (Widget gw) 249{ 250 XmuWidgetNode *node; 251 int i; 252 253 if (XtIsSubclass (gw, toggleWidgetClass)) { 254 for (i = 0, node = widget_list; i < nwidgets; i++, node++) { 255 if (VData(node)->instance == gw) return node; 256 } 257 } else if (XtIsSubclass (gw, listWidgetClass)) { 258 for (i = 0, node = widget_list; i < nwidgets; i++, node++) { 259 if (VData(node)->resource_lw == gw) return node; 260 } 261 } 262 return (XmuWidgetNode *) NULL; 263} 264 265 266static void 267initialize_widgetnode_list (XmuWidgetNode ***listp, int *sizep, int n) 268{ 269 int i; 270 XmuWidgetNode **l; 271 272 if (!*listp) { 273 *listp = (XmuWidgetNode **) 274 XtCalloc ((unsigned int) n, (unsigned int)sizeof(XmuWidgetNode **)); 275 *sizep = ((*listp) ? n : 0); 276 return; 277 } 278 if (n > *sizep) { 279 *listp = (XmuWidgetNode **) XtRealloc ((char *) *listp, 280 (unsigned int) 281 (n * sizeof(XmuWidgetNode **))); 282 if (!*listp) { 283 *sizep = 0; 284 return; 285 } 286 for (i = *sizep, l = (*listp) + i; i < n; i++, l++) *l = 287 (XmuWidgetNode *) NULL; 288 *sizep = n; 289 } 290 return; 291} 292 293 294static Boolean 295set_resource_labels (XmuWidgetNode *node) 296{ 297 Cardinal i; 298 const char **cur; 299 XtResourceList res; 300 XmuWidgetNode **wn; 301 ViewresData *d = VData(node); 302 303 if (!d->resource_labels) { 304 d->resource_labels = 305 (const char **) calloc ((unsigned) d->nnew * 3, 306 (unsigned) sizeof (const char *)); 307 if (!d->resource_labels) return FALSE; 308 } 309 310 cur = d->resource_labels; 311 res = node->resources; 312 wn = node->resourcewn; 313 for (i = 0; i < node->nresources; i++, res++, wn++) { 314 if (*wn == node) { /* should match nnew */ 315 *cur++ = res->resource_name; 316 *cur++ = res->resource_class; 317 *cur++ = res->resource_type; 318 } 319 } 320 if (d->nnewconstraints > 0) { 321 const char *s; 322 323 *cur++ = s = ""; 324 *cur++ = s; 325 *cur++ = s; 326 } 327 res = node->constraints; 328 wn = node->constraintwn; 329 for (i = 0; i < node->nconstraints; i++, res++, wn++) { 330 if (*wn == node) { /* should match nnew */ 331 *cur++ = res->resource_name; 332 *cur++ = res->resource_class; 333 *cur++ = res->resource_type; 334 } 335 } 336 return TRUE; 337} 338 339 340static ViewresData * 341create_viewres_data (XmuWidgetNode *node) 342{ 343 ViewresData *d = 344 (ViewresData *) malloc ((unsigned) sizeof(ViewresData)); 345 346 if (d) { 347 d->resource_labels = NULL; 348 d->nnewresources = XmuWnCountOwnedResources (node, node, False); 349 d->nnewconstraints = XmuWnCountOwnedResources (node, node, True); 350 d->nnew = (d->nnewresources + (d->nnewconstraints 351 ? d->nnewconstraints + 1 : 0)); 352 d->instance = (Widget) NULL; 353 d->resource_lw = (Widget) NULL; 354 d->selection_index = -1; 355 } 356 return d; 357} 358 359static int 360copydown (int start) 361{ 362 XmuWidgetNode **src = &selected_list.elements[start]; 363 XmuWidgetNode **dst = src; 364 int cur; 365 366 for (cur = start; start < selected_list.n_elements; start++, src++) { 367 if (*src) { 368 VData((*src))->selection_index = cur++; 369 *dst++ = *src; 370 } 371 } 372 return (start - cur); 373} 374 375 376static void 377add_to_selected_list (XmuWidgetNode *node, Boolean updatewidget) 378{ 379 ViewresData *d = VData(node); 380 if (!d->instance || d->selection_index >= 0) return; 381 382 if (selected_list.n_elements >= selected_list.max_elements) { 383 initialize_widgetnode_list (&selected_list.elements, 384 &selected_list.max_elements, 385 (selected_list.max_elements * 3) / 2); 386 } 387 INSERT_NODE (node, selected_list.n_elements); 388 selected_list.n_elements++; 389 390 if (updatewidget) XtSetValues (d->instance, true_args, ONE); 391} 392 393static Boolean 394remove_from_selected_list (XmuWidgetNode *node, Boolean updatewidget) 395{ 396 int i, skips; 397 ViewresData *d = VData(node); 398 399 if ((i = d->selection_index) < 0) return FALSE; 400 401 REMOVE_NODE (node); 402 403 /* copy down */ 404 if (selected_list.n_elements > 1) { 405 skips = copydown (i); 406 } else { 407 skips = 1; 408 } 409 selected_list.n_elements -= skips; 410 411 if (updatewidget) XtSetValues (d->instance, false_args, ONE); 412 return TRUE; 413} 414 415static void 416remove_nodes_from_selected_list (int start, int count, Boolean updatewidget) 417{ 418 int i; 419 420 for (i = 0; i < count; i++) { 421 XmuWidgetNode *p = selected_list.elements[start+i]; 422 ViewresData *d = VData(p); 423 REMOVE_NODE (p); 424 if (updatewidget) XtSetValues (d->instance, false_args, ONE); 425 } 426 selected_list.n_elements -= copydown (start); 427} 428 429static void 430add_subtree_to_selected_list (XmuWidgetNode *node, Boolean updatewidget) 431{ 432 if (!node) return; 433 434 add_to_selected_list (node, updatewidget); 435 for (node = node->children; node; node = node->siblings) { 436 add_subtree_to_selected_list (node, updatewidget); 437 } 438} 439 440 441/* ARGSUSED */ 442static void 443variable_labeltype_callback (Widget gw, 444 XtPointer closure, /* TRUE or FALSE */ 445 XtPointer data) 446{ 447 set_labeltype_menu ((Boolean) (long) closure, True); 448} 449 450/* ARGSUSED */ 451static void 452gravity_callback (Widget gw, 453 XtPointer closure, /* TRUE or FALSE */ 454 XtPointer data) 455{ 456 set_orientation_menu ((XtGravity) (long) closure, True); 457} 458 459 460static Boolean 461create_resource_lw (XmuWidgetNode *node) 462{ 463 Arg args[4]; 464 Cardinal n; 465 ViewresData *d = VData(node); 466 467 if (d->nnew == 0) return FALSE; 468 469 if (!d->resource_labels && 470 !set_resource_labels (node)) return FALSE; 471 472 n = 0; 473 XtSetArg (args[n], XtNnumberStrings, 3 * d->nnew); n++; 474 XtSetArg (args[n], XtNlist, d->resource_labels); n++; 475 XtSetArg (args[n], XtNdefaultColumns, 3); n++; 476 XtSetArg (args[n], XtNforceColumns, TRUE); n++; 477 d->resource_lw = XtCreateManagedWidget (node->label, listWidgetClass, 478 XtParent(d->instance), 479 args, n); 480 XtRealizeWidget (d->resource_lw); 481 return TRUE; 482} 483 484static void 485update_selection_items (void) 486{ 487 int i; 488 static Arg args[1] = {{ XtNsensitive, (XtArgVal) FALSE }}; 489 Boolean show = FALSE, hide = FALSE, ancestors = FALSE; 490 Boolean descendants = FALSE; 491 492 for (i = 0; i < selected_list.n_elements; i++) { 493 XmuWidgetNode *node = selected_list.elements[i]; 494 ViewresData *d = VData(node); 495 496 /* 497 * If node has any new resources then may be shown (if not 498 * already being shown). If node has widget and is managed, 499 * then may be hidden. 500 */ 501 if (d->nnew > 0) { 502 if (IsShowing(node)) { 503 hide = TRUE; 504 } else { 505 show = TRUE; 506 } 507 } 508 if (node != topnode) ancestors = TRUE; 509 if (node->children) descendants = TRUE; 510 } 511 512 args[0].value = (XtArgVal) show; 513 XtSetValues (view_widgets[VIEW_SHOW_RESOURCES], args, ONE); 514 args[0].value = (XtArgVal) hide; 515 XtSetValues (view_widgets[VIEW_HIDE_RESOURCES], args, ONE); 516 args[0].value = (XtArgVal) (selected_list.n_elements > 0 ? TRUE : FALSE); 517 XtSetValues (select_widgets[SELECT_NOTHING], args, ONE); 518 args[0].value = (XtArgVal) ancestors; 519 XtSetValues (select_widgets[SELECT_PARENT], args, ONE); 520 XtSetValues (select_widgets[SELECT_ANCESTORS], args, ONE); 521 args[0].value = (XtArgVal) descendants; 522 XtSetValues (select_widgets[SELECT_CHILDREN], args, ONE); 523 XtSetValues (select_widgets[SELECT_DESCENDANTS], args, ONE); 524 args[0].value = (XtArgVal) ((Boolean) (NumberShowing > 0)); 525 XtSetValues (select_widgets[SELECT_SHOWN_RESOURCES], args, ONE); 526} 527 528 529static void 530do_resources (XmuWidgetNode *node, Boolean op, Boolean updatewidget) 531{ 532 ViewresData *d = VData(node); 533 if (op == BOOL_TOGGLE) op = (IsShowing(node) ? BOOL_OFF : BOOL_ON); 534 535 if (op == BOOL_ON) { 536 if (d->resource_lw) { /* if already created */ 537 if (!XtIsManaged(d->resource_lw)) { 538 NumberShowing++; 539 XtManageChild (d->resource_lw); 540 } /* else ignore it */ 541 } else if (create_resource_lw (node)) /* create it */ 542 NumberShowing++; 543 } else if (d->resource_lw) { /* if already created */ 544 if (XtIsManaged (d->resource_lw)) { 545 NumberShowing--; 546 XtUnmanageChild (d->resource_lw); 547 XawListUnhighlight (d->resource_lw); 548 if (updatewidget) remove_from_selected_list (node, TRUE); 549 } /* else ignore it */ 550 } 551} 552 553 554 555/* ARGSUSED */ 556static void 557show_resources_callback ( 558 Widget gw, /* menu or toggle button */ 559 XtPointer closure, /* BOOL_OFF, BOOL_ON, BOOL_TOGGLE */ 560 XtPointer data) /* undefined */ 561{ 562 int op = (long) closure; 563 XmuWidgetNode *node = widget_to_node (gw); 564 565 if (node) { 566 XUnmapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 567 do_resources (node, op, TRUE); 568 } else if (selected_list.n_elements <= 0) { 569 return; 570 } else { 571 int i; 572 573 XUnmapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 574 for (i = 0; i < selected_list.n_elements; i++) { 575 do_resources (selected_list.elements[i], op, FALSE); 576 } 577 } 578 XawTreeForceLayout (treeWidget); 579 XMapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 580 update_selection_items (); 581} 582 583 584/* ARGSUSED */ 585static void 586select_callback ( 587 Widget gw, /* entry widget */ 588 XtPointer closure, /* TRUE or FALSE */ 589 XtPointer data) /* undefined */ 590{ 591 int i; 592 int nselected = selected_list.n_elements; 593 XmuWidgetNode *node; 594 595 switch ((long) closure) { 596 case SELECT_NOTHING: /* clear selection_list */ 597 remove_nodes_from_selected_list (0, nselected, True); 598 break; 599 600 case SELECT_ALL: /* put everything on selection_list */ 601 add_subtree_to_selected_list (topnode, TRUE); 602 break; 603 604 case SELECT_INVERT: /* toggle selection state */ 605 for (i = 0, node = widget_list; i < nwidgets; i++, node++) { 606 ViewresData *d = VData(node); 607 if (d->selection_index < 0) add_to_selected_list (node, TRUE); 608 } 609 remove_nodes_from_selected_list (0, nselected, True); 610 break; 611 612 613 case SELECT_PARENT: /* choose immediate parent */ 614 node = widget_to_node (gw); 615 if (node) { 616 if (node->superclass) 617 add_to_selected_list (node->superclass, TRUE); 618 } else { 619 for (i = 0; i < nselected; i++) { 620 XmuWidgetNode *nodeI = selected_list.elements[i]; 621 if (nodeI->superclass) 622 add_to_selected_list (nodeI->superclass, TRUE); 623 } 624 } 625 break; 626 627 case SELECT_ANCESTORS: /* chain up adding to selection_list */ 628 node = widget_to_node (gw); 629 if (node) { 630 do { 631 add_to_selected_list (node, TRUE); 632 } while ((node = node->superclass) != NULL); 633 } else { 634 for (i = 0; i < nselected; i++) { 635 XmuWidgetNode *parent = selected_list.elements[i]; 636 637 /* 638 * chain up the tree, but stop if we get to nodes that 639 * are already in the selected list. 640 */ 641 while ((parent = parent->superclass) != NULL) { 642 if (VData(parent)->selection_index >= 0) break; 643 add_to_selected_list (parent, TRUE); 644 } 645 } 646 } 647 break; 648 649 case SELECT_CHILDREN: /* all direct sub nodes */ 650 node = widget_to_node (gw); 651 if (node) { 652 add_to_selected_list (node, TRUE); 653 for (node = node->children; node; node = node->siblings) { 654 add_to_selected_list (node, TRUE); 655 } 656 } else { 657 for (i = 0; i < nselected; i++) { 658 XmuWidgetNode *nodeI = selected_list.elements[i]; 659 660 add_to_selected_list (nodeI, TRUE); 661 for (nodeI = nodeI->children; nodeI; nodeI = nodeI->siblings) { 662 add_to_selected_list (nodeI, TRUE); 663 } 664 } 665 } 666 break; 667 668 case SELECT_DESCENDANTS: /* all sub nodes */ 669 node = widget_to_node (gw); 670 if (node) { 671 add_subtree_to_selected_list (node, TRUE); 672 } else { 673 for (i = 0; i < nselected; i++) { 674 XmuWidgetNode *parent = selected_list.elements[i]; 675 676 add_subtree_to_selected_list (parent, TRUE); 677 } 678 } 679 break; 680 681 case SELECT_HAS_RESOURCES: /* put all w/ rescnt > 0 on sel_list */ 682 for (i = 0, node = widget_list; i < nwidgets; i++, node++) { 683 if (VData(node)->nnew > 0) 684 add_to_selected_list (node, TRUE); 685 } 686 break; 687 688 case SELECT_SHOWN_RESOURCES: 689 for (i = 0, node = widget_list; i < nwidgets; i++, node++) { 690 if (IsShowing(node)) add_to_selected_list (node, TRUE); 691 } 692 break; 693 694 default: /* error!!! */ 695 XBell (XtDisplay(gw), 0); 696 return; 697 } 698 699 update_selection_items (); 700} 701 702/* ARGSUSED */ 703static void 704toggle_callback (Widget gw, 705 XtPointer closure, /* XmuWidgetNode for this widget */ 706 XtPointer data) /* on or off */ 707{ 708 XmuWidgetNode *node = (XmuWidgetNode *) closure; 709 Boolean selected = (Boolean) (long) data; 710 711 if (selected) { 712 add_to_selected_list (node, FALSE); 713 } else { 714 (void) remove_from_selected_list (node, FALSE); 715 } 716 717 update_selection_items (); 718} 719 720 721/* 722 * panner/porthole controls - called when the other changes 723 */ 724/* ARGSUSED */ 725static void 726panner_callback ( 727 Widget gw, /* panner widget */ 728 XtPointer closure, /* porthole widget */ 729 XtPointer data) /* report */ 730{ 731 XawPannerReport *rep = (XawPannerReport *) data; 732 Arg args[2]; 733 734 if (!treeWidget) return; 735 736 XtSetArg (args[0], XtNx, -rep->slider_x); 737 XtSetArg (args[1], XtNy, -rep->slider_y); 738 XtSetValues (treeWidget, args, TWO); /* just assume... */ 739} 740 741/* ARGSUSED */ 742static void 743porthole_callback ( 744 Widget gw, /* porthole widget */ 745 XtPointer closure, /* panner widget */ 746 XtPointer data) /* report */ 747{ 748 Widget panner = (Widget) closure; 749 XawPannerReport *rep = (XawPannerReport *) data; 750 Arg args[6]; 751 Cardinal n = TWO; 752 753 XtSetArg (args[0], XtNsliderX, rep->slider_x); 754 XtSetArg (args[1], XtNsliderY, rep->slider_y); 755 if (rep->changed != (XawPRSliderX | XawPRSliderY)) { 756 XtSetArg (args[2], XtNsliderWidth, rep->slider_width); 757 XtSetArg (args[3], XtNsliderHeight, rep->slider_height); 758 XtSetArg (args[4], XtNcanvasWidth, rep->canvas_width); 759 XtSetArg (args[5], XtNcanvasHeight, rep->canvas_height); 760 n = SIX; 761 } 762 XtSetValues (panner, args, n); 763} 764 765 766 767static void 768build_tree (XmuWidgetNode *node, Widget tree, Widget super) 769{ 770 ViewresData *d = VData (node); 771 Widget box, w; /* widget for this Class */ 772 XmuWidgetNode *child; /* iterator over children */ 773 Arg args[3]; /* need to set super node */ 774 Cardinal n; /* count of args */ 775 static XtCallbackRec callback_rec[2] = {{ toggle_callback, NULL }, 776 { NULL, NULL }}; 777 778 779 n = 0; 780 XtSetArg (args[n], XtNtreeParent, super); n++; 781 box = XtCreateManagedWidget (node->label, boxWidgetClass, tree, args, n); 782 783 n = 0; 784 XtSetArg (args[n], XtNlabel, (options.show_variable ? 785 node->label : XmuWnClassname(node))); n++; 786 XtSetArg (args[n], XtNcallback, callback_rec); n++; 787 788 callback_rec[0].closure = (XtPointer) node; 789 w = XtCreateManagedWidget (node->label, toggleWidgetClass, box, args, n); 790 d->instance = w; 791 792 /* 793 * recursively build the rest of the tree 794 */ 795 for (child = node->children; child; child = child->siblings) { 796 build_tree (child, tree, box); 797 } 798} 799 800 801static void 802set_node_labels (XmuWidgetNode *node, int depth) 803{ 804 Arg args[1]; 805 XmuWidgetNode *child; 806 ViewresData *d = VData(node); 807 808 if (!node) return; 809 XtSetArg (args[0], XtNlabel, (options.show_variable ? 810 node->label : XmuWnClassname(node))); 811 XtSetValues (d->instance, args, ONE); 812 813 for (child = node->children; child; child = child->siblings) { 814 set_node_labels (child, depth + 1); 815 } 816} 817 818 819static void 820oneof_sensitive (Boolean choosea, Widget a, Widget b) 821{ 822 static Arg args[1] = { { XtNsensitive, (XtArgVal) NULL } }; 823 824 args[0].value = (XtArgVal) TRUE; 825 XtSetValues (choosea ? a : b, args, ONE); 826 args[0].value = (XtArgVal) FALSE; 827 XtSetValues (choosea ? b : a, args, ONE); 828} 829 830static void 831set_labeltype_menu (Boolean isvar, Boolean doall) 832{ 833 options.show_variable = isvar; 834 oneof_sensitive (isvar, view_widgets[VIEW_CLASSES], 835 view_widgets[VIEW_VARIABLES]); 836 837 if (doall) { 838 XUnmapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 839 set_node_labels (topnode, 0); 840 XawTreeForceLayout (treeWidget); 841 XMapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 842 } 843} 844 845static void 846set_orientation_menu (XtGravity grav, Boolean dosetvalues) 847{ 848#define CHOOSE(val) (sensitiveargs + (grav != (val))) 849 XtSetValues (view_widgets[VIEW_HORIZONTAL], CHOOSE(WestGravity), ONE); 850 XtSetValues (view_widgets[VIEW_VERTICAL], CHOOSE(NorthGravity), ONE); 851#undef CHOOSE 852 853 if (dosetvalues) { 854 Arg args[1]; 855 856 XtSetArg (args[0], XtNgravity, grav); 857 XUnmapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 858 XtSetValues (treeWidget, args, ONE); 859 XMapWindow (XtDisplay(treeWidget), XtWindow(treeWidget)); 860 } 861} 862 863 864/***************************************************************************** 865 * * 866 * viewres - visual class browser for Xt * 867 * * 868 *****************************************************************************/ 869 870int 871main (int argc, char *argv[]) 872{ 873 Widget toplevel, pane, box, dummy, porthole, panner, form; 874 XmuWidgetNode *rootNode; /* always the root of the resource hierarchy */ 875 XtAppContext app_con; 876 Arg args[6]; 877 Dimension canvasWidth, canvasHeight, sliderWidth, sliderHeight; 878 static XtCallbackRec callback_rec[2] = {{ NULL, NULL }, { NULL, NULL }}; 879 XtGravity grav; 880 int i; 881 882 ProgramName = argv[0]; 883 884 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); 885 886 toplevel = XtAppInitialize (&app_con, "Viewres", 887 Options, XtNumber (Options), 888 &argc, argv, (String *) fallback_resources, 889 (ArgList) NULL, ZERO); 890 if (argc != 1) usage (); 891 892 initialize_widgetnode_list (&selected_list.elements, 893 &selected_list.max_elements, 10); 894 895 XtGetApplicationResources (toplevel, (XtPointer) &options, 896 Resources, XtNumber(Resources), NULL, ZERO); 897 XmuWnInitializeNodes (widget_list, nwidgets); 898 899 topnode = XmuWnNameToNode (widget_list, nwidgets, options.top_object); 900 if (!topnode) { 901 fprintf(stderr, "%s: no widget with name \"%s\" found.\n", 902 ProgramName, options.top_object); 903 exit(1); 904 } 905 906 XtAppAddActions (app_con, viewres_actions, XtNumber (viewres_actions)); 907 XtOverrideTranslations 908 (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); 909 910 /* 911 * create dummy widgets to initialize resources 912 */ 913 XtSetArg (args[0], XtNwidth, 1); 914 XtSetArg (args[1], XtNheight, 1); 915 dummy = XtCreateWidget ("dummy", widgetClass, toplevel, args, TWO); 916 rootNode = XmuWnNameToNode(widget_list, nwidgets, "Object"); 917 for (i = 0; i < nwidgets; i++) { 918 XmuWidgetNode *node = &widget_list[i]; 919 XmuWnFetchResources (node, dummy, rootNode); 920 node->data = (XtPointer) create_viewres_data (node); 921 } 922 XtDestroyWidget (dummy); 923 924 pane = XtCreateManagedWidget ("pane", panedWidgetClass, toplevel, 925 (ArgList) NULL, ZERO); 926 927 box = XtCreateManagedWidget ("buttonbox", boxWidgetClass, pane, 928 (ArgList) NULL, ZERO); 929 (void) XtCreateManagedWidget ("quit", commandWidgetClass, box, 930 (ArgList) NULL, ZERO); 931 932 /* 933 * Format menu 934 */ 935 XtSetArg (args[0], XtNmenuName, "viewMenu"); 936 viewButton = XtCreateManagedWidget ("view", menuButtonWidgetClass, box, 937 args, ONE); 938 viewMenu = XtCreatePopupShell ("viewMenu", simpleMenuWidgetClass, 939 viewButton, (ArgList) NULL, ZERO); 940 XtSetArg (args[0], XtNcallback, callback_rec); 941 942#define MAKE_VIEW(n,v,name) \ 943 callback_rec[0].closure = (XtPointer) v; \ 944 view_widgets[n] = XtCreateManagedWidget (name, smeBSBObjectClass, \ 945 viewMenu, args, ONE) 946 callback_rec[0].callback = (XtCallbackProc) gravity_callback; 947 MAKE_VIEW (VIEW_HORIZONTAL, WestGravity, "layoutHorizontal"); 948 MAKE_VIEW (VIEW_VERTICAL, NorthGravity, "layoutVertical"); 949 950 (void) XtCreateManagedWidget ("line1", smeLineObjectClass, viewMenu, 951 (ArgList) NULL, ZERO); 952 953 callback_rec[0].callback = (XtCallbackProc) variable_labeltype_callback; 954 MAKE_VIEW (VIEW_VARIABLES, TRUE, "namesVariable"); 955 MAKE_VIEW (VIEW_CLASSES, FALSE, "namesClass"); 956 957 (void) XtCreateManagedWidget ("line2", smeLineObjectClass, viewMenu, 958 (ArgList) NULL, ZERO); 959 960 callback_rec[0].callback = (XtCallbackProc) show_resources_callback; 961 MAKE_VIEW (VIEW_SHOW_RESOURCES, BOOL_ON, "viewResources"); 962 MAKE_VIEW (VIEW_HIDE_RESOURCES, BOOL_OFF, "viewNoResources"); 963#undef MAKE_VIEW 964 965 /* 966 * Select menu 967 */ 968 XtSetArg (args[0], XtNmenuName, "selectMenu"); 969 selectButton = XtCreateManagedWidget ("select", menuButtonWidgetClass, box, 970 args, ONE); 971 selectMenu = XtCreatePopupShell ("selectMenu", simpleMenuWidgetClass, 972 selectButton, (ArgList) NULL, ZERO); 973 XtSetArg (args[0], XtNcallback, callback_rec); 974 callback_rec[0].callback = (XtCallbackProc) select_callback; 975#define MAKE_SELECT(n,name) \ 976 callback_rec[0].closure = (XtPointer) n; \ 977 select_widgets[n] = XtCreateManagedWidget (name, smeBSBObjectClass, \ 978 selectMenu, args, ONE) 979 MAKE_SELECT (SELECT_NOTHING, "unselect"); 980 MAKE_SELECT (SELECT_ALL, "selectAll"); 981 MAKE_SELECT (SELECT_INVERT, "selectInvert"); 982 (void) XtCreateManagedWidget ("line1", smeLineObjectClass, selectMenu, 983 (ArgList) NULL, ZERO); 984 MAKE_SELECT (SELECT_PARENT, "selectParent"); 985 MAKE_SELECT (SELECT_ANCESTORS, "selectAncestors"); 986 MAKE_SELECT (SELECT_CHILDREN, "selectChildren"); 987 MAKE_SELECT (SELECT_DESCENDANTS, "selectDescendants"); 988 (void) XtCreateManagedWidget ("line2", smeLineObjectClass, selectMenu, 989 (ArgList) NULL, ZERO); 990 MAKE_SELECT (SELECT_HAS_RESOURCES, "selectHasResources"); 991 MAKE_SELECT (SELECT_SHOWN_RESOURCES, "selectShownResources"); 992#undef MAKE_SELECT 993 994 form = XtCreateManagedWidget ("treeform", formWidgetClass, pane, 995 (ArgList) NULL, ZERO); 996 /* 997 * create the panner and the porthole and then connect them with the 998 * callbacks (passing the other widget each callback) 999 */ 1000 XtSetArg (args[0], XtNbackgroundPixmap, None); /* faster updates */ 1001 porthole = XtCreateManagedWidget ("porthole", portholeWidgetClass, form, 1002 args, ONE); 1003 panner = XtCreateManagedWidget ("panner", pannerWidgetClass, form, 1004 (ArgList) NULL, ZERO); 1005 1006 XtSetArg (args[0], XtNreportCallback, callback_rec); 1007 callback_rec[0].callback = (XtCallbackProc) panner_callback; 1008 callback_rec[0].closure = (XtPointer) porthole; 1009 XtSetValues (panner, args, ONE); 1010 1011 callback_rec[0].callback = (XtCallbackProc) porthole_callback; 1012 callback_rec[0].closure = (XtPointer) panner; 1013 XtSetValues (porthole, args, ONE); 1014 1015 /* 1016 * now that the panner and porthole are set up, insert the tree and 1017 * fix up the menu, fill in the nodes 1018 */ 1019 treeWidget = XtCreateManagedWidget ("tree", treeWidgetClass, 1020 porthole, (ArgList) NULL, ZERO); 1021 1022 set_labeltype_menu (options.show_variable, FALSE); 1023 XtSetArg (args[0], XtNgravity, &grav); 1024 XtGetValues (treeWidget, args, ONE); 1025 set_orientation_menu (grav, FALSE); 1026 update_selection_items (); 1027 build_tree (topnode, treeWidget, (Widget) NULL); 1028 1029 /* 1030 * Realize the tree, but do not map it (we set mappedWhenManaged to 1031 * false up above). Get the initial size of the tree so that we can 1032 * size the panner appropriately. 1033 */ 1034 XtRealizeWidget (toplevel); 1035 1036 wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 1037 False); 1038 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 1039 &wm_delete_window, 1); 1040 1041 XtSetArg (args[0], XtNwidth, &canvasWidth); 1042 XtSetArg (args[1], XtNheight, &canvasHeight); 1043 XtGetValues (treeWidget, args, TWO); 1044 1045 XtSetArg (args[0], XtNwidth, &sliderWidth); 1046 XtSetArg (args[1], XtNheight, &sliderHeight); 1047 XtGetValues (porthole, args, TWO); 1048 1049 XtSetArg (args[0], XtNcanvasWidth, canvasWidth); 1050 XtSetArg (args[1], XtNcanvasHeight, canvasHeight); 1051 XtSetArg (args[2], XtNsliderWidth, sliderWidth); 1052 XtSetArg (args[3], XtNsliderHeight, sliderHeight); 1053 XtSetValues (panner, args, FOUR); 1054 1055 XRaiseWindow (XtDisplay(panner), XtWindow(panner)); 1056 XtAppMainLoop (app_con); 1057 1058 return 0; 1059} 1060 1061 1062 1063/***************************************************************************** 1064 * * 1065 * viewres translation table action routines * 1066 * * 1067 *****************************************************************************/ 1068 1069/* ARGSUSED */ 1070static void 1071ActionQuit (Widget w, XEvent *event, 1072 String *params, Cardinal *num_params) 1073{ 1074 exit (0); 1075} 1076 1077/* ARGSUSED */ 1078static void 1079ActionSetLableType (Widget w, XEvent *event, 1080 String *params, Cardinal *num_params) 1081{ 1082 const char *cmd; 1083 Boolean oldvar = options.show_variable, newvar; 1084 1085 switch (*num_params) { 1086 case 0: 1087 cmd = "toggle"; 1088 break; 1089 case 1: 1090 cmd = params[0]; 1091 break; 1092 default: 1093 XBell (XtDisplay(w), 0); 1094 return; 1095 } 1096 1097 if (XmuCompareISOLatin1 (cmd, "toggle") == 0) { 1098 newvar = !oldvar; 1099 } else if (XmuCompareISOLatin1 (cmd, "variable") == 0) { 1100 newvar = TRUE; 1101 } else if (XmuCompareISOLatin1 (cmd, "class") == 0) { 1102 newvar = FALSE; 1103 } else { 1104 XBell (XtDisplay(w), 0); 1105 return; 1106 } 1107 1108 if (newvar != oldvar) set_labeltype_menu (newvar, TRUE); 1109 return; 1110} 1111 1112/* ARGSUSED */ 1113static void 1114ActionSetOrientation (Widget w, XEvent *event, 1115 String *params, Cardinal *num_params) 1116{ 1117 XtGravity newgrav = ForgetGravity; 1118 1119 if (*num_params < 1) { 1120 Arg arg; 1121 XtGravity oldgrav = ForgetGravity; 1122 1123 XtSetArg (arg, XtNgravity, &oldgrav); 1124 XtGetValues (treeWidget, &arg, ONE); 1125 switch (oldgrav) { 1126 case WestGravity: newgrav = NorthGravity; break; 1127 case NorthGravity: newgrav = WestGravity; break; 1128 case EastGravity: newgrav = SouthGravity; break; 1129 case SouthGravity: newgrav = EastGravity; break; 1130 default: 1131 return; 1132 } 1133 } else { 1134 XrmValue fromval, toval; 1135 1136 fromval.size = sizeof (String); 1137 fromval.addr = (XPointer) params[0]; 1138 toval.size = sizeof (XtGravity); 1139 toval.addr = (XPointer) &newgrav; 1140 XtConvertAndStore (treeWidget, XtRString, &fromval, 1141 XtRGravity, &toval); 1142 } 1143 1144 switch (newgrav) { 1145 case WestGravity: case NorthGravity: case EastGravity: case SouthGravity: 1146 break; 1147 default: 1148 XBell (XtDisplay(w), 0); 1149 return; 1150 } 1151 1152 set_orientation_menu (newgrav, TRUE); 1153 return; 1154} 1155 1156 1157static void 1158do_single_arg (Widget w, String *params, Cardinal nparams, 1159 struct _nametable table[] , int nentries, XtCallbackProc proc) 1160{ 1161 int obj; 1162 int i; 1163 1164 if (nparams != 1) { 1165 XBell (XtDisplay(w), 0); 1166 return; 1167 } 1168 1169 for (i = 0; i < nentries; i++) { 1170 if (XmuCompareISOLatin1 (params[0], table[i].name) == 0) { 1171 obj = table[i].value; 1172 goto found; 1173 } 1174 } 1175 XBell (XtDisplay(w), 0); 1176 return; 1177 1178 found: 1179 /* 1180 * use any old widget 1181 */ 1182 (*proc) (w, (XtPointer) (long) obj, (XtPointer) NULL); 1183} 1184 1185 1186/* ARGSUSED */ 1187static void 1188ActionSelect (Widget w, XEvent *event, 1189 String *params, Cardinal *num_params) 1190{ 1191 do_single_arg (w, params, *num_params, select_nametable, 1192 (int) XtNumber(select_nametable), select_callback); 1193} 1194 1195 1196/* ARGSUSED */ 1197static void ActionResources (Widget w, XEvent *event, 1198 String *params, Cardinal *num_params) 1199{ 1200 if (*num_params == 0) { 1201 show_resources_callback (w, (XtPointer) BOOL_TOGGLE, (XtPointer) NULL); 1202 } else { 1203 do_single_arg (w, params, *num_params, boolean_nametable, 1204 (int) XtNumber(boolean_nametable), 1205 show_resources_callback); 1206 } 1207} 1208 1209