1 /* NetHack 3.6 winmisc.c $NHDT-Date: 1554135506 2019/04/01 16:18:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.44 $ */
2 /* Copyright (c) Dean Luick, 1992 */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata 1994-1999 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
8 /* JNetHack may be freely redistributed. See license for details. */
11 * Misc. popup windows: player selection and extended commands.
13 * + Global functions: player_selection() and get_ext_cmd().
17 #define PRESERVE_NO_SYSV /* X11 include files may define SYSV */
20 #include <X11/Intrinsic.h>
21 #include <X11/StringDefs.h>
22 #include <X11/Shell.h>
23 #include <X11/Xaw/Command.h>
24 #include <X11/Xaw/Form.h>
25 #include <X11/Xaw/Label.h>
26 #include <X11/Xaw/AsciiText.h>
27 #include <X11/Xaw/Scrollbar.h>
28 #include <X11/Xaw/Toggle.h>
29 #include <X11/Xaw/Viewport.h>
30 #include <X11/Xaw/Cardinals.h>
31 #include <X11/Xaw/List.h>
32 #include <X11/Xos.h> /* for index() */
33 #include <X11/Xatom.h>
35 #ifdef PRESERVE_NO_SYSV
39 #undef PRESERVE_NO_SYSV
46 static Widget extended_command_popup = 0;
47 static Widget extended_command_form;
48 static Widget *extended_commands = 0;
49 static const char **command_list;
50 static short *command_indx;
51 static int extended_cmd_selected; /* index of the selected command; */
52 static int ps_selected; /* index of selected role */
53 #define PS_RANDOM (-50)
55 /* 'r' for random won't work for role but will for race, gender, alignment */
56 static const char ps_randchars[] = "*@\n\rrR";
57 static const char ps_quitchars[] = "\033qQ";
60 static boolean ec_full_list = FALSE;
61 static boolean ec_active = FALSE;
62 static int ec_nchars = 0;
63 static char ec_chars[EC_NCHARS];
66 boolean plsel_ask_name;
68 static const char plsel_dialog_translations[] = "#override\n\
69 <Key>Escape: plsel_quit()\n\
70 <Key>Return: plsel_play()";
72 static const char plsel_input_accelerators[] = "#override\n\
73 <Key>Escape: plsel_quit()\n\
74 <Key>Return: plsel_play()\n\
77 static const char extended_command_translations[] = "#override\n\
78 <Key>Left: scroll(4)\n\
79 <Key>Right: scroll(6)\n\
81 <Key>Down: scroll(2)\n\
82 <Btn4Down>: scroll(8)\n\
83 <Btn5Down>: scroll(2)\n\
86 static const char player_select_translations[] = "#override\n\
88 static const char race_select_translations[] = "#override\n\
90 static const char gend_select_translations[] = "#override\n\
92 static const char algn_select_translations[] = "#override\n\
95 static const char popup_entry_translations[] = "#override\n\
96 <Btn4Down>: scroll(8)\n\
97 <Btn5Down>: scroll(2)";
99 static void FDECL(ps_quit, (Widget, XtPointer, XtPointer));
100 static void FDECL(ps_random, (Widget, XtPointer, XtPointer));
101 static void FDECL(ps_select, (Widget, XtPointer, XtPointer));
102 static void FDECL(extend_select, (Widget, XtPointer, XtPointer));
103 static void FDECL(extend_dismiss, (Widget, XtPointer, XtPointer));
104 static void FDECL(extend_help, (Widget, XtPointer, XtPointer));
105 static void FDECL(popup_delete, (Widget, XEvent *, String *, Cardinal *));
106 static void NDECL(ec_dismiss);
107 static void FDECL(ec_scroll_to_view, (int));
108 static void NDECL(init_extended_commands_popup);
109 static Widget FDECL(make_menu, (const char *, const char *, const char *,
110 const char *, XtCallbackProc, const char *,
111 XtCallbackProc, int, const char **,
112 Widget **, XtCallbackProc, Widget *));
114 void NDECL(X11_player_selection_setupOthers);
115 void NDECL(X11_player_selection_randomize);
117 /* Bad Hack alert. Using integers instead of XtPointers */
122 return (XtPointer) (ptrdiff_t) i;
129 return (int) (ptrdiff_t) x;
132 /* Player Selection ------------------------------------------------------- */
135 ps_quit(w, client_data, call_data)
137 XtPointer client_data, call_data;
143 ps_selected = PS_QUIT;
144 exit_x_event = TRUE; /* leave event loop */
149 ps_random(w, client_data, call_data)
151 XtPointer client_data, call_data;
157 ps_selected = PS_RANDOM;
158 exit_x_event = TRUE; /* leave event loop */
163 ps_select(w, client_data, call_data)
165 XtPointer client_data, call_data;
170 ps_selected = (int) (ptrdiff_t) client_data;
171 exit_x_event = TRUE; /* leave event loop */
176 ps_key(w, event, params, num_params)
180 Cardinal *num_params;
183 char rolechars[QBUFSZ];
190 (void) memset(rolechars, '\0', sizeof rolechars); /* for index() */
191 for (i = 0; roles[i].name.m; ++i) {
192 ch = lowc(*roles[i].name.m);
193 /* if (flags.female && roles[i].name.f) ch = lowc(*roles[i].name.f);
195 /* this supports at most two roles with the same first letter */
196 if (index(rolechars, ch))
200 ch = key_event_to_char((XKeyEvent *) event);
201 if (ch == '\0') { /* don't accept nul char/modifier event */
205 mark = index(rolechars, ch);
207 mark = index(rolechars, lowc(ch));
209 mark = index(rolechars, highc(ch));
211 if (index(ps_randchars, ch))
212 ps_selected = PS_RANDOM;
213 else if (index(ps_quitchars, ch))
214 ps_selected = PS_QUIT;
216 X11_nhbell(); /* no such class */
220 ps_selected = (int) (mark - rolechars);
226 race_key(w, event, params, num_params)
230 Cardinal *num_params;
233 char racechars[QBUFSZ];
240 (void) memset(racechars, '\0', sizeof racechars); /* for index() */
241 for (i = 0; races[i].noun; ++i) {
242 ch = lowc(*races[i].noun);
243 /* this supports at most two races with the same first letter */
244 if (index(racechars, ch))
248 ch = key_event_to_char((XKeyEvent *) event);
249 if (ch == '\0') { /* don't accept nul char/modifier event */
253 mark = index(racechars, ch);
255 mark = index(racechars, lowc(ch));
257 mark = index(racechars, highc(ch));
259 if (index(ps_randchars, ch))
260 ps_selected = PS_RANDOM;
261 else if (index(ps_quitchars, ch))
262 ps_selected = PS_QUIT;
264 X11_nhbell(); /* no such race */
268 ps_selected = (int) (mark - racechars);
274 gend_key(w, event, params, num_params)
278 Cardinal *num_params;
281 static char gendchars[] = "mf";
287 ch = key_event_to_char((XKeyEvent *) event);
288 if (ch == '\0') { /* don't accept nul char/modifier event */
292 mark = index(gendchars, ch);
294 mark = index(gendchars, lowc(ch));
296 if (index(ps_randchars, ch))
297 ps_selected = PS_RANDOM;
298 else if (index(ps_quitchars, ch))
299 ps_selected = PS_QUIT;
301 X11_nhbell(); /* no such gender */
305 ps_selected = (int) (mark - gendchars);
311 algn_key(w, event, params, num_params)
315 Cardinal *num_params;
318 static char algnchars[] = "LNC";
324 ch = key_event_to_char((XKeyEvent *) event);
325 if (ch == '\0') { /* don't accept nul char/modifier event */
329 mark = index(algnchars, ch);
331 mark = index(algnchars, highc(ch));
333 if (index(ps_randchars, ch))
334 ps_selected = PS_RANDOM;
335 else if (index(ps_quitchars, ch))
336 ps_selected = PS_QUIT;
338 X11_nhbell(); /* no such alignment */
342 ps_selected = (int) (mark - algnchars);
346 int plsel_n_races, plsel_n_roles;
347 Widget *plsel_race_radios = (Widget *) 0;
348 Widget *plsel_role_radios = (Widget *) 0;
349 Widget *plsel_gend_radios = (Widget *) 0;
350 Widget *plsel_align_radios = (Widget *) 0;
352 Widget plsel_name_input;
354 Widget plsel_btn_play;
357 plsel_dialog_acceptvalues()
362 flags.initrace = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
363 flags.initrole = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
364 flags.initgend = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
365 flags.initalign = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
367 XtSetArg(args[0], nhStr(XtNstring), &s);
368 XtGetValues(plsel_name_input, args, ONE);
370 (void) strncpy(plname, (char *) s, sizeof plname - 1);
371 plname[sizeof plname - 1] = '\0';
372 (void) mungspaces(plname);
373 if (strlen(plname) < 1)
374 (void) strcpy(plname, "Mumbles");
375 iflags.renameinprogress = FALSE;
380 plsel_quit(w, event, params, num_params)
384 Cardinal *num_params;
391 ps_selected = PS_QUIT;
392 exit_x_event = TRUE; /* leave event loop */
397 plsel_play(w, event, params, num_params)
401 Cardinal *num_params;
411 XtSetArg(args[0], nhStr(XtNsensitive), &state);
412 XtGetValues(plsel_btn_play, args, ONE);
415 plsel_dialog_acceptvalues();
416 exit_x_event = TRUE; /* leave event loop */
424 plsel_randomize(w, event, params, num_params)
428 Cardinal *num_params;
435 X11_player_selection_randomize();
438 /* enable or disable the Play button */
440 plsel_set_play_button(state)
445 XtSetArg(args[0], nhStr(XtNsensitive), !state);
446 XtSetValues(plsel_btn_play, args, ONE);
450 plsel_set_sensitivities(setcurr)
456 int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
457 int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
459 plsel_set_play_button(ra < 0 || ro < 0);
461 if (ra < 0 || ro < 0)
466 for (j = 0; roles[j].name.m; j++) {
467 boolean v = validrace(j, ra);
471 XtSetArg(args[0], nhStr(XtNsensitive), v);
472 XtSetValues(plsel_role_radios[j], args, ONE);
476 if (!validrace(ro, c))
480 XawToggleSetCurrent(plsel_role_radios[0], i2xtp(c + 1));
484 for (j = 0; races[j].noun; j++) {
485 boolean v = validrace(ro, j);
489 XtSetArg(args[0], nhStr(XtNsensitive), v);
490 XtSetValues(plsel_race_radios[j], args, ONE);
494 if (!validrace(ro, c))
498 XawToggleSetCurrent(plsel_race_radios[0], i2xtp(c + 1));
500 X11_player_selection_setupOthers();
504 X11_player_selection_randomize()
506 int nrole = plsel_n_roles;
507 int nrace = plsel_n_races;
509 boolean fully_specified_role, choose_race_first;
510 boolean picksomething = (flags.initrole == ROLE_NONE
511 || flags.initrace == ROLE_NONE
512 || flags.initgend == ROLE_NONE
513 || flags.initalign == ROLE_NONE);
515 if (flags.randomall && picksomething) {
516 if (flags.initrole == ROLE_NONE)
517 flags.initrole = ROLE_RANDOM;
518 if (flags.initrace == ROLE_NONE)
519 flags.initrace = ROLE_RANDOM;
520 if (flags.initgend == ROLE_NONE)
521 flags.initgend = ROLE_RANDOM;
522 if (flags.initalign == ROLE_NONE)
523 flags.initalign = ROLE_RANDOM;
528 /* Randomize race and role, unless specified in config */
530 if (ro == ROLE_NONE || ro == ROLE_RANDOM) {
532 if (flags.initrole != ROLE_RANDOM) {
533 fully_specified_role = FALSE;
537 if (ra == ROLE_NONE || ra == ROLE_RANDOM) {
539 if (flags.initrace != ROLE_RANDOM) {
540 fully_specified_role = FALSE;
544 /* make sure we have a valid combination, honoring
545 the users request if possible. */
546 choose_race_first = FALSE;
547 if (flags.initrace >= 0 && flags.initrole < 0) {
548 choose_race_first = TRUE;
551 while (!validrace(ro,ra)) {
552 if (choose_race_first) {
554 if (flags.initrole != ROLE_RANDOM) {
555 fully_specified_role = FALSE;
559 if (flags.initrace != ROLE_RANDOM) {
560 fully_specified_role = FALSE;
566 if (g == ROLE_NONE) {
567 g = rn2(ROLE_GENDERS);
568 fully_specified_role = FALSE;
570 while (!validgend(ro,ra,g)) {
571 g = rn2(ROLE_GENDERS);
575 if (a == ROLE_NONE) {
576 a = rn2(ROLE_ALIGNS);
577 fully_specified_role = FALSE;
579 while (!validalign(ro,ra,a)) {
580 a = rn2(ROLE_ALIGNS);
583 XawToggleSetCurrent(plsel_gend_radios[0], i2xtp(g + 1));
584 XawToggleSetCurrent(plsel_align_radios[0], i2xtp(a + 1));
585 XawToggleSetCurrent(plsel_race_radios[0], i2xtp(ra + 1));
586 XawToggleSetCurrent(plsel_role_radios[0], i2xtp(ro + 1));
587 plsel_set_sensitivities(FALSE);
591 X11_player_selection_setupOthers()
594 int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
595 int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
596 int valid = -1, c = 0, j;
597 int gchecked = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
598 int achecked = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
600 if (ro < 0 || ra < 0)
603 for (j = 0; j < ROLE_GENDERS; j++) {
604 boolean v = validgend(ro, ra, j);
608 XtSetArg(args[0], nhStr(XtNsensitive), v);
609 XtSetValues(plsel_gend_radios[j], args, ONE);
613 if (!validgend(ro, ra, c))
616 XawToggleSetCurrent(plsel_gend_radios[0], i2xtp(c + 1));
620 for (j = 0; j < ROLE_ALIGNS; j++) {
621 boolean v = validalign(ro, ra, j);
625 XtSetArg(args[0], nhStr(XtNsensitive), v);
626 XtSetValues(plsel_align_radios[j], args, ONE);
630 if (!validalign(ro, ra, c))
633 XawToggleSetCurrent(plsel_align_radios[0], i2xtp(c + 1));
637 racetoggleCallback(w, client, call)
639 XtPointer client, call;
644 int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
645 int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
651 plsel_set_play_button(ra < 0 || ro < 0);
653 if (ra < 0 || ro < 0)
658 for (j = 0; roles[j].name.m; j++) {
659 boolean v = validrace(j, ra);
663 XtSetArg(args[0], nhStr(XtNsensitive), v);
664 XtSetValues(plsel_role_radios[j], args, ONE);
668 if (!validrace(c, ra))
672 XawToggleSetCurrent(plsel_role_radios[0], i2xtp(j));
674 X11_player_selection_setupOthers();
678 roletoggleCallback(w, client, call)
680 XtPointer client, call;
685 int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
686 int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
692 plsel_set_play_button(ra < 0 || ro < 0);
694 if (ra < 0 || ro < 0)
699 for (j = 0; races[j].noun; j++) {
700 boolean v = validrace(ro, j);
704 XtSetArg(args[0], nhStr(XtNsensitive), v);
705 XtSetValues(plsel_race_radios[j], args, ONE);
709 if (!validrace(ro, c))
713 XawToggleSetCurrent(plsel_race_radios[0], i2xtp(j));
715 X11_player_selection_setupOthers();
719 gendertoggleCallback(w, client, call)
721 XtPointer client, call;
723 int i, r = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
729 plsel_set_play_button(r < 0);
731 for (i = 0; roles[i].name.m; i++) {
732 if (roles[i].name.f) {
735 XtSetArg(args[0], XtNlabel,
736 (r < 1) ? roles[i].name.m : roles[i].name.f);
737 XtSetValues(plsel_role_radios[i], args, ONE);
743 aligntoggleCallback(w, client, call)
745 XtPointer client, call;
747 int r = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
753 plsel_set_play_button(r < 0);
757 plsel_random_btn_callback(w, client, call)
766 X11_player_selection_randomize();
770 plsel_play_btn_callback(w, client, call)
779 plsel_dialog_acceptvalues();
780 exit_x_event = TRUE; /* leave event loop */
784 plsel_quit_btn_callback(w, client, call)
793 ps_selected = PS_QUIT;
794 exit_x_event = TRUE; /* leave event loop */
798 X11_create_player_selection_name(form)
801 Widget namelabel, name_vp, name_form;
807 XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
808 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
809 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
810 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
811 XtSetArg(args[num_args], XtNallowVert, False); num_args++;
812 XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
813 name_vp = XtCreateManagedWidget("name_vp", viewportWidgetClass, form,
817 XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
818 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
819 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
820 name_form = XtCreateManagedWidget("name_form", formWidgetClass, name_vp,
824 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
825 XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
827 XtSetArg(args[num_args], nhStr(XtNlabel), "Name"); num_args++;
829 XtSetArg(args[num_args], nhStr(XtNlabel), "
\96¼
\91O"); num_args++;
830 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
832 namelabel = XtCreateManagedWidget("name_label",
833 labelWidgetClass, name_form,
837 XtSetArg(args[num_args], nhStr(XtNfromVert), namelabel); num_args++;
838 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
839 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
840 XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
841 XtSetArg(args[num_args], nhStr(XtNeditType),
842 !plsel_ask_name ? XawtextRead : XawtextEdit); num_args++;
843 XtSetArg(args[num_args], nhStr(XtNresize), XawtextResizeWidth); num_args++;
844 XtSetArg(args[num_args], nhStr(XtNstring), plname); num_args++;
845 XtSetArg(args[num_args], XtNinsertPosition, strlen(plname)); num_args++;
846 XtSetArg(args[num_args], nhStr(XtNaccelerators),
847 XtParseAcceleratorTable(plsel_input_accelerators)); num_args++;
848 plsel_name_input = XtCreateManagedWidget("name_input",
849 asciiTextWidgetClass, name_form,
852 XtInstallAccelerators(plsel_name_input, plsel_name_input);
853 if (plsel_ask_name) {
854 XtSetKeyboardFocus(form, plsel_name_input);
856 XtSetArg(args[0], nhStr(XtNdisplayCaret), False);
857 XtSetValues(plsel_name_input, args, ONE);
864 X11_player_selection_dialog()
866 Widget popup, popup_vp;
869 Widget racelabel, race_form, race_vp, race_form2;
870 Widget rolelabel, role_form, role_vp, role_form2;
871 Widget gendlabel, gend_form,
872 gend_radio_m, gend_radio_f, gend_vp, gend_form2;
873 Widget alignlabel, align_form,
874 align_radio_l, align_radio_n, align_radio_c, align_vp, align_form2;
875 Widget btn_vp, btn_form, random_btn, play_btn, quit_btn;
881 int cwid = (winwid / 3) - 14;
884 XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
886 XtSetArg(args[num_args], XtNtitle, "Player Selection"); num_args++;
888 XtSetArg(args[num_args], XtNtitle, "
\83v
\83\8c\83C
\83\84\81[
\91I
\91ð"); num_args++;
889 popup = XtCreatePopupShell("player_selection_dialog",
890 transientShellWidgetClass,
891 toplevel, args, num_args);
894 XtSetArg(args[num_args], XtNtranslations,
895 XtParseTranslationTable(plsel_dialog_translations)); num_args++;
896 popup_vp = XtCreateManagedWidget("plsel_vp", viewportWidgetClass,
897 popup, args, num_args);
900 XtSetArg(args[num_args], XtNtranslations,
901 XtParseTranslationTable(plsel_dialog_translations)); num_args++;
902 form = XtCreateManagedWidget("plsel_form", formWidgetClass, popup_vp,
905 name_vp = X11_create_player_selection_name(form);
908 XtSetArg(args[num_args], XtNwidth, winwid); num_args++;
909 XtSetValues(name_vp, args, num_args);
912 * Layout; role is centered rather than first:
914 * +------------------------------------+
916 * +------------------------------------+
917 * +--------+ +------------+ +---------+
918 * | human | |archeologist| | male |
919 * | elf | | barbarian | | female |
920 * | dwarf | | caveman | +---------+
921 * | gnome | | healer | +---------+
922 * | orc | | knight | | lawful |
923 * +--------+ | monk | | neutral |
924 * | priest | | chaotic |
925 * | rogue | +---------+
926 * | ranger | +--------+
927 * | samurai | + Random +
928 * | tourist | + Play +
929 * | valkyrie | + Quit +
930 * | wizard | +--------+
934 * make name box same width as race+gap+role+gap+gender/alignment
935 * (resize it after the other boxes have been placed);
936 * make Random/Play/Quit buttons same width as gender/alignment and
937 * align bottom of them with bottom of role (they already specify
938 * the same width for the label text but different decorations--
939 * room for radio button box--of the other widgets results in the
940 * total width being different);
941 * add 'random' to each of the four boxes and Choose to the Random/
942 * Play/Quit buttons; if none of the four 'random's are currently
943 * selected, gray-out Choose; conversely, when Choose or Play is
944 * clicked on, make the random assignments for any/all of the four
945 * boxes which have 'random' selected.
946 * Maybe: move gender box underneath race, bottom aligned with role
947 * and move alignment up to where gender currently is. If that's
948 * done, move role column first and race+gender to middle.
951 /********************************************/
956 XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
957 race_form = XtCreateManagedWidget("race_form", formWidgetClass, form,
962 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
964 XtSetArg(args[num_args], nhStr(XtNlabel), "Race"); num_args++;
966 XtSetArg(args[num_args], nhStr(XtNlabel), "
\8eí
\91°"); num_args++;
967 racelabel = XtCreateManagedWidget("race_label",
968 labelWidgetClass, race_form,
972 XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
973 XtSetArg(args[num_args], nhStr(XtNfromVert), racelabel); num_args++;
974 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
975 XtSetArg(args[num_args], XtNallowVert, True); num_args++;
976 XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
977 race_vp = XtCreateManagedWidget("race_vp", viewportWidgetClass, race_form,
981 race_form2 = XtCreateManagedWidget("race_form2", formWidgetClass, race_vp,
984 for (i = 0; races[i].noun; i++)
988 plsel_race_radios = (Widget *) alloc(sizeof (Widget) * plsel_n_races);
990 /* race radio buttons */
991 for (i = 0; races[i].noun; i++) {
996 XtSetArg(args[num_args], nhStr(XtNfromVert),
997 tmpwidget); num_args++;
998 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1000 XtSetArg(args[num_args], nhStr(XtNradioGroup),
1001 plsel_race_radios[0]); num_args++;
1002 XtSetArg(args[num_args], nhStr(XtNradioData), (i + 1)); num_args++;
1004 racewidget = XtCreateManagedWidget(races[i].noun,
1008 XtAddCallback(racewidget, XtNcallback, racetoggleCallback, i2xtp(i));
1009 tmpwidget = racewidget;
1010 plsel_race_radios[i] = racewidget;
1013 XawToggleUnsetCurrent(plsel_race_radios[0]);
1015 /********************************************/
1019 XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
1020 XtSetArg(args[num_args], nhStr(XtNfromHoriz), race_form); num_args++;
1021 role_form = XtCreateManagedWidget("role_form", formWidgetClass, form,
1026 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
1027 XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
1028 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
1030 XtSetArg(args[num_args], nhStr(XtNlabel), "Role"); num_args++;
1032 XtSetArg(args[num_args], nhStr(XtNlabel), "
\90E
\8bÆ"); num_args++;
1033 rolelabel = XtCreateManagedWidget("role_label", labelWidgetClass,
1034 role_form, args, num_args);
1037 XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
1038 XtSetArg(args[num_args], nhStr(XtNfromVert), rolelabel); num_args++;
1039 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
1040 XtSetArg(args[num_args], XtNallowVert, True); num_args++;
1041 XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
1042 role_vp = XtCreateManagedWidget("role_vp", viewportWidgetClass, role_form,
1046 role_form2 = XtCreateManagedWidget("role_form2", formWidgetClass, role_vp,
1049 for (i = 0; roles[i].name.m; i++)
1053 plsel_role_radios = (Widget *) alloc(sizeof (Widget) * plsel_n_roles);
1055 /* role radio buttons */
1056 for (i = 0; roles[i].name.m; i++) {
1061 XtSetArg(args[num_args], nhStr(XtNfromVert),
1062 tmpwidget); num_args++;
1063 XtSetArg(args[num_args], nhStr(XtNwidth), cwid); num_args++;
1065 XtSetArg(args[num_args], nhStr(XtNradioGroup),
1066 plsel_role_radios[0]); num_args++;
1067 XtSetArg(args[num_args], nhStr(XtNradioData), (i + 1)); num_args++;
1069 rolewidget = XtCreateManagedWidget(roles[i].name.m, toggleWidgetClass,
1070 role_form2, args, num_args);
1071 XtAddCallback(rolewidget, XtNcallback, roletoggleCallback, i2xtp(i));
1072 tmpwidget = rolewidget;
1073 plsel_role_radios[i] = rolewidget;
1075 XawToggleUnsetCurrent(plsel_role_radios[0]);
1077 /********************************************/
1081 plsel_gend_radios = (Widget *) alloc(sizeof (Widget) * ROLE_GENDERS);
1084 XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
1085 XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
1086 gend_form = XtCreateManagedWidget("gender_form", formWidgetClass, form,
1091 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
1092 XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
1093 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
1095 XtSetArg(args[num_args], nhStr(XtNlabel), "Gender"); num_args++;
1097 XtSetArg(args[num_args], nhStr(XtNlabel), "
\90«
\95Ê"); num_args++;
1098 gendlabel = XtCreateManagedWidget("gender_label", labelWidgetClass,
1099 gend_form, args, num_args);
1102 XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
1103 XtSetArg(args[num_args], nhStr(XtNfromVert), gendlabel); num_args++;
1104 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
1105 XtSetArg(args[num_args], XtNallowVert, True); num_args++;
1106 XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
1107 gend_vp = XtCreateManagedWidget("gender_vp", viewportWidgetClass,
1108 gend_form, args, num_args);
1111 gend_form2 = XtCreateManagedWidget("gender_form2", formWidgetClass,
1112 gend_vp, args, num_args);
1114 /* gender radio buttons */
1116 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1117 XtSetArg(args[num_args], nhStr(XtNradioData), 1); num_args++;
1118 plsel_gend_radios[0] = gend_radio_m
1120 = XtCreateManagedWidget("Male", toggleWidgetClass,
1122 = XtCreateManagedWidget("
\92j
\90«", toggleWidgetClass,
1123 gend_form2, args, num_args);
1125 XtSetArg(args[num_args], nhStr(XtNfromVert), gend_radio_m); num_args++;
1126 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1127 XtSetArg(args[num_args], nhStr(XtNradioGroup),
1128 plsel_gend_radios[0]); num_args++;
1129 XtSetArg(args[num_args], nhStr(XtNradioData), 2); num_args++;
1130 plsel_gend_radios[1] = gend_radio_f
1132 = XtCreateManagedWidget("Female", toggleWidgetClass,
1134 = XtCreateManagedWidget("
\8f\97\90«", toggleWidgetClass,
1135 gend_form2, args, num_args);
1137 XawToggleUnsetCurrent(plsel_gend_radios[0]);
1139 XtAddCallback(gend_radio_m, XtNcallback,
1140 gendertoggleCallback, (XtPointer) (1));
1141 XtAddCallback(gend_radio_f, XtNcallback,
1142 gendertoggleCallback, (XtPointer) (2));
1144 /********************************************/
1148 plsel_align_radios = (Widget *) alloc(sizeof (Widget) * ROLE_ALIGNS);
1151 XtSetArg(args[num_args], nhStr(XtNfromVert), gend_form); num_args++;
1152 XtSetArg(args[num_args], nhStr(XtNvertDistance), 30); num_args++;
1153 XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
1154 align_form = XtCreateManagedWidget("align_form", formWidgetClass, form,
1159 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
1160 XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
1161 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
1163 XtSetArg(args[num_args], nhStr(XtNlabel), "Alignment"); num_args++;
1165 XtSetArg(args[num_args], nhStr(XtNlabel), "
\91®
\90«"); num_args++;
1166 alignlabel = XtCreateManagedWidget("align_label", labelWidgetClass,
1167 align_form, args, num_args);
1170 XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
1171 XtSetArg(args[num_args], nhStr(XtNfromVert), alignlabel); num_args++;
1172 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
1173 XtSetArg(args[num_args], XtNallowVert, True); num_args++;
1174 XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
1175 align_vp = XtCreateManagedWidget("align_vp", viewportWidgetClass,
1176 align_form, args, num_args);
1179 align_form2 = XtCreateManagedWidget("align_form2", formWidgetClass,
1180 align_vp, args, num_args);
1183 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1184 XtSetArg(args[num_args], nhStr(XtNradioData), 1); num_args++;
1185 plsel_align_radios[0] = align_radio_l
1187 = XtCreateManagedWidget("Lawful", toggleWidgetClass,
1189 = XtCreateManagedWidget("
\92\81\8f\98", toggleWidgetClass,
1190 align_form2, args, num_args);
1192 XtSetArg(args[num_args], nhStr(XtNfromVert), align_radio_l); num_args++;
1193 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1194 XtSetArg(args[num_args], nhStr(XtNradioGroup),
1195 plsel_align_radios[0]); num_args++;
1196 XtSetArg(args[num_args], nhStr(XtNradioData), 2); num_args++;
1197 plsel_align_radios[1] = align_radio_n
1199 = XtCreateManagedWidget("Neutral", toggleWidgetClass,
1201 = XtCreateManagedWidget("
\92\86\97§", toggleWidgetClass,
1202 align_form2, args, num_args);
1204 XtSetArg(args[num_args], nhStr(XtNfromVert), align_radio_n); num_args++;
1205 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1206 XtSetArg(args[num_args], nhStr(XtNradioGroup),
1207 plsel_align_radios[0]); num_args++;
1208 XtSetArg(args[num_args], nhStr(XtNradioData), 3); num_args++;
1209 plsel_align_radios[2] = align_radio_c
1211 = XtCreateManagedWidget("Chaotic", toggleWidgetClass,
1213 = XtCreateManagedWidget("
\8d¬
\93×", toggleWidgetClass,
1214 align_form2, args, num_args);
1216 XawToggleUnsetCurrent(plsel_align_radios[0]);
1218 XtAddCallback(align_radio_l, XtNcallback,
1219 aligntoggleCallback, (XtPointer) (1));
1220 XtAddCallback(align_radio_n, XtNcallback,
1221 aligntoggleCallback, (XtPointer) (2));
1222 XtAddCallback(align_radio_c, XtNcallback,
1223 aligntoggleCallback, (XtPointer) (3));
1225 /********************************************/
1230 XtSetArg(args[num_args], nhStr(XtNfromVert), align_form); num_args++;
1231 XtSetArg(args[num_args], nhStr(XtNvertDistance), 30); num_args++;
1232 XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
1233 XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
1234 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
1235 XtSetArg(args[num_args], XtNallowVert, False); num_args++;
1236 XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
1237 btn_vp = XtCreateManagedWidget("btn_vp", viewportWidgetClass, form,
1241 btn_form = XtCreateManagedWidget("btn_form", formWidgetClass, btn_vp,
1244 /* "Random" button */
1247 XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
1248 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
1249 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
1250 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1252 XtSetArg(args[num_args], nhStr(XtNlabel), "Random"); num_args++;
1254 XtSetArg(args[num_args], nhStr(XtNlabel), "
\83\89\83\93\83_
\83\80"); num_args++;
1255 random_btn = XtCreateManagedWidget("random", commandWidgetClass, btn_form,
1257 XtAddCallback(random_btn, XtNcallback, plsel_random_btn_callback, form);
1262 XtSetArg(args[num_args], nhStr(XtNfromVert), random_btn); num_args++;
1263 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
1264 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
1265 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1267 XtSetArg(args[num_args], nhStr(XtNlabel), "Play"); num_args++;
1269 XtSetArg(args[num_args], nhStr(XtNlabel), "
\83v
\83\8c\83C
\8aJ
\8en"); num_args++;
1270 plsel_btn_play = play_btn
1271 = XtCreateManagedWidget("play", commandWidgetClass, btn_form,
1273 XtAddCallback(play_btn, XtNcallback, plsel_play_btn_callback, form);
1278 XtSetArg(args[num_args], nhStr(XtNfromVert), play_btn); num_args++;
1279 XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
1280 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
1281 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
1282 XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
1284 XtSetArg(args[num_args], nhStr(XtNlabel), "Quit"); num_args++;
1286 XtSetArg(args[num_args], nhStr(XtNlabel), "
\8fI
\97¹"); num_args++;
1287 quit_btn = XtCreateManagedWidget("quit", commandWidgetClass, btn_form,
1289 XtAddCallback(quit_btn, XtNcallback, plsel_quit_btn_callback, form);
1291 /********************************************/
1293 XtRealizeWidget(popup);
1294 X11_player_selection_randomize();
1296 if (flags.randomall) {
1297 plsel_dialog_acceptvalues();
1300 nh_XtPopup(popup, (int) XtGrabExclusive, form);
1301 /* The callback will enable the event loop exit. */
1302 (void) x_event(EXIT_ON_EXIT);
1305 nh_XtPopdown(popup);
1306 XtDestroyWidget(popup);
1308 if (plsel_race_radios)
1309 free(plsel_race_radios);
1311 if (plsel_role_radios)
1312 free(plsel_role_radios);
1314 if (plsel_gend_radios)
1315 free(plsel_gend_radios);
1317 if (plsel_align_radios)
1318 free(plsel_align_radios);
1320 if (ps_selected == PS_QUIT || program_state.done_hup) {
1322 X11_exit_nhwindows((char *) 0);
1327 /* Global functions ======================================================== */
1329 X11_player_selection_prompts()
1331 int num_roles, num_races, num_gends, num_algns, i, availcount, availindex;
1332 Widget popup, player_form;
1333 const char **choices;
1334 char qbuf[QBUFSZ], plbuf[QBUFSZ];
1341 /* avoid unnecessary prompts further down */
1342 rigid_role_checks();
1344 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1345 flags.initrace, flags.initgend,
1348 while (flags.initrole < 0) {
1349 if (flags.initrole == ROLE_RANDOM || flags.randomall) {
1350 flags.initrole = pick_role(flags.initrace, flags.initgend,
1351 flags.initalign, PICK_RANDOM);
1356 for (num_roles = 0; roles[num_roles].name.m; ++num_roles)
1358 choices = (const char **) alloc(sizeof (char *) * num_roles);
1361 for (i = 0; i < num_roles; i++) {
1363 if (ok_role(i, flags.initrace, flags.initgend,
1365 choices[i] = roles[i].name.m;
1366 if (flags.initgend >= 0 && flags.female
1368 choices[i] = roles[i].name.f;
1374 else if (flags.initalign >= 0)
1375 flags.initalign = -1; /* reset */
1376 else if (flags.initgend >= 0)
1377 flags.initgend = -1;
1378 else if (flags.initrace >= 0)
1379 flags.initrace = -1;
1381 panic("no available ROLE+race+gender+alignment combinations");
1384 Sprintf(qbuf, "Choose your %s Role", s_suffix(plbuf));
1386 Sprintf(qbuf, "%s
\90E
\8bÆ
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
1390 make_menu("player_selection", qbuf, player_select_translations,
1391 "quit", ps_quit, "random", ps_random, num_roles,
1392 choices, (Widget **) 0, ps_select, &player_form);
1394 make_menu("player_selection", qbuf, player_select_translations,
1395 "
\94²
\82¯
\82é", ps_quit, "
\83\89\83\93\83_
\83\80", ps_random, num_roles,
1396 choices, (Widget **) 0, ps_select, &player_form);
1400 positionpopup(popup, FALSE);
1401 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
1403 /* The callbacks will enable the event loop exit. */
1404 (void) x_event(EXIT_ON_EXIT);
1406 nh_XtPopdown(popup);
1407 XtDestroyWidget(popup);
1408 free((genericptr_t) choices), choices = 0;
1410 if (ps_selected == PS_QUIT || program_state.done_hup) {
1412 X11_exit_nhwindows((char *) 0);
1414 } else if (ps_selected == PS_RANDOM) {
1415 flags.initrole = ROLE_RANDOM;
1416 } else if (ps_selected < 0 || ps_selected >= num_roles) {
1417 panic("player_selection: bad role select value %d", ps_selected);
1419 flags.initrole = ps_selected;
1423 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1424 flags.initrace, flags.initgend,
1427 while (!validrace(flags.initrole, flags.initrace)) {
1428 if (flags.initrace == ROLE_RANDOM || flags.randomall) {
1429 flags.initrace = pick_race(flags.initrole, flags.initgend,
1430 flags.initalign, PICK_RANDOM);
1434 for (num_races = 0; races[num_races].noun; ++num_races)
1436 choices = (const char **) alloc(sizeof(char *) * num_races);
1438 availcount = availindex = 0;
1439 for (i = 0; i < num_races; i++) {
1441 if (ok_race(flags.initrole, i, flags.initgend,
1443 choices[i] = races[i].noun;
1445 availindex = i; /* used iff only one */
1450 else if (flags.initalign >= 0)
1451 flags.initalign = -1; /* reset */
1452 else if (flags.initgend >= 0)
1453 flags.initgend = -1;
1455 panic("no available role+RACE+gender+alignment combinations");
1458 if (availcount == 1) {
1459 flags.initrace = availindex;
1460 free((genericptr_t) choices), choices = 0;
1463 Sprintf(qbuf, "Pick your %s race", s_suffix(plbuf));
1465 Sprintf(qbuf, "%s
\8eí
\91°
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
1469 make_menu("race_selection", qbuf, race_select_translations,
1470 "quit", ps_quit, "random", ps_random, num_races,
1471 choices, (Widget **) 0, ps_select, &player_form);
1474 make_menu("race_selection", qbuf, race_select_translations,
1475 "
\94²
\82¯
\82é", ps_quit, "
\83\89\83\93\83_
\83\80", ps_random, num_races,
1476 choices, (Widget **) 0, ps_select, &player_form);
1480 positionpopup(popup, FALSE);
1481 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
1483 /* The callbacks will enable the event loop exit. */
1484 (void) x_event(EXIT_ON_EXIT);
1486 nh_XtPopdown(popup);
1487 XtDestroyWidget(popup);
1488 free((genericptr_t) choices), choices = 0;
1490 if (ps_selected == PS_QUIT || program_state.done_hup) {
1492 X11_exit_nhwindows((char *) 0);
1494 } else if (ps_selected == PS_RANDOM) {
1495 flags.initrace = ROLE_RANDOM;
1496 } else if (ps_selected < 0 || ps_selected >= num_races) {
1497 panic("player_selection: bad race select value %d",
1500 flags.initrace = ps_selected;
1502 } /* more than one race choice available */
1505 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1506 flags.initrace, flags.initgend,
1509 while (!validgend(flags.initrole, flags.initrace, flags.initgend)) {
1510 if (flags.initgend == ROLE_RANDOM || flags.randomall) {
1511 flags.initgend = pick_gend(flags.initrole, flags.initrace,
1512 flags.initalign, PICK_RANDOM);
1515 /* select a gender */
1516 num_gends = 2; /* genders[2] isn't allowed */
1517 choices = (const char **) alloc(sizeof(char *) * num_gends);
1519 availcount = availindex = 0;
1520 for (i = 0; i < num_gends; i++) {
1522 if (ok_gend(flags.initrole, flags.initrace, i,
1524 choices[i] = genders[i].adj;
1526 availindex = i; /* used iff only one */
1531 else if (flags.initalign >= 0)
1532 flags.initalign = -1; /* reset */
1534 panic("no available role+race+GENDER+alignment combinations");
1537 if (availcount == 1) {
1538 flags.initgend = availindex;
1539 free((genericptr_t) choices), choices = 0;
1542 Sprintf(qbuf, "Your %s gender?", s_suffix(plbuf));
1544 Sprintf(qbuf, "%s
\90«
\95Ê
\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
1547 make_menu("gender_selection", qbuf, gend_select_translations,
1548 "quit", ps_quit, "random", ps_random, num_gends,
1549 choices, (Widget **) 0, ps_select, &player_form);
1552 make_menu("gender_selection", qbuf, gend_select_translations,
1553 "
\94²
\82¯
\82é", ps_quit, "
\83\89\83\93\83_
\83\80", ps_random, num_gends,
1554 choices, (Widget **) 0, ps_select, &player_form);
1558 positionpopup(popup, FALSE);
1559 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
1561 /* The callbacks will enable the event loop exit. */
1562 (void) x_event(EXIT_ON_EXIT);
1564 nh_XtPopdown(popup);
1565 XtDestroyWidget(popup);
1566 free((genericptr_t) choices), choices = 0;
1568 if (ps_selected == PS_QUIT || program_state.done_hup) {
1570 X11_exit_nhwindows((char *) 0);
1572 } else if (ps_selected == PS_RANDOM) {
1573 flags.initgend = ROLE_RANDOM;
1574 } else if (ps_selected < 0 || ps_selected >= num_gends) {
1575 panic("player_selection: bad gender select value %d",
1578 flags.initgend = ps_selected;
1580 } /* more than one gender choice available */
1583 (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
1584 flags.initrace, flags.initgend,
1587 while (!validalign(flags.initrole, flags.initrace, flags.initalign)) {
1588 if (flags.initalign == ROLE_RANDOM || flags.randomall) {
1589 flags.initalign = pick_align(flags.initrole, flags.initrace,
1590 flags.initgend, PICK_RANDOM);
1593 /* select an alignment */
1594 num_algns = 3; /* aligns[3] isn't allowed */
1595 choices = (const char **) alloc(sizeof(char *) * num_algns);
1597 availcount = availindex = 0;
1598 for (i = 0; i < num_algns; i++) {
1600 if (ok_align(flags.initrole, flags.initrace, flags.initgend,
1602 choices[i] = aligns[i].adj;
1604 availindex = i; /* used iff only one */
1610 panic("no available role+race+gender+ALIGNMENT combinations");
1613 if (availcount == 1) {
1614 flags.initalign = availindex;
1615 free((genericptr_t) choices), choices = 0;
1618 Sprintf(qbuf, "Your %s alignment?", s_suffix(plbuf));
1620 Sprintf(qbuf, "%s
\91®
\90«
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D", s_suffix(plbuf));
1622 popup = make_menu("alignment_selection", qbuf,
1623 algn_select_translations, "quit", ps_quit,
1624 "random", ps_random, num_algns, choices,
1625 (Widget **) 0, ps_select, &player_form);
1627 popup = make_menu("alignment_selection", qbuf,
1628 algn_select_translations, "
\94²
\82¯
\82é", ps_quit,
1629 "
\83\89\83\93\83_
\83\80", ps_random, num_algns, choices,
1630 (Widget **) 0, ps_select, &player_form);
1634 positionpopup(popup, FALSE);
1635 nh_XtPopup(popup, (int) XtGrabExclusive, player_form);
1637 /* The callbacks will enable the event loop exit. */
1638 (void) x_event(EXIT_ON_EXIT);
1640 nh_XtPopdown(popup);
1641 XtDestroyWidget(popup);
1642 free((genericptr_t) choices), choices = 0;
1644 if (ps_selected == PS_QUIT || program_state.done_hup) {
1646 X11_exit_nhwindows((char *) 0);
1648 } else if (ps_selected == PS_RANDOM) {
1649 flags.initalign = ROLE_RANDOM;
1650 } else if (ps_selected < 0 || ps_selected >= num_algns) {
1651 panic("player_selection: bad alignment select value %d",
1654 flags.initalign = ps_selected;
1656 } /* more than one alignment choice available */
1661 X11_player_selection()
1663 if (iflags.wc_player_selection == VIA_DIALOG) {
1666 char *defplname = get_login_name();
1668 char *defplname = (char *)0;
1670 (void) strncpy(plname, defplname ? defplname : "Mumbles",
1672 plname[sizeof plname - 1] = '\0';
1673 iflags.renameinprogress = TRUE;
1675 X11_player_selection_dialog();
1676 } else { /* iflags.wc_player_selection == VIA_PROMPTS */
1677 X11_player_selection_prompts();
1681 /* called by core to have the player pick an extended command */
1685 if (iflags.extmenu != ec_full_list) {
1686 /* player has toggled the 'extmenu' option, toss the old widgets */
1687 if (extended_commands)
1688 release_extended_cmds(); /* will set extended_commands to Null */
1689 ec_full_list = iflags.extmenu;
1691 if (!extended_commands)
1692 init_extended_commands_popup();
1694 extended_cmd_selected = -1; /* reset selected value */
1695 ec_scroll_to_view(-1); /* force scroll bar to top */
1697 positionpopup(extended_command_popup, FALSE); /* center on cursor */
1698 nh_XtPopup(extended_command_popup, (int) XtGrabExclusive,
1699 extended_command_form);
1701 /* The callbacks will enable the event loop exit. */
1702 (void) x_event(EXIT_ON_EXIT);
1704 if (extended_cmd_selected < 0)
1706 return command_indx[extended_cmd_selected];
1710 release_extended_cmds()
1712 if (extended_commands) {
1713 XtDestroyWidget(extended_command_popup), extended_command_popup = 0;
1714 free((genericptr_t) extended_commands), extended_commands = 0;
1715 free((genericptr_t) command_list), command_list = (const char **) 0;
1716 free((genericptr_t) command_indx), command_indx = (short *) 0;
1720 /* End global functions =================================================== */
1722 /* Extended Command ------------------------------------------------------- */
1725 extend_select(w, client_data, call_data)
1727 XtPointer client_data, call_data;
1729 int selected = (int) (ptrdiff_t) client_data;
1734 if (extended_cmd_selected != selected) {
1735 /* visibly deselect old one */
1736 if (extended_cmd_selected >= 0)
1737 swap_fg_bg(extended_commands[extended_cmd_selected]);
1739 /* select new one */
1740 swap_fg_bg(extended_commands[selected]);
1741 extended_cmd_selected = selected;
1744 nh_XtPopdown(extended_command_popup);
1745 /* reset colors while popped down */
1746 swap_fg_bg(extended_commands[extended_cmd_selected]);
1748 exit_x_event = TRUE; /* leave event loop */
1753 extend_dismiss(w, client_data, call_data)
1755 XtPointer client_data, call_data;
1766 extend_help(w, client_data, call_data)
1768 XtPointer client_data, call_data;
1774 /* We might need to make it known that we already have one listed. */
1780 ec_delete(w, event, params, num_params)
1784 Cardinal *num_params;
1786 if (w == extended_command_popup) {
1789 popup_delete(w, event, params, num_params);
1795 popup_delete(w, event, params, num_params)
1799 Cardinal *num_params;
1805 ps_selected = PS_QUIT;
1807 exit_x_event = TRUE; /* leave event loop */
1813 /* unselect while still visible */
1814 if (extended_cmd_selected >= 0)
1815 swap_fg_bg(extended_commands[extended_cmd_selected]);
1816 extended_cmd_selected = -1; /* dismiss */
1817 nh_XtPopdown(extended_command_popup);
1819 exit_x_event = TRUE; /* leave event loop */
1822 /* scroll the extended command menu if necessary
1823 so that choices extended_cmd_selected through ec_indx will be visible */
1825 ec_scroll_to_view(ec_indx)
1826 int ec_indx; /* might be greater than extended_cmd_selected */
1828 Widget viewport, scrollbar, tmpw;
1831 Position lo_y, hi_y; /* ext cmd label y */
1832 float s_shown, s_top; /* scrollbar pos */
1834 Dimension h, hh, wh, vh; /* widget and viewport heights */
1835 Dimension border_width;
1837 boolean force_top = (ec_indx < 0);
1840 * If the extended command menu needs to be scrolled in order to move
1841 * either the highlighted entry (extended_cmd_selected) or the target
1842 * entry (ec_indx) into view, we want to make both end up visible.
1843 * [Highligthed one is the first matching entry when the user types
1844 * something, such as "adjust" after typing 'a', and will be chosen
1845 * by pressing <return>. Target entry is one past the last matching
1846 * entry (or last matching entry itself if at end of command list),
1847 * showing the user the other potential matches so far.]
1849 * If that's not possible (maybe menu has been resized so that it's
1850 * too small), the highlighted entry takes precedence and the target
1851 * will be decremented until close enough to fit.
1857 /* get viewport and scrollbar widgets */
1858 tmpw = extended_commands[ec_indx];
1859 viewport = XtParent(tmpw);
1861 scrollbar = XtNameToWidget(tmpw, "*vertical");
1864 tmpw = XtParent(tmpw);
1867 if (scrollbar && viewport) {
1868 /* get selected ext command label y position and height */
1870 XtSetArg(args[num_args], XtNy, &hi_y); num_args++;
1871 XtSetArg(args[num_args], XtNheight, &h); num_args++;
1872 XtSetArg(args[num_args], nhStr(XtNborderWidth), &border_width);
1874 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), &distance);
1876 XtGetValues(extended_commands[ec_indx], args, num_args);
1877 if (distance < 1 || distance > 32766) /* defaultDistance is weird */
1879 /* vertical distance between top of one command widget and the next */
1880 hh = h + distance + 2 * border_width;
1881 /* location of the highlighted entry, if any */
1882 if (extended_cmd_selected >= 0) {
1883 XtSetArg(args[0], XtNy, &lo_y);
1884 XtGetValues(extended_commands[extended_cmd_selected], args, ONE);
1888 /* get menu widget and viewport heights */
1889 XtSetArg(args[0], XtNheight, &wh);
1890 XtGetValues(tmpw, args, ONE);
1891 XtSetArg(args[0], XtNheight, &vh);
1892 XtGetValues(viewport, args, ONE);
1894 /* widget might be too small if it has been resized or
1895 there are a very large number of ambiguous choices */
1896 if (hi_y - lo_y > wh) {
1897 ec_indx = extended_cmd_selected;
1899 ec_indx += (wh / hh);
1900 XtSetArg(args[0], XtNy, &hi_y);
1901 XtGetValues(extended_commands[ec_indx], args, num_args);
1904 /* get scrollbar "height" and "top" position; floats between 0-1 */
1906 XtSetArg(args[num_args], XtNshown, &s_shown); num_args++;
1907 XtSetArg(args[num_args], nhStr(XtNtopOfThumb), &s_top); num_args++;
1908 XtGetValues(scrollbar, args, num_args);
1911 s_max = (s_top + s_shown) * vh;
1913 /* scroll if outside the view */
1916 XtCallCallbacks(scrollbar, XtNjumpProc, &s_min);
1917 } else if ((int) lo_y <= (int) s_min) {
1918 s_min = (float) (lo_y / (float) vh);
1919 XtCallCallbacks(scrollbar, XtNjumpProc, &s_min);
1920 } else if ((int) (hi_y + h) >= (int) s_max) {
1921 s_min = (float) ((hi_y + h) / (float) vh) - s_shown;
1922 XtCallCallbacks(scrollbar, XtNjumpProc, &s_min);
1927 /* decide whether extcmdlist[idx] should be part of extended commands menu */
1932 /* #shell or #suspect might not be available;
1933 'extmenu' option controls whether we show full list
1934 or just the traditional extended commands */
1935 if ((extcmdlist[idx].flags & CMD_NOT_AVAILABLE) != 0
1936 || ((extcmdlist[idx].flags & AUTOCOMPLETE) == 0 && !ec_full_list)
1937 || strlen(extcmdlist[idx].ef_txt) < 2) /* ignore "#" and "?" */
1945 ec_key(w, event, params, num_params)
1949 Cardinal *num_params;
1956 XKeyEvent *xkey = (XKeyEvent *) event;
1961 ch = key_event_to_char(xkey);
1963 if (ch == '\0') { /* don't accept nul char/modifier event */
1966 } else if (ch == '?') {
1967 extend_help((Widget) 0, (XtPointer) 0, (XtPointer) 0);
1969 } else if (index("\033\n\r", ch)) {
1971 /* unselect while still visible */
1972 if (extended_cmd_selected >= 0)
1973 swap_fg_bg(extended_commands[extended_cmd_selected]);
1974 extended_cmd_selected = -1; /* dismiss */
1977 nh_XtPopdown(extended_command_popup);
1978 /* unselect while invisible */
1979 if (extended_cmd_selected >= 0)
1980 swap_fg_bg(extended_commands[extended_cmd_selected]);
1982 exit_x_event = TRUE; /* leave event loop */
1985 } else if (ch == MENU_FIRST_PAGE || ch == MENU_LAST_PAGE) {
1986 hbar = vbar = (Widget) 0;
1987 find_scrollbars(w, &hbar, &vbar);
1989 top = (ch == MENU_FIRST_PAGE) ? 0.0 : 1.0;
1990 XtCallCallbacks(vbar, XtNjumpProc, &top);
1993 } else if (ch == MENU_NEXT_PAGE || ch == MENU_PREVIOUS_PAGE) {
1994 hbar = vbar = (Widget) 0;
1995 find_scrollbars(w, &hbar, &vbar);
1997 XtSetArg(arg[0], nhStr(XtNshown), &shown);
1998 XtSetArg(arg[1], nhStr(XtNtopOfThumb), &top);
1999 XtGetValues(vbar, arg, TWO);
2000 top += ((ch == MENU_NEXT_PAGE) ? shown : -shown);
2001 XtCallCallbacks(vbar, XtNjumpProc, &top);
2007 * If too much time has elapsed, treat current key as starting a new
2008 * choice, otherwise it is a continuation of the choice in progress.
2009 * Extra letters might be needed to disambiguate between choices
2010 * ("ride" vs "rub", for instance), or player may just be typing in
2013 if (ec_active && (xkey->time - ec_time) > 2500) /* 2.5 seconds */
2021 ec_time = xkey->time;
2022 ec_chars[ec_nchars++] = ch;
2023 if (ec_nchars >= EC_NCHARS)
2024 ec_nchars = EC_NCHARS - 1; /* don't overflow */
2026 for (pass = 0; pass < 2; pass++) {
2028 /* first pass finished, but no matching command was found */
2029 /* start a new one with the last char entered */
2030 if (extended_cmd_selected >= 0)
2031 swap_fg_bg(extended_commands[extended_cmd_selected]);
2032 extended_cmd_selected = -1; /* dismiss */
2033 ec_chars[0] = ec_chars[ec_nchars - 1];
2036 for (i = 0; command_list[i]; ++i) {
2037 if (!strncmp(ec_chars, command_list[i], ec_nchars)) {
2038 if (extended_cmd_selected != i) {
2039 /* I should use set() and unset() actions, but how do
2040 I send the an action to the widget? */
2041 if (extended_cmd_selected >= 0)
2042 swap_fg_bg(extended_commands[extended_cmd_selected]);
2043 extended_cmd_selected = i;
2044 swap_fg_bg(extended_commands[extended_cmd_selected]);
2046 /* advance to one past last matching entry, so that all
2047 ambiguous choices, plus one to show thare aren't any
2048 more such, will scroll into view */
2050 if (!command_list[i + 1])
2051 break; /* end of list */
2053 } while (!strncmp(ec_chars, command_list[i], ec_nchars));
2055 ec_scroll_to_view(i);
2063 * Use our own home-brewed version menu because simpleMenu is designed to
2064 * be used from a menubox.
2067 init_extended_commands_popup()
2069 int i, j, num_commands, ignore_cmds = 0;
2071 /* count commands */
2072 for (num_commands = 0; extcmdlist[num_commands].ef_txt; num_commands++)
2073 if (ignore_extcmd(num_commands))
2076 j = num_commands - ignore_cmds;
2077 command_list = (const char **) alloc((unsigned) (j * sizeof (char *) + 1));
2078 command_indx = (short *) alloc((unsigned) (j * sizeof (short) + 1));
2080 for (i = j = 0; i < num_commands; i++) {
2081 if (ignore_extcmd(i))
2083 command_indx[j] = (short) i;
2084 command_list[j++] = extcmdlist[i].ef_txt;
2086 command_list[j] = (char *) 0;
2087 command_indx[j] = -1;
2091 extended_command_popup =
2092 make_menu("extended_commands", "Extended Commands",
2093 extended_command_translations, "dismiss", extend_dismiss,
2094 "help", extend_help, num_commands, command_list,
2095 &extended_commands, extend_select, &extended_command_form);
2097 extended_command_popup =
2098 make_menu("extended_commands", "
\8ag
\92£
\83R
\83}
\83\93\83h",
2099 extended_command_translations, "
\8eæ
\8fÁ", extend_dismiss,
2100 "
\83w
\83\8b\83v", extend_help, num_commands, command_list,
2101 &extended_commands, extend_select, &extended_command_form);
2105 /* ------------------------------------------------------------------------ */
2108 * Create a popup widget of the following form:
2111 * ----------- ------------
2112 * |left_name| |right_name|
2113 * ----------- ------------
2114 * ------------------------
2116 * ------------------------
2117 * ------------------------
2119 * ------------------------
2122 * ------------------------
2124 * ------------------------
2127 make_menu(popup_name, popup_label, popup_translations, left_name,
2128 left_callback, right_name, right_callback, num_names, widget_names,
2129 command_widgets, name_callback, formp)
2130 const char *popup_name;
2131 const char *popup_label;
2132 const char *popup_translations;
2133 const char *left_name;
2134 XtCallbackProc left_callback;
2135 const char *right_name;
2136 XtCallbackProc right_callback;
2138 const char **widget_names; /* return array of command widgets */
2139 Widget **command_widgets;
2140 XtCallbackProc name_callback;
2141 Widget *formp; /* return */
2143 Widget popup, popform, form, label, above, left, right, view;
2144 Widget *commands, *curr;
2148 Dimension width, other_width, max_width, border_width,
2149 height, cumulative_height, screen_height;
2151 char btnname[BUFSZ];
2153 commands = (Widget *) alloc((unsigned) num_names * sizeof (Widget));
2156 XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
2157 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
2158 popup = XtCreatePopupShell(popup_name, transientShellWidgetClass,
2159 toplevel, args, num_args);
2160 XtOverrideTranslations(
2161 popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: ec_delete()"));
2164 XtSetArg(args[num_args], XtNtranslations,
2165 XtParseTranslationTable(popup_translations)); num_args++;
2166 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
2167 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0); num_args++;
2168 popform = XtCreateManagedWidget("topmenuform", formWidgetClass, popup,
2173 XtSetArg(args[num_args], XtNforceBars, False); num_args++;
2174 XtSetArg(args[num_args], XtNallowVert, True); num_args++;
2175 /*XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;*/
2176 XtSetArg(args[num_args], nhStr(XtNuseBottom), True); num_args++;
2177 XtSetArg(args[num_args], nhStr(XtNuseRight), True); num_args++;
2178 XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
2179 XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
2180 XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
2181 XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
2182 XtSetArg(args[num_args], XtNtranslations,
2183 XtParseTranslationTable(popup_translations)); num_args++;
2184 view = XtCreateManagedWidget("menuformview", viewportWidgetClass, popform,
2188 XtSetArg(args[num_args], XtNtranslations,
2189 XtParseTranslationTable(popup_translations)); num_args++;
2190 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
2191 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0); num_args++;
2192 *formp = form = XtCreateManagedWidget("menuform", formWidgetClass, view,
2196 * Get the default distance between objects in the viewport widget.
2197 * (Something is fishy here: 'distance' ends up being 0 but there
2198 * is a non-zero gap between the borders of the internal widgets.
2199 * It matches exactly the default value of 4 for defaultDistance.)
2202 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), &distance); num_args++;
2203 XtSetArg(args[num_args], nhStr(XtNborderWidth), &border_width); num_args++;
2204 XtGetValues(view, args, num_args);
2205 if (distance < 1 || distance > 32766)
2212 #if defined(X11R6) && defined(XI18N)
2213 XtSetArg(args[num_args], XtNinternational, True); num_args++;
2215 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
2216 label = XtCreateManagedWidget(popup_label, labelWidgetClass, form, args,
2219 cumulative_height = 0;
2220 XtSetArg(args[0], XtNheight, &height);
2221 XtGetValues(label, args, ONE);
2222 cumulative_height += distance + height; /* no border for label */
2225 * Create the left button.
2228 XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
2229 XtSetArg(args[num_args], nhStr(XtNlabel), left_name); num_args++;
2231 XtSetArg(args[num_args], nhStr(XtNshapeStyle),
2232 XmuShapeRoundedRectangle); num_args++;
2234 Sprintf(btnname, "btn_%s", left_name);
2235 left = XtCreateManagedWidget(btnname, commandWidgetClass, form, args,
2237 XtAddCallback(left, XtNcallback, left_callback, (XtPointer) 0);
2238 skip = (distance < 4) ? 8 : 2 * distance;
2241 XtSetArg(args[0], XtNheight, &height);
2242 XtGetValues(left, args, ONE);
2243 cumulative_height += distance + height + 2 * border_width;
2246 * Create right button.
2249 XtSetArg(args[num_args], nhStr(XtNfromHoriz), left); num_args++;
2250 XtSetArg(args[num_args], nhStr(XtNhorizDistance), skip); num_args++;
2251 XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
2252 XtSetArg(args[num_args], nhStr(XtNlabel), right_name); num_args++;
2254 XtSetArg(args[num_args], nhStr(XtNshapeStyle),
2255 XmuShapeRoundedRectangle); num_args++;
2257 #if defined(X11R6) && defined(XI18N)
2258 XtSetArg(args[num_args], XtNinternational, True); num_args++;
2260 Sprintf(btnname, "btn_%s", right_name);
2261 right = XtCreateManagedWidget(btnname, commandWidgetClass, form, args,
2263 XtAddCallback(right, XtNcallback, right_callback, (XtPointer) 0);
2265 XtInstallAccelerators(form, left);
2266 XtInstallAccelerators(form, right);
2269 * Create and place the command widgets.
2271 for (i = 0, above = left, curr = commands; i < num_names; i++) {
2272 if (!widget_names[i])
2275 XtSetArg(args[num_args], XtNtranslations,
2276 XtParseTranslationTable(popup_entry_translations)); num_args++;
2277 XtSetArg(args[num_args], nhStr(XtNfromVert), above); num_args++;
2278 if (above == left) {
2279 /* if first, we are farther apart */
2280 XtSetArg(args[num_args], nhStr(XtNvertDistance), skip); num_args++;
2281 cumulative_height += skip;
2283 cumulative_height += distance;
2284 cumulative_height += height + 2 * border_width;
2286 #if defined(X11R6) && defined(XI18N)
2287 XtSetArg(args[num_args], XtNinternational, True);
2290 *curr = XtCreateManagedWidget(widget_names[i], commandWidgetClass,
2291 form, args, num_args);
2292 XtAddCallback(*curr, XtNcallback, name_callback,
2293 (XtPointer) (ptrdiff_t) i);
2296 cumulative_height += distance; /* space at bottom of form */
2299 * Now find the largest width. Start with width of left + right buttons
2300 * ('dismiss' + 'help' or 'quit' + 'random'), since they are adjacent.
2302 XtSetArg(args[0], XtNwidth, &max_width);
2303 XtGetValues(left, args, ONE);
2304 XtSetArg(args[0], XtNwidth, &width);
2305 XtGetValues(right, args, ONE);
2306 /* doesn't count leftmost 'distance + border_width' and
2307 rightmost 'border_width + distance' since all entries have those */
2308 max_width = max_width + border_width + skip + border_width + width;
2310 /* Next, the title. */
2311 XtSetArg(args[0], XtNwidth, &width);
2312 XtGetValues(label, args, ONE);
2313 if (width > max_width)
2316 /* Finally, the commands. */
2317 for (i = 0, curr = commands; i < num_names; i++) {
2318 if (!widget_names[i])
2320 XtSetArg(args[0], XtNwidth, &width);
2321 XtGetValues(*curr, args, ONE);
2322 if (width > max_width)
2328 * Re-do the two side-by-side widgets to take up half the width each.
2330 * With max_width and skip both having even values, we never have to
2331 * tweak left or right to maybe be one pixel wider than the other.
2335 XtSetArg(args[0], XtNwidth, &width);
2336 XtGetValues(left, args, ONE);
2337 XtSetArg(args[0], XtNwidth, &other_width);
2338 XtGetValues(right, args, ONE);
2339 if (width + border_width + skip / 2 < max_width / 2
2340 && other_width + border_width + skip / 2 < max_width / 2) {
2341 /* both are narrower than half */
2342 width = other_width = max_width / 2 - border_width - skip / 2;
2343 XtSetArg(args[0], XtNwidth, width);
2344 XtSetValues(left, args, ONE);
2345 XtSetArg(args[0], XtNwidth, other_width);
2346 XtSetValues(right, args, ONE);
2347 } else if (width + border_width + skip / 2 < max_width / 2) {
2348 /* 'other_width' (right) is half or more */
2349 width = max_width - other_width - 2 * border_width - skip;
2350 XtSetArg(args[0], XtNwidth, width);
2351 XtSetValues(left, args, ONE);
2352 } else if (other_width + border_width + skip / 2 < max_width / 2) {
2353 /* 'width' (left) is half or more */
2354 other_width = max_width - width - 2 * border_width - skip;
2355 XtSetArg(args[0], XtNwidth, other_width);
2356 XtSetValues(right, args, ONE);
2358 ; /* both are exactly half... */
2362 * Finally, set all of the single line widgets to the largest width.
2364 XtSetArg(args[0], XtNwidth, max_width);
2365 XtSetValues(label, args, ONE);
2367 for (i = 0, curr = commands; i < num_names; i++) {
2368 if (!widget_names[i])
2370 XtSetArg(args[0], XtNwidth, max_width);
2371 XtSetValues(*curr, args, ONE);
2375 if (command_widgets)
2376 *command_widgets = commands;
2378 free((char *) commands);
2381 * If the menu's complete height is too big for the display,
2382 * forcing the height to be smaller will cause the vertical
2383 * scroll bar (enabled but not forced above) to be included.
2385 screen_height = XHeightOfScreen(XtScreen(popup));
2386 screen_height -= appResources.extcmd_height_delta; /* NetHack.ad */
2387 if (cumulative_height >= screen_height) {
2388 /* 25 is a guesstimate for scrollbar width;
2389 window manager might override the request for y==1 */
2391 XtSetArg(args[num_args], XtNy, 1); num_args++;
2392 XtSetArg(args[num_args], XtNwidth, max_width + 25); num_args++;
2393 XtSetArg(args[num_args], XtNheight, screen_height - 1); num_args++;
2394 XtSetValues(popup, args, num_args);
2396 XtRealizeWidget(popup);
2397 XSetWMProtocols(XtDisplay(popup), XtWindow(popup), &wm_delete_window, 1);
2399 /* during role selection, highlight "random" as pre-selected choice */
2400 if (right_callback == ps_random && index(ps_randchars, '\n'))