Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2018-10-18 23:26:20 -04:00
11 changed files with 4280 additions and 3589 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -163,6 +163,14 @@ Elbereth hypocrisy penalty doesn't apply if attacking a monster which isn't
Elbereth hypocrisy penalty reduced when alignment is already low Elbereth hypocrisy penalty reduced when alignment is already low
during character creation, don't unset alternate weapon when a shield gets during character creation, don't unset alternate weapon when a shield gets
worn (was preventing knight from having lance set up as uswapwep) worn (was preventing knight from having lance set up as uswapwep)
preformatted Guidebook.txt split line in middle of "' '" for #wait command
prevent simiulated screenshot in Guidebook.txt from spanning page boundary
overview information for former hero was not being set properly when bones
file was saved, so current hero coming across a dead hero's grave
didn't have #overview feedback augmented with "final resting place"
in Guidebook.mn and Guidebook.txt, the 'I' command mis-described `IX' as
displaying inventory items whose bless/curse state is "known"
(Guidebook.tex correctly had "unknown")
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
@@ -231,6 +239,9 @@ X11: allow mouse wheel scrolling to work in menus by default
X11: handle paged menu control keys X11: handle paged menu control keys
X11: remember perm_invent window geometry X11: remember perm_invent window geometry
X11: handle X errors via panic X11: handle X errors via panic
X11: don't reuse perm_invent window for picking an object
X11: obey mouse_support and allow toggling it in game
X11: obey menu movement keys
General New Features General New Features

View File

@@ -307,6 +307,7 @@ E void FDECL(highlight_yn, (BOOLEAN_P));
E void FDECL(nh_XtPopup, (Widget, int, Widget)); E void FDECL(nh_XtPopup, (Widget, int, Widget));
E void FDECL(nh_XtPopdown, (Widget)); E void FDECL(nh_XtPopdown, (Widget));
E void FDECL(win_X11_init, (int)); E void FDECL(win_X11_init, (int));
E void FDECL(find_scrollbars, (Widget, Widget *, Widget *));
E void FDECL(nh_keyscroll, (Widget, XEvent *, String *, Cardinal *)); E void FDECL(nh_keyscroll, (Widget, XEvent *, String *, Cardinal *));
/* ### winmesg.c ### */ /* ### winmesg.c ### */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 bones.c $NHDT-Date: 1508827591 2017/10/24 06:46:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */ /* NetHack 3.6 bones.c $NHDT-Date: 1539653203 2018/10/16 01:26:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.73 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -463,6 +463,7 @@ make_bones:
resetobjs(level.buriedobjlist, FALSE); resetobjs(level.buriedobjlist, FALSE);
/* Hero is no longer on the map. */ /* Hero is no longer on the map. */
u.ux0 = u.ux, u.uy0 = u.uy;
u.ux = u.uy = 0; u.ux = u.uy = 0;
/* Clear all memory from the level. */ /* Clear all memory from the level. */
@@ -488,7 +489,7 @@ make_bones:
formatkiller(newbones->how, sizeof newbones->how, how, TRUE); formatkiller(newbones->how, sizeof newbones->how, how, TRUE);
Strcpy(newbones->when, yyyymmddhhmmss(when)); Strcpy(newbones->when, yyyymmddhhmmss(when));
/* final resting place, used to decide when bones are discovered */ /* final resting place, used to decide when bones are discovered */
newbones->frpx = u.ux, newbones->frpy = u.uy; newbones->frpx = u.ux0, newbones->frpy = u.uy0;
newbones->bonesknown = FALSE; newbones->bonesknown = FALSE;
/* if current character died on a bones level, the cemetery list /* if current character died on a bones level, the cemetery list
will have multiple entries, most recent (this dead hero) first */ will have multiple entries, most recent (this dead hero) first */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 detect.c $NHDT-Date: 1522891623 2018/04/05 01:27:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.81 $ */ /* NetHack 3.6 detect.c $NHDT-Date: 1539908137 2018/10/19 00:15:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.83 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2018. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1539,44 +1539,41 @@ mfind0(mtmp, via_warning)
struct monst *mtmp; struct monst *mtmp;
boolean via_warning; boolean via_warning;
{ {
xchar x = mtmp->mx, int x = mtmp->mx, y = mtmp->my;
y = mtmp->my; boolean found_something = FALSE;
if (via_warning && !warning_of(mtmp)) if (via_warning && !warning_of(mtmp))
return -1; return -1;
if (mtmp->m_ap_type) { if (mtmp->m_ap_type) {
seemimic(mtmp); seemimic(mtmp);
find: found_something = TRUE;
exercise(A_WIS, TRUE); } else if (mtmp->mundetected
if (!canspotmon(mtmp)) { && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) {
if (glyph_is_invisible(levl[x][y].glyph)) { if (via_warning) {
/* Found invisible monster in a square which already has Your("warning senses cause you to take a second %s.",
* an 'I' in it. Logically, this should still take time Blind ? "to check nearby" : "look close by");
* and lead to a return 1, but if we did that the player display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
* would keep finding the same monster every turn. }
*/
return -1;
} else {
You_feel("an unseen monster!");
map_invisible(x, y);
}
} else if (!sensemon(mtmp))
You("find %s.",
mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
return 1;
}
if (!canspotmon(mtmp)) {
if (mtmp->mundetected
&& (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL))
if (via_warning) {
Your("warning senses cause you to take a second %s.",
Blind ? "to check nearby" : "look close by");
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
}
mtmp->mundetected = 0; mtmp->mundetected = 0;
newsym(x, y); newsym(x, y);
goto find; found_something = TRUE;
}
if (found_something) {
if (!canspotmon(mtmp) && glyph_is_invisible(levl[x][y].glyph))
return -1; /* Found invisible monster in square which already has
* 'I' in it. Logically, this should still take time
* and lead to `return 1', but if we did that the hero
* would keep finding the same monster every turn. */
exercise(A_WIS, TRUE);
if (!canspotmon(mtmp)) {
map_invisible(x, y);
You_feel("an unseen monster!");
} else if (!sensemon(mtmp)) {
You("find %s.", mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
}
return 1;
} }
return 0; return 0;
} }

View File

@@ -1307,6 +1307,7 @@ char **argv;
/* add another option that can be set */ /* add another option that can be set */
set_wc_option_mod_status(WC_TILED_MAP, SET_IN_GAME); set_wc_option_mod_status(WC_TILED_MAP, SET_IN_GAME);
set_option_mod_status("mouse_support", SET_IN_GAME);
load_default_resources(); /* create default_resource_data[] */ load_default_resources(); /* create default_resource_data[] */
@@ -2547,6 +2548,20 @@ int dir;
return; return;
} }
void
find_scrollbars(w, horiz, vert)
Widget w;
Widget *horiz, *vert;
{
if (w) {
do {
*horiz = XtNameToWidget(w, "*horizontal");
*vert = XtNameToWidget(w, "*vertical");
w = XtParent(w);
} while (!*horiz && !*vert && w);
}
}
/* Callback /* Callback
* Scroll a viewport, using standard NH 1,2,3,4,6,7,8,9 directions. * Scroll a viewport, using standard NH 1,2,3,4,6,7,8,9 directions.
*/ */
@@ -2559,7 +2574,7 @@ String *params;
Cardinal *num_params; Cardinal *num_params;
{ {
Arg arg[2]; Arg arg[2];
Widget horiz_sb, vert_sb, scrollw; Widget horiz_sb = (Widget) 0, vert_sb = (Widget) 0;
float top, shown; float top, shown;
Boolean do_call; Boolean do_call;
int direction; int direction;
@@ -2572,12 +2587,7 @@ Cardinal *num_params;
direction = atoi(params[0]); direction = atoi(params[0]);
scrollw = viewport; find_scrollbars(viewport, &horiz_sb, &vert_sb);
do {
horiz_sb = XtNameToWidget(scrollw, "*horizontal");
vert_sb = XtNameToWidget(scrollw, "*vertical");
scrollw = XtParent(scrollw);
} while (!horiz_sb && !vert_sb && scrollw);
#define H_DELTA 0.25 /* distance of horiz shift */ #define H_DELTA 0.25 /* distance of horiz shift */
/* vert shift is half of curr distance */ /* vert shift is half of curr distance */

View File

@@ -1029,6 +1029,9 @@ Cardinal *num_params;
switch (event->type) { switch (event->type) {
case ButtonPress: case ButtonPress:
if (!iflags.wc_mouse_support)
return;
button = (XButtonEvent *) event; button = (XButtonEvent *) event;
#ifdef VERBOSE_INPUT #ifdef VERBOSE_INPUT
printf("button press\n"); printf("button press\n");

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winmenu.c $NHDT-Date: 1539216247 2018/10/11 00:04:07 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.18 $ */ /* NetHack 3.6 winmenu.c $NHDT-Date: 1539812601 2018/10/17 21:43:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.28 $ */
/* Copyright (c) Dean Luick, 1992 */ /* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -21,6 +21,7 @@
#include <X11/Xaw/Command.h> #include <X11/Xaw/Command.h>
#include <X11/Xaw/Viewport.h> #include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Cardinals.h> #include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Box.h> #include <X11/Xaw/Box.h>
#include <X11/Xos.h> #include <X11/Xos.h>
@@ -37,7 +38,8 @@
XColor FDECL(get_nhcolor, (struct xwindow *, int)); XColor FDECL(get_nhcolor, (struct xwindow *, int));
static void FDECL(init_menu_nhcolors, (struct xwindow *)); static void FDECL(init_menu_nhcolors, (struct xwindow *));
static void FDECL(menu_size_change_handler, (Widget, XtPointer,
XEvent *, Boolean *));
static void FDECL(menu_select, (Widget, XtPointer, XtPointer)); 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_ok, (Widget, XtPointer, XtPointer));
@@ -52,6 +54,11 @@ static void FDECL(select_match, (struct xwindow *, char *));
static void FDECL(invert_all, (struct xwindow *)); static void FDECL(invert_all, (struct xwindow *));
static void FDECL(invert_match, (struct xwindow *, char *)); static void FDECL(invert_match, (struct xwindow *, char *));
static void FDECL(menu_popdown, (struct xwindow *)); static void FDECL(menu_popdown, (struct xwindow *));
static Widget FDECL(menu_create_buttons, (struct xwindow *, Widget, Widget));
static void FDECL(load_boldfont, (struct xwindow *, Widget));
static void FDECL(menu_create_entries, (struct xwindow *, struct menu *));
static void FDECL(destroy_menu_entry_widgets, (struct xwindow *));
static void NDECL(create_menu_translation_tables);
static void FDECL(move_menu, (struct menu *, struct menu *)); static void FDECL(move_menu, (struct menu *, struct menu *));
static void FDECL(free_menu_line_entries, (struct menu *)); static void FDECL(free_menu_line_entries, (struct menu *));
@@ -75,6 +82,49 @@ static const char menu_entry_translations[] = "#override\n\
<Btn4Down>: scroll(8)\n\ <Btn4Down>: scroll(8)\n\
<Btn5Down>: scroll(2)"; <Btn5Down>: scroll(2)";
XtTranslations menu_entry_translation_table = (XtTranslations) 0;
XtTranslations menu_translation_table = (XtTranslations) 0;
XtTranslations menu_del_translation_table = (XtTranslations) 0;
static void
create_menu_translation_tables()
{
if (!menu_translation_table) {
menu_translation_table = XtParseTranslationTable(menu_translations);
menu_entry_translation_table
= XtParseTranslationTable(menu_entry_translations);
menu_del_translation_table
= XtParseTranslationTable("<Message>WM_PROTOCOLS: menu_delete()");
}
}
/*ARGSUSED*/
static void
menu_size_change_handler(w, ptr, event, flag)
Widget w;
XtPointer ptr;
XEvent *event;
Boolean *flag;
{
struct xwindow *wp = (struct xwindow *) ptr;
nhUse(w);
nhUse(flag);
if (!wp || !event)
return;
if (iflags.perm_invent && wp == &window_list[WIN_INVEN]
&& wp->menu_information->how == PICK_NONE) {
get_widget_window_geometry(wp->popup,
&wp->menu_information->permi_x,
&wp->menu_information->permi_y,
&wp->menu_information->permi_w,
&wp->menu_information->permi_h);
}
}
/* /*
* Menu callback. * Menu callback.
*/ */
@@ -275,6 +325,27 @@ Cardinal *num_params;
else else
X11_nhbell(); X11_nhbell();
return; return;
} else if (ch == MENU_FIRST_PAGE || ch == MENU_LAST_PAGE) {
Widget hbar = (Widget) 0, vbar = (Widget) 0;
float top = (ch == MENU_FIRST_PAGE) ? 0.0 : 1.0;
find_scrollbars(wp->w, &hbar, &vbar);
if (vbar)
XtCallCallbacks(vbar, XtNjumpProc, &top);
return;
} else if (ch == MENU_NEXT_PAGE || ch == MENU_PREVIOUS_PAGE) {
Widget hbar = (Widget) 0, vbar = (Widget) 0;
find_scrollbars(wp->w, &hbar, &vbar);
if (vbar) {
float shown, top;
Arg arg[2];
XtSetArg(arg[0], nhStr(XtNshown), &shown);
XtSetArg(arg[1], nhStr(XtNtopOfThumb), &top);
XtGetValues(vbar, arg, TWO);
top += ((ch == MENU_NEXT_PAGE) ? shown : -shown);
if (vbar)
XtCallCallbacks(vbar, XtNjumpProc, &top);
}
return;
} else if (index(menu_info->curr_menu.gacc, ch)) { } else if (index(menu_info->curr_menu.gacc, ch)) {
group_accel: group_accel:
/* matched a group accelerator */ /* matched a group accelerator */
@@ -521,15 +592,6 @@ static void
menu_popdown(wp) menu_popdown(wp)
struct xwindow *wp; struct xwindow *wp;
{ {
if (iflags.perm_invent && wp == &window_list[WIN_INVEN]
&& wp->menu_information->how == PICK_NONE) {
get_widget_window_geometry(wp->popup,
&wp->menu_information->permi_x,
&wp->menu_information->permi_y,
&wp->menu_information->permi_w,
&wp->menu_information->permi_h);
}
nh_XtPopdown(wp->popup); /* remove the event grab */ nh_XtPopdown(wp->popup); /* remove the event grab */
XtDestroyWidget(wp->popup); XtDestroyWidget(wp->popup);
wp->w = wp->popup = (Widget) 0; wp->w = wp->popup = (Widget) 0;
@@ -538,8 +600,7 @@ struct xwindow *wp;
wp->menu_information->is_up = FALSE; /* menu is down */ wp->menu_information->is_up = FALSE; /* menu is down */
} }
/* Global functions ======================================================== /* Global functions ======================================================= */
*/
void void
X11_start_menu(window) X11_start_menu(window)
@@ -653,10 +714,292 @@ const char *query;
menu_info->new_menu.query = copy_of(query); menu_info->new_menu.query = copy_of(query);
} }
int
X11_select_menu(window, how, menu_list)
winid window;
int how;
menu_item **menu_list;
{
x11_menu_item *curr;
struct xwindow *wp;
struct menu_info_t *menu_info;
Arg args[10];
Cardinal num_args;
int retval;
Dimension v_pixel_width, v_pixel_height;
boolean labeled;
Widget viewport_widget, form, label, all;
char gacc[QBUFSZ], *ap;
boolean permi;
*menu_list = (menu_item *) 0;
check_winid(window);
wp = &window_list[window];
menu_info = wp->menu_information;
if (!menu_info->is_menu) {
impossible("select_menu: called before start_menu");
return 0;
}
debugpline2("X11_select_menu(%i, %i)", window, how);
create_menu_translation_tables();
if (menu_info->permi && how != PICK_NONE) {
/* Core is reusing perm_invent window for picking an item.
But it could be even on a different screen!
Create a new temp window for it instead. */
winid newwin = X11_create_nhwindow(NHW_MENU);
struct xwindow *nwp = &window_list[newwin];
X11_start_menu(newwin);
move_menu(&menu_info->new_menu, &nwp->menu_information->new_menu);
for (curr = nwp->menu_information->new_menu.base; curr;
curr = curr->next)
curr->window = newwin;
nwp->menu_information->permi = FALSE;
retval = X11_select_menu(newwin, how, menu_list);
destroy_menu_entry_widgets(nwp);
X11_destroy_nhwindow(newwin);
return retval;
}
menu_info->how = (short) how;
/* collect group accelerators; for PICK_NONE, they're ignored;
for PICK_ONE, only those which match exactly one entry will be
accepted; for PICK_ANY, those which match any entry are okay */
gacc[0] = '\0';
if (menu_info->how != PICK_NONE) {
int i, n, gcnt[128];
#define GSELIDX(c) ((c) & 127) /* guard against `signed char' */
for (i = 0; i < SIZE(gcnt); i++)
gcnt[i] = 0;
for (n = 0, curr = menu_info->new_menu.base; curr; curr = curr->next)
if (curr->gselector && curr->gselector != curr->selector) {
++n;
++gcnt[GSELIDX(curr->gselector)];
}
if (n > 0) /* at least one group accelerator found */
for (ap = gacc, curr = menu_info->new_menu.base; curr;
curr = curr->next)
if (curr->gselector && !index(gacc, curr->gselector)
&& (menu_info->how == PICK_ANY
|| gcnt[GSELIDX(curr->gselector)] == 1)) {
*ap++ = curr->gselector;
*ap = '\0'; /* re-terminate for index() */
}
}
menu_info->new_menu.gacc = copy_of(gacc);
reset_menu_count(menu_info);
labeled = (menu_info->new_menu.query && *(menu_info->new_menu.query))
? TRUE
: FALSE;
permi = (window == WIN_INVEN && iflags.perm_invent && how == PICK_NONE);
if (menu_info->is_up) {
if (!menu_info->permi) {
destroy_menu_entry_widgets(wp);
nh_XtPopdown(wp->popup);
XtDestroyWidget(wp->popup);
wp->w = wp->popup = (Widget) 0;
menu_info->is_up = FALSE;
}
}
if (!menu_info->is_up) {
menu_info->permi = permi;
num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True);
num_args++;
if (permi && menu_info->permi_x != -1) {
XtSetArg(args[num_args], nhStr(XtNwidth), menu_info->permi_w);
num_args++;
XtSetArg(args[num_args], nhStr(XtNheight), menu_info->permi_h);
num_args++;
}
wp->popup = XtCreatePopupShell((window == WIN_INVEN)
? "inventory" : "menu",
(how == PICK_NONE)
? topLevelShellWidgetClass
: transientShellWidgetClass,
toplevel, args, num_args);
XtOverrideTranslations(wp->popup, menu_del_translation_table);
if (permi)
XtAddEventHandler(wp->popup, StructureNotifyMask, False,
menu_size_change_handler, (XtPointer) wp);
num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
menu_translation_table); 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++;
label = labeled ? XtCreateManagedWidget(menu_info->new_menu.query,
labelWidgetClass, form,
args, num_args)
: (Widget) 0;
all = menu_create_buttons(wp, form, label);
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++;
#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], XtNtranslations,
menu_translation_table); num_args++;
viewport_widget = XtCreateManagedWidget(
"menu_viewport", /* name */
viewportWidgetClass, form, /* parent widget */
args, num_args); /* values, and number of values */
num_args = 0;
XtSetArg(args[num_args], XtNwidth, 100);
num_args++;
XtSetArg(args[num_args], XtNheight, 500);
num_args++;
wp->w = XtCreateManagedWidget("menu_list", formWidgetClass,
viewport_widget, args, num_args);
}
if (menu_info->is_up && permi && menu_info->curr_menu.base) {
/* perm_invent window - explicitly destroy old menu entry widgets,
without recreating whole window */
destroy_menu_entry_widgets(wp);
free_menu_line_entries(&menu_info->curr_menu);
}
/* make new menu the current menu */
move_menu(&menu_info->new_menu, &menu_info->curr_menu);
menu_create_entries(wp, &menu_info->curr_menu);
/* 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++;
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. */
v_pixel_width += 14;
/* shrink to fit vertically */
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++;
XtSetValues(wp->w, args, num_args);
}
XtRealizeWidget(wp->popup); /* need to realize before we position */
/* if menu is not up, position it */
if (!menu_info->is_up) {
positionpopup(wp->popup, FALSE);
}
menu_info->is_up = TRUE;
if (permi) {
if (permi && menu_info->permi_x != -1) {
/* Cannot set window x,y at creation time,
we must move the window now instead */
XMoveWindow(XtDisplay(wp->popup), XtWindow(wp->popup),
menu_info->permi_x, menu_info->permi_y);
}
/* cant use nh_XtPopup() because it may try to grab the focus */
XtPopup(wp->popup, (int) XtGrabNone);
if (permi && menu_info->permi_x == -1) {
/* remember perm_invent window geometry the first time */
get_widget_window_geometry(wp->popup,
&menu_info->permi_x,
&menu_info->permi_y,
&menu_info->permi_w,
&menu_info->permi_h);
}
if (!updated_inventory) {
XMapRaised(XtDisplay(wp->popup), XtWindow(wp->popup));
}
XSetWMProtocols(XtDisplay(wp->popup), XtWindow(wp->popup),
&wm_delete_window, 1);
retval = 0;
} else {
menu_info->is_active = TRUE; /* waiting for user response */
menu_info->cancelled = FALSE;
nh_XtPopup(wp->popup, (int) XtGrabExclusive, wp->w);
(void) x_event(EXIT_ON_EXIT);
menu_info->is_active = FALSE;
if (menu_info->cancelled)
return -1;
retval = 0;
for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
if (curr->selected)
retval++;
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;
if (!toomany)
mi++;
if (how == PICK_ONE && !curr->preselected)
break;
}
}
} /* ?(WIN_INVEN && PICK_NONE) */
return retval;
}
/* End global functions =================================================== */
/*
* Allocate a copy of the given string. If null, return a string of
* zero length.
*/
static char *
copy_of(s)
const char *s;
{
if (!s)
s = "";
return dupstr(s);
}
/* /*
* Create ok, cancel, all, none, invert, and search buttons. * Create ok, cancel, all, none, invert, and search buttons.
*/ */
Widget static Widget
menu_create_buttons(wp, form, under) menu_create_buttons(wp, form, under)
struct xwindow *wp; struct xwindow *wp;
Widget form,under; Widget form,under;
@@ -778,7 +1121,7 @@ Widget form,under;
return all; return all;
} }
void static void
load_boldfont(wp, w) load_boldfont(wp, w)
struct xwindow *wp; struct xwindow *wp;
Widget w; Widget w;
@@ -803,7 +1146,7 @@ Widget w;
wp->menu_information->boldfs = XLoadQueryFont(dpy, fontname); wp->menu_information->boldfs = XLoadQueryFont(dpy, fontname);
} }
void static void
menu_create_entries(wp, curr_menu) menu_create_entries(wp, curr_menu)
struct xwindow *wp; struct xwindow *wp;
struct menu *curr_menu; struct menu *curr_menu;
@@ -858,20 +1201,21 @@ struct menu *curr_menu;
} }
XtSetArg(args[num_args], XtNtranslations, XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(menu_entry_translations)); num_args++; menu_entry_translation_table); num_args++;
menulineidx++; menulineidx++;
Sprintf(tmpbuf, "menuline_%s", (canpick) ? "command" : "label"); Sprintf(tmpbuf, "menuline_%s", (canpick) ? "command" : "label");
curr->w = linewidget curr->w = linewidget = XtCreateManagedWidget(tmpbuf,
= XtCreateManagedWidget(tmpbuf, canpick
canpick ? commandWidgetClass ? commandWidgetClass
: labelWidgetClass, : labelWidgetClass,
wp->w, args, num_args); wp->w, args, num_args);
if (attr == ATR_BOLD) { if (attr == ATR_BOLD) {
load_boldfont(wp, curr->w); load_boldfont(wp, curr->w);
num_args = 0; num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfont), wp->menu_information->boldfs); num_args++; XtSetArg(args[num_args], nhStr(XtNfont),
wp->menu_information->boldfs); num_args++;
XtSetValues(curr->w, args, num_args); XtSetValues(curr->w, args, num_args);
} }
@@ -882,272 +1226,29 @@ struct menu *curr_menu;
} }
} }
int static void
X11_select_menu(window, how, menu_list) destroy_menu_entry_widgets(wp)
winid window; struct xwindow *wp;
int how;
menu_item **menu_list;
{ {
x11_menu_item *curr; WidgetList wlist;
struct xwindow *wp; Cardinal numchild;
struct menu_info_t *menu_info; Arg args[5];
Arg args[10];
Cardinal num_args; Cardinal num_args;
int retval; x11_menu_item *curr;
Dimension v_pixel_width, v_pixel_height; struct menu_info_t *menu_info;
boolean labeled;
Widget viewport_widget, form, label, all; if (!wp || !wp->w)
char gacc[QBUFSZ], *ap; return;
boolean permi;
*menu_list = (menu_item *) 0;
check_winid(window);
wp = &window_list[window];
menu_info = wp->menu_information; menu_info = wp->menu_information;
if (!menu_info->is_menu) {
impossible("select_menu: called before start_menu");
return 0;
}
debugpline2("X11_select_menu(%i, %i)", window, how);
menu_info->how = (short) how;
/* collect group accelerators; for PICK_NONE, they're ignored;
for PICK_ONE, only those which match exactly one entry will be
accepted; for PICK_ANY, those which match any entry are okay */
gacc[0] = '\0';
if (menu_info->how != PICK_NONE) {
int i, n, gcnt[128];
#define GSELIDX(c) ((c) & 127) /* guard against `signed char' */
for (i = 0; i < SIZE(gcnt); i++)
gcnt[i] = 0;
for (n = 0, curr = menu_info->new_menu.base; curr; curr = curr->next)
if (curr->gselector && curr->gselector != curr->selector) {
++n;
++gcnt[GSELIDX(curr->gselector)];
}
if (n > 0) /* at least one group accelerator found */
for (ap = gacc, curr = menu_info->new_menu.base; curr;
curr = curr->next)
if (curr->gselector && !index(gacc, curr->gselector)
&& (menu_info->how == PICK_ANY
|| gcnt[GSELIDX(curr->gselector)] == 1)) {
*ap++ = curr->gselector;
*ap = '\0'; /* re-terminate for index() */
}
}
menu_info->new_menu.gacc = copy_of(gacc);
reset_menu_count(menu_info);
labeled = (menu_info->new_menu.query && *(menu_info->new_menu.query))
? TRUE
: FALSE;
permi = (window == WIN_INVEN && iflags.perm_invent && how == PICK_NONE);
if (menu_info->is_up) {
if (!menu_info->permi) {
nh_XtPopdown(wp->popup);
XtDestroyWidget(wp->popup);
wp->w = wp->popup = (Widget) 0;
menu_info->is_up = FALSE;
}
}
if (!menu_info->is_up) {
menu_info->permi = permi;
num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True);
num_args++;
if (permi && menu_info->permi_x != -1) {
XtSetArg(args[num_args], nhStr(XtNwidth), menu_info->permi_w);
num_args++;
XtSetArg(args[num_args], nhStr(XtNheight), menu_info->permi_h);
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()"));
num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
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++;
label = labeled ? XtCreateManagedWidget(menu_info->new_menu.query,
labelWidgetClass, form,
args, num_args)
: (Widget) 0;
all = menu_create_buttons(wp, form, label);
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++;
#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], XtNtranslations,
XtParseTranslationTable(menu_translations)); num_args++;
viewport_widget = XtCreateManagedWidget(
"menu_viewport", /* name */
viewportWidgetClass, form, /* parent widget */
args, num_args); /* values, and number of values */
num_args = 0;
XtSetArg(args[num_args], XtNwidth, 100);
num_args++;
XtSetArg(args[num_args], XtNheight, 500);
num_args++;
wp->w = XtCreateManagedWidget("menu_list", formWidgetClass,
viewport_widget, args, num_args);
}
if (menu_info->is_up && permi && menu_info->curr_menu.base) {
/* perm_invent window - explicitly destroy old menu entry widgets,
without recreating whole window */
WidgetList wlist;
Cardinal numchild;
num_args = 0;
XtSetArg(args[num_args], XtNchildren, &wlist); num_args++;
XtSetArg(args[num_args], XtNnumChildren, &numchild); num_args++;
XtGetValues(wp->w, args, num_args);
XtUnmanageChildren(wlist, numchild);
for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
if (curr->w)
XtDestroyWidget(curr->w);
free_menu_line_entries(&menu_info->curr_menu);
}
/* make new menu the current menu */
move_menu(&menu_info->new_menu, &menu_info->curr_menu);
menu_create_entries(wp, &menu_info->curr_menu);
/* if viewport will be bigger than the screen, limit its height */
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNwidth, &v_pixel_width); num_args++; XtSetArg(args[num_args], XtNchildren, &wlist); num_args++;
XtSetArg(args[num_args], XtNheight, &v_pixel_height); num_args++; XtSetArg(args[num_args], XtNnumChildren, &numchild); num_args++;
XtGetValues(wp->w, args, num_args); XtGetValues(wp->w, args, num_args);
if ((Dimension) XtScreen(wp->w)->height * 5 / 6 < v_pixel_height) { XtUnmanageChildren(wlist, numchild);
/* scrollbar is 14 pixels wide. Widen the form to accommodate it. */ for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
v_pixel_width += 14; if (curr->w)
XtDestroyWidget(curr->w);
/* shrink to fit vertically */
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++;
XtSetValues(wp->w, args, num_args);
}
XtRealizeWidget(wp->popup); /* need to realize before we position */
/* if menu is not up, position it */
if (!menu_info->is_up) {
positionpopup(wp->popup, FALSE);
}
menu_info->is_up = TRUE;
if (permi) {
if (permi && menu_info->permi_x != -1) {
/* Cannot set window x,y at creation time,
we must move the window now instead */
XMoveWindow(XtDisplay(wp->popup), XtWindow(wp->popup),
menu_info->permi_x, menu_info->permi_y);
}
/* cant use nh_XtPopup() because it may try to grab the focus */
XtPopup(wp->popup, (int) XtGrabNone);
if (permi && menu_info->permi_x == -1) {
/* remember perm_invent window geometry the first time */
get_widget_window_geometry(wp->popup,
&menu_info->permi_x,
&menu_info->permi_y,
&menu_info->permi_w,
&menu_info->permi_h);
}
if (!updated_inventory) {
XMapRaised(XtDisplay(wp->popup), XtWindow(wp->popup));
}
XSetWMProtocols(XtDisplay(wp->popup), XtWindow(wp->popup),
&wm_delete_window, 1);
retval = 0;
} else {
menu_info->is_active = TRUE; /* waiting for user response */
menu_info->cancelled = FALSE;
nh_XtPopup(wp->popup, (int) XtGrabExclusive, wp->w);
(void) x_event(EXIT_ON_EXIT);
menu_info->is_active = FALSE;
if (menu_info->cancelled)
return -1;
retval = 0;
for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
if (curr->selected)
retval++;
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;
if (!toomany)
mi++;
if (how == PICK_ONE && !curr->preselected)
break;
}
}
} /* ?(WIN_INVEN && PICK_NONE) */
return retval;
}
/* End global functions ====================================================
*/
/*
* Allocate a copy of the given string. If null, return a string of
* zero length.
*/
static char *
copy_of(s)
const char *s;
{
if (!s)
s = "";
return dupstr(s);
} }
static void static void
@@ -1325,7 +1426,8 @@ struct xwindow *wp;
{ {
clear_old_menu(wp); /* this will also destroy the widgets */ clear_old_menu(wp); /* this will also destroy the widgets */
if (wp->menu_information->boldfs) if (wp->menu_information->boldfs)
XFreeFont(wp->menu_information->boldfs_dpy, wp->menu_information->boldfs); XFreeFont(wp->menu_information->boldfs_dpy,
wp->menu_information->boldfs);
free((genericptr_t) wp->menu_information); free((genericptr_t) wp->menu_information);
wp->menu_information = (struct menu_info_t *) 0; wp->menu_information = (struct menu_info_t *) 0;
wp->type = NHW_NONE; /* allow re-use */ wp->type = NHW_NONE; /* allow re-use */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winmisc.c $NHDT-Date: 1457079197 2016/03/04 08:13:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.25 $ */ /* NetHack 3.6 winmisc.c $NHDT-Date: 1539892610 2018/10/18 19:56:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.39 $ */
/* Copyright (c) Dean Luick, 1992 */ /* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -71,6 +71,8 @@ static const char extended_command_translations[] = "#override\n\
<Key>Right: scroll(6)\n\ <Key>Right: scroll(6)\n\
<Key>Up: scroll(8)\n\ <Key>Up: scroll(8)\n\
<Key>Down: scroll(2)\n\ <Key>Down: scroll(2)\n\
<Btn4Down>: scroll(8)\n\
<Btn5Down>: scroll(2)\n\
<Key>: ec_key()"; <Key>: ec_key()";
static const char player_select_translations[] = "#override\n\ static const char player_select_translations[] = "#override\n\
@@ -82,6 +84,10 @@ static const char gend_select_translations[] = "#override\n\
static const char algn_select_translations[] = "#override\n\ static const char algn_select_translations[] = "#override\n\
<Key>: algn_key()"; <Key>: algn_key()";
static const char popup_entry_translations[] = "#override\n\
<Btn4Down>: scroll(8)\n\
<Btn5Down>: scroll(2)";
static void FDECL(ps_quit, (Widget, XtPointer, XtPointer)); static void FDECL(ps_quit, (Widget, XtPointer, XtPointer));
static void FDECL(ps_random, (Widget, XtPointer, XtPointer)); static void FDECL(ps_random, (Widget, XtPointer, XtPointer));
static void FDECL(ps_select, (Widget, XtPointer, XtPointer)); static void FDECL(ps_select, (Widget, XtPointer, XtPointer));
@@ -114,8 +120,7 @@ XtPointer x;
return (long)x; return (long)x;
} }
/* Player Selection -------------------------------------------------------- /* Player Selection ------------------------------------------------------- */
*/
/* ARGSUSED */ /* ARGSUSED */
static void static void
ps_quit(w, client_data, call_data) ps_quit(w, client_data, call_data)
@@ -1237,12 +1242,15 @@ X11_player_selection_dialog()
XtRealizeWidget(popup); XtRealizeWidget(popup);
X11_player_selection_randomize(); X11_player_selection_randomize();
ps_selected = -1; if (flags.randomall) {
plsel_dialog_acceptvalues();
nh_XtPopup(popup, (int) XtGrabExclusive, form); } else {
ps_selected = -1;
nh_XtPopup(popup, (int) XtGrabExclusive, form);
}
/* The callback will enable the event loop exit. */ /* The callback will enable the event loop exit. */
(void) x_event(EXIT_ON_EXIT); (void) x_event(flags.randomall ? EXIT_ON_SENT_EVENT : EXIT_ON_EXIT);
nh_XtPopdown(popup); nh_XtPopdown(popup);
XtDestroyWidget(popup); XtDestroyWidget(popup);
@@ -1266,8 +1274,7 @@ X11_player_selection_dialog()
} }
} }
/* Global functions ========================================================= /* Global functions ======================================================== */
*/
void void
X11_player_selection_prompts() X11_player_selection_prompts()
{ {
@@ -1603,11 +1610,9 @@ release_extended_cmds()
} }
} }
/* End global functions ===================================================== /* End global functions =================================================== */
*/
/* Extended Command -------------------------------------------------------- /* Extended Command ------------------------------------------------------- */
*/
/* ARGSUSED */ /* ARGSUSED */
static void static void
extend_select(w, client_data, call_data) extend_select(w, client_data, call_data)
@@ -1948,8 +1953,7 @@ init_extended_commands_popup()
free((char *) command_list); free((char *) command_list);
} }
/* ------------------------------------------------------------------------- /* ------------------------------------------------------------------------ */
*/
/* /*
* Create a popup widget of the following form: * Create a popup widget of the following form:
@@ -1987,7 +1991,7 @@ Widget **command_widgets;
XtCallbackProc name_callback; XtCallbackProc name_callback;
Widget *formp; /* return */ Widget *formp; /* return */
{ {
Widget popup, form, label, above, left, right, view; Widget popup, popform, form, label, above, left, right, view;
Widget *commands, *curr; Widget *commands, *curr;
int i; int i;
Arg args[8]; Arg args[8];
@@ -2000,22 +2004,41 @@ Widget *formp; /* return */
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True); num_args++; XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
popup = XtCreatePopupShell(popup_name, transientShellWidgetClass, popup = XtCreatePopupShell(popup_name, transientShellWidgetClass,
toplevel, args, num_args); toplevel, args, num_args);
XtOverrideTranslations( XtOverrideTranslations(
popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: ec_delete()")); popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: ec_delete()"));
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
XtSetArg(args[num_args], XtNtranslations, XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(popup_translations)); num_args++; XtParseTranslationTable(popup_translations)); num_args++;
view = XtCreateManagedWidget("menuformview", viewportWidgetClass, popup, XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0); num_args++;
popform = XtCreateManagedWidget("topmenuform", formWidgetClass, popup,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
/*XtSetArg(args[num_args], XtNborderWidth, 0); 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(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], XtNtranslations,
XtParseTranslationTable(popup_translations)); num_args++;
view = XtCreateManagedWidget("menuformview", viewportWidgetClass, popform,
args, num_args); args, num_args);
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNtranslations, XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(popup_translations)); num_args++; XtParseTranslationTable(popup_translations)); num_args++;
XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0); num_args++;
*formp = form = XtCreateManagedWidget("menuform", formWidgetClass, view, *formp = form = XtCreateManagedWidget("menuform", formWidgetClass, view,
args, num_args); args, num_args);
@@ -2089,6 +2112,8 @@ Widget *formp; /* return */
if (!widget_names[i]) if (!widget_names[i])
continue; continue;
num_args = 0; num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(popup_entry_translations)); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromVert), above); num_args++; XtSetArg(args[num_args], nhStr(XtNfromVert), above); num_args++;
if (above == left) { if (above == left) {
/* if first, we are farther apart */ /* if first, we are farther apart */