Merge branch 'NetHack-3.6.2-beta01' into NetHack-3.6.2

This commit is contained in:
nhmall
2018-10-18 21:44:30 -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
during character creation, don't unset alternate weapon when a shield gets
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
@@ -231,6 +239,9 @@ X11: allow mouse wheel scrolling to work in menus by default
X11: handle paged menu control keys
X11: remember perm_invent window geometry
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

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_XtPopdown, (Widget));
E void FDECL(win_X11_init, (int));
E void FDECL(find_scrollbars, (Widget, Widget *, Widget *));
E void FDECL(nh_keyscroll, (Widget, XEvent *, String *, Cardinal *));
/* ### 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) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -460,6 +460,7 @@ make_bones:
resetobjs(level.buriedobjlist, FALSE);
/* Hero is no longer on the map. */
u.ux0 = u.ux, u.uy0 = u.uy;
u.ux = u.uy = 0;
/* Clear all memory from the level. */
@@ -485,7 +486,7 @@ make_bones:
formatkiller(newbones->how, sizeof newbones->how, how, TRUE);
Strcpy(newbones->when, yyyymmddhhmmss(when));
/* 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;
/* if current character died on a bones level, the cemetery list
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) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1539,44 +1539,41 @@ mfind0(mtmp, via_warning)
struct monst *mtmp;
boolean via_warning;
{
xchar x = mtmp->mx,
y = mtmp->my;
int x = mtmp->mx, y = mtmp->my;
boolean found_something = FALSE;
if (via_warning && !warning_of(mtmp))
return -1;
if (mtmp->m_ap_type) {
seemimic(mtmp);
find:
exercise(A_WIS, TRUE);
if (!canspotmon(mtmp)) {
if (glyph_is_invisible(levl[x][y].glyph)) {
/* Found invisible monster in a square which already has
* an 'I' in it. Logically, this should still take time
* and lead to a return 1, but if we did that the player
* 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 */
}
found_something = TRUE;
} else 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;
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;
}

View File

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

View File

@@ -1029,6 +1029,9 @@ Cardinal *num_params;
switch (event->type) {
case ButtonPress:
if (!iflags.wc_mouse_support)
return;
button = (XButtonEvent *) event;
#ifdef VERBOSE_INPUT
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 */
/* NetHack may be freely redistributed. See license for details. */
@@ -21,6 +21,7 @@
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Box.h>
#include <X11/Xos.h>
@@ -37,7 +38,8 @@
XColor FDECL(get_nhcolor, (struct xwindow *, int));
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(invert_line, (struct xwindow *, x11_menu_item *, int, long));
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_match, (struct xwindow *, char *));
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(free_menu_line_entries, (struct menu *));
@@ -75,6 +82,49 @@ static const char menu_entry_translations[] = "#override\n\
<Btn4Down>: scroll(8)\n\
<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.
*/
@@ -275,6 +325,27 @@ Cardinal *num_params;
else
X11_nhbell();
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)) {
group_accel:
/* matched a group accelerator */
@@ -521,15 +592,6 @@ static void
menu_popdown(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 */
XtDestroyWidget(wp->popup);
wp->w = wp->popup = (Widget) 0;
@@ -538,8 +600,7 @@ struct xwindow *wp;
wp->menu_information->is_up = FALSE; /* menu is down */
}
/* Global functions ========================================================
*/
/* Global functions ======================================================= */
void
X11_start_menu(window)
@@ -653,10 +714,292 @@ const char *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.
*/
Widget
static Widget
menu_create_buttons(wp, form, under)
struct xwindow *wp;
Widget form,under;
@@ -778,7 +1121,7 @@ Widget form,under;
return all;
}
void
static void
load_boldfont(wp, w)
struct xwindow *wp;
Widget w;
@@ -803,7 +1146,7 @@ Widget w;
wp->menu_information->boldfs = XLoadQueryFont(dpy, fontname);
}
void
static void
menu_create_entries(wp, curr_menu)
struct xwindow *wp;
struct menu *curr_menu;
@@ -858,20 +1201,21 @@ struct menu *curr_menu;
}
XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(menu_entry_translations)); num_args++;
menu_entry_translation_table); num_args++;
menulineidx++;
Sprintf(tmpbuf, "menuline_%s", (canpick) ? "command" : "label");
curr->w = linewidget
= XtCreateManagedWidget(tmpbuf,
canpick ? commandWidgetClass
: labelWidgetClass,
wp->w, args, num_args);
curr->w = linewidget = XtCreateManagedWidget(tmpbuf,
canpick
? commandWidgetClass
: labelWidgetClass,
wp->w, args, num_args);
if (attr == ATR_BOLD) {
load_boldfont(wp, curr->w);
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);
}
@@ -882,272 +1226,29 @@ struct menu *curr_menu;
}
}
int
X11_select_menu(window, how, menu_list)
winid window;
int how;
menu_item **menu_list;
static void
destroy_menu_entry_widgets(wp)
struct xwindow *wp;
{
x11_menu_item *curr;
struct xwindow *wp;
struct menu_info_t *menu_info;
Arg args[10];
WidgetList wlist;
Cardinal numchild;
Arg args[5];
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;
x11_menu_item *curr;
struct menu_info_t *menu_info;
if (!wp || !wp->w)
return;
*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);
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;
XtSetArg(args[num_args], XtNwidth, &v_pixel_width); num_args++;
XtSetArg(args[num_args], XtNheight, &v_pixel_height); num_args++;
XtSetArg(args[num_args], XtNchildren, &wlist); num_args++;
XtSetArg(args[num_args], XtNnumChildren, &numchild); 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);
XtUnmanageChildren(wlist, numchild);
for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
if (curr->w)
XtDestroyWidget(curr->w);
}
static void
@@ -1325,7 +1426,8 @@ struct xwindow *wp;
{
clear_old_menu(wp); /* this will also destroy the widgets */
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);
wp->menu_information = (struct menu_info_t *) 0;
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 */
/* 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>Up: scroll(8)\n\
<Key>Down: scroll(2)\n\
<Btn4Down>: scroll(8)\n\
<Btn5Down>: scroll(2)\n\
<Key>: ec_key()";
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\
<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_random, (Widget, XtPointer, XtPointer));
static void FDECL(ps_select, (Widget, XtPointer, XtPointer));
@@ -114,8 +120,7 @@ XtPointer x;
return (long)x;
}
/* Player Selection --------------------------------------------------------
*/
/* Player Selection ------------------------------------------------------- */
/* ARGSUSED */
static void
ps_quit(w, client_data, call_data)
@@ -1237,12 +1242,15 @@ X11_player_selection_dialog()
XtRealizeWidget(popup);
X11_player_selection_randomize();
ps_selected = -1;
nh_XtPopup(popup, (int) XtGrabExclusive, form);
if (flags.randomall) {
plsel_dialog_acceptvalues();
} else {
ps_selected = -1;
nh_XtPopup(popup, (int) XtGrabExclusive, form);
}
/* 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);
XtDestroyWidget(popup);
@@ -1266,8 +1274,7 @@ X11_player_selection_dialog()
}
}
/* Global functions =========================================================
*/
/* Global functions ======================================================== */
void
X11_player_selection_prompts()
{
@@ -1603,11 +1610,9 @@ release_extended_cmds()
}
}
/* End global functions =====================================================
*/
/* End global functions =================================================== */
/* Extended Command --------------------------------------------------------
*/
/* Extended Command ------------------------------------------------------- */
/* ARGSUSED */
static void
extend_select(w, client_data, call_data)
@@ -1948,8 +1953,7 @@ init_extended_commands_popup()
free((char *) command_list);
}
/* -------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------ */
/*
* Create a popup widget of the following form:
@@ -1987,7 +1991,7 @@ Widget **command_widgets;
XtCallbackProc name_callback;
Widget *formp; /* return */
{
Widget popup, form, label, above, left, right, view;
Widget popup, popform, form, label, above, left, right, view;
Widget *commands, *curr;
int i;
Arg args[8];
@@ -2000,22 +2004,41 @@ Widget *formp; /* return */
num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
popup = XtCreatePopupShell(popup_name, transientShellWidgetClass,
toplevel, args, num_args);
XtOverrideTranslations(
popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: ec_delete()"));
num_args = 0;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
XtSetArg(args[num_args], XtNtranslations,
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);
num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
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,
args, num_args);
@@ -2089,6 +2112,8 @@ Widget *formp; /* return */
if (!widget_names[i])
continue;
num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(popup_entry_translations)); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromVert), above); num_args++;
if (above == left) {
/* if first, we are farther apart */