widgets.c revision 278eca22
1/*
2 * $Xorg: widgets.c,v 1.4 2001/02/09 02:05:30 xorgcvs Exp $
3 *
4Copyright 1989, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25 */
26/* $XFree86: xc/programs/editres/widgets.c,v 1.5 2001/01/17 23:44:52 dawes Exp $ */
27
28/*
29 * Code for creating all widgets used by EditRes.
30 */
31
32#include <stdio.h>
33#include <X11/Intrinsic.h>
34#include <X11/StringDefs.h>	/* Get standard string definations. */
35
36#include <X11/Xaw/AsciiText.h>
37#include <X11/Xaw/Box.h>
38#include <X11/Xaw/Cardinals.h>
39#include <X11/Xaw/Label.h>
40#include <X11/Xaw/List.h>
41#include <X11/Xaw/MenuButton.h>
42#include <X11/Xaw/Paned.h>
43#include <X11/Xaw/Panner.h>
44#include <X11/Xaw/Porthole.h>
45#include <X11/Xaw/SmeBSB.h>
46#include <X11/Xaw/SmeLine.h>
47#include <X11/Xaw/SimpleMenu.h>
48#include <X11/Xaw/Toggle.h>
49#include <X11/Xaw/Tree.h>
50#include <X11/Xaw/Viewport.h>
51
52#include "editresP.h"
53
54
55
56/*
57 * functions.
58 */
59
60static Widget CreateTopArea ( Widget parent );
61static void CreateCommandMenu ( Widget parent, String toolkit );
62static void CreateTreeCommandMenu ( Widget parent, String toolkit );
63static void CreateResourceNameForm ( Widget parent, WNode * node );
64static void SetToggleGroupLeaders ( WNode * node );
65static void MakeBoxLookNice ( Widget dot, Widget star, Widget any,
66			      Widget single, Widget name, Widget class,
67			      int endbox );
68static void CreateLists ( Widget parent, WNode * node, char **names,
69			  char **cons_names );
70static void CreateValueWidget ( Widget parent, WNode * node );
71static void PopupOnNode ( WNode * node, Widget shell );
72static void FreeClientData ( Widget w, XtPointer ptr, XtPointer junk );
73static void FreeResBox ( Widget w, XtPointer ptr, XtPointer junk );
74
75
76
77/*      Function Name: RebuildMenusAndLabel
78 *      Description: Determins if the user has selected an application
79 *                   which uses a different toolkit.  Xt is the default.
80 *                   If this is so, destroys and recreates the menus and
81 *                   information label at the top of the application.
82 *      Arguments: toolkit - name of the toolkit.
83 *      Returns: none.
84 */
85
86static Widget box = NULL;
87static Widget hPane = NULL;
88
89#define Offset(index) sizeof(String) * index
90
91#define res_entry(index, name, class) \
92  {name, class, XtRString, sizeof(String), \
93     Offset(index), XtRString, (XtPointer)NULL}
94
95static XtResource resources[] = {
96  res_entry(0, "label0", "Label0"),
97  res_entry(1, "label1", "Label1"),
98  res_entry(2, "label2", "Label2"),
99  res_entry(3, "label3", "Label3"),
100  res_entry(4, "label4", "Label4"),
101  res_entry(5, "label5", "Label5"),
102  res_entry(6, "label6", "Label6"),
103  res_entry(7, "label7", "Label7"),
104  res_entry(8, "label8", "Label8"),
105  res_entry(9, "label9", "Label9"),
106  res_entry(11, "label11", "Label11"),
107  res_entry(12, "label12", "Label12"),
108  res_entry(13, "label13", "Label13"),
109  res_entry(14, "label14", "Label14"),
110  res_entry(15, "label15", "Label15"),
111  res_entry(16, "label16", "Label16"),
112  res_entry(17, "label17", "Label17"),
113  res_entry(18, "label18", "Label18"),
114  res_entry(19, "label19", "Label19"),
115  res_entry(20, "label20", "Label20"),
116  res_entry(21, "label21", "Label21"),
117  res_entry(22, "label22", "Label22"),
118  res_entry(23, "label23", "Label23"),
119  res_entry(24, "label24", "Label24"),
120  res_entry(25, "label25", "Label25"),
121  res_entry(26, "label26", "Label26"),
122  res_entry(27, "label27", "Label27"),
123  res_entry(28, "label28", "Label28"),
124  res_entry(29, "label29", "Label29"),
125  res_entry(30, "label30", "Label30"),
126  res_entry(31, "label31", "Label31"),
127  res_entry(32, "label32", "Label32"),
128  res_entry(33, "label33", "Label33"),
129  res_entry(34, "label34", "Label34"),
130  res_entry(35, "label35", "Label35"),
131  res_entry(36, "label36", "Label36")
132};
133
134#undef res_entry
135
136#undef Offset
137
138void
139RebuildMenusAndLabel(String toolkit)
140{
141  if (strcmp(global_effective_toolkit, toolkit)) {
142    CreateCommandMenu(box, toolkit);
143    CreateTreeCommandMenu(box, toolkit);
144    XtDestroyWidget(global_screen_data.info_label);
145    global_screen_data.info_label = XtCreateManagedWidget(toolkit,
146							  labelWidgetClass,
147							  hPane, NULL, ZERO);
148    /* get the new toolkit label application resources for info_label */
149    XtGetApplicationResources(global_screen_data.info_label,
150			      res_labels, resources,
151			      XtNumber(resources), NULL, 0);
152
153    global_effective_toolkit = toolkit;
154  }
155}
156
157
158
159/*      Function Name: BuildWidgetTree
160 *      Description: Creates all widgets for Editres.
161 *      Arguments: parent - the shell to put them into.
162 *      Returns: none.
163 */
164
165void
166BuildWidgetTree(Widget parent)
167{
168    Widget paned, porthole, panner;
169
170    paned = XtCreateManagedWidget("paned", panedWidgetClass, parent,
171                                  NULL, ZERO);
172
173    panner = CreateTopArea(paned);
174
175    porthole = XtCreateManagedWidget("porthole", portholeWidgetClass,
176                                     paned, NULL, ZERO);
177
178/*
179 * Allow the panner and porthole to talk to each other.
180 */
181
182    XtAddCallback(porthole,
183                  XtNreportCallback, PortholeCallback, (XtPointer) panner);
184    XtAddCallback(panner,
185                  XtNreportCallback, PannerCallback, (XtPointer) porthole);
186
187    global_tree_parent = porthole;
188}
189
190
191
192
193/*	Function Name: CreateTopArea
194 *	Description: Creates the top part of the display
195 *	Arguments: parent - widget to put this menu bar into.
196 *	Returns: none.
197 */
198
199
200static Widget
201CreateTopArea(Widget parent)
202{
203    Widget panner;
204
205    box = XtCreateManagedWidget("box", boxWidgetClass, parent, NULL, ZERO);
206
207    CreateCommandMenu(box, "xt");
208    CreateTreeCommandMenu(box, "xt");
209
210    hPane = XtCreateManagedWidget("hPane",panedWidgetClass, parent, NULL,ZERO);
211
212    {
213	panner = XtCreateManagedWidget("panner", pannerWidgetClass,
214				       hPane, NULL, ZERO);
215
216	global_screen_data.info_label = XtCreateManagedWidget("xt",
217							     labelWidgetClass,
218							     hPane, NULL,ZERO);
219
220	/* get the "xt label" application resources for info_label */
221	XtGetApplicationResources(global_screen_data.info_label,
222				  res_labels, resources,
223				  XtNumber(resources), NULL, 0);
224
225    }
226
227    return(panner);
228}
229
230
231
232/*	Function Name: SetEntriesInsensitive
233 *	Description: Make menu entries unusable.
234 *	Arguments: entries - address of widget array.
235 *                 num - number of widgets.
236 *                 sensitive - whether to sensitize or desensitize.
237 *	Returns: none.
238 */
239void
240SetEntriesSensitive(Widget *entries, int num, Boolean sensitive)
241{
242int i; for (i=0; i<num; i++) XtSetSensitive(entries[i], sensitive);
243}
244
245
246
247/*	Function Name: CreateCommandMenu
248 *	Description: Creates the command menu.
249 *	Arguments: parent - widget to put this menu into.
250 *                 toolkit - name given to the SimpleMenu widget.
251 *	Returns: none.
252 */
253
254static Widget cmenu = NULL, cbutton = NULL;
255/* at first most menu entries are insensitive */
256static Boolean CM_set_insensitive = True;
257Widget CM_entries[NUM_CM_ENTRIES];
258
259static void
260CreateCommandMenu(Widget parent, String toolkit)
261{
262    Arg args[1];
263
264    if (cmenu) { XtDestroyWidget(cmenu); CM_set_insensitive = False; }
265    else
266      cbutton = XtCreateManagedWidget("commands", menuButtonWidgetClass,
267				      parent, NULL, ZERO);
268
269    /* set the menu name to the toolkit name */
270    XtSetArg(args[0], XtNmenuName, toolkit);
271    XtSetValues(cbutton, args, ONE);
272
273    cmenu = XtCreatePopupShell(toolkit, simpleMenuWidgetClass, cbutton,
274			       NULL, ZERO);
275
276    CM_entries[0] = XtCreateManagedWidget("sendTree", smeBSBObjectClass,cmenu,
277					   NULL, ZERO);
278    XtAddCallback(CM_entries[0], XtNcallback, SendTree, (XtPointer) TRUE);
279
280    CM_entries[1]=XtCreateManagedWidget("refreshTree",smeBSBObjectClass,cmenu,
281					 NULL, ZERO);
282    XtAddCallback(CM_entries[1], XtNcallback, SendTree, (XtPointer) FALSE);
283
284    CM_entries[2] = XtCreateManagedWidget("dumpTreeToFile",
285					   smeBSBObjectClass,cmenu,
286					   NULL, ZERO);
287    XtAddCallback(CM_entries[2], XtNcallback, DumpTreeToFile, NULL);
288
289    CM_entries[3] = XtCreateManagedWidget("line", smeLineObjectClass, cmenu,
290				  NULL, ZERO);
291    CM_entries[4]= XtCreateManagedWidget("getResourceList",
292					  smeBSBObjectClass,cmenu,
293					  NULL, ZERO);
294    XtAddCallback(CM_entries[4], XtNcallback, GetResourceList, NULL);
295
296    CM_entries[5] = XtCreateManagedWidget("setValues", smeBSBObjectClass,
297					   cmenu,
298					   NULL, ZERO);
299    XtAddCallback(CM_entries[5], XtNcallback, InitSetValues, NULL);
300
301    CM_entries[6] = XtCreateManagedWidget("line", smeLineObjectClass, cmenu,
302					   NULL, ZERO);
303
304    CM_entries[7] = XtCreateManagedWidget("quit", smeBSBObjectClass, cmenu,
305					   NULL, ZERO);
306    XtAddCallback(CM_entries[7], XtNcallback, Quit, NULL);
307
308    if (CM_set_insensitive)
309      SetEntriesSensitive(&CM_entries[CM_OFFSET], CM_NUM, False);
310}
311
312
313
314/*	Function Name: CreateTreeCommandMenu
315 *	Description: Creats the command menu.
316 *	Arguments: parent - widget to put this menu into.
317 *	Returns: none.
318 */
319
320#define SELECT 0
321#define ACTIVATE 1
322#define LABEL 2
323#define LINE 3
324#define FIND 4
325#define FLASH 5
326
327struct tree_ops_menu {
328    char * name;
329    int type;
330    XtPointer data;
331};
332
333static Widget tmenu = NULL, tbutton = NULL;
334/* at first most menu entries are insensitive */
335static Boolean TM_set_insensitive = True;
336Widget TM_entries[NUM_TM_ENTRIES];
337
338static void
339CreateTreeCommandMenu(Widget parent, String toolkit)
340{
341    int i, number;
342    static struct tree_ops_menu tree_menu[] = {
343	{ "showClientWidget", FIND, (XtPointer) NULL },
344        { "selectAll", SELECT, (XtPointer) SelectAll },
345	{ "unselectAll", SELECT, (XtPointer) SelectNone },
346	{ "invertAll", SELECT, (XtPointer) SelectInvert },
347	{ "line", LINE, (XtPointer) NULL },
348	{ "selectChildren", SELECT, (XtPointer) SelectChildren },
349        { "selectParent", SELECT, (XtPointer) SelectParent },
350	{ "selectDescendants", SELECT, (XtPointer) SelectDescendants },
351        { "selectAncestors", SELECT, (XtPointer) SelectAncestors },
352        { "line", LINE, (XtPointer) NULL },
353        { "showWidgetNames", LABEL, (XtPointer) NameLabel },
354        { "showClassNames", LABEL, (XtPointer) ClassLabel },
355        { "showWidgetIDs", LABEL, (XtPointer) IDLabel},
356        { "showWidgetWindows", LABEL, (XtPointer) WindowLabel },
357        { "line", LINE, (XtPointer) NULL },
358	{ "flashActiveWidgets", FLASH, (XtPointer) NULL }
359    };
360    Arg args[1];
361
362    if (tmenu) { XtDestroyWidget(tmenu); TM_set_insensitive = False; }
363    else
364      tbutton = XtCreateManagedWidget("treeCommands", menuButtonWidgetClass,
365				      parent, NULL, ZERO);
366
367    XtSetArg(args[0], XtNmenuName, toolkit);
368    XtSetValues(tbutton, args, ONE);
369
370    tmenu = XtCreatePopupShell(toolkit, simpleMenuWidgetClass, tbutton,
371			      NULL, ZERO);
372
373    for ( i = 0, number = XtNumber(tree_menu) ; i < number ; i++) {
374	XtCallbackProc func;
375	WidgetClass class = smeBSBObjectClass;
376
377	switch (tree_menu[i].type) {
378	case SELECT:
379	    func = TreeSelect;
380	    break;
381	case LABEL:
382	    func = TreeRelabel;
383	    break;
384	case LINE:
385	    func = NULL;
386	    class = smeLineObjectClass;
387	    break;
388	case FIND:
389	    func = FindWidget;
390	    break;
391	case FLASH:
392	    func = FlashActiveWidgets;
393	    break;
394	default:
395	    continue;
396	}
397
398	TM_entries[i] = XtCreateManagedWidget(tree_menu[i].name, class, tmenu,
399				      NULL, ZERO);
400	if (func != NULL)
401	    XtAddCallback(TM_entries[i], XtNcallback, func,tree_menu[i].data);
402    }
403    if (TM_set_insensitive) SetEntriesSensitive(&TM_entries[TM_OFFSET],
404						 TM_NUM, False);
405}
406
407
408
409static Pixmap old_pixmap;
410
411/*	Function Name: PrepareToLayoutTree
412 *	Description: prepares the Tree widget to be layed out.
413 *	Arguments: tree - the Tree widget.
414 *	Returns: none
415 */
416
417void
418PrepareToLayoutTree(Widget tree)
419{
420    Arg args[1];
421
422    XtSetArg(args[0], XtNbackgroundPixmap, &old_pixmap);
423    XtGetValues(XtParent(tree), args, ONE);
424
425    XtSetArg(args[0], XtNbackgroundPixmap, None);
426    XtSetValues(XtParent(tree), args, ONE);
427
428    XtUnmapWidget(tree);
429}
430
431
432
433/*	Function Name: LayoutTree
434 *	Description: Laysout the tree widget.
435 *	Arguments: tree - the widget tree.
436 *	Returns: none.
437 */
438
439void
440LayoutTree(Widget tree)
441{
442    Arg args[1];
443
444    XawTreeForceLayout(tree);
445    XtMapWidget(tree);
446
447    XtSetArg(args[0], XtNbackgroundPixmap, old_pixmap);
448    XtSetValues(XtParent(tree), args, ONE);
449}
450
451
452
453/************************************************************
454 *
455 * Functions for creating the Resource Box.
456 *
457 ************************************************************/
458
459/*	Function Name: CreateResourceBoxWidgets
460 *	Description: Creates the widgets that make up the resource box.
461 *	Arguments: node - the widget node.
462 *                 names - the list of names that make up the normal resources.
463 *                 cons_names - the list of names that make up
464 *                              the constraint resources.
465 *	Returns: none.
466 */
467
468void
469CreateResourceBoxWidgets(WNode *node, char **names, char **cons_names)
470{
471    Widget pane, box, button, viewport, pane_child;
472    ResourceBoxInfo * res_box;
473    Dimension max_width = WidthOfScreen(XtScreen(node->widget)) - 20;
474    Dimension max_height = HeightOfScreen(XtScreen(node->widget)) - 40;
475
476    res_box = (ResourceBoxInfo *) XtMalloc(sizeof(ResourceBoxInfo));
477    node->resources->res_box = res_box;
478
479    res_box->shell = XtVaCreatePopupShell(global_effective_toolkit,
480					  /*RESOURCE_BOX,*/
481					  transientShellWidgetClass,
482					  node->widget,
483					  XtNmaxWidth, max_width,
484					  XtNmaxHeight, max_height, NULL);
485    XtAddCallback(res_box->shell, XtNdestroyCallback,
486		  FreeResBox, (XtPointer) node);
487
488    pane = XtCreateManagedWidget("pane", panedWidgetClass,
489				 res_box->shell, NULL, ZERO);
490
491    viewport = XtCreateManagedWidget("mainViewport", viewportWidgetClass,
492				     pane, NULL, 0);
493    pane_child = XtCreateManagedWidget("pane", panedWidgetClass,
494				       viewport, NULL, ZERO);
495
496    res_box->res_label = XtCreateManagedWidget("resourceLabel",
497					       labelWidgetClass,
498					       pane_child, NULL, ZERO);
499
500    CreateResourceNameForm(pane_child, node);
501    CreateLists(pane_child, node, names, cons_names);
502    CreateValueWidget(pane, node);
503
504    XtSetKeyboardFocus(pane, res_box->value_wid); /* send keyboard to value. */
505
506    box = XtCreateManagedWidget("commandBox", boxWidgetClass,
507				 pane, NULL, ZERO);
508
509    button = XtCreateManagedWidget("setFile", commandWidgetClass,
510				   box, NULL, ZERO);
511    XtAddCallback(button, XtNcallback, SetFile, NULL);
512
513    button = XtCreateManagedWidget("save", commandWidgetClass,
514				   box, NULL, ZERO);
515    XtAddCallback(button, XtNcallback, SaveResource,(XtPointer) res_box);
516
517    button = XtCreateManagedWidget("apply", commandWidgetClass,
518				   box, NULL, ZERO);
519    XtAddCallback(button, XtNcallback, ApplyResource,(XtPointer) node);
520
521    button = XtCreateManagedWidget("saveAndApply", commandWidgetClass,
522				   box, NULL, ZERO);
523    XtAddCallback(button, XtNcallback, SaveResource,(XtPointer) res_box);
524    XtAddCallback(button, XtNcallback, ApplyResource,(XtPointer) node);
525
526    button = XtCreateManagedWidget("cancel", commandWidgetClass,
527				   box, NULL, ZERO);
528    XtAddCallback(button,XtNcallback,PopdownResBox,(XtPointer)res_box->shell);
529
530    SetToggleGroupLeaders(node);
531    PopupOnNode(node, res_box->shell);
532}
533
534
535
536/*	Function Name: CreateResourceNameForm
537 *	Description: Creates the Form widget with children that represent
538 *                   the full resource name for this object.
539 *	Arguments: parent - parent of the form.
540 *                 node - the node corrosponding to this object.
541 *	Returns: none
542 */
543
544static void
545CreateResourceNameForm(Widget parent, WNode *node)
546{
547    ResourceBoxInfo * res_box = node->resources->res_box;
548    AnyInfo *new_info = NULL, *old_info;
549    char **names, **classes;
550    Widget form;
551    NameInfo * name_info = NULL;
552    Cardinal num_args;
553    Arg args[10];
554    int i;
555    Widget dot, star, name, class, single, any;
556
557    GetNamesAndClasses(node, &names, &classes);
558
559    form = XtCreateManagedWidget("namesAndClasses", formWidgetClass,
560				 parent, NULL, ZERO);
561
562    name = class = any = NULL;
563    i = 0;
564    old_info = NULL;
565    while (TRUE) {
566
567	num_args = 0;
568	XtSetArg(args[num_args], XtNfromHoriz, name); num_args++;
569	XtSetArg(args[num_args], XtNradioData, "."); num_args++;
570	dot = XtCreateManagedWidget("dot", toggleWidgetClass,
571				    form, args, num_args);
572	XtAddCallback(dot, XtNcallback,
573		      ActivateWidgetsAndSetResourceString,(XtPointer) node);
574
575	num_args = 0;
576	XtSetArg(args[num_args], XtNfromHoriz, class); num_args++;
577	XtSetArg(args[num_args], XtNfromVert, dot); num_args++;
578	XtSetArg(args[num_args], XtNradioGroup, dot); num_args++;
579	XtSetArg(args[num_args], XtNradioData, "*"); num_args++;
580	star = XtCreateManagedWidget("star", toggleWidgetClass,
581				     form, args, num_args);
582	XtAddCallback(star,XtNcallback,
583		      ActivateWidgetsAndSetResourceString, (XtPointer) node);
584
585	if (name_info != NULL) {
586	    name_info->next = (NameInfo *) XtMalloc(sizeof(NameInfo));
587	    name_info = name_info->next;
588	}
589	else
590	    res_box->name_info =
591		     name_info = (NameInfo *) XtMalloc(sizeof(NameInfo));
592
593	name_info->sep_leader = dot;
594	name_info->name_leader = NULL;
595
596	if (names[i] != NULL) {
597	    new_info = (AnyInfo *) XtMalloc(sizeof(AnyInfo));
598	    new_info->node = node;
599	    new_info->left_dot = dot;
600	    new_info->left_star = star;
601	    new_info->left_count = 0;
602	    if (old_info != NULL)
603		old_info->right_count = &(new_info->left_count);
604	}
605	else if (old_info != NULL)
606	    old_info->right_count = NULL;
607
608	if (old_info != NULL) {
609	    old_info->right_dot = dot;
610	    old_info->right_star = star;
611
612	    XtAddCallback(any, XtNcallback, AnyChosen, (XtPointer) old_info);
613	    XtAddCallback(any, XtNdestroyCallback,
614			  FreeClientData, (XtPointer) old_info);
615	}
616
617	if ( names[i] == NULL) /* no more name and class boxes. */
618	    break;
619
620	old_info = new_info;
621
622	num_args = 0;
623	XtSetArg(args[num_args], XtNfromHoriz, dot); num_args++;
624	XtSetArg(args[num_args], XtNlabel, names[i]); num_args++;
625	XtSetArg(args[num_args], XtNradioData, names[i]); num_args++;
626	name = XtCreateManagedWidget("name", toggleWidgetClass,
627				     form, args, num_args);
628	XtAddCallback(name,XtNcallback,
629		      ActivateWidgetsAndSetResourceString,(XtPointer) node);
630
631	num_args = 0;
632	XtSetArg(args[num_args], XtNfromHoriz, star); num_args++;
633	XtSetArg(args[num_args], XtNfromVert, name); num_args++;
634	XtSetArg(args[num_args], XtNlabel, classes[i]); num_args++;
635	XtSetArg(args[num_args], XtNradioGroup, name); num_args++;
636	XtSetArg(args[num_args], XtNradioData, classes[i]); num_args++;
637	class = XtCreateManagedWidget("class", toggleWidgetClass,
638				      form,args,num_args);
639	XtAddCallback(class, XtNcallback,
640		      ActivateWidgetsAndSetResourceString,(XtPointer) node);
641
642	num_args = 0;
643	XtSetArg(args[num_args], XtNfromHoriz, star); num_args++;
644	XtSetArg(args[num_args], XtNfromVert, class); num_args++;
645	XtSetArg(args[num_args], XtNradioData, "?"); num_args++;
646	XtSetArg(args[num_args], XtNradioGroup, name); num_args++;
647	single = XtCreateManagedWidget("single", toggleWidgetClass,
648				       form, args, num_args);
649	XtAddCallback(single,XtNcallback,
650		      ActivateWidgetsAndSetResourceString,(XtPointer) node);
651
652	num_args = 0;
653	XtSetArg(args[num_args], XtNfromHoriz, any); num_args++;
654	XtSetArg(args[num_args], XtNfromVert, single); num_args++;
655	XtSetArg(args[num_args], XtNradioGroup, name); num_args++;
656	XtSetArg(args[num_args], XtNradioData, ANY_RADIO_DATA); num_args++;
657	any = XtCreateManagedWidget("any", toggleWidgetClass,
658				    form, args, num_args);
659
660	name_info->name_leader = name;
661
662	MakeBoxLookNice(dot, star, any, single, name, class,
663			(i == 0 ? -1 : (names[i + 1] ? 0 : 1)));
664
665	i++;
666    }
667
668    name_info->next = NULL;
669    XtFree((char *)names);		/* Free what you allocate... */
670    XtFree((char *)classes);
671}
672
673
674
675/*	Function Name: SetToggleGroupLeaders
676 *	Description: Sets the leaders of each toggle group.
677 *                 node - The widget node containing this res box.
678 *	Returns: none
679 */
680
681static void
682SetToggleGroupLeaders(WNode *node)
683{
684    NameInfo *name;
685    ResourceBoxInfo * res_box = node->resources->res_box;
686    static Arg args[] = {
687	{XtNstate, (XtArgVal) TRUE}
688    };
689
690    for (name  = res_box->name_info; name != NULL; name = name->next) {
691	XtSetValues(name->sep_leader, args, XtNumber(args));
692	if (name->name_leader != NULL)
693	    XtSetValues(name->name_leader, args, XtNumber(args));
694    }
695    SetResourceString(NULL, (XtPointer) node, NULL);
696}
697
698
699
700/*	Function Name: MakeBoxLookNice
701 *	Description: Resizes the box that contains the resource names
702 *                   to look a bit nicer.
703 *	Arguments: dot, star - the widgets containing the separator types.
704 *                 any, single, name, class - the widgets that contain the
705 *                                     name and class of this object.
706 *	Returns: none.
707 */
708
709static void
710MakeBoxLookNice(Widget dot, Widget star, Widget any, Widget single,
711		Widget name, Widget class, int endbox)
712{
713
714#define MAX_HDIST 3
715
716    Arg args[10];
717    Cardinal num_args;
718    Dimension any_width, name_class_width, dot_star_width;
719    Dimension width_1, width_2;
720    int h_dist[MAX_HDIST];
721    int i;
722
723    /*
724     * Make sure that the dot and star widgets are the same size.
725     */
726
727    num_args = 0;
728    XtSetArg(args[num_args], XtNhorizDistance, &(h_dist[0])); num_args++;
729    XtSetArg(args[num_args], XtNwidth, &width_1); num_args++;
730    XtGetValues(dot, args, num_args);
731
732    num_args = 0;
733    XtSetArg(args[num_args], XtNhorizDistance, &(h_dist[1])); num_args++;
734    XtSetArg(args[num_args], XtNwidth, &width_2); num_args++;
735    XtGetValues(star, args, num_args);
736
737    num_args = 0;
738    XtSetArg(args[num_args], XtNhorizDistance, &(h_dist[2])); num_args++;
739    XtSetArg(args[num_args], XtNwidth, &any_width); num_args++;
740    XtGetValues(any, args, num_args);
741
742    dot_star_width = (width_1 > width_2) ? width_1 : width_2;
743    for (i = 1 ; i < MAX_HDIST; i++) {
744	if (h_dist[i] > h_dist[0]) h_dist[0] = h_dist[i];
745    }
746
747    num_args = 0;
748    XtSetArg(args[num_args], XtNhorizDistance, h_dist[0]); num_args++;
749    XtSetValues(any, args, num_args);
750
751    /*
752     * Add a new arg, and continue...
753     */
754    XtSetArg(args[num_args], XtNwidth, dot_star_width); num_args++;
755    XtSetValues(star, args, num_args);
756    XtSetValues(dot, args, num_args);
757
758
759    /*
760     * Now make sure that the Any Widget is as wide as the longest
761     * of the name and class widgets, plus space for the dot and star widgets.
762     * Don't forget the Form widget's internal space.
763     */
764
765    num_args = 0;
766    XtSetArg(args[num_args], XtNwidth, &width_1); num_args++;
767    XtSetArg(args[num_args], XtNhorizDistance, &(h_dist[0])); num_args++;
768    XtGetValues(name, args, num_args);
769
770    num_args = 0;
771    XtSetArg(args[num_args], XtNwidth, &width_2); num_args++;
772    XtSetArg(args[num_args], XtNhorizDistance, &(h_dist[1])); num_args++;
773    XtGetValues(class, args, num_args);
774
775    if (width_2 > width_1) width_1 = width_2;
776    if (h_dist[1] > h_dist[0]) h_dist[0] = h_dist[1];
777
778    num_args = 0;
779    XtSetArg(args[num_args], XtNwidth, &width_2); num_args++;
780    XtSetArg(args[num_args], XtNhorizDistance, &(h_dist[1])); num_args++;
781    XtGetValues(single, args, num_args);
782
783    name_class_width = (width_1 > width_2) ? width_1 : width_2;
784    if (h_dist[1] > h_dist[0]) h_dist[0] = h_dist[1];
785    if (any_width > name_class_width)
786	name_class_width = any_width;
787    any_width = dot_star_width + h_dist[0] + name_class_width;
788
789    num_args = 0;
790    if (endbox < 0) {
791	any_width -= dot_star_width & 1;
792	XtSetArg(args[num_args], XtNhorizDistance,
793		 h_dist[2] + (dot_star_width >> 1) + (dot_star_width & 1));
794	++num_args;
795    }
796
797    XtSetArg(args[num_args], XtNwidth, any_width); num_args++;
798    XtSetValues(any, args, num_args);
799
800    num_args = 0;
801    XtSetArg(args[num_args], XtNwidth, name_class_width); num_args++;
802    XtSetArg(args[num_args], XtNhorizDistance, h_dist[0]); num_args++;
803    XtSetValues(name, args, num_args);
804    XtSetValues(class, args, num_args);
805    XtSetValues(single, args, num_args);
806}
807
808
809
810/*	Function Name: CreateLists
811 *	Description: Creates the list widgets for the normal and constraint
812 *                   resources
813 *	Arguments: parent - parent of the lists.
814 *                 node - The widget node containing this res box.
815 *                 names, cons_names - lists for norm and cons resource boxes.
816 *	Returns: none
817 */
818
819static char* noneList[] = {"None"};
820
821static void
822CreateLists(Widget parent, WNode *node, char **names, char **cons_names)
823{
824    Widget viewport;
825    Cardinal num_args;
826    ResourceBoxInfo * res_box = node->resources->res_box;
827    Arg args[3];
828
829    (void) XtCreateManagedWidget("namesLabel", labelWidgetClass,
830				 parent, NULL, ZERO);
831
832    num_args = 0;
833    /* if the first list item is the widget name we want an empty
834     * list.
835     */
836    if (!names) {
837        XtSetArg(args[num_args], XtNlist, noneList); num_args++;
838        XtSetArg(args[num_args], XtNnumberStrings, 1); num_args++;
839        XtSetArg(args[num_args], XtNsensitive, False); num_args++;
840    }
841    else { XtSetArg(args[num_args], XtNlist, names); num_args++; }
842    viewport = XtCreateManagedWidget("normalViewport", viewportWidgetClass,
843				     parent, NULL, 0);
844    res_box->norm_list = XtCreateManagedWidget("namesList", listWidgetClass,
845				      viewport, args, num_args);
846    XtAddCallback(res_box->norm_list, XtNcallback,
847		  ResourceListCallback, (XtPointer) node);
848    XtAddCallback(res_box->norm_list, XtNdestroyCallback,
849		  FreeClientData, (XtPointer) names);
850
851    if (cons_names != NULL) {
852	(void) XtCreateManagedWidget("constraintLabel", labelWidgetClass,
853				     parent, NULL, ZERO);
854
855	num_args = 0;
856	XtSetArg(args[num_args], XtNlist, cons_names); num_args++;
857	viewport = XtCreateManagedWidget("constraintViewport", viewportWidgetClass,
858					 parent, NULL, 0);
859	res_box->cons_list = XtCreateManagedWidget("constraintList",
860						   listWidgetClass,
861						   viewport, args, num_args);
862	XtAddCallback(res_box->cons_list, XtNcallback,
863		      ResourceListCallback, (XtPointer) node);
864	XtAddCallback(res_box->cons_list, XtNdestroyCallback,
865		      FreeClientData, (XtPointer) cons_names);
866    }
867    else
868	res_box->cons_list = NULL;
869}
870
871/*	Function Name: CreateValueWidget
872 *	Description: Creates the value widget for entering the resources value.
873 *	Arguments: parent - parent of this widget.
874 *                 res_box - the resource box info.
875 *	Returns: none.
876 */
877
878static void
879CreateValueWidget(Widget parent, WNode *node)
880{
881    Widget form, label;
882    Cardinal num_args;
883    Arg args[10];
884    ResourceBoxInfo * res_box = node->resources->res_box;
885
886    form = XtCreateManagedWidget("valueForm", formWidgetClass,
887				 parent, NULL, ZERO);
888
889    num_args = 0;
890    XtSetArg(args[num_args], XtNleft, XawChainLeft); num_args++;
891    XtSetArg(args[num_args], XtNright, XawChainLeft); num_args++;
892    XtSetArg(args[num_args], XtNtop, XawChainTop); num_args++;
893    XtSetArg(args[num_args], XtNbottom, XawChainBottom); num_args++;
894    label = XtCreateManagedWidget("valueLabel", labelWidgetClass,
895				 form, args, num_args);
896
897    num_args = 0;
898    XtSetArg(args[num_args], XtNfromHoriz, label); num_args++;
899    XtSetArg(args[num_args], XtNleft, XawChainLeft); num_args++;
900    XtSetArg(args[num_args], XtNright, XawChainRight); num_args++;
901    XtSetArg(args[num_args], XtNtop, XawChainTop); num_args++;
902    XtSetArg(args[num_args], XtNbottom, XawChainBottom); num_args++;
903    res_box->value_wid = XtCreateManagedWidget("valueText",
904					       asciiTextWidgetClass,
905					       form, args, num_args);
906#ifdef notdef
907    XtAddCallback(XawTextGetSource(res_box->value_wid), XtNcallback,
908		  SetResourceString, (XtPointer) node);
909#endif
910}
911
912
913
914/*	Function Name: PopupOnNode
915 *	Description: Pops a shell widget up centered on the node specified.
916 *	Arguments: node - the node.
917 *                 shell - the shell to popup.
918 *	Returns: none.
919 */
920
921static void
922PopupOnNode(WNode *node, Widget shell)
923{
924    Arg args[3];
925    Cardinal num_args;
926    Position x, y, max_loc;
927    Dimension width, height, bw;
928
929    num_args = 0;
930    XtSetArg(args[num_args], XtNwidth, &width); num_args++;
931    XtSetArg(args[num_args], XtNheight, &height); num_args++;
932    XtSetArg(args[num_args], XtNborderWidth, &bw); num_args++;
933    XtGetValues(node->widget, args, num_args);
934    XtTranslateCoords(node->widget,
935		      (Position) (width/2 + bw), (Position) (height/2 + bw),
936		      &x, &y);
937
938    XtOverrideTranslations
939      (shell, XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()"));
940    XtRealizeWidget(shell);
941    wm_delete_window = XInternAtom(XtDisplay(shell), "WM_DELETE_WINDOW",
942				   False);
943    (void) XSetWMProtocols (XtDisplay(shell), XtWindow(shell),
944                            &wm_delete_window, 1);
945    XtGetValues(shell, args, num_args);	/* use same arg_list. */
946
947    x -= (Position) (width/2 + bw);
948    y -= (Position) (height/2 + bw);
949
950    max_loc = WidthOfScreen(XtScreen(shell)) - (Position) (width + 2 * bw);
951    if (x > max_loc)
952	x = max_loc;
953    if (x < 0)
954	x = 0;
955
956    max_loc = HeightOfScreen(XtScreen(shell)) - (Position) (height + 2 * bw);
957    if (y > max_loc)
958	y = max_loc;
959    if (y < 0)
960	y = 0;
961
962    num_args = 0;
963    XtSetArg(args[num_args], XtNx, x); num_args++;
964    XtSetArg(args[num_args], XtNy, y); num_args++;
965    XtSetValues(shell, args, num_args);
966
967    XtPopup(shell, XtGrabNone);
968}
969
970
971
972/*	Function Name: FreeClientData
973 *	Description: Frees the client data passed to this function.
974 *	Arguments: w - UNUSED.
975 *                 list_ptr - pointer to the list to check.
976 *                 junk - UNUSED.
977 *	Returns: none
978 */
979
980/* ARGSUSED */
981static void
982FreeClientData(Widget w, XtPointer ptr, XtPointer junk)
983{
984    XtFree(ptr);
985}
986
987
988
989/*	Function Name: FreeResBox.
990 *	Description: Frees resource box allocated memory.
991 *	Arguments: w - UNUSED.
992 *                 ptr - pointer to the node that has this resources box.
993 *                 junk - UNUSED.
994 *	Returns: none
995 */
996
997/* ARGSUSED */
998static void
999FreeResBox(Widget w, XtPointer ptr, XtPointer junk)
1000{
1001    WNode * node = (WNode *) ptr;
1002    NameInfo *old_name, *name = node->resources->res_box->name_info;
1003
1004    global_resource_box_up = FALSE;
1005
1006    XtFree((XtPointer) node->resources->res_box);
1007    node->resources->res_box = NULL;
1008
1009    while (name != NULL) {
1010	old_name = name;
1011	name = name->next;
1012	XtFree((XtPointer) old_name);
1013    }
1014}
1015
1016
1017
1018