]> granicus.if.org Git - nethack/commitdiff
curses: support digits as menu group accelerators
authorPatR <rankin@nethack.org>
Fri, 11 Feb 2022 18:04:03 +0000 (10:04 -0800)
committerPatR <rankin@nethack.org>
Fri, 11 Feb 2022 18:04:03 +0000 (10:04 -0800)
Have curses catch up with tty, X11, and Qt:  if a menu of objects has
any heavy iron balls, their entries can be toggled on or off by using
'0' as a group accelerator.  That's been supported by tty and X11 for
ages and by Qt since yesterday.  This also supports having any digit
as a group accelerator so that the 'O' hack to pick number_pad mode by
typing the digit that matches the value description works (except for
menu entry for mode -1; '5' happens to work for that one but doesn't
match its description).

doc/fixes3-7-0.txt
win/curses/cursdial.c

index 28745e48b3633c421ad27bf61238039234cb5e2f..e4384ccffdbb6171dfe2817f7b9a3bcf5108db9d 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.782 $ $NHDT-Date: 1644545143 2022/02/11 02:05:43 $
+NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.784 $ $NHDT-Date: 1644602632 2022/02/11 18:03:52 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -1079,6 +1079,9 @@ curses: sometimes entering a count during menu selection caused the menu to
        but no longer displayed
 curses: support backspace/delete when entering a count during menu selection
 curses: make extended command prompt behave more sensibly
+curses: if a menu of objects contains at least one iron ball, and player is
+       not alreadly in the midst of entering a count, recognize '0' as a
+       group accelerator rather than the start of a count
 macOS: Xcode project was failing to build if the path to the NetHack source
        tree contained a space; the issue was within some shell script code
        contained within the project
index 993f083b4cbb00773d069fed0578b4df5cae280f..907a8c8e13fae8dbd101cdf02fd54cd5ab99332a 100644 (file)
@@ -75,15 +75,15 @@ static void menu_determine_pages(nhmenu *menu);
 static boolean menu_is_multipage(nhmenu *menu, int width, int height);
 static void menu_win_size(nhmenu *menu);
 #ifdef NCURSES_MOUSE_VERSION
-static nhmenu_item *get_menuitem_y(nhmenu *menu, WINDOW * win UNUSED,
+static nhmenu_item *get_menuitem_y(nhmenu *menu, WINDOW *win UNUSED,
                                    int page_num, int liney);
 #endif /*NCURSES_MOUSE_VERSION*/
-static void menu_display_page(nhmenu *menu, WINDOW * win, int page_num,
-                              char *);
-static int menu_get_selections(WINDOW * win, nhmenu *menu, int how);
-static void menu_select_deselect(WINDOW * win, nhmenu_item *item,
+static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num,
+                              char *, char *);
+static int menu_get_selections(WINDOW *win, nhmenu *menu, int how);
+static void menu_select_deselect(WINDOW *win, nhmenu_item *item,
                                  menu_op operation, int);
-static int menu_operation(WINDOW * win, nhmenu *menu, menu_op operation,
+static int menu_operation(WINDOW *win, nhmenu *menu, menu_op operation,
                           int page_num);
 static void menu_clear_selections(nhmenu *menu);
 static int menu_max_height(void);
@@ -101,7 +101,10 @@ static nhmenu *nhmenus = NULL;  /* NetHack menu array */
    or a wish.  Note: EDIT_GETLIN not supported for popup prompting. */
 
 void
-curses_line_input_dialog(const char *prompt, char *answer, int buffer)
+curses_line_input_dialog(
+    const char *prompt,
+    char *answer,
+    int buffer)
 {
     int map_height, map_width, maxwidth, remaining_buf, winx, winy, count;
     WINDOW *askwin, *bwin;
@@ -195,8 +198,10 @@ curses_line_input_dialog(const char *prompt, char *answer, int buffer)
 /* Get a single character response from the player, such as a y/n prompt */
 
 int
-curses_character_input_dialog(const char *prompt, const char *choices,
-                              char def)
+curses_character_input_dialog(
+    const char *prompt,
+    const char *choices,
+    char def)
 {
     WINDOW *askwin = NULL;
 #ifdef PDCURSES
@@ -427,8 +432,7 @@ curses_ext_cmd(void)
             if (ec) {
                 curses_toggle_color_attr(extwin, NONE, A_UNDERLINE, ON);
                 wmove(extwin, starty, (int) strlen(cur_choice) + startx + 2);
-                wprintw(extwin, "%s",
-                        ec->ef_txt + (int) strlen(cur_choice));
+                wprintw(extwin, "%s", ec->ef_txt + (int) strlen(cur_choice));
                 curses_toggle_color_attr(extwin, NONE, A_UNDERLINE, OFF);
             }
         }
@@ -448,7 +452,9 @@ curses_ext_cmd(void)
         if (letter == '\r' || letter == '\n') {
             (void) mungspaces(cur_choice);
             if (ret == -1) {
-                matches = extcmds_match(cur_choice, ECM_IGNOREAC|ECM_EXACTMATCH, &ecmatches);
+                matches = extcmds_match(cur_choice,
+                                        (ECM_IGNOREAC | ECM_EXACTMATCH),
+                                        &ecmatches);
                 if (matches == 1 && ecmatches)
                     ret = ecmatches[0];
             }
@@ -589,10 +595,15 @@ curs_new_menu_item(winid wid, const char *str)
 /* Add a menu item to the given menu window */
 
 void
-curses_add_nhmenu_item(winid wid, const glyph_info *glyphinfo,
-                       const ANY_P *identifier, char accelerator,
-                       char group_accel, int attr,
-                       const char *str, unsigned itemflags)
+curses_add_nhmenu_item(
+    winid wid,
+    const glyph_info *glyphinfo,
+    const ANY_P *identifier,
+    char accelerator,
+    char group_accel,
+    int attr,
+    const char *str,
+    unsigned itemflags)
 {
     nhmenu_item *new_item, *current_items, *menu_item_ptr;
     nhmenu *current_menu = get_menu(wid);
@@ -634,7 +645,9 @@ curses_add_nhmenu_item(winid wid, const glyph_info *glyphinfo,
 /* for menu->bottom_heavy -- insert enough blank lines at top of
    first page to make the last page become a full one */
 static void
-curs_pad_menu(nhmenu *current_menu, boolean do_pad UNUSED)
+curs_pad_menu(
+    nhmenu *current_menu,
+    boolean do_pad UNUSED)
 {
     nhmenu_item *menu_item_ptr;
     int numpages = current_menu->num_pages;
@@ -720,7 +733,10 @@ curses_finalize_nhmenu(winid wid, const char *prompt)
 /* Display a nethack menu, and return a selection, if applicable */
 
 int
-curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected)
+curses_display_nhmenu(
+    winid wid,
+    int how,
+    MENU_ITEM_P **_selected)
 {
     nhmenu *current_menu = get_menu(wid);
     nhmenu_item *menu_item_ptr;
@@ -1078,7 +1094,11 @@ menu_win_size(nhmenu *menu)
 
 #ifdef NCURSES_MOUSE_VERSION
 static nhmenu_item *
-get_menuitem_y(nhmenu *menu, WINDOW * win UNUSED, int page_num, int liney)
+get_menuitem_y(
+    nhmenu *menu,
+    WINDOW *win UNUSED,
+    int page_num,
+    int liney)
 {
     nhmenu_item *menu_item_ptr;
     int count, num_lines, entry_cols = menu->width;
@@ -1136,7 +1156,11 @@ get_menuitem_y(nhmenu *menu, WINDOW * win UNUSED, int page_num, int liney)
 /* Displays menu selections in the given window */
 
 static void
-menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors)
+menu_display_page(
+    nhmenu *menu, WINDOW *win,
+    int page_num,      /* page number, 1..n rather than 0..n-1 */
+    char *selectors,   /* selection letters on current page */
+    char *groupaccels) /* group accelerator characters on any page */
 {
     nhmenu_item *menu_item_ptr;
     int count, curletter, entry_cols, start_col, num_lines;
@@ -1148,6 +1172,9 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors)
     /* letters assigned to entries on current page */
     if (selectors)
         (void) memset((genericptr_t) selectors, 0, 256);
+    /* characters assigned to group accelerators on any page */
+    if (groupaccels)
+        (void) memset((genericptr_t) groupaccels, 0, 256);
 
     /* Cycle through entries until we are on the correct page */
 
@@ -1180,6 +1207,14 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors)
     /* Display items for current page */
 
     while (menu_item_ptr != NULL) {
+        /* collect group accelerators for every page */
+        if (groupaccels && menu_item_ptr->identifier.a_void != NULL) {
+            unsigned gch = (unsigned) menu_item_ptr->group_accel;
+
+            if (gch > 0 && gch <= 255) /* note: skip it if 0 */
+                groupaccels[gch] = 1;
+        }
+        /* remaining processing applies to current page only */
         if (menu_item_ptr->page_num != page_num) {
             break;
         }
@@ -1224,7 +1259,8 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors)
         }
 #if 0
         /* FIXME: menuglyphs not implemented yet */
-        if (menu_item_ptr->glyphinfo.glyph != NO_GLYPH && iflags.use_menu_glyphs) {
+        if (menu_item_ptr->glyphinfo.glyph != NO_GLYPH
+            && iflags.use_menu_glyphs) {
             color = (int) menu_item_ptr->glyphinfo.color;
             curses_toggle_color_attr(win, color, NONE, ON);
             mvwaddch(win, menu_item_ptr->line_num + 1, start_col, curletter);
@@ -1299,9 +1335,13 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors)
 /* split out from menu_get_selections() so that perm_invent scrolling
    can be controlled from outside the normal menu activity */
 boolean
-curs_nonselect_menu_action(WINDOW *win, void *menu_v, int how,
-                           int curletter, int *curpage_p,
-                           char selectors[256], int *num_selected_p)
+curs_nonselect_menu_action(
+    WINDOW *win, void *menu_v,
+    int how,
+    int curletter,
+    int *curpage_p,
+    char selectors[256],
+    int *num_selected_p)
 {
     nhmenu_item *menu_item_ptr;
     nhmenu *menu = (nhmenu *) menu_v;
@@ -1350,8 +1390,8 @@ curs_nonselect_menu_action(WINDOW *win, void *menu_v, int how,
     case MENU_NEXT_PAGE:
     case ' ':
         if (*curpage_p < menu->num_pages) {
-             ++(*curpage_p);
-            menu_display_page(menu, win, *curpage_p, selectors);
+            ++(*curpage_p);
+            menu_display_page(menu, win, *curpage_p, selectors, (char *) 0);
         } else if (menucmd == ' ') {
             dismiss = TRUE;
             break;
@@ -1362,21 +1402,21 @@ curs_nonselect_menu_action(WINDOW *win, void *menu_v, int how,
     case MENU_PREVIOUS_PAGE:
         if (*curpage_p > 1) {
             --(*curpage_p);
-            menu_display_page(menu, win, *curpage_p, selectors);
+            menu_display_page(menu, win, *curpage_p, selectors, (char *) 0);
         }
         break;
     case KEY_END:
     case MENU_LAST_PAGE:
         if (*curpage_p != menu->num_pages) {
             *curpage_p = menu->num_pages;
-            menu_display_page(menu, win, *curpage_p, selectors);
+            menu_display_page(menu, win, *curpage_p, selectors, (char *) 0);
         }
         break;
     case KEY_HOME:
     case MENU_FIRST_PAGE:
         if (*curpage_p != 1) {
             *curpage_p = 1;
-            menu_display_page(menu, win, *curpage_p, selectors);
+            menu_display_page(menu, win, *curpage_p, selectors, (char *) 0);
         }
         break;
     case MENU_SEARCH: {
@@ -1435,11 +1475,11 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
     int curpage = !menu->bottom_heavy ? 1 : menu->num_pages;
     int num_selected = 0;
     boolean dismiss = FALSE;
-    char selectors[256];
+    char selectors[256], groupaccels[256];
     nhmenu_item *menu_item_ptr = menu->entries;
 
     activemenu = win;
-    menu_display_page(menu, win, curpage, selectors);
+    menu_display_page(menu, win, curpage, selectors, groupaccels);
 
     while (!dismiss) {
         curletter = getch();
@@ -1466,7 +1506,8 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
             }
             break;
         case PICK_ANY:
-            if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
+            if (curletter <= 0 || curletter >= 256
+                || (!selectors[curletter] && !groupaccels[curletter])) {
                 menucmd = (curletter <= 0 || curletter >= 255) ? curletter
                           : (int) (uchar) map_menu_cmd(curletter);
                 switch (menucmd) {
@@ -1492,7 +1533,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
             }
             /*FALLTHRU*/
         default:
-            if (isdigit(curletter)) {
+            if (isdigit(curletter) && !groupaccels[curletter]) {
                 count = curses_get_count(curletter);
                 /* after count, we know some non-digit is already pending */
                 curletter = getch();
@@ -1506,7 +1547,8 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
             }
         }
 
-        if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
+        if (curletter <= 0 || curletter >= 256
+            || (!selectors[curletter] && !groupaccels[curletter])) {
             dismiss = curs_nonselect_menu_action(win, (void *) menu, how,
                                                  curletter, &curpage,
                                                  selectors, &num_selected);
@@ -1526,7 +1568,8 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
                         && curletter == menu_item_ptr->group_accel)) {
                     if (curpage != menu_item_ptr->page_num) {
                         curpage = menu_item_ptr->page_num;
-                        menu_display_page(menu, win, curpage, selectors);
+                        menu_display_page(menu, win, curpage, selectors,
+                                          (char *) 0);
                     }
 
                     if (how == PICK_ONE) {
@@ -1577,8 +1620,11 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
    page than the one currently shown. */
 
 static void
-menu_select_deselect(WINDOW *win, nhmenu_item *item,
-                     menu_op operation, int current_page)
+menu_select_deselect(
+    WINDOW *win,
+    nhmenu_item *item,
+    menu_op operation,
+    int current_page)
 {
     int curletter = item->accelerator;
     boolean visible = (item->page_num == current_page);
@@ -1612,8 +1658,11 @@ on the given menu page.  If menu_page is 0, then perform opetation on
 all pages in menu.  Returns last page displayed.  */
 
 static int
-menu_operation(WINDOW * win, nhmenu *menu, menu_op
-               operation, int page_num)
+menu_operation(
+    WINDOW *win,
+    nhmenu *menu,
+    menu_op operation,
+    int page_num)
 {
     int first_page, last_page, current_page;
     nhmenu_item *menu_item_ptr = menu->entries;
@@ -1637,7 +1686,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op
     current_page = first_page;
 
     if (page_num == 0) {
-        menu_display_page(menu, win, current_page, (char *) 0);
+        menu_display_page(menu, win, current_page, (char *) 0, (char *) 0);
     }
 
     if (menu_item_ptr == NULL) {        /* Page not found */
@@ -1652,14 +1701,15 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op
             }
 
             current_page = menu_item_ptr->page_num;
-            menu_display_page(menu, win, current_page, (char *) 0);
+            menu_display_page(menu, win, current_page, (char *) 0, (char *) 0);
         }
 
         if (menu_item_ptr->identifier.a_void != NULL) {
             if (operation != INVERT
                 || menuitem_invert_test(0, menu_item_ptr->itemflags,
                                         menu_item_ptr->selected))
-                menu_select_deselect(win, menu_item_ptr, operation, current_page);
+                menu_select_deselect(win, menu_item_ptr,
+                                     operation, current_page);
         }
 
         menu_item_ptr = menu_item_ptr->next_item;
@@ -1690,3 +1740,5 @@ menu_max_height(void)
 {
     return term_rows - 2;
 }
+
+/*cursdial.c*/