1 /* NetHack 3.6 winmisc.c $NHDT-Date: 1432512807 2015/05/25 00:13:27 $ $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
2 /* Copyright (c) Dean Luick, 1992 */
3 /* NetHack may be freely redistributed. See license for details. */
6 * Misc. popup windows: player selection and extended commands.
8 * + Global functions: player_selection() and get_ext_cmd().
12 ** Japanese version Copyright (C) Issei Numata, 1994-1999
13 ** changing point is marked `JP' (94/6/7) or XI18N (96/7/19)
14 ** For 3.4.0, Copyright (c) Kentaro Shirakata, 2002
15 ** JNetHack may be freely redistributed. See license for details.
19 #define PRESERVE_NO_SYSV /* X11 include files may define SYSV */
22 #include <X11/Intrinsic.h>
23 #include <X11/StringDefs.h>
24 #include <X11/Shell.h>
25 #include <X11/Xaw/Command.h>
26 #include <X11/Xaw/Form.h>
27 #include <X11/Xaw/Label.h>
28 #include <X11/Xaw/Cardinals.h>
29 #include <X11/Xos.h> /* for index() */
30 #include <X11/Xatom.h>
32 #ifdef PRESERVE_NO_SYSV
36 #undef PRESERVE_NO_SYSV
43 static Widget extended_command_popup = 0;
44 static Widget extended_command_form;
45 static Widget *extended_commands = 0;
46 static int extended_command_selected; /* index of the selected command; */
47 static int ps_selected; /* index of selected role */
48 #define PS_RANDOM (-50)
50 static const char ps_randchars[] = "*@";
51 static const char ps_quitchars[] = "\033qQ";
54 static boolean ec_active = FALSE;
55 static int ec_nchars = 0;
56 static char ec_chars[EC_NCHARS];
59 static const char extended_command_translations[] = "#override\n\
62 static const char player_select_translations[] = "#override\n\
64 static const char race_select_translations[] = "#override\n\
66 static const char gend_select_translations[] = "#override\n\
68 static const char algn_select_translations[] = "#override\n\
71 static void FDECL(popup_delete, (Widget, XEvent *, String *, Cardinal *));
72 static void NDECL(ec_dismiss);
73 static Widget FDECL(make_menu,
74 (const char *, const char *, const char *, const char *,
75 XtCallbackProc, const char *, XtCallbackProc, int,
76 const char **, Widget **, XtCallbackProc, Widget *));
77 static void NDECL(init_extended_commands_popup);
78 static void FDECL(ps_quit, (Widget, XtPointer, XtPointer));
79 static void FDECL(ps_random, (Widget, XtPointer, XtPointer));
80 static void FDECL(ps_select, (Widget, XtPointer, XtPointer));
82 /* Player Selection --------------------------------------------------------
86 ps_quit(w, client_data, call_data)
88 XtPointer client_data, call_data;
94 ps_selected = PS_QUIT;
95 exit_x_event = TRUE; /* leave event loop */
100 ps_random(w, client_data, call_data)
102 XtPointer client_data, call_data;
108 ps_selected = PS_RANDOM;
109 exit_x_event = TRUE; /* leave event loop */
114 ps_select(w, client_data, call_data)
116 XtPointer client_data, call_data;
121 ps_selected = (int) client_data;
122 exit_x_event = TRUE; /* leave event loop */
127 ps_key(w, event, params, num_params)
131 Cardinal *num_params;
134 char rolechars[QBUFSZ];
141 (void) memset(rolechars, '\0', sizeof rolechars); /* for index() */
142 for (i = 0; roles[i].name.m; ++i) {
143 ch = lowc(*roles[i].name.m);
144 /* if (flags.female && roles[i].name.f) ch = lowc(*roles[i].name.f);
146 /* this supports at most two roles with the same first letter */
147 if (index(rolechars, ch))
151 ch = key_event_to_char((XKeyEvent *) event);
152 if (ch == '\0') { /* don't accept nul char/modifier event */
156 mark = index(rolechars, ch);
158 mark = index(rolechars, lowc(ch));
160 mark = index(rolechars, highc(ch));
162 if (index(ps_randchars, ch))
163 ps_selected = PS_RANDOM;
164 else if (index(ps_quitchars, ch))
165 ps_selected = PS_QUIT;
167 X11_nhbell(); /* no such class */
171 ps_selected = (int) (mark - rolechars);
177 race_key(w, event, params, num_params)
181 Cardinal *num_params;
184 char racechars[QBUFSZ];
191 (void) memset(racechars, '\0', sizeof racechars); /* for index() */
192 for (i = 0; races[i].noun; ++i) {
193 ch = lowc(*races[i].noun);
194 /* this supports at most two races with the same first letter */
195 if (index(racechars, ch))
199 ch = key_event_to_char((XKeyEvent *) event);
200 if (ch == '\0') { /* don't accept nul char/modifier event */
204 mark = index(racechars, ch);
206 mark = index(racechars, lowc(ch));
208 mark = index(racechars, highc(ch));
210 if (index(ps_randchars, ch))
211 ps_selected = PS_RANDOM;
212 else if (index(ps_quitchars, ch))
213 ps_selected = PS_QUIT;
215 X11_nhbell(); /* no such race */
219 ps_selected = (int) (mark - racechars);
225 gend_key(w, event, params, num_params)
229 Cardinal *num_params;
232 static char gendchars[] = "mf";
238 ch = key_event_to_char((XKeyEvent *) event);
239 if (ch == '\0') { /* don't accept nul char/modifier event */
243 mark = index(gendchars, ch);
245 mark = index(gendchars, lowc(ch));
247 if (index(ps_randchars, ch))
248 ps_selected = PS_RANDOM;
249 else if (index(ps_quitchars, ch))
250 ps_selected = PS_QUIT;
252 X11_nhbell(); /* no such gender */
256 ps_selected = (int) (mark - gendchars);
262 algn_key(w, event, params, num_params)
266 Cardinal *num_params;
269 static char algnchars[] = "LNC";
275 ch = key_event_to_char((XKeyEvent *) event);
276 if (ch == '\0') { /* don't accept nul char/modifier event */
280 mark = index(algnchars, ch);
282 mark = index(algnchars, highc(ch));
284 if (index(ps_randchars, ch))
285 ps_selected = PS_RANDOM;
286 else if (index(ps_quitchars, ch))
287 ps_selected = PS_QUIT;
289 X11_nhbell(); /* no such alignment */
293 ps_selected = (int) (mark - algnchars);
297 /* Global functions =========================================================
300 X11_player_selection()
302 int num_roles, num_races, num_gends, num_algns, i, availcount, availindex;
303 Widget popup, player_form;
304 const char **choices;
305 char qbuf[QBUFSZ], plbuf[QBUFSZ];
312 /* avoid unnecessary prompts further down */
315 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
316 flags.initrace, flags.initgend,
319 while (flags.initrole < 0) {
320 if (flags.initrole == ROLE_RANDOM || flags.randomall) {
321 flags.initrole = pick_role(flags.initrace, flags.initgend,
322 flags.initalign, PICK_RANDOM);
327 for (num_roles = 0; roles[num_roles].name.m; ++num_roles)
329 choices = (const char **) alloc(sizeof(char *) * num_roles);
332 for (i = 0; i < num_roles; i++) {
334 if (ok_role(i, flags.initrace, flags.initgend,
336 choices[i] = roles[i].name.m;
337 if (flags.initgend >= 0 && flags.female
339 choices[i] = roles[i].name.f;
345 else if (flags.initalign >= 0)
346 flags.initalign = -1; /* reset */
347 else if (flags.initgend >= 0)
349 else if (flags.initrace >= 0)
352 panic("no available ROLE+race+gender+alignment combinations");
355 Sprintf(qbuf, "Choose your %s Role", s_suffix(plbuf));
357 Sprintf(qbuf, "%s
\90E
\8bÆ
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
361 make_menu("player_selection", qbuf, player_select_translations,
362 "quit", ps_quit, "random", ps_random, num_roles,
363 choices, (Widget **) 0, ps_select, &player_form);
365 make_menu("player_selection", qbuf, player_select_translations,
366 "
\94²
\82¯
\82é", ps_quit, "
\83\89\83\93\83_
\83\80", ps_random, num_roles,
367 choices, (Widget **) 0, ps_select, &player_form);
371 positionpopup(popup, FALSE);
372 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
374 /* The callbacks will enable the event loop exit. */
375 (void) x_event(EXIT_ON_EXIT);
378 XtDestroyWidget(popup);
379 free((genericptr_t) choices), choices = 0;
381 if (ps_selected == PS_QUIT || program_state.done_hup) {
383 X11_exit_nhwindows((char *) 0);
385 } else if (ps_selected == PS_RANDOM) {
386 flags.initrole = ROLE_RANDOM;
387 } else if (ps_selected < 0 || ps_selected >= num_roles) {
388 panic("player_selection: bad role select value %d", ps_selected);
390 flags.initrole = ps_selected;
394 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
395 flags.initrace, flags.initgend,
398 while (!validrace(flags.initrole, flags.initrace)) {
399 if (flags.initrace == ROLE_RANDOM || flags.randomall) {
400 flags.initrace = pick_race(flags.initrole, flags.initgend,
401 flags.initalign, PICK_RANDOM);
405 for (num_races = 0; races[num_races].noun; ++num_races)
407 choices = (const char **) alloc(sizeof(char *) * num_races);
409 availcount = availindex = 0;
410 for (i = 0; i < num_races; i++) {
412 if (ok_race(flags.initrole, i, flags.initgend,
414 choices[i] = races[i].noun;
416 availindex = i; /* used iff only one */
421 else if (flags.initalign >= 0)
422 flags.initalign = -1; /* reset */
423 else if (flags.initgend >= 0)
426 panic("no available role+RACE+gender+alignment combinations");
429 if (availcount == 1) {
430 flags.initrace = availindex;
431 free((genericptr_t) choices), choices = 0;
434 Sprintf(qbuf, "Pick your %s race", s_suffix(plbuf));
436 Sprintf(qbuf, "%s
\8eí
\91°
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
440 make_menu("race_selection", qbuf, race_select_translations,
441 "quit", ps_quit, "random", ps_random, num_races,
442 choices, (Widget **) 0, ps_select, &player_form);
445 make_menu("race_selection", qbuf, race_select_translations,
446 "
\94²
\82¯
\82é", ps_quit, "
\83\89\83\93\83_
\83\80", ps_random, num_races,
447 choices, (Widget **) 0, ps_select, &player_form);
451 positionpopup(popup, FALSE);
452 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
454 /* The callbacks will enable the event loop exit. */
455 (void) x_event(EXIT_ON_EXIT);
458 XtDestroyWidget(popup);
459 free((genericptr_t) choices), choices = 0;
461 if (ps_selected == PS_QUIT || program_state.done_hup) {
463 X11_exit_nhwindows((char *) 0);
465 } else if (ps_selected == PS_RANDOM) {
466 flags.initrace = ROLE_RANDOM;
467 } else if (ps_selected < 0 || ps_selected >= num_races) {
468 panic("player_selection: bad race select value %d",
471 flags.initrace = ps_selected;
473 } /* more than one race choice available */
476 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
477 flags.initrace, flags.initgend,
480 while (!validgend(flags.initrole, flags.initrace, flags.initgend)) {
481 if (flags.initgend == ROLE_RANDOM || flags.randomall) {
482 flags.initgend = pick_gend(flags.initrole, flags.initrace,
483 flags.initalign, PICK_RANDOM);
486 /* select a gender */
487 num_gends = 2; /* genders[2] isn't allowed */
488 choices = (const char **) alloc(sizeof(char *) * num_gends);
490 availcount = availindex = 0;
491 for (i = 0; i < num_gends; i++) {
493 if (ok_gend(flags.initrole, flags.initrace, i,
495 choices[i] = genders[i].adj;
497 availindex = i; /* used iff only one */
502 else if (flags.initalign >= 0)
503 flags.initalign = -1; /* reset */
505 panic("no available role+race+GENDER+alignment combinations");
508 if (availcount == 1) {
509 flags.initgend = availindex;
510 free((genericptr_t) choices), choices = 0;
513 Sprintf(qbuf, "Your %s gender?", s_suffix(plbuf));
515 Sprintf(qbuf, "%s
\90«
\95Ê
\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
518 make_menu("gender_selection", qbuf, gend_select_translations,
519 "quit", ps_quit, "random", ps_random, num_gends,
520 choices, (Widget **) 0, ps_select, &player_form);
523 make_menu("gender_selection", qbuf, gend_select_translations,
524 "
\94²
\82¯
\82é", ps_quit, "
\83\89\83\93\83_
\83\80", ps_random, num_gends,
525 choices, (Widget **) 0, ps_select, &player_form);
529 positionpopup(popup, FALSE);
530 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
532 /* The callbacks will enable the event loop exit. */
533 (void) x_event(EXIT_ON_EXIT);
536 XtDestroyWidget(popup);
537 free((genericptr_t) choices), choices = 0;
539 if (ps_selected == PS_QUIT || program_state.done_hup) {
541 X11_exit_nhwindows((char *) 0);
543 } else if (ps_selected == PS_RANDOM) {
544 flags.initgend = ROLE_RANDOM;
545 } else if (ps_selected < 0 || ps_selected >= num_gends) {
546 panic("player_selection: bad gender select value %d",
549 flags.initgend = ps_selected;
551 } /* more than one gender choice available */
554 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
555 flags.initrace, flags.initgend,
558 while (!validalign(flags.initrole, flags.initrace, flags.initalign)) {
559 if (flags.initalign == ROLE_RANDOM || flags.randomall) {
560 flags.initalign = pick_align(flags.initrole, flags.initrace,
561 flags.initgend, PICK_RANDOM);
564 /* select an alignment */
565 num_algns = 3; /* aligns[3] isn't allowed */
566 choices = (const char **) alloc(sizeof(char *) * num_algns);
568 availcount = availindex = 0;
569 for (i = 0; i < num_algns; i++) {
571 if (ok_align(flags.initrole, flags.initrace, flags.initgend,
573 choices[i] = aligns[i].adj;
575 availindex = i; /* used iff only one */
581 panic("no available role+race+gender+ALIGNMENT combinations");
584 if (availcount == 1) {
585 flags.initalign = availindex;
586 free((genericptr_t) choices), choices = 0;
589 Sprintf(qbuf, "Your %s alignment?", s_suffix(plbuf));
591 Sprintf(qbuf, "%s
\91®
\90«
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
593 popup = make_menu("alignment_selection", qbuf,
594 algn_select_translations, "quit", ps_quit,
595 "random", ps_random, num_algns, choices,
596 (Widget **) 0, ps_select, &player_form);
598 popup = make_menu("alignment_selection", qbuf,
599 algn_select_translations, "
\94²
\82¯
\82é", ps_quit,
600 "
\83\89\83\93\83_
\83\80", ps_random, num_algns, choices,
601 (Widget **) 0, ps_select, &player_form);
605 positionpopup(popup, FALSE);
606 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
608 /* The callbacks will enable the event loop exit. */
609 (void) x_event(EXIT_ON_EXIT);
612 XtDestroyWidget(popup);
613 free((genericptr_t) choices), choices = 0;
615 if (ps_selected == PS_QUIT || program_state.done_hup) {
617 X11_exit_nhwindows((char *) 0);
619 } else if (ps_selected == PS_RANDOM) {
620 flags.initalign = ROLE_RANDOM;
621 } else if (ps_selected < 0 || ps_selected >= num_algns) {
622 panic("player_selection: bad alignment select value %d",
625 flags.initalign = ps_selected;
627 } /* more than one alignment choice available */
634 static Boolean initialized = False;
637 init_extended_commands_popup();
641 extended_command_selected = -1; /* reset selected value */
643 positionpopup(extended_command_popup, FALSE); /* center on cursor */
644 nh_XtPopup(extended_command_popup, (int) XtGrabExclusive,
645 extended_command_form);
647 /* The callbacks will enable the event loop exit. */
648 (void) x_event(EXIT_ON_EXIT);
650 return extended_command_selected;
653 /* End global functions =====================================================
656 /* Extended Command --------------------------------------------------------
660 extend_select(w, client_data, call_data)
662 XtPointer client_data, call_data;
664 int selected = (int) client_data;
669 if (extended_command_selected != selected) {
670 /* visibly deselect old one */
671 if (extended_command_selected >= 0)
672 swap_fg_bg(extended_commands[extended_command_selected]);
675 swap_fg_bg(extended_commands[selected]);
676 extended_command_selected = selected;
679 nh_XtPopdown(extended_command_popup);
680 /* reset colors while popped down */
681 swap_fg_bg(extended_commands[extended_command_selected]);
683 exit_x_event = TRUE; /* leave event loop */
688 extend_dismiss(w, client_data, call_data)
690 XtPointer client_data, call_data;
701 extend_help(w, client_data, call_data)
703 XtPointer client_data, call_data;
709 /* We might need to make it known that we already have one listed. */
715 ec_delete(w, event, params, num_params)
719 Cardinal *num_params;
721 if (w == extended_command_popup) {
724 popup_delete(w, event, params, num_params);
730 popup_delete(w, event, params, num_params)
734 Cardinal *num_params;
740 ps_selected = PS_QUIT;
742 exit_x_event = TRUE; /* leave event loop */
748 /* unselect while still visible */
749 if (extended_command_selected >= 0)
750 swap_fg_bg(extended_commands[extended_command_selected]);
751 extended_command_selected = -1; /* dismiss */
752 nh_XtPopdown(extended_command_popup);
754 exit_x_event = TRUE; /* leave event loop */
759 ec_key(w, event, params, num_params)
763 Cardinal *num_params;
767 XKeyEvent *xkey = (XKeyEvent *) event;
773 ch = key_event_to_char(xkey);
775 if (ch == '\0') { /* don't accept nul char/modifier event */
778 } else if (index("\033\n\r", ch)) {
780 /* unselect while still visible */
781 if (extended_command_selected >= 0)
782 swap_fg_bg(extended_commands[extended_command_selected]);
783 extended_command_selected = -1; /* dismiss */
786 nh_XtPopdown(extended_command_popup);
787 /* unselect while invisible */
788 if (extended_command_selected >= 0)
789 swap_fg_bg(extended_commands[extended_command_selected]);
791 exit_x_event = TRUE; /* leave event loop */
796 /* too much time has elapsed */
797 if ((xkey->time - ec_time) > 500)
805 ec_time = xkey->time;
806 ec_chars[ec_nchars++] = ch;
807 if (ec_nchars >= EC_NCHARS)
808 ec_nchars = EC_NCHARS - 1; /* don't overflow */
810 for (i = 0; extcmdlist[i].ef_txt; i++) {
811 if (extcmdlist[i].ef_txt[0] == '?')
814 if (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars)) {
815 if (extended_command_selected != i) {
816 /* I should use set() and unset() actions, but how do */
817 /* I send the an action to the widget? */
818 if (extended_command_selected >= 0)
819 swap_fg_bg(extended_commands[extended_command_selected]);
820 extended_command_selected = i;
821 swap_fg_bg(extended_commands[extended_command_selected]);
829 * Use our own home-brewed version menu because simpleMenu is designed to
830 * be used from a menubox.
833 init_extended_commands_popup()
836 const char **command_list;
839 for (num_commands = 0; extcmdlist[num_commands].ef_txt; num_commands++)
842 /* If the last entry is "help", don't use it. */
843 if (strcmp(extcmdlist[num_commands - 1].ef_txt, "?") == 0)
847 (const char **) alloc((unsigned) num_commands * sizeof(char *));
849 for (i = 0; i < num_commands; i++)
850 command_list[i] = extcmdlist[i].ef_txt;
853 extended_command_popup =
854 make_menu("extended_commands", "Extended Commands",
855 extended_command_translations, "dismiss", extend_dismiss,
856 "help", extend_help, num_commands, command_list,
857 &extended_commands, extend_select, &extended_command_form);
859 extended_command_popup =
860 make_menu("extended_commands", "
\8ag
\92£
\83R
\83}
\83\93\83h",
861 extended_command_translations, "
\8eæ
\8fÁ", extend_dismiss,
862 "
\83w
\83\8b\83v", extend_help, num_commands, command_list,
863 &extended_commands, extend_select, &extended_command_form);
866 free((char *) command_list);
869 /* -------------------------------------------------------------------------
873 * Create a popup widget of the following form:
876 * ----------- ------------
877 * |left_name| |right_name|
878 * ----------- ------------
879 * ------------------------
881 * ------------------------
882 * ------------------------
884 * ------------------------
887 * ------------------------
889 * ------------------------
892 make_menu(popup_name, popup_label, popup_translations, left_name,
893 left_callback, right_name, right_callback, num_names, widget_names,
894 command_widgets, name_callback, formp)
895 const char *popup_name;
896 const char *popup_label;
897 const char *popup_translations;
898 const char *left_name;
899 XtCallbackProc left_callback;
900 const char *right_name;
901 XtCallbackProc right_callback;
903 const char **widget_names; /* return array of command widgets */
904 Widget **command_widgets;
905 XtCallbackProc name_callback;
906 Widget *formp; /* return */
908 Widget popup, form, label, above, left, right;
909 Widget *commands, *curr;
913 Dimension width, max_width;
916 commands = (Widget *) alloc((unsigned) num_names * sizeof(Widget));
919 XtSetArg(args[num_args], XtNallowShellResize, True);
922 popup = XtCreatePopupShell(popup_name, transientShellWidgetClass,
923 toplevel, args, num_args);
924 XtOverrideTranslations(
925 popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: ec_delete()"));
928 XtSetArg(args[num_args], XtNtranslations,
929 XtParseTranslationTable(popup_translations));
931 *formp = form = XtCreateManagedWidget("menuform", formWidgetClass, popup,
934 /* Get the default distance between objects in the form widget. */
936 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), &distance);
938 XtGetValues(form, args, num_args);
944 #if defined(X11R6) && defined(XI18N)
945 XtSetArg(args[num_args], XtNinternational, True);
948 XtSetArg(args[num_args], XtNborderWidth, 0);
950 label = XtCreateManagedWidget(popup_label, labelWidgetClass, form, args,
954 * Create the left button.
957 XtSetArg(args[num_args], nhStr(XtNfromVert), label);
960 XtSetArg(args[num_args], nhStr(XtNshapeStyle),
961 XmuShapeRoundedRectangle); num_args++;
963 left = XtCreateManagedWidget(left_name, commandWidgetClass, form, args,
965 XtAddCallback(left, XtNcallback, left_callback, (XtPointer) 0);
966 skip = 3 * distance; /* triple the spacing */
971 * Create right button.
974 XtSetArg(args[num_args], nhStr(XtNfromHoriz), left);
976 XtSetArg(args[num_args], nhStr(XtNfromVert), label);
979 XtSetArg(args[num_args], nhStr(XtNshapeStyle),
980 XmuShapeRoundedRectangle); num_args++;
982 #if defined(X11R6) && defined(XI18N)
983 XtSetArg(args[num_args], XtNinternational, True);
986 right = XtCreateManagedWidget(right_name, commandWidgetClass, form, args,
988 XtAddCallback(right, XtNcallback, right_callback, (XtPointer) 0);
990 XtInstallAccelerators(form, left);
991 XtInstallAccelerators(form, right);
994 * Create and place the command widgets.
996 for (i = 0, above = left, curr = commands; i < num_names; i++) {
997 if (!widget_names[i])
1000 XtSetArg(args[num_args], nhStr(XtNfromVert), above);
1002 if (above == left) {
1003 /* if first, we are farther apart */
1004 XtSetArg(args[num_args], nhStr(XtNvertDistance), skip);
1008 #if defined(X11R6) && defined(XI18N)
1009 XtSetArg(args[num_args], XtNinternational, True);
1012 *curr = XtCreateManagedWidget(widget_names[i], commandWidgetClass,
1013 form, args, num_args);
1014 XtAddCallback(*curr, XtNcallback, name_callback, (XtPointer) i);
1019 * Now find the largest width. Start with the width dismiss + help
1020 * buttons, since they are adjacent.
1022 XtSetArg(args[0], XtNwidth, &max_width);
1023 XtGetValues(left, args, ONE);
1024 XtSetArg(args[0], XtNwidth, &width);
1025 XtGetValues(right, args, ONE);
1026 max_width = max_width + width + distance;
1028 /* Next, the title. */
1029 XtSetArg(args[0], XtNwidth, &width);
1030 XtGetValues(label, args, ONE);
1031 if (width > max_width)
1034 /* Finally, the commands. */
1035 for (i = 0, curr = commands; i < num_names; i++) {
1036 if (!widget_names[i])
1038 XtSetArg(args[0], XtNwidth, &width);
1039 XtGetValues(*curr, args, ONE);
1040 if (width > max_width)
1046 * Finally, set all of the single line widgets to the largest width.
1048 XtSetArg(args[0], XtNwidth, max_width);
1049 XtSetValues(label, args, ONE);
1051 for (i = 0, curr = commands; i < num_names; i++) {
1052 if (!widget_names[i])
1054 XtSetArg(args[0], XtNwidth, max_width);
1055 XtSetValues(*curr, args, ONE);
1059 if (command_widgets)
1060 *command_widgets = commands;
1062 free((char *) commands);
1064 XtRealizeWidget(popup);
1065 XSetWMProtocols(XtDisplay(popup), XtWindow(popup), &wm_delete_window, 1);