buttons.c revision ae5a67ad
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#ifdef INCLUDE_XPRINT_SUPPORT
286    XtSetArg(arglist[0], XtNsensitive, True);
287    XtSetValues(man_globals->print_entry, arglist, ONE);
288#endif                          /* INCLUDE_XPRINT_SUPPORT */
289
290    man_globals->label = XtCreateManagedWidget("manualTitle", labelWidgetClass,
291                                               hpane, NULL, (Cardinal) 0);
292
293/* Create Directory */
294
295    if (full_instance) {
296        num_args = 0;
297        XtSetArg(arglist[num_args], XtNallowVert, TRUE);
298        num_args++;
299
300        mpw->directory = XtCreateWidget(DIRECTORY_NAME, viewportWidgetClass,
301                                        pane, arglist, num_args);
302
303        man_globals->current_directory = INITIAL_DIR;
304        MakeDirectoryBox(man_globals, mpw->directory,
305                         mpw->box + man_globals->current_directory,
306                         man_globals->current_directory);
307        XtManageChild(mpw->box[man_globals->current_directory]);
308    }
309
310/* Create Manpage */
311
312    mpw->manpage = XtCreateWidget(MANUALPAGE, scrollByLineWidgetClass,
313                                  pane, NULL, (Cardinal) 0);
314
315}
316
317/*	Function Name: StartManpage
318 *	Description: Starts up a new manpage.
319 *	Arguments: man_globals - the pseudo globals variable.
320 *                 help - is this a help file?
321 *                 page - Is there a page to display?
322 *	Returns: none.
323 */
324
325static void
326StartManpage(ManpageGlobals * man_globals, Boolean help, Boolean page)
327{
328    Widget dir = man_globals->manpagewidgets.directory;
329    Widget manpage = man_globals->manpagewidgets.manpage;
330    Widget label = man_globals->label;
331    Arg arglist[1];
332
333/*
334 * If there is a helpfile then put up both screens if both_show is set.
335 */
336
337    if (page || help) {
338        if (help)
339            strcpy(man_globals->manpage_title, "Xman Help");
340
341        if (man_globals->both_shown) {
342            XtManageChild(dir);
343            man_globals->dir_shown = TRUE;
344
345            XtSetArg(arglist[0], XtNpreferredPaneSize,
346                     resources.directory_height);
347            XtSetValues(dir, arglist, (Cardinal) 1);
348
349            XtSetArg(arglist[0], XtNsensitive, FALSE);
350            XtSetValues(man_globals->manpage_entry, arglist, ONE);
351            XtSetValues(man_globals->dir_entry, arglist, ONE);
352
353            XtSetArg(arglist[0], XtNlabel, SHOW_ONE);
354            XtSetValues(man_globals->both_screens_entry, arglist, ONE);
355            ChangeLabel(label,
356                        man_globals->section_name[man_globals->
357                                                  current_directory]);
358        }
359        else {
360            ChangeLabel(label, man_globals->manpage_title);
361        }
362        XtManageChild(manpage);
363        man_globals->dir_shown = FALSE;
364    }
365/*
366 * Since There is file to display, put up directory and do not allow change
367 * to manpage, show both, or help.
368 */
369    else {
370        XtManageChild(dir);
371        man_globals->dir_shown = TRUE;
372        XtSetArg(arglist[0], XtNsensitive, FALSE);
373        XtSetValues(man_globals->manpage_entry, arglist, ONE);
374        XtSetValues(man_globals->help_entry, arglist, ONE);
375        XtSetValues(man_globals->both_screens_entry, arglist, ONE);
376        man_globals->both_shown = FALSE;
377        ChangeLabel(label,
378                    man_globals->section_name[man_globals->current_directory]);
379    }
380
381/*
382 * Start 'er up, and change the cursor.
383 */
384
385    XtRealizeWidget(man_globals->This_Manpage);
386    SaveGlobals(man_globals->This_Manpage, man_globals);
387    XtMapWidget(man_globals->This_Manpage);
388    AddCursor(man_globals->This_Manpage, resources.cursors.manpage);
389    XtSetArg(arglist[0], XtNtransientFor, man_globals->This_Manpage);
390    XtSetValues(XtParent(man_globals->standby), arglist, (Cardinal) 1);
391    XtSetValues(XtParent(man_globals->save), arglist, (Cardinal) 1);
392    XtRealizeWidget(XtParent(man_globals->standby));
393    XtRealizeWidget(XtParent(man_globals->save));
394    AddCursor(XtParent(man_globals->standby), resources.cursors.top);
395    AddCursor(XtParent(man_globals->save), resources.cursors.top);
396
397/*
398 * Set up ICCCM delete window.
399 */
400    XtOverrideTranslations
401        (man_globals->This_Manpage,
402         XtParseTranslationTable("<Message>WM_PROTOCOLS: RemoveThisManpage()"));
403    (void) XSetWMProtocols(XtDisplay(man_globals->This_Manpage),
404                           XtWindow(man_globals->This_Manpage),
405                           &wm_delete_window, 1);
406
407}
408
409/*      Function Name: MenuDestroy
410 *      Description: free's data associated with menu when it is destroyed.
411 *      Arguments: w - menu widget.
412 *                 free_me - data to free.
413 *                 junk - not used.
414 *      Returns: none.
415 */
416
417/* ARGSUSED */
418static void
419MenuDestroy(Widget w, XtPointer free_me, XtPointer junk)
420{
421    XtFree((char *) free_me);
422}
423
424/*      Function Name:   CreateOptionMenu
425 *      Description: Create the option menu.
426 *      Arguments: man_globals - the manual page globals.
427 *                 parent - the button that activates the menu.
428 *      Returns: none.
429 */
430
431static void
432CreateOptionMenu(ManpageGlobals * man_globals, Widget parent)
433{
434    Widget menu, entry;
435    int i;
436    static const char *option_names[] = {     /* Names of the buttons. */
437        DIRECTORY,
438        MANPAGE,
439        HELP,
440        SEARCH,
441        BOTH_SCREENS,
442        REMOVE_MANPAGE,
443        OPEN_MANPAGE,
444#ifdef INCLUDE_XPRINT_SUPPORT
445        PRINT_MANPAGE,
446#endif                          /* INCLUDE_XPRINT_SUPPORT */
447        SHOW_VERSION,
448        QUIT
449    };
450
451    menu = XtCreatePopupShell(OPTION_MENU, simpleMenuWidgetClass, parent,
452                              NULL, (Cardinal) 0);
453    man_globals->option_menu = menu;
454
455    for (i = 0; i < NUM_OPTIONS; i++) {
456        entry = XtCreateManagedWidget(option_names[i], smeBSBObjectClass,
457                                      menu, NULL, ZERO);
458        XtAddCallback(entry, XtNcallback, OptionCallback,
459                      (caddr_t) man_globals);
460        switch (i) {
461        case 0:
462            man_globals->dir_entry = entry;
463            break;
464        case 1:
465            man_globals->manpage_entry = entry;
466            break;
467        case 2:
468            man_globals->help_entry = entry;
469            break;
470        case 3:
471            man_globals->search_entry = entry;
472            break;
473        case 4:
474            man_globals->both_screens_entry = entry;
475            break;
476        case 5:
477            man_globals->remove_entry = entry;
478            break;
479        case 6:
480            man_globals->open_entry = entry;
481            break;
482#ifdef INCLUDE_XPRINT_SUPPORT
483        case 7:
484            man_globals->print_entry = entry;
485            break;
486        case 8:
487            man_globals->version_entry = entry;
488            break;
489        case 9:
490            man_globals->quit_entry = entry;
491            break;
492#else                           /* !INCLUDE_XPRINT_SUPPORT */
493        case 7:
494            man_globals->version_entry = entry;
495            break;
496        case 8:
497            man_globals->quit_entry = entry;
498            break;
499#endif                          /* !INCLUDE_XPRINT_SUPPORT */
500        default:
501            Error(("CreateOptionMenu: Unknown id=%d\n", i));
502            break;
503        }
504    }
505
506#ifdef INCLUDE_XPRINT_SUPPORT
507    XtVaSetValues(man_globals->print_entry, XtNsensitive, FALSE, NULL);
508#endif                          /* INCLUDE_XPRINT_SUPPORT */
509}
510
511/*      Function Name: CreateSectionMenu
512 *      Description: Create the Section menu.
513 *      Arguments: man_globals - the manual page globals.
514 *                 parent - the button that activates the menu.
515 *      Returns: none.
516 */
517
518static void
519CreateSectionMenu(ManpageGlobals * man_globals, Widget parent)
520{
521    Widget menu, entry;
522    int i;
523    MenuStruct *menu_struct;
524    Arg args[1];
525    Cardinal num_args;
526    char entry_name[BUFSIZ];
527
528    menu = XtCreatePopupShell(SECTION_MENU, simpleMenuWidgetClass, parent,
529                              NULL, (Cardinal) 0);
530
531    for (i = 0; i < sections; i++) {
532        num_args = 0;
533        XtSetArg(args[num_args], XtNlabel, manual[i].blabel);
534        num_args++;
535        snprintf(entry_name, sizeof(entry_name), "section%d", i);
536
537        entry = XtCreateManagedWidget(entry_name, smeBSBObjectClass,
538                                      menu, args, num_args);
539        menu_struct = (MenuStruct *) XtMalloc(sizeof(MenuStruct));
540        menu_struct->data = (caddr_t) man_globals;
541        menu_struct->number = i;
542        XtAddCallback(entry, XtNcallback, DirPopupCallback,
543                      (caddr_t) menu_struct);
544        XtAddCallback(entry, XtNdestroyCallback, MenuDestroy,
545                      (caddr_t) menu_struct);
546
547    }
548}
549
550/*	Function Name: CreateList
551 *	Description: this function prints a label in the directory list
552 *	Arguments: section - the manual section.
553 *	Returns: none
554 */
555
556static char **
557CreateList(int section)
558{
559    char **ret_list, **current;
560    int count;
561
562    ret_list = (char **) XtMalloc((manual[section].nentries + 1) *
563                                  sizeof(char *));
564
565    for (current = ret_list, count = 0; count < manual[section].nentries;
566         count++, current++)
567        *current = CreateManpageName(manual[section].entries[count], section,
568                                     manual[section].flags);
569
570    *current = NULL;            /* NULL terminate the list. */
571    return (ret_list);
572}
573
574/*	Function Name: MakeDirectoryBox
575 *	Description: make a directory box.
576 *	Arguments: man_globals - the pseudo global structure for each manpage.
577 *                 parent - this guys parent widget.
578 *                 dir_disp - the directory display widget.
579 *                 section - the section number.
580 *	Returns: none.
581 */
582
583void
584MakeDirectoryBox(ManpageGlobals * man_globals, Widget parent, Widget * dir_disp,
585                 int section)
586{
587    Arg arglist[10];
588    Cardinal num_args;
589    char *name, label_name[BUFSIZ];
590
591    if (*dir_disp != NULL)      /* If we have one, don't make another. */
592        return;
593
594    name = manual[section].blabel;      /* Set the section name */
595    snprintf(label_name, sizeof(label_name), "Directory of: %s", name);
596    man_globals->section_name[section] = XtNewString(label_name);
597
598    num_args = 0;
599    XtSetArg(arglist[num_args], XtNlist, CreateList(section));
600    num_args++;
601    XtSetArg(arglist[num_args], XtNfont, resources.fonts.directory);
602    num_args++;
603
604    *dir_disp = XtCreateWidget(DIRECTORY_NAME, listWidgetClass, parent,
605                               arglist, num_args);
606
607    XtAddCallback(*dir_disp, XtNcallback,
608                  DirectoryHandler, (caddr_t) man_globals);
609}
610
611/*	Function Name: MakeSaveWidgets.
612 *	Description: This functions creates two popup widgets, the please
613 *                   standby widget and the would you like to save widget.
614 *	Arguments: man_globals - the pseudo globals structure for each man page
615 *                 parent - the realized parent for both popups.
616 *	Returns: none.
617 */
618
619void
620MakeSaveWidgets(ManpageGlobals * man_globals, Widget parent)
621{
622    Widget shell, dialog;       /* misc. widgets. */
623    Arg warg[1];
624    Cardinal n = 0;
625
626/* make the please stand by popup widget. */
627    if (XtIsRealized(parent)) {
628        XtSetArg(warg[0], XtNtransientFor, parent);
629        n++;
630    }
631    shell = XtCreatePopupShell("pleaseStandBy", transientShellWidgetClass,
632                               parent, warg, (Cardinal) n);
633
634    man_globals->standby = XtCreateManagedWidget("label", labelWidgetClass,
635                                                 shell, NULL, (Cardinal) 0);
636
637    man_globals->save = XtCreatePopupShell("likeToSave",
638                                           transientShellWidgetClass,
639                                           parent, warg, n);
640
641    dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
642                                   man_globals->save, NULL, (Cardinal) 0);
643
644    XawDialogAddButton(dialog, FILE_SAVE, NULL, NULL);
645    XawDialogAddButton(dialog, CANCEL_FILE_SAVE, NULL, NULL);
646
647    if (XtIsRealized(parent)) {
648        XtRealizeWidget(shell);
649        AddCursor(shell, resources.cursors.top);
650        XtRealizeWidget(man_globals->save);
651        AddCursor(man_globals->save, resources.cursors.top);
652    }
653}
654
655/*      Function Name: FormUpWidgets
656 *      Description: Sizes widgets to look nice.
657 *      Arguments: parent - the common parent of all the widgets.
658 *                 full_size - array of widget names that will be full size.
659 *                 half_size - array of widget names that will be half size.
660 *      Returns: none
661 */
662
663void
664FormUpWidgets(Widget parent, const char **full_size, const char **half_size)
665{
666    Widget *full_widgets, *half_widgets, *temp, long_widget;
667    Dimension longest, length, b_width;
668    int interior_dist;
669    Arg arglist[2];
670
671    full_widgets = ConvertNamesToWidgets(parent, full_size);
672    half_widgets = ConvertNamesToWidgets(parent, half_size);
673
674    long_widget = NULL;
675    longest = 0;
676    XtSetArg(arglist[0], XtNwidth, &length);
677    XtSetArg(arglist[1], XtNborderWidth, &b_width);
678
679/*
680 * Find Longest widget.
681 */
682
683    for (temp = full_widgets; *temp != (Widget) NULL; temp++) {
684        XtGetValues(*temp, arglist, (Cardinal) 2);
685        length += 2 * b_width;
686        if (length > longest) {
687            longest = length;
688            long_widget = *temp;
689        }
690    }
691
692    if (long_widget == (Widget) NULL) { /* Make sure we found one. */
693        PopupWarning(GetGlobals(parent),
694                     "Could not find longest widget, aborting...");
695        XtFree((char *) full_widgets);
696        XtFree((char *) half_widgets);
697        return;
698    }
699
700/*
701 * Set all other full_widgets to this length.
702 */
703
704    for (temp = full_widgets; *temp != (Widget) NULL; temp++)
705        if (long_widget != *temp) {
706            Dimension width, border_width;
707
708            XtSetArg(arglist[0], XtNborderWidth, &border_width);
709            XtGetValues(*temp, arglist, (Cardinal) 1);
710
711            width = longest - 2 * border_width;
712            XtSetArg(arglist[0], XtNwidth, width);
713            XtSetValues(*temp, arglist, (Cardinal) 1);
714        }
715
716/*
717 * Set all the half widgets to the right length.
718 */
719
720    XtSetArg(arglist[0], XtNdefaultDistance, &interior_dist);
721    XtGetValues(parent, arglist, (Cardinal) 1);
722
723    for (temp = half_widgets; *temp != (Widget) NULL; temp++) {
724        Dimension width, border_width;
725
726        XtSetArg(arglist[0], XtNborderWidth, &border_width);
727        XtGetValues(*temp, arglist, (Cardinal) 1);
728
729        width = (int) (longest - interior_dist) / 2 - 2 * border_width;
730        XtSetArg(arglist[0], XtNwidth, width);
731        XtSetValues(*temp, arglist, (Cardinal) 1);
732    }
733
734    XtFree((char *) full_widgets);
735    XtFree((char *) half_widgets);
736}
737
738/*      Function Name: ConvertNamesToWidgets
739 *      Description: Converts a list of names into a list of widgets.
740 *      Arguments: parent - the common parent of these widgets.
741 *                 names - an array of widget names.
742 *      Returns: an array of widget id's.
743 */
744
745static Widget *
746ConvertNamesToWidgets(Widget parent, const char **names)
747{
748    const char **temp;
749    Widget *ids, *temp_ids;
750    int count;
751
752    for (count = 0, temp = names; *temp != NULL; count++, temp++);
753
754    ids = (Widget *) XtMalloc((count + 1) * sizeof(Widget));
755
756    for (temp_ids = ids; *names != NULL; names++, temp_ids++) {
757        *temp_ids = XtNameToWidget(parent, *names);
758        if (*temp_ids == NULL) {
759            char error_buf[BUFSIZ];
760
761            snprintf(error_buf, sizeof(error_buf),
762                     "Could not find widget named '%s'", *names);
763            PrintError(error_buf);
764            XtFree((char *) ids);
765            return (NULL);
766        }
767    }
768
769    *temp_ids = (Widget) NULL;
770    return (ids);
771}
772