]> granicus.if.org Git - nethack/commitdiff
X11 menus - support pre-selected menu entries
authorPatR <rankin@nethack.org>
Sun, 31 Jan 2016 03:39:29 +0000 (19:39 -0800)
committerPatR <rankin@nethack.org>
Sun, 31 Jan 2016 03:39:29 +0000 (19:39 -0800)
X11 had been ignoring add_menu(..., MENU_SELECTED) to specify a
pre-selected menu entry.  This adds support for that.

Attempt to implement pre-selected entry for PICK_ONE menu sanely by
returning the pre-selected entry instead of toggling it off if the
user chooses it explicitly.   Inner workings of menus are convoluted
so I'm not sure it's 100% correct, although testing hasn't found any
problems.  (tty currently returns 0 for "nothing picked" when
explicitly picking a pre-selected entry in a PICK_ONE menu, and the
core jumps through hoops to handle it.  That can't be cleaned up until
all interfaces which support pre-selected entries achieve sanity.)

Make "random" be chosen for <return> or <enter> during role selection
and highlight it to reflect that.  (Role selection for X11 uses its
own code instead of nethack menus, so pre-selection isn't applicable.)

doc/fixes36.1
include/winX.h
win/X11/winmenu.c
win/X11/winmisc.c

index 293447b3e6e5bcf3fd12e43532e0df3564e94740..bf9cc0be983bd06da26d0db7e68dd731f6845a15 100644 (file)
@@ -164,6 +164,7 @@ MacOSX: force TIMED_DELAY build option on so that 'runmode' run-time option
 X11: core bug for '`' (backtick) and #terrain commands was only noticed by
        X11 interface: impossible "add_menu: called before start_menu"
 X11: enable a scroll bar in menu windows
+X11: support pre-selected entries in menu windows
 X11: make the extended command menu be easier to use and look a little nicer
 X11: make the getline text entry widget display a bigger text entry area
 
index e462dfe94018c0d72e849b23a256c3d953edfc1a..dcd588d6ffd13e388739d9d674e62a260e271f3d 100644 (file)
@@ -1,5 +1,5 @@
 /* NetHack 3.6 winX.h  $NHDT-Date: 1453447524 2016/01/22 07:25:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.19 $ */
-/* Copyright (c) Dean Luick, 1992                                */
+/* Copyright (c) Dean Luick, 1992                                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -52,7 +52,7 @@ struct text_map_info_t {
 
     int square_width,  /* Saved font information so      */
         square_height, /*   we can calculate the correct */
-        square_ascent, /*   placement of changes.        */
+        square_ascent, /*   placement of changes.        */
         square_lbearing;
 };
 
@@ -70,7 +70,7 @@ struct tile_map_info_t {
 
     int square_width,  /* Saved tile information so      */
         square_height, /*   we can calculate the correct */
-        square_ascent, /*   placement of changes.        */
+        square_ascent, /*   placement of changes.        */
         square_lbearing;
 };
 
@@ -101,16 +101,16 @@ struct mesg_info_t {
     struct line_element *head;       /* head of circular line queue */
     struct line_element *line_here;  /* current drawn line position */
     struct line_element *last_pause; /* point to the line after the prev */
-    /*     bottom of screen                    */
+                                     /*     bottom of screen             */
     struct line_element *last_pause_head; /* pointer to head of previous */
-    /* turn                                    */
+                                          /* turn                        */
     GC gc;           /* GC for text drawing */
     int char_width,  /* Saved font information so we can  */
         char_height, /*   calculate the correct placement */
-        char_ascent, /*   of changes.               */
+        char_ascent, /*   of changes.                     */
         char_lbearing;
-    Dimension viewport_width, /* Saved viewport size, so we can adjust */
-        viewport_height;      /*   the slider on a resize.              */
+    Dimension viewport_width,  /* Saved viewport size, so we can adjust */
+              viewport_height; /*   the slider on a resize.             */
     Boolean dirty;            /* Lines have been added to the window. */
 };
 
@@ -132,6 +132,7 @@ typedef struct x11_mi {
     char *str;           /* The text of the item. */
     int attr;            /* Attribute for the line. */
     boolean selected;    /* Been selected? */
+    boolean preselected; /*   in advance?  */
     char selector;       /* Char used to select this entry. */
     char gselector;      /* Group selector. */
 } x11_menu_item;
@@ -145,7 +146,7 @@ struct menu {
     String *list_pointer; /* String list. */
     Boolean *sensitive;   /* Active list. */
     char curr_selector;   /* Next keyboard accelerator to assign, */
-    /*   if 0, then we're out.         */
+                          /*   if 0, then we're out.              */
 };
 
 struct menu_info_t {
@@ -213,19 +214,19 @@ struct xwindow {
 
 #define MAX_WINDOWS 20 /* max number of open windows */
 
-#define NHW_NONE 0 /* Unallocated window type.  Must be        */
-/* different from any other NHW_* type. */
+#define NHW_NONE 0 /* Unallocated window type.  Must be    */
+                   /* different from any other NHW_* type. */
 
 #define NO_CLICK 0 /* No click occurred on the map window. Must */
-/* be different than CLICK_1 and CLICK_2.   */
+                   /* be different than CLICK_1 and CLICK_2.    */
 
 #define DEFAULT_MESSAGE_WIDTH 60 /* width in chars of the message window */
 
-#define DISPLAY_FILE_SIZE 35 /* Max number of lines in the default     */
-/* file display window.                        */
+#define DISPLAY_FILE_SIZE 35 /* Max number of lines in the default */
+                             /* file display window.               */
 
 #define MAX_KEY_STRING 64 /* String size for converting a keypress */
-/* event into a character(s)            */
+                          /* event into a character(s)             */
 
 #define DEFAULT_LINES_DISPLAYED 12 /* # of lines displayed message window */
 #define MAX_HISTORY 60             /* max history saved on message window */
index 8fe7baec3aff57e9dc890f874b8a230482ffc05b..97f8592a4597ae6f5d26bd4568b4cf6d5d7ed611 100644 (file)
@@ -41,8 +41,7 @@
 #include <ctype.h>
 
 static void FDECL(menu_select, (Widget, XtPointer, XtPointer));
-static void FDECL(invert_line,
-                  (struct xwindow *, x11_menu_item *, int, long));
+static void FDECL(invert_line, (struct xwindow *, x11_menu_item *, int, long));
 static void FDECL(menu_ok, (Widget, XtPointer, XtPointer));
 static void FDECL(menu_cancel, (Widget, XtPointer, XtPointer));
 static void FDECL(menu_all, (Widget, XtPointer, XtPointer));
@@ -130,7 +129,9 @@ XtPointer client_data, call_data;
     }
 
     /* if we've reached here, we've found our selected item */
-    curr->selected = !curr->selected;
+    if (menu_info->how != PICK_ONE || !curr->preselected)
+        curr->selected = !curr->selected;
+    curr->preselected = FALSE;
     if (curr->selected) {
         curr->str[2] = (how_many != -1L) ? '#' : '+';
         curr->pick_count = how_many;
@@ -178,7 +179,11 @@ long how_many;
     nhUse(which);
 #endif
     reset_menu_count(wp->menu_information);
-    curr->selected = !curr->selected;
+    /* invert selection unless explicitly choosing the preselected
+       entry of a PICK_ONE menu */
+    if (wp->menu_information->how != PICK_ONE || !curr->preselected)
+        curr->selected = !curr->selected;
+    curr->preselected = FALSE;
     if (curr->selected) {
 #ifdef USE_FWF
         XfwfMultiListHighlightItem((XfwfMultiListWidget) wp->w, which);
@@ -326,9 +331,8 @@ Cardinal *num_params;
                     break;
 
             if (curr) {
-                invert_line(wp, curr, count, menu_info->counting
-                                                 ? menu_info->menu_count
-                                                 : -1L);
+                invert_line(wp, curr, count,
+                            menu_info->counting ? menu_info->menu_count : -1L);
 #ifndef USE_FWF
                 XawListChange(wp->w, menu_info->curr_menu.list_pointer, 0, 0,
                               True);
@@ -468,8 +472,8 @@ struct xwindow *wp;
 
 #ifndef USE_FWF
     if (changed)
-        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0,
-                      0, True);
+        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                      0, 0, True);
 #endif
 }
 
@@ -492,8 +496,8 @@ struct xwindow *wp;
 
 #ifndef USE_FWF
     if (changed)
-        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0,
-                      0, True);
+        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                      0, 0, True);
 #endif
 }
 
@@ -511,8 +515,8 @@ struct xwindow *wp;
             invert_line(wp, curr, count, -1L);
 
 #ifndef USE_FWF
-    XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0, 0,
-                  True);
+    XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                  0, 0, True);
 #endif
 }
 
@@ -528,15 +532,18 @@ char *match; /* wildcard pattern for pmatch() */
     reset_menu_count(wp->menu_information);
     for (count = 0, curr = wp->menu_information->curr_menu.base; curr;
          curr = curr->next, count++)
-        if (curr->identifier.a_void != 0 && pmatchi(match, curr->str)) {
-            invert_line(wp, curr, count, -1L);
-            changed = TRUE;
+        if (curr->identifier.a_void != 0) {
+            if (pmatchi(match, curr->str)) {
+                invert_line(wp, curr, count, -1L);
+                changed = TRUE;
+            }
+            curr->preselected = FALSE;
         }
 
 #ifndef USE_FWF
     if (changed)
-        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0,
-                      0, True);
+        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                      0, 0, True);
 #endif
 }
 
@@ -545,26 +552,30 @@ select_match(wp, match)
 struct xwindow *wp;
 char *match; /* wildcard pattern for pmatch() */
 {
-    x11_menu_item *curr;
+    x11_menu_item *curr, *found = 0;
     int count;
 
     reset_menu_count(wp->menu_information);
     for (count = 0, curr = wp->menu_information->curr_menu.base; curr;
          curr = curr->next, count++)
-        if (curr->identifier.a_void != 0 && pmatchi(match, curr->str)) {
-            if (!curr->selected) {
-                invert_line(wp, curr, count, -1L);
+        if (curr->identifier.a_void != 0) {
+            if (!found && pmatchi(match, curr->str))
+                found = curr;
+            curr->preselected = FALSE;
+        }
+
+    if (found) {
+        if (!found->selected) {
+            invert_line(wp, found, count, -1L);
 #ifndef USE_FWF
-                XawListChange(wp->w,
-                              wp->menu_information->curr_menu.list_pointer, 0,
-                              0, True);
+            XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                          0, 0, True);
 #endif
-            }
-            return;
         }
-
-    /* no match */
-    X11_nhbell();
+    } else {
+        /* no match */
+        X11_nhbell();
+    }
 }
 
 static void
@@ -610,6 +621,8 @@ int *items;
            printf("sync: selecting %s\n", curr->str);
 #endif
         curr->selected = found ? TRUE : FALSE;
+        /* once active selection takes place, preselection becomes history */
+        curr->preselected = FALSE;
     }
 }
 #endif /* USE_FWF */
@@ -650,7 +663,6 @@ boolean preselected;
     struct menu_info_t *menu_info;
 
     nhUse(glyph);
-    nhUse(preselected); /*FIXME*/
 
     check_winid(window);
     menu_info = window_list[window].menu_information;
@@ -663,8 +675,7 @@ boolean preselected;
     item->next = (x11_menu_item *) 0;
     item->identifier = *identifier;
     item->attr = attr;
-    /*    item->selected = preselected; */
-    item->selected = FALSE;
+    item->selected = item->preselected = preselected;
     item->pick_count = -1L;
 
     if (identifier->a_void) {
@@ -688,7 +699,7 @@ boolean preselected;
             impossible("Menu item too long (%d).", len);
             len = BUFSZ - 1;
         }
-        Sprintf(buf, "%c - ", ch ? ch : ' ');
+        Sprintf(buf, "%c %c ", ch ? ch : ' ', preselected ? '+' : '-');
         (void) strncpy(buf + 4, str, len);
         buf[4 + len] = '\0';
         item->str = copy_of(buf);
@@ -828,58 +839,46 @@ menu_item **menu_list;
         num_args = 0;
         XtSetArg(args[num_args], XtNallowShellResize, True);
         num_args++;
-        wp->popup =
-            XtCreatePopupShell(window == WIN_INVEN ? "inventory" : "menu",
-                               how == PICK_NONE ? topLevelShellWidgetClass
-                                                : transientShellWidgetClass,
-                               toplevel, args, num_args);
-        XtOverrideTranslations(
-            wp->popup,
-            XtParseTranslationTable("<Message>WM_PROTOCOLS: menu_delete()"));
+        wp->popup = XtCreatePopupShell((window == WIN_INVEN)
+                                           ? "inventory" : "menu",
+                                       (how == PICK_NONE)
+                                           ? topLevelShellWidgetClass
+                                           : transientShellWidgetClass,
+                                       toplevel, args, num_args);
+        XtOverrideTranslations(wp->popup,
+                               XtParseTranslationTable(
+                                     "<Message>WM_PROTOCOLS: menu_delete()"));
 
         num_args = 0;
         XtSetArg(args[num_args], XtNtranslations,
-                 XtParseTranslationTable(menu_translations));
-        num_args++;
+                 XtParseTranslationTable(menu_translations)); num_args++;
         form = XtCreateManagedWidget("mform", formWidgetClass, wp->popup,
                                      args, num_args);
 
         num_args = 0;
-        XtSetArg(args[num_args], XtNborderWidth, 0);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+        XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 
-        if (labeled)
-            label =
-                XtCreateManagedWidget(menu_info->new_menu.query,
-                                      labelWidgetClass, form, args, num_args);
-        else
-            label = NULL;
+        label = labeled ? XtCreateManagedWidget(menu_info->new_menu.query,
+                                                labelWidgetClass, form,
+                                                args, num_args)
+                        : (Widget) 0;
 
         /*
          * Create ok, cancel, all, none, invert, and search buttons..
          */
         maxlblwidth = 0;
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
-        ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args,
-                                   num_args);
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+        ok = XtCreateManagedWidget("OK", commandWidgetClass, form,
+                                   args, num_args);
         XtAddCallback(ok, XtNcallback, menu_ok, (XtPointer) wp);
         XtSetArg(args[0], XtNwidth, &lblwidth[0]);
         XtGetValues(lblwidget[0] = ok, args, ONE);
@@ -887,20 +886,14 @@ menu_item **menu_list;
             maxlblwidth = lblwidth[0];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), ok);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), ok); num_args++;
         XtSetArg(args[num_args], nhStr(XtNsensitive), how != PICK_NONE);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+                                                                   num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
         cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form,
                                        args, num_args);
         XtAddCallback(cancel, XtNcallback, menu_cancel, (XtPointer) wp);
@@ -911,22 +904,15 @@ menu_item **menu_list;
 
         sens = (how == PICK_ANY);
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), cancel);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNsensitive), sens);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
-        all = XtCreateManagedWidget("all", commandWidgetClass, form, args,
-                                    num_args);
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), cancel); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNsensitive), sens); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+        all = XtCreateManagedWidget("all", commandWidgetClass, form,
+                                    args, num_args);
         XtAddCallback(all, XtNcallback, menu_all, (XtPointer) wp);
         XtSetArg(args[0], XtNwidth, &lblwidth[2]);
         XtGetValues(lblwidget[2] = all, args, ONE);
@@ -934,22 +920,15 @@ menu_item **menu_list;
             maxlblwidth = lblwidth[2];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), all);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNsensitive), sens);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
-        none = XtCreateManagedWidget("none", commandWidgetClass, form, args,
-                                     num_args);
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), all); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNsensitive), sens); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+        none = XtCreateManagedWidget("none", commandWidgetClass, form,
+                                     args, num_args);
         XtAddCallback(none, XtNcallback, menu_none, (XtPointer) wp);
         XtSetArg(args[0], XtNwidth, &lblwidth[3]);
         XtGetValues(lblwidget[3] = none, args, ONE);
@@ -957,20 +936,13 @@ menu_item **menu_list;
             maxlblwidth = lblwidth[3];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), none);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNsensitive), sens);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), none); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNsensitive), sens); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
         invert = XtCreateManagedWidget("invert", commandWidgetClass, form,
                                        args, num_args);
         XtAddCallback(invert, XtNcallback, menu_invert, (XtPointer) wp);
@@ -980,20 +952,14 @@ menu_item **menu_list;
             maxlblwidth = lblwidth[4];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), invert);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), invert); num_args++;
         XtSetArg(args[num_args], nhStr(XtNsensitive), how != PICK_NONE);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+                                                                   num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
         search = XtCreateManagedWidget("search", commandWidgetClass, form,
                                        args, num_args);
         XtAddCallback(search, XtNcallback, menu_search, (XtPointer) wp);
@@ -1013,27 +979,18 @@ menu_item **menu_list;
         }
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNallowVert), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNallowHoriz), False);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNuseBottom), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNuseRight), True);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNallowVert), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNallowHoriz), False); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNuseBottom), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNuseRight), True); num_args++;
 #if 0
         XtSetArg(args[num_args], nhStr(XtNforceBars), True); num_args++;
 #endif
-        XtSetArg(args[num_args], nhStr(XtNfromVert), all);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainRight);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), all); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
         viewport_widget = XtCreateManagedWidget(
             "menu_viewport",           /* name */
             viewportWidgetClass, form, /* parent widget */
@@ -1043,22 +1000,16 @@ menu_item **menu_list;
         move_menu(&menu_info->new_menu, &menu_info->curr_menu);
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNforceColumns), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNcolumnSpacing), 1);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNdefaultColumns), 1);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNforceColumns), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNcolumnSpacing), 1); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNdefaultColumns), 1); num_args++;
         XtSetArg(args[num_args], nhStr(XtNlist),
-                 menu_info->curr_menu.list_pointer);
-        num_args++;
+                 menu_info->curr_menu.list_pointer); num_args++;
 #ifdef USE_FWF
         XtSetArg(args[num_args], nhStr(XtNsensitiveArray),
-                 menu_info->curr_menu.sensitive);
-        num_args++;
+                 menu_info->curr_menu.sensitive); num_args++;
         XtSetArg(args[num_args], nhStr(XtNmaxSelectable),
-                 menu_info->curr_menu.count);
-        num_args++;
+                 menu_info->curr_menu.count); num_args++;
 #endif
         wp->w = XtCreateManagedWidget("menu_list", /* name */
 #ifdef USE_FWF
@@ -1074,16 +1025,13 @@ menu_item **menu_list;
 
         /* Get the font and margin information. */
         num_args = 0;
-        XtSetArg(args[num_args], XtNfont, &menu_info->fs);
-        num_args++;
+        XtSetArg(args[num_args], XtNfont, &menu_info->fs); num_args++;
         XtSetArg(args[num_args], XtNinternalHeight,
-                 &menu_info->internal_height);
-        num_args++;
+                 &menu_info->internal_height); num_args++;
         XtSetArg(args[num_args], XtNinternalWidth,
-                 &menu_info->internal_width);
-        num_args++;
+                 &menu_info->internal_width); num_args++;
         XtSetArg(args[num_args], nhStr(XtNrowSpacing), &row_spacing);
-        num_args++;
+                                                                   num_args++;
         XtGetValues(wp->w, args, num_args);
 
         /* font height is ascent + descent */
@@ -1094,10 +1042,8 @@ menu_item **menu_list;
         menu_info->valid_widgets = TRUE;
 
         num_args = 0;
-        XtSetArg(args[num_args], XtNwidth, &v_pixel_width);
-        num_args++;
-        XtSetArg(args[num_args], XtNheight, &v_pixel_height);
-        num_args++;
+        XtSetArg(args[num_args], XtNwidth, &v_pixel_width); num_args++;
+        XtSetArg(args[num_args], XtNheight, &v_pixel_height); num_args++;
         XtGetValues(wp->w, args, num_args);
     } else {
         Dimension len;
@@ -1114,9 +1060,8 @@ menu_item **menu_list;
 
         /* add viewport internal border */
         v_pixel_width += 2 * menu_info->internal_width;
-        v_pixel_height =
-            (2 * menu_info->internal_height)
-            + (menu_info->new_menu.count * menu_info->line_height);
+        v_pixel_height = (2 * menu_info->internal_height)
+                       + (menu_info->new_menu.count * menu_info->line_height);
 
         /* make new menu the current menu */
         move_menu(&menu_info->new_menu, &menu_info->curr_menu);
@@ -1131,10 +1076,8 @@ menu_item **menu_list;
 
     /* if viewport will be bigger than the screen, limit its height */
     num_args = 0;
-    XtSetArg(args[num_args], XtNwidth, &v_pixel_width);
-    num_args++;
-    XtSetArg(args[num_args], XtNheight, &v_pixel_height);
-    num_args++;
+    XtSetArg(args[num_args], XtNwidth, &v_pixel_width); num_args++;
+    XtSetArg(args[num_args], XtNheight, &v_pixel_height); num_args++;
     XtGetValues(wp->w, args, num_args);
     if ((Dimension) XtScreen(wp->w)->height * 5 / 6 < v_pixel_height) {
         /* scrollbar is 14 pixels wide.  Widen the form to accommodate it. */
@@ -1144,10 +1087,8 @@ menu_item **menu_list;
         v_pixel_height = XtScreen(wp->w)->height * 5 / 6;
 
         num_args = 0;
-        XtSetArg(args[num_args], XtNwidth, v_pixel_width);
-        num_args++;
-        XtSetArg(args[num_args], XtNheight, v_pixel_height);
-        num_args++;
+        XtSetArg(args[num_args], XtNwidth, v_pixel_width); num_args++;
+        XtSetArg(args[num_args], XtNheight, v_pixel_height); num_args++;
         XtSetValues(wp->w, args, num_args);
     }
     XtRealizeWidget(wp->popup); /* need to realize before we position */
@@ -1181,16 +1122,22 @@ menu_item **menu_list;
 
         if (retval) {
             menu_item *mi;
+            boolean toomany = (how == PICK_ONE && retval > 1);
 
+            if (toomany)
+                retval = 1;
             *menu_list = mi = (menu_item *) alloc(retval * sizeof(menu_item));
             for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
                 if (curr->selected) {
                     mi->item = curr->identifier;
                     mi->count = curr->pick_count;
-                    mi++;
+                    if (!toomany)
+                        mi++;
+                    if (how == PICK_ONE && !curr->preselected)
+                        break;
                 }
         }
-    }
+    } /* ?(WIN_INVEN && PICK_NONE) */
 
     return retval;
 }
@@ -1201,8 +1148,6 @@ menu_item **menu_list;
 /*
  * Allocate a copy of the given string.  If null, return a string of
  * zero length.
- *
- * This is an exact duplicate of copy_of() in tty/wintty.c.
  */
 static char *
 copy_of(s)
@@ -1210,7 +1155,7 @@ const char *s;
 {
     if (!s)
         s = "";
-    return strcpy((char *) alloc((unsigned) (strlen(s) + 1)), s);
+    return dupstr(s);
 }
 
 static void
index d1d44d906a294dca1b8895b202db025c331b4656..960577e14ce78ed1e1ad09bd7f7a408e8e2ef41f 100644 (file)
 static Widget extended_command_popup = 0;
 static Widget extended_command_form;
 static Widget *extended_commands = 0;
-static int extended_command_selected; /* index of the selected command; */
+static int extended_cmd_selected; /* index of the selected command; */
 static int ps_selected;               /* index of selected role */
 #define PS_RANDOM (-50)
 #define PS_QUIT (-75)
-static const char ps_randchars[] = "*@";
+/* 'r' for random won't work for role but will for race, gender, alignment */
+static const char ps_randchars[] = "*@\n\rrR";
 static const char ps_quitchars[] = "\033qQ";
 
 #define EC_NCHARS 32
@@ -591,7 +592,7 @@ X11_get_ext_cmd()
         initialized = True;
     }
 
-    extended_command_selected = -1; /* reset selected value */
+    extended_cmd_selected = -1; /* reset selected value */
 
     positionpopup(extended_command_popup, FALSE); /* center on cursor */
     nh_XtPopup(extended_command_popup, (int) XtGrabExclusive,
@@ -600,7 +601,7 @@ X11_get_ext_cmd()
     /* The callbacks will enable the event loop exit. */
     (void) x_event(EXIT_ON_EXIT);
 
-    return extended_command_selected;
+    return extended_cmd_selected;
 }
 
 /* End global functions =====================================================
@@ -619,19 +620,19 @@ XtPointer client_data, call_data;
     nhUse(w);
     nhUse(call_data);
 
-    if (extended_command_selected != selected) {
+    if (extended_cmd_selected != selected) {
         /* visibly deselect old one */
-        if (extended_command_selected >= 0)
-            swap_fg_bg(extended_commands[extended_command_selected]);
+        if (extended_cmd_selected >= 0)
+            swap_fg_bg(extended_commands[extended_cmd_selected]);
 
         /* select new one */
         swap_fg_bg(extended_commands[selected]);
-        extended_command_selected = selected;
+        extended_cmd_selected = selected;
     }
 
     nh_XtPopdown(extended_command_popup);
     /* reset colors while popped down */
-    swap_fg_bg(extended_commands[extended_command_selected]);
+    swap_fg_bg(extended_commands[extended_cmd_selected]);
     ec_active = FALSE;
     exit_x_event = TRUE; /* leave event loop */
 }
@@ -699,9 +700,9 @@ static void
 ec_dismiss()
 {
     /* unselect while still visible */
-    if (extended_command_selected >= 0)
-        swap_fg_bg(extended_commands[extended_command_selected]);
-    extended_command_selected = -1; /* dismiss */
+    if (extended_cmd_selected >= 0)
+        swap_fg_bg(extended_commands[extended_cmd_selected]);
+    extended_cmd_selected = -1; /* dismiss */
     nh_XtPopdown(extended_command_popup);
     ec_active = FALSE;
     exit_x_event = TRUE; /* leave event loop */
@@ -718,17 +719,17 @@ ec_scroll_to_view()
     float s_min, s_max;
     Position vh; /* viewport height */
 
-    if (extended_command_selected < 0)
+    if (extended_cmd_selected < 0)
         return;
 
     /* get selected ext command label y position and height */
     num_args = 0;
     XtSetArg(args[num_args], XtNy, &y); num_args++;
     XtSetArg(args[num_args], XtNheight, &h); num_args++;
-    XtGetValues(extended_commands[extended_command_selected], args, num_args);
+    XtGetValues(extended_commands[extended_cmd_selected], args, num_args);
 
     /* get viewport and scrollbar widgets */
-    tmpw = extended_commands[extended_command_selected];
+    tmpw = extended_commands[extended_cmd_selected];
     viewport = XtParent(tmpw);
     do {
         tmpw = XtParent(tmpw);
@@ -744,7 +745,7 @@ ec_scroll_to_view()
         /* get scrollbar "height" and "top" position; floats between 0-1 */
         num_args = 0;
         XtSetArg(args[num_args], XtNshown, &s_shown); num_args++;
-        XtSetArg(args[num_args], XtNtopOfThumb, &s_top); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtopOfThumb), &s_top); num_args++;
         XtGetValues(scrollbar, args, num_args);
 
         s_min = s_top * vh;
@@ -789,15 +790,15 @@ Cardinal *num_params;
     } else if (index("\033\n\r", ch)) {
         if (ch == '\033') {
             /* unselect while still visible */
-            if (extended_command_selected >= 0)
-                swap_fg_bg(extended_commands[extended_command_selected]);
-            extended_command_selected = -1; /* dismiss */
+            if (extended_cmd_selected >= 0)
+                swap_fg_bg(extended_commands[extended_cmd_selected]);
+            extended_cmd_selected = -1; /* dismiss */
         }
 
         nh_XtPopdown(extended_command_popup);
         /* unselect while invisible */
-        if (extended_command_selected >= 0)
-            swap_fg_bg(extended_commands[extended_command_selected]);
+        if (extended_cmd_selected >= 0)
+            swap_fg_bg(extended_commands[extended_cmd_selected]);
 
         exit_x_event = TRUE; /* leave event loop */
         ec_active = FALSE;
@@ -811,7 +812,7 @@ Cardinal *num_params;
      * ("ride" vs "rub", for instance), or player may just be typing in
      * the whole word.
      */
-    if ((xkey->time - ec_time) > 2500) /* 2.5 seconds */
+    if (ec_active && (xkey->time - ec_time) > 2500) /* 2.5 seconds */
         ec_active = FALSE;
 
     if (!ec_active) {
@@ -828,9 +829,9 @@ Cardinal *num_params;
         if (pass == 1) {
             /* first pass finished, but no matching command was found */
             /* start a new one with the last char entered */
-            if (extended_command_selected >= 0)
-                swap_fg_bg(extended_commands[extended_command_selected]);
-            extended_command_selected = -1; /* dismiss */
+            if (extended_cmd_selected >= 0)
+                swap_fg_bg(extended_commands[extended_cmd_selected]);
+            extended_cmd_selected = -1; /* dismiss */
             ec_chars[0] = ec_chars[ec_nchars-1];
             ec_nchars = 1;
         }
@@ -839,13 +840,13 @@ Cardinal *num_params;
                 continue;
 
             if (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars)) {
-                if (extended_command_selected != i) {
+                if (extended_cmd_selected != i) {
                     /* I should use set() and unset() actions, but how do */
                     /* I send the an action to the widget? */
-                    if (extended_command_selected >= 0)
-                        swap_fg_bg(extended_commands[extended_command_selected]);
-                    extended_command_selected = i;
-                    swap_fg_bg(extended_commands[extended_command_selected]);
+                    if (extended_cmd_selected >= 0)
+                        swap_fg_bg(extended_commands[extended_cmd_selected]);
+                    extended_cmd_selected = i;
+                    swap_fg_bg(extended_commands[extended_cmd_selected]);
                 }
                 ec_scroll_to_view();
                 return;
@@ -1154,5 +1155,9 @@ Widget *formp; /* return */
     XtRealizeWidget(popup);
     XSetWMProtocols(XtDisplay(popup), XtWindow(popup), &wm_delete_window, 1);
 
+    /* during role selection, highlight "random" as pre-selected choice */
+    if (right_callback == ps_random && index(ps_randchars, '\n'))
+        swap_fg_bg(right);
+
     return popup;
 }