From 757c51bb3c2e28f429533caadfea178d678e038d Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 30 Jan 2016 19:39:29 -0800 Subject: [PATCH] X11 menus - support pre-selected menu entries 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 or 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 | 1 + include/winX.h | 31 +++-- win/X11/winmenu.c | 347 +++++++++++++++++++--------------------------- win/X11/winmisc.c | 65 +++++---- 4 files changed, 198 insertions(+), 246 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 293447b3e..bf9cc0be9 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 diff --git a/include/winX.h b/include/winX.h index e462dfe94..dcd588d6f 100644 --- a/include/winX.h +++ b/include/winX.h @@ -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 */ diff --git a/win/X11/winmenu.c b/win/X11/winmenu.c index 8fe7baec3..97f8592a4 100644 --- a/win/X11/winmenu.c +++ b/win/X11/winmenu.c @@ -41,8 +41,7 @@ #include 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("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( + "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 diff --git a/win/X11/winmisc.c b/win/X11/winmisc.c index d1d44d906..960577e14 100644 --- a/win/X11/winmisc.c +++ b/win/X11/winmisc.c @@ -38,11 +38,12 @@ 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; } -- 2.40.0