1 /*
2 
3 Copyright (c) 1987, 1988  X Consortium
4 
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12 
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
23 
24 Except as contained in this notice, the name of the X Consortium shall
25 not be used in advertising or otherwise to promote the sale, use or
26 other dealings in this Software without prior written authorization
27 from 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 
46 static void CreateOptionMenu(ManpageGlobals * man_globals, Widget parent);
47 static void CreateSectionMenu(ManpageGlobals * man_globals, Widget parent);
48 static void StartManpage(ManpageGlobals * man_globals, Boolean help,
49                          Boolean page);
50 static 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 
60 Widget top;                     /* needed in PopupWarning, misc.c */
61 
62 void
MakeTopBox(void)63 MakeTopBox(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 
148 Widget
CreateManpage(FILE * file)149 CreateManpage(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 
173 ManpageGlobals *
InitPsuedoGlobals(void)174 InitPsuedoGlobals(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 
213 void
CreateManpageWidget(ManpageGlobals * man_globals,String name,Boolean full_instance)214 CreateManpageWidget(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 
325 static void
StartManpage(ManpageGlobals * man_globals,Boolean help,Boolean page)326 StartManpage(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 */
418 static void
MenuDestroy(Widget w,XtPointer free_me,XtPointer junk)419 MenuDestroy(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 
431 static void
CreateOptionMenu(ManpageGlobals * man_globals,Widget parent)432 CreateOptionMenu(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 
518 static void
CreateSectionMenu(ManpageGlobals * man_globals,Widget parent)519 CreateSectionMenu(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 
556 static char **
CreateList(int section)557 CreateList(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 
583 void
MakeDirectoryBox(ManpageGlobals * man_globals,Widget parent,Widget * dir_disp,int section)584 MakeDirectoryBox(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 
619 void
MakeSaveWidgets(ManpageGlobals * man_globals,Widget parent)620 MakeSaveWidgets(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 
663 void
FormUpWidgets(Widget parent,const char ** full_size,const char ** half_size)664 FormUpWidgets(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 
745 static Widget *
ConvertNamesToWidgets(Widget parent,const char ** names)746 ConvertNamesToWidgets(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