1/*
2
3Copyright (c) 1987, 1988  X Consortium
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be included
14in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of the X Consortium shall
25not be used in advertising or otherwise to promote the sale, use or
26other dealings in this Software without prior written authorization
27from the X Consortium.
28
29*/
30
31/*
32 * xman - X window system manual page display program.
33 * Author:    Chris D. Peterson, MIT Project Athena
34 * Created:   October 27, 1987
35 */
36
37#include "globals.h"
38#include "vendor.h"
39
40/* The files with the icon bits in them. */
41
42#include "icon_open.h"
43#include "icon_help.h"
44#include "iconclosed.h"
45
46static void CreateOptionMenu(ManpageGlobals * man_globals, Widget parent);
47static void CreateSectionMenu(ManpageGlobals * man_globals, Widget parent);
48static void StartManpage(ManpageGlobals * man_globals, Boolean help,
49                         Boolean page);
50static Widget *ConvertNamesToWidgets(Widget parent, const char **names);
51
52/*	Function Name: MakeTopBox
53 *	Description: This function creates the top menu, in a shell widget.
54 *	Arguments: none.
55 *	Returns: the top level widget
56 */
57
58#define TOPARGS 5
59
60Widget top;                     /* needed in PopupWarning, misc.c */
61
62void
63MakeTopBox(void)
64{
65    Widget form, command, label;        /* widgets. */
66    Arg arglist[TOPARGS];       /* An argument list */
67    Cardinal num_args = 0;      /* The number of arguments. */
68    ManpageGlobals *man_globals;
69    static const char *full_size[] = {
70        "topLabel", MANPAGE_BUTTON, NULL
71    };
72    static const char *half_size[] = {
73        HELP_BUTTON, QUIT_BUTTON, NULL
74    };
75
76/* create the top icon. */
77
78    num_args = 0;
79    XtSetArg(arglist[num_args], XtNiconPixmap,
80             XCreateBitmapFromData(XtDisplay(initial_widget),
81                                   XtScreen(initial_widget)->root,
82                                   (const char *) iconclosed_bits,
83                                   iconclosed_width, iconclosed_height));
84    num_args++;
85    XtSetArg(arglist[num_args], XtNtitle, resources.title);
86    num_args++;
87    XtSetArg(arglist[num_args], XtNiconic, resources.iconic);
88    num_args++;
89    top = XtCreatePopupShell(TOPBOXNAME, topLevelShellWidgetClass,
90                             initial_widget, arglist, num_args);
91
92    form = XtCreateManagedWidget("form", formWidgetClass, top,
93                                 NULL, (Cardinal) 0);
94
95    label = XtCreateManagedWidget("topLabel", labelWidgetClass, form,
96                                  NULL, (Cardinal) 0);
97
98    num_args = 0;
99    XtSetArg(arglist[num_args], XtNfromVert, label);
100    num_args++;
101    command = XtCreateManagedWidget(HELP_BUTTON, commandWidgetClass, form,
102                                    arglist, num_args);
103
104    /* use same vertical as help widget. */
105    XtSetArg(arglist[num_args], XtNfromHoriz, command);
106    num_args++;
107    command = XtCreateManagedWidget(QUIT_BUTTON, commandWidgetClass, form,
108                                    arglist, num_args);
109
110    num_args = 0;
111    XtSetArg(arglist[num_args], XtNfromVert, command);
112    num_args++;
113    command = XtCreateManagedWidget(MANPAGE_BUTTON, commandWidgetClass, form,
114                                    arglist, num_args);
115
116    help_widget = NULL;         /* We have not seen the help yet. */
117
118    FormUpWidgets(form, full_size, half_size);
119
120    XtRealizeWidget(top);
121    /* add WM_COMMAND property */
122    XSetCommand(XtDisplay(top), XtWindow(top), saved_argv, saved_argc);
123
124    man_globals =
125        (ManpageGlobals *) XtCalloc(ONE, (Cardinal) sizeof(ManpageGlobals));
126    MakeSearchWidget(man_globals, top);
127    MakeSaveWidgets(man_globals, top);
128
129    SaveGlobals((man_globals->This_Manpage = top), man_globals);
130    XtMapWidget(top);
131    AddCursor(top, resources.cursors.top);
132
133/*
134 * Set up ICCCM delete window.
135 */
136    XtOverrideTranslations
137        (top, XtParseTranslationTable("<Message>WM_PROTOCOLS: Quit()"));
138    (void) XSetWMProtocols(XtDisplay(top), XtWindow(top), &wm_delete_window, 1);
139
140}
141
142/*	Function Name: CreateManpage
143 *	Description: Creates a new manpage.
144 *	Arguments: none.
145 *	Returns: none.
146 */
147
148Widget
149CreateManpage(FILE * file)
150{
151    ManpageGlobals *man_globals;        /* The pseudo global structure. */
152
153    man_globals = InitPsuedoGlobals();
154    if (man_globals == NULL)
155        return NULL;
156    CreateManpageWidget(man_globals, MANNAME, TRUE);
157
158    if (file == NULL)
159        StartManpage(man_globals, OpenHelpfile(man_globals), FALSE);
160    else {
161        OpenFile(man_globals, file);
162        StartManpage(man_globals, FALSE, TRUE);
163    }
164    return (man_globals->This_Manpage);
165}
166
167/*	Function Name: InitPsuedoGlobals
168 *	Description: Initializes the pseudo global variables.
169 *	Arguments: none.
170 *	Returns: a pointer to a new pseudo globals structure.
171 */
172
173ManpageGlobals *
174InitPsuedoGlobals(void)
175{
176    ManpageGlobals *man_globals;
177
178    /*
179     * Allocate necessary memory.
180     */
181
182    man_globals =
183        (ManpageGlobals *) XtCalloc(ONE, (Cardinal) sizeof(ManpageGlobals));
184    if (!man_globals)
185        return NULL;
186
187    man_globals->search_widget = NULL;
188    man_globals->section_name = (char **) XtMalloc((Cardinal) (sections *
189                                                               sizeof(char *)));
190    man_globals->manpagewidgets.box = (Widget *) XtCalloc((Cardinal) sections,
191                                                          (Cardinal)
192                                                          sizeof(Widget));
193
194    /* Initialize the number of screens that will be shown */
195
196    man_globals->both_shown = resources.both_shown_initial;
197
198    return (man_globals);
199}
200
201/*	Function Name: CreateManpageWidget
202 *	Description: Creates a new manual page widget.
203 *	Arguments: man_globals - a new man_globals structure.
204 *                 name         - name of this shell widget instance.
205 *                 full_instance - if true then create a full manpage,
206 *                                 otherwise create stripped down version
207 *                                 used for help.
208 *	Returns: none
209 */
210
211#define MANPAGEARGS 10
212
213void
214CreateManpageWidget(ManpageGlobals * man_globals,
215                    String name, Boolean full_instance)
216{
217    Arg arglist[MANPAGEARGS];   /* An argument list for widget creation */
218    Cardinal num_args;          /* The number of arguments in the list. */
219    Widget mytop, pane, hpane, mysections;      /* Widgets */
220    ManPageWidgets *mpw = &(man_globals->manpagewidgets);
221
222    num_args = (Cardinal) 0;
223    XtSetArg(arglist[num_args], XtNwidth, default_width);
224    num_args++;
225    XtSetArg(arglist[num_args], XtNheight, default_height);
226    num_args++;
227
228    mytop = XtCreatePopupShell(name, topLevelShellWidgetClass, initial_widget,
229                               arglist, num_args);
230
231    man_globals->This_Manpage = mytop;  /* pointer to root widget of Manualpage. */
232    num_args = 0;
233    if (full_instance)
234        XtSetArg(arglist[num_args], XtNiconPixmap,
235                 XCreateBitmapFromData(XtDisplay(mytop), XtScreen(mytop)->root,
236                                       (const char *) icon_open_bits,
237                                       icon_open_width, icon_open_height));
238    else
239        XtSetArg(arglist[num_args], XtNiconPixmap,
240                 XCreateBitmapFromData(XtDisplay(mytop), XtScreen(mytop)->root,
241                                       (const char *) icon_help_bits,
242                                       icon_help_width, icon_help_height));
243    num_args++;
244    XtSetValues(mytop, arglist, num_args);
245
246    pane = XtCreateManagedWidget("vertPane", panedWidgetClass, mytop, NULL,
247                                 (Cardinal) 0);
248
249/* Create menu bar. */
250
251    hpane = XtCreateManagedWidget("horizPane", panedWidgetClass,
252                                  pane, NULL, (Cardinal) 0);
253    num_args = 0;
254    XtSetArg(arglist[num_args], XtNmenuName, OPTION_MENU);
255    num_args++;
256    (void) XtCreateManagedWidget("options", menuButtonWidgetClass,
257                                 hpane, arglist, num_args);
258
259    CreateOptionMenu(man_globals, mytop);
260
261    num_args = 0;
262    XtSetArg(arglist[num_args], XtNmenuName, SECTION_MENU);
263    num_args++;
264    mysections = XtCreateManagedWidget("sections", menuButtonWidgetClass,
265                                       hpane, arglist, num_args);
266
267    XtSetArg(arglist[0], XtNlabel, SHOW_BOTH);
268    XtSetValues(man_globals->both_screens_entry, arglist, (Cardinal) 1);
269
270    if (full_instance) {
271        MakeSearchWidget(man_globals, mytop);
272        CreateSectionMenu(man_globals, mytop);
273        MakeSaveWidgets(man_globals, mytop);
274    }
275    else {
276        XtSetSensitive(mysections, FALSE);
277        XtSetArg(arglist[0], XtNsensitive, FALSE);
278        XtSetValues(man_globals->dir_entry, arglist, ONE);
279        XtSetValues(man_globals->manpage_entry, arglist, ONE);
280        XtSetValues(man_globals->help_entry, arglist, ONE);
281        XtSetValues(man_globals->search_entry, arglist, ONE);
282        XtSetValues(man_globals->both_screens_entry, arglist, ONE);
283    }
284
285
286    man_globals->label = XtCreateManagedWidget("manualTitle", labelWidgetClass,
287                                               hpane, NULL, (Cardinal) 0);
288
289/* Create Directory */
290
291    if (full_instance) {
292        num_args = 0;
293        XtSetArg(arglist[num_args], XtNallowVert, TRUE);
294        num_args++;
295
296        mpw->directory = XtCreateWidget(DIRECTORY_NAME, viewportWidgetClass,
297                                        pane, arglist, num_args);
298
299        man_globals->current_directory = INITIAL_DIR;
300        MakeDirectoryBox(man_globals, mpw->directory,
301                         mpw->box + man_globals->current_directory,
302                         man_globals->current_directory);
303        XtManageChild(mpw->box[man_globals->current_directory]);
304    }
305
306/* Create Manpage */
307
308    mpw->manpage = XtCreateWidget(MANUALPAGE, scrollByLineWidgetClass,
309                                  pane, NULL, (Cardinal) 0);
310
311}
312
313/*	Function Name: StartManpage
314 *	Description: Starts up a new manpage.
315 *	Arguments: man_globals - the pseudo globals variable.
316 *                 help - is this a help file?
317 *                 page - Is there a page to display?
318 *	Returns: none.
319 */
320
321static void
322StartManpage(ManpageGlobals * man_globals, Boolean help, Boolean page)
323{
324    Widget dir = man_globals->manpagewidgets.directory;
325    Widget manpage = man_globals->manpagewidgets.manpage;
326    Widget label = man_globals->label;
327    Arg arglist[1];
328
329/*
330 * If there is a helpfile then put up both screens if both_show is set.
331 */
332
333    if (page || help) {
334        if (help)
335            strcpy(man_globals->manpage_title, "Xman Help");
336
337        if (man_globals->both_shown) {
338            XtManageChild(dir);
339            man_globals->dir_shown = TRUE;
340
341            XtSetArg(arglist[0], XtNpreferredPaneSize,
342                     resources.directory_height);
343            XtSetValues(dir, arglist, (Cardinal) 1);
344
345            XtSetArg(arglist[0], XtNsensitive, FALSE);
346            XtSetValues(man_globals->manpage_entry, arglist, ONE);
347            XtSetValues(man_globals->dir_entry, arglist, ONE);
348
349            XtSetArg(arglist[0], XtNlabel, SHOW_ONE);
350            XtSetValues(man_globals->both_screens_entry, arglist, ONE);
351            ChangeLabel(label,
352                        man_globals->section_name[man_globals->
353                                                  current_directory]);
354        }
355        else {
356            ChangeLabel(label, man_globals->manpage_title);
357        }
358        XtManageChild(manpage);
359        man_globals->dir_shown = FALSE;
360    }
361/*
362 * Since There is file to display, put up directory and do not allow change
363 * to manpage, show both, or help.
364 */
365    else {
366        XtManageChild(dir);
367        man_globals->dir_shown = TRUE;
368        XtSetArg(arglist[0], XtNsensitive, FALSE);
369        XtSetValues(man_globals->manpage_entry, arglist, ONE);
370        XtSetValues(man_globals->help_entry, arglist, ONE);
371        XtSetValues(man_globals->both_screens_entry, arglist, ONE);
372        man_globals->both_shown = FALSE;
373        ChangeLabel(label,
374                    man_globals->section_name[man_globals->current_directory]);
375    }
376
377/*
378 * Start 'er up, and change the cursor.
379 */
380
381    XtRealizeWidget(man_globals->This_Manpage);
382    SaveGlobals(man_globals->This_Manpage, man_globals);
383    XtMapWidget(man_globals->This_Manpage);
384    AddCursor(man_globals->This_Manpage, resources.cursors.manpage);
385    XtSetArg(arglist[0], XtNtransientFor, man_globals->This_Manpage);
386    XtSetValues(XtParent(man_globals->standby), arglist, (Cardinal) 1);
387    XtSetValues(XtParent(man_globals->save), arglist, (Cardinal) 1);
388    XtRealizeWidget(XtParent(man_globals->standby));
389    XtRealizeWidget(XtParent(man_globals->save));
390    AddCursor(XtParent(man_globals->standby), resources.cursors.top);
391    AddCursor(XtParent(man_globals->save), resources.cursors.top);
392
393/*
394 * Set up ICCCM delete window.
395 */
396    XtOverrideTranslations
397        (man_globals->This_Manpage,
398         XtParseTranslationTable("<Message>WM_PROTOCOLS: RemoveThisManpage()"));
399    (void) XSetWMProtocols(XtDisplay(man_globals->This_Manpage),
400                           XtWindow(man_globals->This_Manpage),
401                           &wm_delete_window, 1);
402
403}
404
405/*      Function Name: MenuDestroy
406 *      Description: free's data associated with menu when it is destroyed.
407 *      Arguments: w - menu widget.
408 *                 free_me - data to free.
409 *                 junk - not used.
410 *      Returns: none.
411 */
412
413/* ARGSUSED */
414static void
415MenuDestroy(Widget w, XtPointer free_me, XtPointer junk)
416{
417    XtFree((char *) free_me);
418}
419
420/*      Function Name:   CreateOptionMenu
421 *      Description: Create the option menu.
422 *      Arguments: man_globals - the manual page globals.
423 *                 parent - the button that activates the menu.
424 *      Returns: none.
425 */
426
427static void
428CreateOptionMenu(ManpageGlobals * man_globals, Widget parent)
429{
430    Widget menu, entry;
431    int i;
432    static const char *option_names[] = {     /* Names of the buttons. */
433        DIRECTORY,
434        MANPAGE,
435        HELP,
436        SEARCH,
437        BOTH_SCREENS,
438        REMOVE_MANPAGE,
439        OPEN_MANPAGE,
440        SHOW_VERSION,
441        QUIT
442    };
443
444    menu = XtCreatePopupShell(OPTION_MENU, simpleMenuWidgetClass, parent,
445                              NULL, (Cardinal) 0);
446    man_globals->option_menu = menu;
447
448    for (i = 0; i < NUM_OPTIONS; i++) {
449        entry = XtCreateManagedWidget(option_names[i], smeBSBObjectClass,
450                                      menu, NULL, ZERO);
451        XtAddCallback(entry, XtNcallback, OptionCallback,
452                      (caddr_t) man_globals);
453        switch (i) {
454        case 0:
455            man_globals->dir_entry = entry;
456            break;
457        case 1:
458            man_globals->manpage_entry = entry;
459            break;
460        case 2:
461            man_globals->help_entry = entry;
462            break;
463        case 3:
464            man_globals->search_entry = entry;
465            break;
466        case 4:
467            man_globals->both_screens_entry = entry;
468            break;
469        case 5:
470            man_globals->remove_entry = entry;
471            break;
472        case 6:
473            man_globals->open_entry = entry;
474            break;
475        case 7:
476            man_globals->version_entry = entry;
477            break;
478        case 8:
479            man_globals->quit_entry = entry;
480            break;
481        default:
482            Error(("CreateOptionMenu: Unknown id=%d\n", i));
483            break;
484        }
485    }
486
487}
488
489/*      Function Name: CreateSectionMenu
490 *      Description: Create the Section menu.
491 *      Arguments: man_globals - the manual page globals.
492 *                 parent - the button that activates the menu.
493 *      Returns: none.
494 */
495
496static void
497CreateSectionMenu(ManpageGlobals * man_globals, Widget parent)
498{
499    Widget menu, entry;
500    int i;
501    MenuStruct *menu_struct;
502    Arg args[1];
503    Cardinal num_args;
504    char entry_name[BUFSIZ];
505
506    menu = XtCreatePopupShell(SECTION_MENU, simpleMenuWidgetClass, parent,
507                              NULL, (Cardinal) 0);
508
509    for (i = 0; i < sections; i++) {
510        num_args = 0;
511        XtSetArg(args[num_args], XtNlabel, manual[i].blabel);
512        num_args++;
513        snprintf(entry_name, sizeof(entry_name), "section%d", i);
514
515        entry = XtCreateManagedWidget(entry_name, smeBSBObjectClass,
516                                      menu, args, num_args);
517        menu_struct = (MenuStruct *) XtMalloc(sizeof(MenuStruct));
518        menu_struct->data = (caddr_t) man_globals;
519        menu_struct->number = i;
520        XtAddCallback(entry, XtNcallback, DirPopupCallback,
521                      (caddr_t) menu_struct);
522        XtAddCallback(entry, XtNdestroyCallback, MenuDestroy,
523                      (caddr_t) menu_struct);
524
525    }
526}
527
528/*	Function Name: CreateList
529 *	Description: this function prints a label in the directory list
530 *	Arguments: section - the manual section.
531 *	Returns: none
532 */
533
534static char **
535CreateList(int section)
536{
537    char **ret_list, **current;
538    int count;
539
540    ret_list = (char **) XtMalloc((manual[section].nentries + 1) *
541                                  sizeof(char *));
542
543    for (current = ret_list, count = 0; count < manual[section].nentries;
544         count++, current++)
545        *current = CreateManpageName(manual[section].entries[count], section,
546                                     manual[section].flags);
547
548    *current = NULL;            /* NULL terminate the list. */
549    return (ret_list);
550}
551
552/*	Function Name: MakeDirectoryBox
553 *	Description: make a directory box.
554 *	Arguments: man_globals - the pseudo global structure for each manpage.
555 *                 parent - this guys parent widget.
556 *                 dir_disp - the directory display widget.
557 *                 section - the section number.
558 *	Returns: none.
559 */
560
561void
562MakeDirectoryBox(ManpageGlobals * man_globals, Widget parent, Widget * dir_disp,
563                 int section)
564{
565    Arg arglist[10];
566    Cardinal num_args;
567    char *name, label_name[BUFSIZ];
568
569    if (*dir_disp != NULL)      /* If we have one, don't make another. */
570        return;
571
572    name = manual[section].blabel;      /* Set the section name */
573    snprintf(label_name, sizeof(label_name), "Directory of: %s", name);
574    man_globals->section_name[section] = XtNewString(label_name);
575
576    num_args = 0;
577    XtSetArg(arglist[num_args], XtNlist, CreateList(section));
578    num_args++;
579    XtSetArg(arglist[num_args], XtNfont, resources.fonts.directory);
580    num_args++;
581
582    *dir_disp = XtCreateWidget(DIRECTORY_NAME, listWidgetClass, parent,
583                               arglist, num_args);
584
585    XtAddCallback(*dir_disp, XtNcallback,
586                  DirectoryHandler, (caddr_t) man_globals);
587}
588
589/*	Function Name: MakeSaveWidgets.
590 *	Description: This functions creates two popup widgets, the please
591 *                   standby widget and the would you like to save widget.
592 *	Arguments: man_globals - the pseudo globals structure for each man page
593 *                 parent - the realized parent for both popups.
594 *	Returns: none.
595 */
596
597void
598MakeSaveWidgets(ManpageGlobals * man_globals, Widget parent)
599{
600    Widget shell, dialog;       /* misc. widgets. */
601    Arg warg[1];
602    Cardinal n = 0;
603
604/* make the please stand by popup widget. */
605    if (XtIsRealized(parent)) {
606        XtSetArg(warg[0], XtNtransientFor, parent);
607        n++;
608    }
609    shell = XtCreatePopupShell("pleaseStandBy", transientShellWidgetClass,
610                               parent, warg, (Cardinal) n);
611
612    man_globals->standby = XtCreateManagedWidget("label", labelWidgetClass,
613                                                 shell, NULL, (Cardinal) 0);
614
615    man_globals->save = XtCreatePopupShell("likeToSave",
616                                           transientShellWidgetClass,
617                                           parent, warg, n);
618
619    dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
620                                   man_globals->save, NULL, (Cardinal) 0);
621
622    XawDialogAddButton(dialog, FILE_SAVE, NULL, NULL);
623    XawDialogAddButton(dialog, CANCEL_FILE_SAVE, NULL, NULL);
624
625    if (XtIsRealized(parent)) {
626        XtRealizeWidget(shell);
627        AddCursor(shell, resources.cursors.top);
628        XtRealizeWidget(man_globals->save);
629        AddCursor(man_globals->save, resources.cursors.top);
630    }
631}
632
633/*      Function Name: FormUpWidgets
634 *      Description: Sizes widgets to look nice.
635 *      Arguments: parent - the common parent of all the widgets.
636 *                 full_size - array of widget names that will be full size.
637 *                 half_size - array of widget names that will be half size.
638 *      Returns: none
639 */
640
641void
642FormUpWidgets(Widget parent, const char **full_size, const char **half_size)
643{
644    Widget *full_widgets, *half_widgets, *temp, long_widget;
645    Dimension longest, length, b_width;
646    int interior_dist;
647    Arg arglist[2];
648
649    full_widgets = ConvertNamesToWidgets(parent, full_size);
650    half_widgets = ConvertNamesToWidgets(parent, half_size);
651
652    long_widget = NULL;
653    longest = 0;
654    XtSetArg(arglist[0], XtNwidth, &length);
655    XtSetArg(arglist[1], XtNborderWidth, &b_width);
656
657/*
658 * Find Longest widget.
659 */
660
661    for (temp = full_widgets; *temp != (Widget) NULL; temp++) {
662        XtGetValues(*temp, arglist, (Cardinal) 2);
663        length += 2 * b_width;
664        if (length > longest) {
665            longest = length;
666            long_widget = *temp;
667        }
668    }
669
670    if (long_widget == (Widget) NULL) { /* Make sure we found one. */
671        PopupWarning(GetGlobals(parent),
672                     "Could not find longest widget, aborting...");
673        XtFree((char *) full_widgets);
674        XtFree((char *) half_widgets);
675        return;
676    }
677
678/*
679 * Set all other full_widgets to this length.
680 */
681
682    for (temp = full_widgets; *temp != (Widget) NULL; temp++)
683        if (long_widget != *temp) {
684            Dimension width, border_width;
685
686            XtSetArg(arglist[0], XtNborderWidth, &border_width);
687            XtGetValues(*temp, arglist, (Cardinal) 1);
688
689            width = longest - 2 * border_width;
690            XtSetArg(arglist[0], XtNwidth, width);
691            XtSetValues(*temp, arglist, (Cardinal) 1);
692        }
693
694/*
695 * Set all the half widgets to the right length.
696 */
697
698    XtSetArg(arglist[0], XtNdefaultDistance, &interior_dist);
699    XtGetValues(parent, arglist, (Cardinal) 1);
700
701    for (temp = half_widgets; *temp != (Widget) NULL; temp++) {
702        Dimension width, border_width;
703
704        XtSetArg(arglist[0], XtNborderWidth, &border_width);
705        XtGetValues(*temp, arglist, (Cardinal) 1);
706
707        width = (int) (longest - interior_dist) / 2 - 2 * border_width;
708        XtSetArg(arglist[0], XtNwidth, width);
709        XtSetValues(*temp, arglist, (Cardinal) 1);
710    }
711
712    XtFree((char *) full_widgets);
713    XtFree((char *) half_widgets);
714}
715
716/*      Function Name: ConvertNamesToWidgets
717 *      Description: Converts a list of names into a list of widgets.
718 *      Arguments: parent - the common parent of these widgets.
719 *                 names - an array of widget names.
720 *      Returns: an array of widget id's.
721 */
722
723static Widget *
724ConvertNamesToWidgets(Widget parent, const char **names)
725{
726    const char **temp;
727    Widget *ids, *temp_ids;
728    int count;
729
730    for (count = 0, temp = names; *temp != NULL; count++, temp++);
731
732    ids = (Widget *) XtMalloc((count + 1) * sizeof(Widget));
733
734    for (temp_ids = ids; *names != NULL; names++, temp_ids++) {
735        *temp_ids = XtNameToWidget(parent, *names);
736        if (*temp_ids == NULL) {
737            char error_buf[BUFSIZ];
738
739            snprintf(error_buf, sizeof(error_buf),
740                     "Could not find widget named '%s'", *names);
741            PrintError(error_buf);
742            XtFree((char *) ids);
743            return (NULL);
744        }
745    }
746
747    *temp_ids = (Widget) NULL;
748    return (ids);
749}
750