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