Merge remote-tracking branch 'origin/NetHack-3.6.0'

This commit is contained in:
keni
2017-10-14 16:00:23 -04:00
45 changed files with 1998 additions and 202 deletions

View File

@@ -982,6 +982,8 @@ Force a lock. Autocompletes. Default key is 'M-f'.
Show what type of thing a map symbol corresponds to. Default key is ';'. Show what type of thing a map symbol corresponds to. Default key is ';'.
.lp #help .lp #help
Show the help menu. Default key is '?', and 'h' if number_pad is on. Show the help menu. Default key is '?', and 'h' if number_pad is on.
.lp #herecmdmenu
Show a menu of possible actions in your current location.
.lp #history .lp #history
Show long version and game history. Default key is 'V'. Show long version and game history. Default key is 'V'.
.lp #inventory .lp #inventory
@@ -2556,6 +2558,9 @@ with the `/' command, ask if you want to see it (default on). Turning help
off makes just looking at things faster, since you aren't interrupted with the off makes just looking at things faster, since you aren't interrupted with the
``More info?'' prompt, but it also means that you might miss some ``More info?'' prompt, but it also means that you might miss some
interesting and/or important information. Persistent. interesting and/or important information. Persistent.
.lp herecmd_menu
When using a windowport that supports mouse and clicking on yourself, show
a menu of possible actions for this location. Same as herecmdmenu command.
.lp hilite_pet .lp hilite_pet
Visually distinguish pets from similar animals (default off). Visually distinguish pets from similar animals (default off).
The behavior of this option depends on the type of windowing you use. The behavior of this option depends on the type of windowing you use.

View File

@@ -3124,6 +3124,10 @@ Turning help off makes just looking at things faster, since you aren't
interrupted with the ``{\tt More info?}'' prompt, but it also means that you interrupted with the ``{\tt More info?}'' prompt, but it also means that you
might miss some interesting and/or important information. Persistent. might miss some interesting and/or important information. Persistent.
%.lp %.lp
\item[\ib{herecmd\verb+_+menu}]
When using a windowport that supports mouse and clicking on yourself, show
a menu of possible actions for this location. Same as herecmdmenu command.
%.lp
\item[\ib{hilite\verb+_+pet}] \item[\ib{hilite\verb+_+pet}]
Visually distinguish pets from similar animals (default off). Visually distinguish pets from similar animals (default off).
The behavior of this option depends on the type of windowing you use. The behavior of this option depends on the type of windowing you use.

View File

@@ -451,6 +451,8 @@ give feedback when released from a bear trap
depending upon how the dynamically inserted pattern-match phrase fit depending upon how the dynamically inserted pattern-match phrase fit
#version output left out "pattern matching via <method>" if the basic NetHack #version output left out "pattern matching via <method>" if the basic NetHack
features entry was split across two lines features entry was split across two lines
recovery of strength lost due to weakness from hunger was vulnerable to abuse
monsters hit by scroll of earth boulder did not get angry
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
@@ -508,6 +510,8 @@ hero poly'd into vampire could drain monster down to 0 HP without killing it,
"you observe a fog cloud where a vampire/bat was" if an unseen vampire on the "you observe a fog cloud where a vampire/bat was" if an unseen vampire on the
far side of a closed door shifted shape to pass under that door far side of a closed door shifted shape to pass under that door
fix mention_walls reporting secret doors as solid stone fix mention_walls reporting secret doors as solid stone
jumping over water unintentionally moved hero through that water, causing
drowning if not able to water walk or fly
Platform- and/or Interface-Specific Fixes Platform- and/or Interface-Specific Fixes
@@ -684,6 +688,8 @@ Master Key of Thievery always finds door and chest traps if used to lock or
blessed (for non-rogues); player is offered the opportunity to disarm blessed (for non-rogues); player is offered the opportunity to disarm
"Elbereth" must now be the only engraved text on a square to function "Elbereth" must now be the only engraved text on a square to function
"Elbereth" now erodes based on attacks by the player, not monsters scared "Elbereth" now erodes based on attacks by the player, not monsters scared
option herecmd_menu to make a mouse click on your character pop up
a context menu, and extended command #herecmdmenu to do the same
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
@@ -703,6 +709,8 @@ X11: status display split into three columns to accomodate Stone/Deaf/Lev/&c;
resources replaced by status_condition[1-3].* resources replaced by status_condition[1-3].*
X11: more terminal-like default resources X11: more terminal-like default resources
win32gui: save and load map colors from registry win32gui: save and load map colors from registry
X11: add new character selection dialog, and obey player_selection:dialog
unix: reduce makefile verbosity by default
NetHack Community Patches (or Variation) Included NetHack Community Patches (or Variation) Included

View File

@@ -536,11 +536,11 @@ E int FDECL(thitmonst, (struct monst *, struct obj *));
E int FDECL(hero_breaks, (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P)); E int FDECL(hero_breaks, (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P));
E int FDECL(breaks, (struct obj *, XCHAR_P, XCHAR_P)); E int FDECL(breaks, (struct obj *, XCHAR_P, XCHAR_P));
E void FDECL(release_camera_demon, (struct obj *, XCHAR_P, XCHAR_P)); E void FDECL(release_camera_demon, (struct obj *, XCHAR_P, XCHAR_P));
E void FDECL(breakobj, E void FDECL(breakobj, (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P, BOOLEAN_P));
(struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P, BOOLEAN_P));
E boolean FDECL(breaktest, (struct obj *)); E boolean FDECL(breaktest, (struct obj *));
E boolean FDECL(walk_path, (coord *, coord *, E boolean FDECL(walk_path, (coord *, coord *,
boolean (*)(genericptr, int, int), genericptr_t)); boolean (*)(genericptr, int, int), genericptr_t));
E boolean FDECL(hurtle_jump, (genericptr_t, int, int));
E boolean FDECL(hurtle_step, (genericptr_t, int, int)); E boolean FDECL(hurtle_step, (genericptr_t, int, int));
/* ### drawing.c ### */ /* ### drawing.c ### */
@@ -2487,6 +2487,7 @@ E void NDECL(port_help);
E void FDECL(sethanguphandler, (void (*)(int))); E void FDECL(sethanguphandler, (void (*)(int)));
E boolean NDECL(authorize_wizard_mode); E boolean NDECL(authorize_wizard_mode);
E boolean FDECL(check_user_string, (char *)); E boolean FDECL(check_user_string, (char *));
E char *NDECL(get_login_name);
#endif /* UNIX */ #endif /* UNIX */
/* ### unixtty.c ### */ /* ### unixtty.c ### */

View File

@@ -191,6 +191,7 @@ struct instance_flags {
* behaviour of various NetHack functions and probably warrant * behaviour of various NetHack functions and probably warrant
* a structure of their own elsewhere some day. * a structure of their own elsewhere some day.
*/ */
boolean herecmd_menu; /* use menu when mouseclick on yourself */
boolean invis_goldsym; /* gold symbol is ' '? */ boolean invis_goldsym; /* gold symbol is ' '? */
int parse_config_file_src; /* hack for parse_config_line() */ int parse_config_file_src; /* hack for parse_config_line() */
int in_lava_effects; /* hack for Boots_off() */ int in_lava_effects; /* hack for Boots_off() */

View File

@@ -946,6 +946,20 @@ static const char *pet_mark_small_xpm[] = {
"..X.." "..X.."
}; };
/* XPM */ /* XPM */
static const char *pile_mark_xpm[] = {
/* width height ncolors chars_per_pixel */
"5 5 2 1",
/* colors */
". c None",
"X c #00FF00",
/* pixels */
"..X..",
"..X..",
"XXXXX",
"..X..",
"..X.."
};
/* XPM */
static const char *satiated_xpm[] = { static const char *satiated_xpm[] = {
/* width height ncolors chars_per_pixel */ /* width height ncolors chars_per_pixel */
"40 40 23 1", "40 40 23 1",

View File

@@ -242,6 +242,7 @@ E boolean exit_x_event; /* exit condition for event loop */
#define EXIT_ON_EXIT 2 #define EXIT_ON_EXIT 2
#define EXIT_ON_SENT_EVENT 3 #define EXIT_ON_SENT_EVENT 3
E int click_x, click_y, click_button, updated_inventory; E int click_x, click_y, click_button, updated_inventory;
E boolean plsel_ask_name;
typedef struct { typedef struct {
Boolean slow; /* issue prompts between map and message wins */ Boolean slow; /* issue prompts between map and message wins */
@@ -334,6 +335,12 @@ E void FDECL(algn_key,
E void FDECL(ec_delete, (Widget, XEvent *, String *, Cardinal *)); E void FDECL(ec_delete, (Widget, XEvent *, String *, Cardinal *));
E void FDECL(ec_key, (Widget, XEvent *, String *, E void FDECL(ec_key, (Widget, XEvent *, String *,
Cardinal *)); /* extended command action */ Cardinal *)); /* extended command action */
E void FDECL(plsel_quit, (Widget, XEvent *, String *,
Cardinal *)); /* player selection dialog */
E void FDECL(plsel_play, (Widget, XEvent *, String *,
Cardinal *)); /* player selection dialog */
E void FDECL(plsel_randomize, (Widget, XEvent *, String *,
Cardinal *)); /* player selection dialog */
E void NDECL(release_extended_cmds); E void NDECL(release_extended_cmds);
/* ### winstatus.c ### */ /* ### winstatus.c ### */

View File

@@ -15,6 +15,7 @@ typedef union any {
int a_int; int a_int;
char a_char; char a_char;
schar a_schar; schar a_schar;
uchar a_uchar;
unsigned int a_uint; unsigned int a_uint;
long a_long; long a_long;
unsigned long a_ulong; unsigned long a_ulong;
@@ -23,6 +24,8 @@ typedef union any {
unsigned long *a_ulptr; unsigned long *a_ulptr;
unsigned *a_uptr; unsigned *a_uptr;
const char *a_string; const char *a_string;
int NDECL((*a_nfunc));
unsigned long a_mask32; /* used by status highlighting */
/* add types as needed */ /* add types as needed */
} anything; } anything;
#define ANY_P union any /* avoid typedef in prototypes */ #define ANY_P union any /* avoid typedef in prototypes */
@@ -45,6 +48,7 @@ enum any_types {
ANY_LPTR, /* pointer to long */ ANY_LPTR, /* pointer to long */
ANY_ULPTR, /* pointer to unsigned long */ ANY_ULPTR, /* pointer to unsigned long */
ANY_STR, /* pointer to null-terminated char string */ ANY_STR, /* pointer to null-terminated char string */
ANY_NFUNC, /* pointer to function taking no args, returning int */
ANY_MASK32 /* 32-bit mask (stored as unsigned long) */ ANY_MASK32 /* 32-bit mask (stored as unsigned long) */
}; };

View File

@@ -227,7 +227,8 @@
&& !BFlying) && !BFlying)
/* May touch surface; does not override any others */ /* May touch surface; does not override any others */
#define Wwalking (u.uprops[WWALKING].extrinsic && !Is_waterlevel(&u.uz)) #define EWwalking u.uprops[WWALKING].extrinsic
#define Wwalking (EWwalking && !Is_waterlevel(&u.uz))
/* Don't get wet, can't go under water; overrides others except levitation */ /* Don't get wet, can't go under water; overrides others except levitation */
/* Wwalking is meaningless on water level */ /* Wwalking is meaningless on water level */

View File

@@ -1769,10 +1769,10 @@ int magic; /* 0=Physical, otherwise skill level */
temp = -temp; temp = -temp;
if (range < temp) if (range < temp)
range = temp; range = temp;
(void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range); (void) walk_path(&uc, &cc, hurtle_jump, (genericptr_t) &range);
/* hurtle_step results in (u.ux, u.uy) == (cc.x, cc.y) and usually /* hurtle_jump -> hurtle_step results in <u.ux,u.uy> == <cc.x,cc.y>
* moves the ball if punished, but does not handle all the effects * and usually moves the ball if punished, but does not handle all
* of landing on the final position. * the effects of landing on the final position.
*/ */
teleds(cc.x, cc.y, FALSE); teleds(cc.x, cc.y, FALSE);
sokoban_guilt(); sokoban_guilt();
@@ -1951,9 +1951,8 @@ struct obj *obj;
if (ABASE(idx) >= AMAX(idx)) if (ABASE(idx) >= AMAX(idx))
continue; continue;
val_limit = AMAX(idx); val_limit = AMAX(idx);
/* don't recover strength lost from hunger */ /* this used to adjust 'val_limit' for A_STR when u.uhs was
if (idx == A_STR && u.uhs >= WEAK) WEAK or worse, but that's handled via ATEMP(A_STR) now */
val_limit--;
if (Fixed_abil) { if (Fixed_abil) {
/* potion/spell of restore ability override sustain ability /* potion/spell of restore ability override sustain ability
intrinsic but unicorn horn usage doesn't */ intrinsic but unicorn horn usage doesn't */

View File

@@ -366,20 +366,27 @@ set_moreluck()
void void
restore_attrib() restore_attrib()
{ {
int i; int i, equilibrium;;
/*
* Note: this gets called on every turn but ATIME() is never set
* to non-zero anywhere, and ATEMP() is only used for strength loss
* from hunger, so it doesn't actually do anything.
*/
for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */ for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
equilibrium = (i == A_STR && u.uhs >= WEAK) ? -1 : 0;
if (ATEMP(i) && ATIME(i)) { if (ATEMP(i) != equilibrium && ATIME(i) != 0) {
if (!(--(ATIME(i)))) { /* countdown for change */ if (!(--(ATIME(i)))) { /* countdown for change */
ATEMP(i) += ATEMP(i) > 0 ? -1 : 1; ATEMP(i) += (ATEMP(i) > 0) ? -1 : 1;
context.botl = 1;
if (ATEMP(i)) /* reset timer */ if (ATEMP(i)) /* reset timer */
ATIME(i) = 100 / ACURR(A_CON); ATIME(i) = 100 / ACURR(A_CON);
} }
} }
} }
(void) encumber_msg(); if (context.botl)
(void) encumber_msg();
} }
#define AVAL 50 /* tune value for exercise gains */ #define AVAL 50 /* tune value for exercise gains */

269
src/cmd.c
View File

@@ -114,6 +114,8 @@ static int NDECL(dosuspend_core); /**/
static int NDECL((*timed_occ_fn)); static int NDECL((*timed_occ_fn));
STATIC_PTR int NDECL(doherecmdmenu);
STATIC_PTR int NDECL(dotherecmdmenu);
STATIC_PTR int NDECL(doprev_message); STATIC_PTR int NDECL(doprev_message);
STATIC_PTR int NDECL(timed_occupation); STATIC_PTR int NDECL(timed_occupation);
STATIC_PTR int NDECL(doextcmd); STATIC_PTR int NDECL(doextcmd);
@@ -181,6 +183,10 @@ STATIC_DCL void FDECL(attributes_enlightenment, (int, int));
static const char *readchar_queue = ""; static const char *readchar_queue = "";
static coord clicklook_cc; static coord clicklook_cc;
STATIC_DCL void FDECL(add_herecmd_menuitem, (winid, int NDECL((*)),
const char *));
STATIC_DCL char FDECL(here_cmd_menu, (BOOLEAN_P));
STATIC_DCL char FDECL(there_cmd_menu, (BOOLEAN_P, int, int));
STATIC_DCL char *NDECL(parse); STATIC_DCL char *NDECL(parse);
STATIC_DCL void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P)); STATIC_DCL void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P));
STATIC_DCL boolean FDECL(help_dir, (CHAR_P, int, const char *)); STATIC_DCL boolean FDECL(help_dir, (CHAR_P, int, const char *));
@@ -2899,6 +2905,8 @@ struct ext_func_tab extcmdlist[] = {
{ ';', "glance", "show what type of thing a map symbol corresponds to", { ';', "glance", "show what type of thing a map symbol corresponds to",
doquickwhatis, IFBURIED | GENERALCMD }, doquickwhatis, IFBURIED | GENERALCMD },
{ '?', "help", "give a help message", dohelp, IFBURIED | GENERALCMD }, { '?', "help", "give a help message", dohelp, IFBURIED | GENERALCMD },
{ '\0', "herecmdmenu", "show menu of commands you can do here",
doherecmdmenu, IFBURIED },
{ 'V', "history", "show long version and game history", { 'V', "history", "show long version and game history",
dohistory, IFBURIED | GENERALCMD }, dohistory, IFBURIED | GENERALCMD },
{ 'i', "inventory", "show your inventory", ddoinv, IFBURIED }, { 'i', "inventory", "show your inventory", ddoinv, IFBURIED },
@@ -2996,6 +3004,9 @@ struct ext_func_tab extcmdlist[] = {
{ C('t'), "teleport", "teleport around the level", dotele, IFBURIED }, { C('t'), "teleport", "teleport around the level", dotele, IFBURIED },
{ '\0', "terrain", "show map without obstructions", { '\0', "terrain", "show map without obstructions",
doterrain, IFBURIED | AUTOCOMPLETE }, doterrain, IFBURIED | AUTOCOMPLETE },
{ '\0', "therecmdmenu",
"show menu of commands you can do from here to adjacent spot",
dotherecmdmenu },
{ 't', "throw", "throw something", dothrow }, { 't', "throw", "throw something", dothrow },
{ '\0', "timeout", "look at timeout queue and hero's timed intrinsics", { '\0', "timeout", "look at timeout queue and hero's timed intrinsics",
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD }, wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
@@ -4658,6 +4669,251 @@ register int x, y;
return x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1; return x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1;
} }
/* #herecmdmenu command */
STATIC_PTR int
doherecmdmenu(VOID_ARGS)
{
char ch = here_cmd_menu(TRUE);
return ch ? 1 : 0;
}
/* #therecmdmenu command, a way to test there_cmd_menu without mouse */
STATIC_PTR int
dotherecmdmenu(VOID_ARGS)
{
char ch;
if (!getdir((const char *) 0) || !isok(u.ux + u.dx, u.uy + u.dy))
return 0;
if (u.dx || u.dy)
ch = there_cmd_menu(TRUE, u.ux + u.dx, u.uy + u.dy);
else
ch = here_cmd_menu(TRUE);
return ch ? 1 : 0;
}
STATIC_OVL void
add_herecmd_menuitem(win, func, text)
winid win;
int NDECL((*func));
const char *text;
{
char ch;
anything any;
if ((ch = cmd_from_func(func)) != '\0') {
any = zeroany;
any.a_nfunc = func;
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, text, MENU_UNSELECTED);
}
}
STATIC_OVL char
there_cmd_menu(doit, x, y)
boolean doit;
int x, y;
{
winid win;
char ch;
char buf[BUFSZ];
schar typ = levl[x][y].typ;
int npick, K = 0;
menu_item *picks = (menu_item *) 0;
struct trap *ttmp;
struct monst *mtmp;
win = create_nhwindow(NHW_MENU);
start_menu(win);
if (IS_DOOR(typ)) {
boolean key_or_pick, card;
int dm = levl[x][y].doormask;
if ((dm & (D_CLOSED | D_LOCKED))) {
add_herecmd_menuitem(win, doopen, "Open the door"), ++K;
/* unfortunately there's no lknown flag for doors to
remember the locked/unlocked state */
key_or_pick = (carrying(SKELETON_KEY) || carrying(LOCK_PICK));
card = (carrying(CREDIT_CARD) != 0);
if (key_or_pick || card) {
Sprintf(buf, "%sunlock the door",
key_or_pick ? "lock or " : "");
add_herecmd_menuitem(win, doapply, upstart(buf)), ++K;
}
/* unfortunately there's no tknown flag for doors (or chests)
to remember whether a trap had been found */
add_herecmd_menuitem(win, dountrap,
"Search the door for a trap"), ++K;
/* [what about #force?] */
add_herecmd_menuitem(win, dokick, "Kick the door"), ++K;
} else if ((dm & D_ISOPEN)) {
add_herecmd_menuitem(win, doclose, "Close the door"), ++K;
}
}
if (typ <= SCORR)
add_herecmd_menuitem(win, dosearch, "Search for secret doors"), ++K;
if ((ttmp = t_at(x, y)) != 0 && ttmp->tseen) {
add_herecmd_menuitem(win, doidtrap, "Examine trap"), ++K;
if (ttmp->ttyp != VIBRATING_SQUARE)
add_herecmd_menuitem(win, dountrap, "Attempt to disarm trap"), ++K;
}
mtmp = m_at(x, y);
if (mtmp && !canspotmon(mtmp))
mtmp = 0;
if (mtmp && which_armor(mtmp, W_SADDLE)) {
char *mnam = x_monnam(mtmp, ARTICLE_THE, (char *) 0,
SUPPRESS_SADDLE, FALSE);
if (!u.usteed) {
Sprintf(buf, "Ride %s", mnam);
add_herecmd_menuitem(win, doride, buf), ++K;
}
Sprintf(buf, "Remove saddle from %s", mnam);
add_herecmd_menuitem(win, doloot, buf), ++K;
}
if (mtmp && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)
&& carrying(SADDLE)) {
Sprintf(buf, "Put saddle on %s", mon_nam(mtmp)), ++K;
add_herecmd_menuitem(win, doapply, buf);
}
#if 0
if (mtmp || glyph_is_invisible(glyph_at(x, y))) {
/* "Attack %s", mtmp ? mon_nam(mtmp) : "unseen creature" */
} else {
/* "Move %s", direction */
}
#endif
if (K) {
end_menu(win, "What do you want to do?");
npick = select_menu(win, PICK_ONE, &picks);
} else {
pline("No applicable actions.");
npick = 0;
}
destroy_nhwindow(win);
ch = '\0';
if (npick > 0) {
int NDECL((*func)) = picks->item.a_nfunc;
free((genericptr_t) picks);
if (doit) {
int ret = (*func)();
ch = (char) ret;
} else {
ch = cmd_from_func(func);
}
}
return ch;
}
STATIC_OVL char
here_cmd_menu(doit)
boolean doit;
{
winid win;
char ch;
char buf[BUFSZ];
schar typ = levl[u.ux][u.uy].typ;
int npick;
menu_item *picks = (menu_item *) 0;
win = create_nhwindow(NHW_MENU);
start_menu(win);
if (IS_FOUNTAIN(typ) || IS_SINK(typ)) {
Sprintf(buf, "Drink from the %s",
defsyms[IS_FOUNTAIN(typ) ? S_fountain : S_sink].explanation);
add_herecmd_menuitem(win, dodrink, buf);
}
if (IS_FOUNTAIN(typ))
add_herecmd_menuitem(win, dodip,
"Dip something into the fountain");
if (IS_THRONE(typ))
add_herecmd_menuitem(win, dosit,
"Sit on the throne");
if ((u.ux == xupstair && u.uy == yupstair)
|| (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up)
|| (u.ux == xupladder && u.uy == yupladder)) {
Sprintf(buf, "Go up the %s",
(u.ux == xupladder && u.uy == yupladder)
? "ladder" : "stairs");
add_herecmd_menuitem(win, doup, buf);
}
if ((u.ux == xdnstair && u.uy == ydnstair)
|| (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)
|| (u.ux == xdnladder && u.uy == ydnladder)) {
Sprintf(buf, "Go down the %s",
(u.ux == xupladder && u.uy == yupladder)
? "ladder" : "stairs");
add_herecmd_menuitem(win, dodown, buf);
}
if (u.usteed) { /* another movement choice */
Sprintf(buf, "Dismount %s",
x_monnam(u.usteed, ARTICLE_THE, (char *) 0,
SUPPRESS_SADDLE, FALSE));
add_herecmd_menuitem(win, doride, buf);
}
#if 0
if (Upolyd) { /* before objects */
Sprintf(buf, "Use %s special ability",
s_suffix(mons[u.umonnum].mname));
add_herecmd_menuitem(win, domonability, buf);
}
#endif
if (OBJ_AT(u.ux, u.uy)) {
struct obj *otmp = level.objects[u.ux][u.uy];
Sprintf(buf, "Pick up %s", otmp->nexthere ? "items" : doname(otmp));
add_herecmd_menuitem(win, dopickup, buf);
if (Is_container(otmp)) {
Sprintf(buf, "Loot %s", doname(otmp));
add_herecmd_menuitem(win, doloot, buf);
}
if (otmp->oclass == FOOD_CLASS) {
Sprintf(buf, "Eat %s", doname(otmp));
add_herecmd_menuitem(win, doeat, buf);
}
}
if (invent)
add_herecmd_menuitem(win, dodrop, "Drop items");
add_herecmd_menuitem(win, donull, "Rest one turn");
add_herecmd_menuitem(win, dosearch, "Search around you");
add_herecmd_menuitem(win, dolook, "Look at what is here");
end_menu(win, "What do you want to do?");
npick = select_menu(win, PICK_ONE, &picks);
destroy_nhwindow(win);
ch = '\0';
if (npick > 0) {
int NDECL((*func)) = picks->item.a_nfunc;
free((genericptr_t) picks);
if (doit) {
int ret = (*func)();
ch = (char) ret;
} else {
ch = cmd_from_func(func);
}
}
return ch;
}
static NEARDATA int last_multi; static NEARDATA int last_multi;
/* /*
@@ -4692,6 +4948,11 @@ int x, y, mod;
} }
if (x == 0 && y == 0) { if (x == 0 && y == 0) {
if (iflags.herecmd_menu) {
cmd[0] = here_cmd_menu(FALSE);
return cmd;
}
/* here */ /* here */
if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)
|| IS_SINK(levl[u.ux][u.uy].typ)) { || IS_SINK(levl[u.ux][u.uy].typ)) {
@@ -4730,6 +4991,13 @@ int x, y, mod;
&& !test_move(u.ux, u.uy, x, y, TEST_MOVE)) { && !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
cmd[1] = Cmd.dirchars[dir]; cmd[1] = Cmd.dirchars[dir];
cmd[2] = '\0'; cmd[2] = '\0';
if (iflags.herecmd_menu) {
cmd[0] = there_cmd_menu(FALSE, u.ux + x, u.uy + y);
if (cmd[0] == '\0')
cmd[1] = '\0';
return cmd;
}
if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) { if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
/* slight assistance to the player: choose kick/open for them /* slight assistance to the player: choose kick/open for them
*/ */
@@ -5096,6 +5364,7 @@ wiz_port_debug()
num_menu_selections = SIZE(menu_selections) - 1; num_menu_selections = SIZE(menu_selections) - 1;
if (num_menu_selections > 0) { if (num_menu_selections > 0) {
menu_item *pick_list; menu_item *pick_list;
win = create_nhwindow(NHW_MENU); win = create_nhwindow(NHW_MENU);
start_menu(win); start_menu(win);
for (k = 0; k < num_menu_selections; ++k) { for (k = 0; k < num_menu_selections; ++k) {

View File

@@ -519,6 +519,25 @@ genericptr_t arg;
return FALSE; return FALSE;
} }
/* hack for hurtle_step() -- it ought to be changed to take an argument
indicating lev/fly-to-dest vs lev/fly-to-dest-minus-one-land-on-dest
vs drag-to-dest; original callers use first mode, jumping wants second,
grappling hook backfire and thrown chained ball need third */
boolean
hurtle_jump(arg, x, y)
genericptr_t arg;
int x, y;
{
boolean res;
long save_EWwalking = EWwalking;
/* prevent jumping over water from being placed in that water */
EWwalking |= I_SPECIAL;
res = hurtle_step(arg, x, y);
EWwalking = save_EWwalking;
return res;
}
/* /*
* Single step for the hero flying through the air from jumping, flying, * Single step for the hero flying through the air from jumping, flying,
* etc. Called from hurtle() and jump() via walk_path(). We expect the * etc. Called from hurtle() and jump() via walk_path(). We expect the
@@ -606,8 +625,8 @@ int x, y;
} }
if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y) if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
&& bad_rock(youmonst.data, x, u.uy)) { && bad_rock(youmonst.data, x, u.uy)) {
boolean too_much = boolean too_much = (invent && (inv_weight() + weight_cap() > 600));
(invent && (inv_weight() + weight_cap() > 600));
/* Move at a diagonal. */ /* Move at a diagonal. */
if (bigmonst(youmonst.data) || too_much) { if (bigmonst(youmonst.data) || too_much) {
You("%sget forcefully wedged into a crevice.", You("%sget forcefully wedged into a crevice.",
@@ -621,14 +640,43 @@ int x, y;
} }
} }
if ((mon = m_at(x, y)) != 0) { if ((mon = m_at(x, y)) != 0
You("bump into %s.", a_monnam(mon)); #if 0 /* we can't include these two exceptions unless we know we're
* going to end up past the current spot rather than on it;
* for that, we need to know that the range is not exhausted
* and also that the next spot doesn't contain an obstacle */
&& !(mon->mundetected && hides_under(mon) && (Flying || Levitation))
&& !(mon->mundetected && mon->data->mlet == S_EEL
&& (Flying || Levitation || Wwalking))
#endif
) {
const char *mnam, *pronoun;
int glyph = glyph_at(x, y);
mon->mundetected = 0; /* wakeup() will handle mimic */
mnam = a_monnam(mon); /* after unhiding */
pronoun = mhim(mon);
if (!strcmp(mnam, "it")) {
/* mhim() uses pronoun_gender() which forces neuter if monster
can't be seen; we want him/her for humanoid sensed by touch */
if (!strcmp(pronoun, "it") && humanoid(mon->data))
pronoun = genders[mon->female].him;
mnam = !strcmp(pronoun, "it") ? "something" : "someone";
}
if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph))
You("find %s by bumping into %s.", mnam, pronoun);
else
You("bump into %s.", mnam);
wakeup(mon, FALSE); wakeup(mon, FALSE);
if (!canspotmon(mon))
map_invisible(mon->mx, mon->my);
setmangry(mon, FALSE); setmangry(mon, FALSE);
wake_nearto(x,y, 10); wake_nearto(x, y, 10);
return FALSE; return FALSE;
} }
if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
if ((u.ux - x) && (u.uy - y)
&& bad_rock(youmonst.data, u.ux, y)
&& bad_rock(youmonst.data, x, u.uy)) { && bad_rock(youmonst.data, x, u.uy)) {
/* Move at a diagonal. */ /* Move at a diagonal. */
if (Sokoban) { if (Sokoban) {

View File

@@ -112,8 +112,11 @@ register struct obj *obj;
void void
init_uhunger() init_uhunger()
{ {
context.botl = (u.uhs != NOT_HUNGRY || ATEMP(A_STR) < 0);
u.uhunger = 900; u.uhunger = 900;
u.uhs = NOT_HUNGRY; u.uhs = NOT_HUNGRY;
if (ATEMP(A_STR) < 0)
ATEMP(A_STR) = 0;
} }
/* tin types [SPINACH_TIN = -1, overrides corpsenm, nut==600] */ /* tin types [SPINACH_TIN = -1, overrides corpsenm, nut==600] */
@@ -2440,10 +2443,7 @@ doeat()
* mails, players who polymorph back to human in the middle of their * mails, players who polymorph back to human in the middle of their
* metallic meal, etc.... * metallic meal, etc....
*/ */
if (!(carried(otmp) ? retouch_object(&otmp, FALSE) if (!is_edible(otmp)) {
: touch_artifact(otmp, &youmonst))) {
return 1;
} else if (!is_edible(otmp)) {
You("cannot eat that!"); You("cannot eat that!");
return 0; return 0;
} else if ((otmp->owornmask & (W_ARMOR | W_TOOL | W_AMUL | W_SADDLE)) } else if ((otmp->owornmask & (W_ARMOR | W_TOOL | W_AMUL | W_SADDLE))
@@ -2451,6 +2451,9 @@ doeat()
/* let them eat rings */ /* let them eat rings */
You_cant("eat %s you're wearing.", something); You_cant("eat %s you're wearing.", something);
return 0; return 0;
} else if (!(carried(otmp) ? retouch_object(&otmp, FALSE)
: touch_artifact(otmp, &youmonst))) {
return 1; /* got blasted so use a turn */
} }
if (is_metallic(otmp) && u.umonnum == PM_RUST_MONSTER if (is_metallic(otmp) && u.umonnum == PM_RUST_MONSTER
&& otmp->oerodeproof) { && otmp->oerodeproof) {
@@ -2465,13 +2468,26 @@ doeat()
/* The regurgitated object's rustproofing is gone now */ /* The regurgitated object's rustproofing is gone now */
otmp->oerodeproof = 0; otmp->oerodeproof = 0;
make_stunned((HStun & TIMEOUT) + (long) rn2(10), TRUE); make_stunned((HStun & TIMEOUT) + (long) rn2(10), TRUE);
You("spit %s out onto the %s.", the(xname(otmp)), /*
surface(u.ux, u.uy)); * We don't expect rust monsters to be wielding welded weapons
if (carried(otmp)) { * or wearing cursed rings which were rustproofed, but guard
freeinv(otmp); * against the possibility just in case.
dropy(otmp); */
if (welded(otmp) || (otmp->cursed && (otmp->owornmask & W_RING))) {
otmp->bknown = 1; /* for ring; welded() does this for weapon */
You("spit out %s.", the(xname(otmp)));
} else {
You("spit %s out onto the %s.", the(xname(otmp)),
surface(u.ux, u.uy));
if (carried(otmp)) {
/* no need to check for leash in use; it's not metallic */
if (otmp->owornmask)
remove_worn_item(otmp, FALSE);
freeinv(otmp);
dropy(otmp);
}
stackobj(otmp);
} }
stackobj(otmp);
return 1; return 1;
} }
/* KMH -- Slow digestion is... indigestible */ /* KMH -- Slow digestion is... indigestible */
@@ -2961,10 +2977,23 @@ boolean incr;
} }
if (newhs != u.uhs) { if (newhs != u.uhs) {
if (newhs >= WEAK && u.uhs < WEAK) if (newhs >= WEAK && u.uhs < WEAK) {
losestr(1); /* this may kill you -- see below */ /* this used to be losestr(1) which had the potential to
else if (newhs < WEAK && u.uhs >= WEAK) be fatal (still handled below) by reducing HP if it
losestr(-1); tried to take base strength below minimum of 3 */
ATEMP(A_STR) = -1; /* temporary loss overrides Fixed_abil */
/* defer context.botl status update until after hunger message */
} else if (newhs < WEAK && u.uhs >= WEAK) {
/* this used to be losestr(-1) which could be abused by
becoming weak while wearing ring of sustain ability,
removing ring, eating to 'restore' strength which boosted
strength by a point each time the cycle was performed;
substituting "while polymorphed" for sustain ability and
"rehumanize" for ring removal might have done that too */
ATEMP(A_STR) = 0; /* repair of loss also overrides Fixed_abil */
/* defer context.botl status update until after hunger message */
}
switch (newhs) { switch (newhs) {
case HUNGRY: case HUNGRY:
if (Hallucination) { if (Hallucination) {

View File

@@ -763,6 +763,7 @@ time_t when; /* date+time at end of game */
dump_redirect(FALSE); dump_redirect(FALSE);
#else #else
nhUse(how); nhUse(how);
nhUse(when);
#endif #endif
} }

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 options.c $NHDT-Date: 1507164574 2017/10/05 00:49:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.311 $ */ /* NetHack 3.6 options.c $NHDT-Date: 1507846854 2017/10/12 22:20:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.315 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -129,6 +129,7 @@ static struct Bool_Opt {
{ "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE }, { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
{ "goldX", &iflags.goldX, FALSE, SET_IN_GAME }, { "goldX", &iflags.goldX, FALSE, SET_IN_GAME },
{ "help", &flags.help, TRUE, SET_IN_GAME }, { "help", &flags.help, TRUE, SET_IN_GAME },
{ "herecmd_menu", &iflags.herecmd_menu, FALSE, SET_IN_GAME },
{ "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/ { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
{ "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME }, { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
{ "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/ { "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/
@@ -3719,8 +3720,19 @@ boolean tinitial, tfrom_file;
vision_full_recalc = 1; /* delayed recalc */ vision_full_recalc = 1; /* delayed recalc */
if (iflags.use_color) if (iflags.use_color)
need_redraw = TRUE; /* darkroom refresh */ need_redraw = TRUE; /* darkroom refresh */
} else if (boolopt[i].addr == &iflags.wc_tiled_map } else if (boolopt[i].addr == &iflags.wc_ascii_map) {
|| boolopt[i].addr == &flags.showrace /* toggling ascii_map; set tiled_map to its opposite;
what does it mean to turn off ascii map if tiled map
isn't supported? -- right now, we do nothing */
iflags.wc_tiled_map = negated;
need_redraw = TRUE;
} else if (boolopt[i].addr == &iflags.wc_tiled_map) {
/* toggling tiled_map; set ascii_map to its opposite;
as with ascii_map, what does it mean to turn off tiled
map if ascii map isn't supported? */
iflags.wc_ascii_map = negated;
need_redraw = TRUE;
} else if (boolopt[i].addr == &flags.showrace
|| boolopt[i].addr == &iflags.use_inverse || boolopt[i].addr == &iflags.use_inverse
|| boolopt[i].addr == &iflags.hilite_pile || boolopt[i].addr == &iflags.hilite_pile
|| boolopt[i].addr == &iflags.hilite_pet) { || boolopt[i].addr == &iflags.hilite_pet) {
@@ -5523,7 +5535,8 @@ const char *mapping;
ape = (struct autopickup_exception *) alloc(sizeof *ape); ape = (struct autopickup_exception *) alloc(sizeof *ape);
ape->regex = regex_init(); ape->regex = regex_init();
if (!regex_compile(text, ape->regex)) { if (!regex_compile(text, ape->regex)) {
config_error_add("%s: %s", APE_regex_error, regex_error_desc(ape->regex)); config_error_add("%s: %s", APE_regex_error,
regex_error_desc(ape->regex));
regex_free(ape->regex); regex_free(ape->regex);
free((genericptr_t) ape); free((genericptr_t) ape);
return 0; return 0;
@@ -6182,13 +6195,11 @@ STATIC_OVL boolean
wc_supported(optnam) wc_supported(optnam)
const char *optnam; const char *optnam;
{ {
int k = 0; int k;
while (wc_options[k].wc_name) { for (k = 0; wc_options[k].wc_name; ++k) {
if (!strcmp(wc_options[k].wc_name, optnam) if (!strcmp(wc_options[k].wc_name, optnam))
&& (windowprocs.wincap & wc_options[k].wc_bit)) return (windowprocs.wincap & wc_options[k].wc_bit) ? TRUE : FALSE;
return TRUE;
k++;
} }
return FALSE; return FALSE;
} }
@@ -6242,13 +6253,12 @@ STATIC_OVL boolean
wc2_supported(optnam) wc2_supported(optnam)
const char *optnam; const char *optnam;
{ {
int k = 0; int k;
while (wc2_options[k].wc_name) { for (k = 0; wc2_options[k].wc_name; ++k) {
if (!strcmp(wc2_options[k].wc_name, optnam) if (!strcmp(wc2_options[k].wc_name, optnam))
&& (windowprocs.wincap2 & wc2_options[k].wc_bit)) return (windowprocs.wincap2 & wc2_options[k].wc_bit) ? TRUE
return TRUE; : FALSE;
k++;
} }
return FALSE; return FALSE;
} }

View File

@@ -565,8 +565,8 @@ register struct obj *otmp;
i = rn2(A_MAX); /* start at a random point */ i = rn2(A_MAX); /* start at a random point */
for (ii = 0; ii < A_MAX; ii++) { for (ii = 0; ii < A_MAX; ii++) {
lim = AMAX(i); lim = AMAX(i);
if (i == A_STR && u.uhs >= 3) /* this used to adjust 'lim' for A_STR when u.uhs was
--lim; /* WEAK */ WEAK or worse, but that's handled via ATEMP(A_STR) now */
if (ABASE(i) < lim) { if (ABASE(i) < lim) {
ABASE(i) = lim; ABASE(i) = lim;
context.botl = 1; context.botl = 1;

View File

@@ -343,7 +343,7 @@ int trouble;
u.utrap = 0; u.utrap = 0;
break; break;
case TROUBLE_STARVING: case TROUBLE_STARVING:
losestr(-1); /* temporarily lost strength recovery now handled by init_uhunger() */
/*FALLTHRU*/ /*FALLTHRU*/
case TROUBLE_HUNGRY: case TROUBLE_HUNGRY:
Your("%s feels content.", body_part(STOMACH)); Your("%s feels content.", body_part(STOMACH));

View File

@@ -1714,6 +1714,7 @@ boolean confused, helmet_protects, byu, skip_uswallow;
} }
} else } else
dmg = 0; dmg = 0;
wake_nearto(u.ux, u.uy, 4 * 4);
/* Must be before the losehp(), for bones files */ /* Must be before the losehp(), for bones files */
if (!flooreffects(otmp2, u.ux, u.uy, "fall")) { if (!flooreffects(otmp2, u.ux, u.uy, "fall")) {
place_object(otmp2, u.ux, u.uy); place_object(otmp2, u.ux, u.uy);
@@ -1779,7 +1780,10 @@ boolean confused, byu;
pline("%s is killed.", Monnam(mtmp)); pline("%s is killed.", Monnam(mtmp));
mondied(mtmp); mondied(mtmp);
} }
} else {
wakeup(mtmp, byu);
} }
wake_nearto(x, y, 4 * 4);
} else if (u.uswallow && mtmp == u.ustuck) { } else if (u.uswallow && mtmp == u.ustuck) {
obfree(otmp2, (struct obj *) 0); obfree(otmp2, (struct obj *) 0);
/* fall through to player */ /* fall through to player */

View File

@@ -332,6 +332,9 @@ RANDOBJ =
# used by `make depend' to reconstruct this Makefile; you shouldn't need this # used by `make depend' to reconstruct this Makefile; you shouldn't need this
AWK = nawk AWK = nawk
#VERBOSEMAKE = 1
# ---------------------------------------- # ----------------------------------------
# #
# Nothing below this line should have to be changed. # Nothing below this line should have to be changed.
@@ -339,6 +342,20 @@ AWK = nawk
# Other things that have to be reconfigured are in config.h, # Other things that have to be reconfigured are in config.h,
# {unixconf.h, pcconf.h, tosconf.h}, and possibly system.h # {unixconf.h, pcconf.h, tosconf.h}, and possibly system.h
# Verbosity
ACTUAL_CC := $(CC)
CC_V0 = @echo "[CC] $<"; $(ACTUAL_CC)
CC_V = $(CC_V0)
CC_V1 = $(ACTUAL_CC)
CC = $(CC_V$(VERBOSEMAKE))
ACTUAL_CXX := $(CXX)
CXX_V0 = @echo "[CXX] $<"; $(ACTUAL_CXX)
CXX_V = $(CXX_V0)
CXX_V1 = $(ACTUAL_CXX)
CXX = $(CXX_V$(VERBOSEMAKE))
MAKEDEFS = ../util/makedefs MAKEDEFS = ../util/makedefs
# timestamp files to reduce `make' overhead and shorten .o dependency lists # timestamp files to reduce `make' overhead and shorten .o dependency lists
@@ -438,7 +455,7 @@ $(GAME): $(SYSTEM)
Sysunix: $(HOBJ) Makefile Sysunix: $(HOBJ) Makefile
@echo "Loading ..." @echo "Loading ..."
$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS) @$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
@touch Sysunix @touch Sysunix
Sys3B2: $(HOBJ) Makefile Sys3B2: $(HOBJ) Makefile

View File

@@ -130,6 +130,20 @@ LEXYYC = lex.yy.c
# #
# Nothing below this line should have to be changed. # Nothing below this line should have to be changed.
# Verbosity
ACTUAL_CC := $(CC)
CC_V0 = @echo "[CC] $<"; $(ACTUAL_CC)
CC_V = $(CC_V0)
CC_V1 = $(ACTUAL_CC)
CC = $(CC_V$(VERBOSEMAKE))
ACTUAL_CXX := $(CXX)
CXX_V0 = @echo "[CXX] $<"; $(ACTUAL_CXX)
CXX_V = $(CXX_V0)
CXX_V1 = $(ACTUAL_CXX)
CXX = $(CXX_V$(VERBOSEMAKE))
# timestamps for primary header files, matching src/Makefile # timestamps for primary header files, matching src/Makefile
CONFIG_H = ../src/config.h-t CONFIG_H = ../src/config.h-t
HACK_H = ../src/hack.h-t HACK_H = ../src/hack.h-t
@@ -232,8 +246,7 @@ lev_main.o: lev_main.c $(HACK_H) ../include/sp_lev.h ../include/tcap.h \
# egrep will return failure if it doesn't find anything, but we know there # egrep will return failure if it doesn't find anything, but we know there
# is one "_cplusplus" inside a comment # is one "_cplusplus" inside a comment
lev_lex.o: lev_lex.c $(HACK_H) ../include/lev_comp.h ../include/sp_lev.h lev_lex.o: lev_lex.c $(HACK_H) ../include/lev_comp.h ../include/sp_lev.h
@echo $(CC) -c $(CFLAGS) lev_lex.c $(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus lev_lex.c` lev_lex.c
@$(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus lev_lex.c` lev_lex.c
# '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run # '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run
../include/lev_comp.h: lev_yacc.c ../include/lev_comp.h: lev_yacc.c
@@ -270,8 +283,7 @@ dgn_main.o: dgn_main.c $(CONFIG_H) ../include/dlb.h
# see dgn_comp.l for WEIRD_LEX discussion # see dgn_comp.l for WEIRD_LEX discussion
dgn_lex.o: dgn_lex.c $(CONFIG_H) ../include/dgn_comp.h ../include/dgn_file.h dgn_lex.o: dgn_lex.c $(CONFIG_H) ../include/dgn_comp.h ../include/dgn_file.h
@echo $(CC) -c $(CFLAGS) dgn_lex.c $(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus dgn_lex.c` dgn_lex.c
@$(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus dgn_lex.c` dgn_lex.c
# '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run # '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run
../include/dgn_comp.h: dgn_yacc.c ../include/dgn_comp.h: dgn_yacc.c

View File

@@ -20,7 +20,7 @@ VARDIR = $(HACKDIR)
POSTINSTALL= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf; POSTINSTALL= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(INSTDIR)/nh10.pcf; (cd $(INSTDIR); mkfontdir); POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(INSTDIR)/nh10.pcf; (cd $(INSTDIR); mkfontdir);
CFLAGS=-O -I../include -DNOTPARMDECL CFLAGS=-g -O -I../include -DNOTPARMDECL
CFLAGS+=-DHACKDIR=\"$(HACKDIR)\" CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\"
CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\" CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"

View File

@@ -26,6 +26,11 @@ x) hints=/dev/null
;; ;;
esac esac
if [ ! -f "$hints" ]; then
echo "Cannot find hints file $hfile"
exit 1
fi
/bin/sh ./mkmkfile.sh Makefile.top TOP ../../Makefile $hints $hfile /bin/sh ./mkmkfile.sh Makefile.top TOP ../../Makefile $hints $hfile
/bin/sh ./mkmkfile.sh Makefile.dat DAT ../../dat/Makefile $hints $hfile /bin/sh ./mkmkfile.sh Makefile.dat DAT ../../dat/Makefile $hints $hfile
/bin/sh ./mkmkfile.sh Makefile.doc DOC ../../doc/Makefile $hints $hfile /bin/sh ./mkmkfile.sh Makefile.doc DOC ../../doc/Makefile $hints $hfile

View File

@@ -696,4 +696,18 @@ get_unix_pw()
return pw; return pw;
} }
char *
get_login_name()
{
static char buf[BUFSZ];
struct passwd *pw = get_unix_pw();
buf[0] = '\0';
if (pw)
(void)strcpy(buf, pw->pw_name);
return buf;
}
/*unixmain.c*/ /*unixmain.c*/

View File

@@ -18,6 +18,7 @@ extern "C" {
#undef max #undef max
#include <QtGui/QtGui> #include <QtGui/QtGui>
#include <QStringList>
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets> #include <QtWidgets/QtWidgets>
#include <QtMultimedia/QSound> #include <QtMultimedia/QSound>
@@ -119,6 +120,9 @@ NetHackQtBind::NetHackQtBind(int& argc, char** argv) :
main = new NetHackQtMainWindow(keybuffer); main = new NetHackQtMainWindow(keybuffer);
connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit())); connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
qt_settings=new NetHackQtSettings(main->width(),main->height()); qt_settings=new NetHackQtSettings(main->width(),main->height());
msgs_strings = new QStringList();
msgs_initd = false;
msgs_saved = false;
} }
void NetHackQtBind::qt_init_nhwindows(int* argc, char** argv) void NetHackQtBind::qt_init_nhwindows(int* argc, char** argv)
@@ -493,51 +497,48 @@ int NetHackQtBind::qt_doprev_message()
char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, CHAR_P def) char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, CHAR_P def)
{ {
QString question(QString::fromLatin1(question_)); QString question(QString::fromLatin1(question_));
QString message;
char yn_esc_map='\033';
if (choices) {
// anything beyond <esc> is hidden>
QString choicebuf = choices;
size_t cb = choicebuf.indexOf('\033');
choicebuf = choicebuf.mid(0U, cb);
message = QString("%1 [%2] ").arg(question, choicebuf);
if (def) message += QString("(%1) ").arg(QChar(def));
// escape maps to 'q' or 'n' or default, in that order
yn_esc_map = (index(choices, 'q') ? 'q' :
(index(choices, 'n') ? 'n' : def));
} else {
message = question;
}
if (qt_settings->ynInMessages() && WIN_MESSAGE!=WIN_ERR) { if (qt_settings->ynInMessages() && WIN_MESSAGE!=WIN_ERR) {
// Similar to X11 windowport `slow' feature. // Similar to X11 windowport `slow' feature.
QString message; int result = -1;
char yn_esc_map='\033';
if (choices) {
// anything beyond <esc> is hidden>
QString choicebuf = choices;
size_t cb = choicebuf.indexOf('\033');
choicebuf = choicebuf.mid(0U, cb);
message = QString("%1 [%2] ").arg(question, choicebuf);
if (def) message += QString("(%1) ").arg(QChar(def));
// escape maps to 'q' or 'n' or default, in that order
yn_esc_map = (index(choices, 'q') ? 'q' :
(index(choices, 'n') ? 'n' : def));
} else {
message = question;
}
#ifdef USE_POPUPS #ifdef USE_POPUPS
// Improve some special-cases (DIRKS 08/02/23) if (choices) {
if (strcmp (choices,"ynq") == 0) { if (!strcmp(choices,"ynq"))
switch (QMessageBox::information (NetHackQtBind::mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2)) result = QMessageBox::information (NetHackQtBind::mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2);
{ else if (!strcmp(choices,"yn"))
case 0: return 'y'; result = QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Yes", "&No",0,1);
case 1: return 'n'; else if (!strcmp(choices, "rl"))
case 2: return 'q'; result = QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Right", "&Left",0,1);
}
}
if (strcmp (choices,"yn") == 0) { if (result >= 0 && result < strlen(choices)) {
switch (QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Yes", "&No",0,1)) char yn_resp = choices[result];
{ message += QString(" %1").arg(yn_resp);
case 0: return 'y'; result = yn_resp;
case 1: return 'n'; }
} }
}
#endif #endif
NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message); NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message);
int result=-1; while (result < 0) {
while (result<0) {
char ch=NetHackQtBind::qt_nhgetch(); char ch=NetHackQtBind::qt_nhgetch();
if (ch=='\033') { if (ch=='\033') {
result=yn_esc_map; result=yn_esc_map;
@@ -558,7 +559,12 @@ char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, C
return result; return result;
} else { } else {
NetHackQtYnDialog dialog(mainWidget(),question,choices,def); NetHackQtYnDialog dialog(mainWidget(),question,choices,def);
return dialog.Exec(); char ret = dialog.Exec();
if (!(ret == '\0' || ret == '\033') && choices)
message += QString(" %1").arg(ret);
else if (def)
message += QString(" %1").arg(def);
NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message);
} }
} }
@@ -605,6 +611,55 @@ void NetHackQtBind::qt_outrip(winid wid, int how, time_t when)
window->UseRIP(how, when); window->UseRIP(how, when);
} }
char * NetHackQtBind::qt_getmsghistory(BOOLEAN_P init)
{
NetHackQtMessageWindow* window = main->GetMessageWindow();
if (window)
return (char *)window->GetStr(init);
return NULL;
}
void NetHackQtBind::qt_putmsghistory(const char *msg, BOOLEAN_P is_restoring)
{
NetHackQtMessageWindow* window = main->GetMessageWindow();
if (!window)
return;
if (is_restoring && !msgs_initd) {
/* we're restoring history from the previous session, but new
messages have already been issued this session */
int i = 0;
const char *str;
while ((str = window->GetStr((i == 0)))) {
msgs_strings->append(str);
i++;
}
msgs_initd = true;
msgs_saved = (i > 0);
window->ClearMessages();
}
if (msg) {
//raw_printf("msg='%s'", msg);
window->PutStr(ATR_NONE, QString::fromLatin1(msg));
#ifdef DUMPLOG
dumplogmsg(msg);
#endif
} else if (msgs_saved) {
/* restore strings */
int i;
for (i = 0; i < msgs_strings->size(); i++) {
window->PutStr(ATR_NONE, msgs_strings->at((i)));
#ifdef DUMPLOG
dumplogmsg(msgs_strings->at(i).toLatin1().constData());
#endif
}
delete msgs_strings;
msgs_initd = false;
}
}
bool NetHackQtBind::notify(QObject *receiver, QEvent *event) bool NetHackQtBind::notify(QObject *receiver, QEvent *event)
{ {
// Ignore Alt-key navigation to menubar, it's annoying when you // Ignore Alt-key navigation to menubar, it's annoying when you
@@ -658,6 +713,9 @@ NetHackQtKeyBuffer NetHackQtBind::keybuffer;
NetHackQtClickBuffer NetHackQtBind::clickbuffer; NetHackQtClickBuffer NetHackQtBind::clickbuffer;
NetHackQtMainWindow* NetHackQtBind::main=0; NetHackQtMainWindow* NetHackQtBind::main=0;
QFrame* NetHackQtBind::splash=0; QFrame* NetHackQtBind::splash=0;
QStringList *NetHackQtBind::msgs_strings;
boolean NetHackQtBind::msgs_saved = false;
boolean NetHackQtBind::msgs_initd = false;
static void Qt_positionbar(char *) {} static void Qt_positionbar(char *) {}
@@ -683,7 +741,7 @@ struct window_procs Qt_procs = {
nethack_qt4::NetHackQtBind::qt_destroy_nhwindow, nethack_qt4::NetHackQtBind::qt_destroy_nhwindow,
nethack_qt4::NetHackQtBind::qt_curs, nethack_qt4::NetHackQtBind::qt_curs,
nethack_qt4::NetHackQtBind::qt_putstr, nethack_qt4::NetHackQtBind::qt_putstr,
nethack_qt4::NetHackQtBind::qt_putstr, /* FIXME: should be qt_putmixed() */ genl_putmixed,
nethack_qt4::NetHackQtBind::qt_display_file, nethack_qt4::NetHackQtBind::qt_display_file,
nethack_qt4::NetHackQtBind::qt_start_menu, nethack_qt4::NetHackQtBind::qt_start_menu,
nethack_qt4::NetHackQtBind::qt_add_menu, nethack_qt4::NetHackQtBind::qt_add_menu,
@@ -728,7 +786,8 @@ struct window_procs Qt_procs = {
#endif #endif
genl_preference_update, genl_preference_update,
genl_getmsghistory, genl_putmsghistory, nethack_qt4::NetHackQtBind::qt_getmsghistory,
nethack_qt4::NetHackQtBind::qt_putmsghistory,
genl_status_init, genl_status_init,
genl_status_finish, genl_status_enablefield, genl_status_finish, genl_status_enablefield,
#ifdef STATUS_HILITES #ifdef STATUS_HILITES

View File

@@ -78,6 +78,9 @@ public:
static void qt_start_screen(); static void qt_start_screen();
static void qt_end_screen(); static void qt_end_screen();
static char *qt_getmsghistory(BOOLEAN_P init);
static void qt_putmsghistory(const char *msg, BOOLEAN_P is_restoring);
static void qt_outrip(winid wid, int how, time_t when); static void qt_outrip(winid wid, int how, time_t when);
static int qt_kbhit(); static int qt_kbhit();
@@ -85,6 +88,10 @@ public:
private: private:
virtual bool notify(QObject *receiver, QEvent *event); virtual bool notify(QObject *receiver, QEvent *event);
static QStringList *msgs_strings;
static boolean msgs_saved;
static boolean msgs_initd;
}; };
} // namespace nethack_qt4 } // namespace nethack_qt4

View File

@@ -73,13 +73,8 @@ void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
drawWorn(painter,uarms,0,1); // Shield drawWorn(painter,uarms,0,1); // Shield
drawWorn(painter,uarmg,0,2); // Gloves - repeated drawWorn(painter,uarmg,0,2); // Gloves - repeated
drawWorn(painter,uarmg,2,2); // Gloves - repeated drawWorn(painter,uarmg,2,2); // Gloves - repeated
#ifdef TOURIST
drawWorn(painter,uarmf,1,5); // Shoes (feet) drawWorn(painter,uarmf,1,5); // Shoes (feet)
drawWorn(painter,uarmu,1,4); // Undershirt drawWorn(painter,uarmu,1,4); // Undershirt
#else
drawWorn(painter,0 ,1,5,false);
drawWorn(painter,uarmf,1,4); // Shoes (feet)
#endif
drawWorn(painter,uleft,0,3); // RingL drawWorn(painter,uleft,0,3); // RingL
drawWorn(painter,uright,2,3); // RingR drawWorn(painter,uright,2,3); // RingR

View File

@@ -861,14 +861,22 @@ void NetHackQtMainWindow::doKeys(const QString& k)
void NetHackQtMainWindow::AddMessageWindow(NetHackQtMessageWindow* window) void NetHackQtMainWindow::AddMessageWindow(NetHackQtMessageWindow* window)
{ {
message=window; message=window;
hsplitter->insertWidget(0, message->Widget()); if (!qt_compact_mode)
hsplitter->insertWidget(0, message->Widget());
ShowIfReady(); ShowIfReady();
} }
NetHackQtMessageWindow * NetHackQtMainWindow::GetMessageWindow()
{
return message;
}
void NetHackQtMainWindow::AddMapWindow(NetHackQtMapWindow2* window) void NetHackQtMainWindow::AddMapWindow(NetHackQtMapWindow2* window)
{ {
map=window; map=window;
vsplitter->insertWidget(1, map->Widget()); if (!qt_compact_mode)
vsplitter->insertWidget(1, map->Widget());
ShowIfReady(); ShowIfReady();
connect(map,SIGNAL(resized()),this,SLOT(layout())); connect(map,SIGNAL(resized()),this,SLOT(layout()));
} }
@@ -876,7 +884,8 @@ void NetHackQtMainWindow::AddMapWindow(NetHackQtMapWindow2* window)
void NetHackQtMainWindow::AddStatusWindow(NetHackQtStatusWindow* window) void NetHackQtMainWindow::AddStatusWindow(NetHackQtStatusWindow* window)
{ {
status=window; status=window;
hsplitter->insertWidget(2, status->Widget()); if (!qt_compact_mode)
hsplitter->insertWidget(2, status->Widget());
ShowIfReady(); ShowIfReady();
} }

View File

@@ -41,6 +41,7 @@ public:
NetHackQtMainWindow(NetHackQtKeyBuffer&); NetHackQtMainWindow(NetHackQtKeyBuffer&);
void AddMessageWindow(NetHackQtMessageWindow* window); void AddMessageWindow(NetHackQtMessageWindow* window);
NetHackQtMessageWindow * GetMessageWindow();
void AddMapWindow(NetHackQtMapWindow2* window); void AddMapWindow(NetHackQtMapWindow2* window);
void AddStatusWindow(NetHackQtStatusWindow* window); void AddStatusWindow(NetHackQtStatusWindow* window);
void RemoveWindow(NetHackQtWindow* window); void RemoveWindow(NetHackQtWindow* window);

View File

@@ -71,6 +71,7 @@ NetHackQtMapViewport::NetHackQtMapViewport(NetHackQtClickBuffer& click_sink) :
change(10) change(10)
{ {
pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm); pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
pile_annotation = QPixmap(pile_mark_xpm);
Clear(); Clear();
cursor.setX(0); cursor.setX(0);
@@ -157,29 +158,33 @@ void NetHackQtMapViewport::paintEvent(QPaintEvent* event)
QString(QChar(ch)).left(1) QString(QChar(ch)).left(1)
); );
} }
if (glyph_is_pet(g)
#ifdef TEXTCOLOR #ifdef TEXTCOLOR
&& ::iflags.hilite_pet if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
} else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
}
#endif #endif
) { }
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation); }
}
}
}
painter.setFont(font()); painter.setFont(font());
} else { } else {
for (int j=garea.top(); j<=garea.bottom(); j++) { for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) { for (int i=garea.left(); i<=garea.right(); i++) {
unsigned short g=Glyph(i,j); unsigned short g=Glyph(i,j);
int color;
int ch;
unsigned special;
mapglyph(g, &ch, &color, &special, i, j);
qt_settings->glyphs().drawCell(painter, g, i, j); qt_settings->glyphs().drawCell(painter, g, i, j);
if (glyph_is_pet(g)
#ifdef TEXTCOLOR #ifdef TEXTCOLOR
&& ::iflags.hilite_pet if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
} else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
}
#endif #endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
} }
} }
} }
@@ -649,6 +654,7 @@ NetHackQtMapWindow::NetHackQtMapWindow(NetHackQtClickBuffer& click_sink) :
viewport.setPalette(palette); viewport.setPalette(palette);
pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm); pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
pile_annotation = QPixmap(pile_mark_xpm);
cursor.setX(0); cursor.setX(0);
cursor.setY(0); cursor.setY(0);
@@ -835,13 +841,13 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
Qt::AlignCenter, Qt::AlignCenter,
QString(QChar(ch)).left(1) QString(QChar(ch)).left(1)
); );
if (glyph_is_pet(g)
#ifdef TEXTCOLOR #ifdef TEXTCOLOR
&& ::iflags.hilite_pet if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
} else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
}
#endif #endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
} }
} }
@@ -850,14 +856,18 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
for (int j=garea.top(); j<=garea.bottom(); j++) { for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) { for (int i=garea.left(); i<=garea.right(); i++) {
unsigned short g=Glyph(i,j); unsigned short g=Glyph(i,j);
int color;
int ch;
unsigned special;
mapglyph(g, &ch, &color, &special, i, j);
qt_settings->glyphs().drawCell(painter, g, i, j); qt_settings->glyphs().drawCell(painter, g, i, j);
if (glyph_is_pet(g)
#ifdef TEXTCOLOR #ifdef TEXTCOLOR
&& ::iflags.hilite_pet if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
} else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
}
#endif #endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
} }
} }
} }

View File

@@ -33,6 +33,7 @@ private:
unsigned short& Glyph(int x, int y) { return glyph[y][x]; } unsigned short& Glyph(int x, int y) { return glyph[y][x]; }
QPoint cursor; QPoint cursor;
QPixmap pet_annotation; QPixmap pet_annotation;
QPixmap pile_annotation;
NetHackQtClickBuffer& clicksink; NetHackQtClickBuffer& clicksink;
Clusterizer change; Clusterizer change;

View File

@@ -132,6 +132,7 @@ NetHackQtMenuWindow::NetHackQtMenuWindow(QWidget *parent) :
grid->setRowStretch(2, 1); grid->setRowStretch(2, 1);
setFocusPolicy(Qt::StrongFocus); setFocusPolicy(Qt::StrongFocus);
table->setFocusPolicy(Qt::NoFocus); table->setFocusPolicy(Qt::NoFocus);
connect(table, SIGNAL(cellClicked(int,int)), this, SLOT(cellToggleSelect(int,int)));
setLayout(grid); setLayout(grid);
} }
@@ -482,11 +483,11 @@ void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
accept(); accept();
else if (key==MENU_SEARCH) else if (key==MENU_SEARCH)
Search(); Search();
else if (key==MENU_SELECT_ALL) else if (key==MENU_SELECT_ALL || key==MENU_SELECT_PAGE)
All(); All();
else if (key==MENU_INVERT_ALL) else if (key==MENU_INVERT_ALL || key==MENU_INVERT_PAGE)
Invert(); Invert();
else if (key==MENU_UNSELECT_ALL) else if (key==MENU_UNSELECT_ALL || key==MENU_UNSELECT_PAGE)
ChooseNone(); ChooseNone();
else if (('0' <= key && key <= '9') || key == '\b') else if (('0' <= key && key <= '9') || key == '\b')
InputCount(key); InputCount(key);
@@ -501,6 +502,9 @@ void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
void NetHackQtMenuWindow::All() void NetHackQtMenuWindow::All()
{ {
if (how != PICK_ANY)
return;
for (int i=0; i<itemcount; i++) { for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0); QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText(""); if (count != NULL) count->setText("");
@@ -511,6 +515,9 @@ void NetHackQtMenuWindow::All()
} }
void NetHackQtMenuWindow::ChooseNone() void NetHackQtMenuWindow::ChooseNone()
{ {
if (how != PICK_ANY)
return;
for (int i=0; i<itemcount; i++) { for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0); QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText(""); if (count != NULL) count->setText("");
@@ -521,6 +528,9 @@ void NetHackQtMenuWindow::ChooseNone()
} }
void NetHackQtMenuWindow::Invert() void NetHackQtMenuWindow::Invert()
{ {
if (how != PICK_ANY)
return;
for (int i=0; i<itemcount; i++) { for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0); QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText(""); if (count != NULL) count->setText("");
@@ -531,6 +541,9 @@ void NetHackQtMenuWindow::Invert()
} }
void NetHackQtMenuWindow::Search() void NetHackQtMenuWindow::Search()
{ {
if (how == PICK_NONE)
return;
NetHackQtStringRequestor requestor(this, "Search for:"); NetHackQtStringRequestor requestor(this, "Search for:");
char line[256]; char line[256];
if (requestor.Get(line)) { if (requestor.Get(line)) {
@@ -560,6 +573,11 @@ void NetHackQtMenuWindow::ToggleSelect(int i)
} }
} }
void NetHackQtMenuWindow::cellToggleSelect(int i, int j)
{
ToggleSelect(i);
}
void NetHackQtMenuWindow::DoSelection(bool) void NetHackQtMenuWindow::DoSelection(bool)
{ {
if (how == PICK_ONE) { if (how == PICK_ONE) {

View File

@@ -66,6 +66,7 @@ public slots:
void Search(); void Search();
void ToggleSelect(int); void ToggleSelect(int);
void cellToggleSelect(int, int);
void DoSelection(bool); void DoSelection(bool);
protected: protected:

View File

@@ -35,6 +35,7 @@ NetHackQtMessageWindow::NetHackQtMessageWindow() :
list->setFocusPolicy(Qt::NoFocus); list->setFocusPolicy(Qt::NoFocus);
::iflags.window_inited = 1; ::iflags.window_inited = 1;
map = 0; map = 0;
currgetmsg = 0;
connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(updateFont())); connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(updateFont()));
updateFont(); updateFont();
} }
@@ -72,6 +73,12 @@ void NetHackQtMessageWindow::Clear()
map->clearMessages(); map->clearMessages();
} }
void NetHackQtMessageWindow::ClearMessages()
{
if (list)
list->clear();
}
void NetHackQtMessageWindow::Display(bool block) void NetHackQtMessageWindow::Display(bool block)
{ {
if (changed) { if (changed) {
@@ -80,6 +87,20 @@ void NetHackQtMessageWindow::Display(bool block)
} }
} }
const char * NetHackQtMessageWindow::GetStr(bool init)
{
if (init)
currgetmsg = 0;
QListWidgetItem *item = list->item(currgetmsg++);
if (item) {
QString str = item->text();
//raw_printf("getstr[%i]='%s'", currgetmsg, str.toLatin1().constData());
return str.toLatin1().constData();
}
return NULL;
}
void NetHackQtMessageWindow::PutStr(int attr, const QString& text) void NetHackQtMessageWindow::PutStr(int attr, const QString& text)
{ {
#ifdef USER_SOUNDS #ifdef USER_SOUNDS

View File

@@ -22,15 +22,18 @@ public:
virtual QWidget* Widget(); virtual QWidget* Widget();
virtual void Clear(); virtual void Clear();
virtual void Display(bool block); virtual void Display(bool block);
virtual const char *GetStr(bool init);
virtual void PutStr(int attr, const QString& text); virtual void PutStr(int attr, const QString& text);
void Scroll(int dx, int dy); void Scroll(int dx, int dy);
void ClearMessages();
void setMap(NetHackQtMapWindow2*); void setMap(NetHackQtMapWindow2*);
private: private:
QListWidget* list; QListWidget* list;
bool changed; bool changed;
int currgetmsg;
NetHackQtMapWindow2* map; NetHackQtMapWindow2* map;
private slots: private slots:

View File

@@ -37,7 +37,7 @@ namespace nethack_qt4 {
void centerOnMain( QWidget* w ); void centerOnMain( QWidget* w );
// end temporary // end temporary
static const char nh_attribution[] = "<center><big>NetHack</big>" static const char nh_attribution[] = "<center><big>NetHack %1</big>"
"<br><small>by the NetHack DevTeam</small></center>"; "<br><small>by the NetHack DevTeam</small></center>";
class NhPSListViewItem : public QTableWidgetItem { class NhPSListViewItem : public QTableWidgetItem {
@@ -158,8 +158,9 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
| | | | +--------------+ | | | | +--------------+
3 | | | | ...stretch... 3 | | | | ...stretch...
| | | | | | | |
4 | | | | [ Play ] 4 | | | | [ Random ]
5 | | | | [ Quit ] 5 | | | | [ Play ]
6 | | | | [ Quit ]
+---------+ +---------+ +---------+ +---------+
*/ */
@@ -177,37 +178,39 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
connect(name, SIGNAL(textChanged(const QString&)), connect(name, SIGNAL(textChanged(const QString&)),
this, SLOT(selectName(const QString&)) ); this, SLOT(selectName(const QString&)) );
name->setFocus(); name->setFocus();
QGroupBox* genderbox = new QGroupBox("Sex",this); QGroupBox* genderbox = new QGroupBox("Gender",this);
QButtonGroup *gendergroup = new QButtonGroup(this); QButtonGroup *gendergroup = new QButtonGroup(this);
QGroupBox* alignbox = new QGroupBox("Alignment",this); QGroupBox* alignbox = new QGroupBox("Alignment",this);
QButtonGroup *aligngroup = new QButtonGroup(this); QButtonGroup *aligngroup = new QButtonGroup(this);
QVBoxLayout* vbgb = new QVBoxLayout(genderbox); QVBoxLayout* vbgb = new QVBoxLayout(genderbox);
vbgb->addSpacing(fontMetrics().height()*3/4);
QVBoxLayout* vbab = new QVBoxLayout(alignbox); QVBoxLayout* vbab = new QVBoxLayout(alignbox);
vbab->addSpacing(fontMetrics().height()); char versionbuf[QBUFSZ];
QLabel* logo = new QLabel(nh_attribution, this); QLabel* logo = new QLabel(QString(nh_attribution).arg(version_string(versionbuf)), this);
l->addWidget( namebox, 0,0,1,3 ); l->addWidget( namebox, 0,0,1,3 );
#ifdef QT_CHOOSE_RACE_FIRST #ifdef QT_CHOOSE_RACE_FIRST
race = new NhPSListView(this); race = new NhPSListView(this);
role = new NhPSListView(this); role = new NhPSListView(this);
l->addWidget( race, 1,0,5,1 ); l->addWidget( race, 1,0,6,1 );
l->addWidget( role, 1,1,5,1 ); l->addWidget( role, 1,1,6,1 );
#else #else
role = new NhPSListView(this); role = new NhPSListView(this);
race = new NhPSListView(this); race = new NhPSListView(this);
l->addWidget( role, 1,0,5,1 ); l->addWidget( role, 1,0,6,1 );
l->addWidget( race, 1,1,5,1 ); l->addWidget( race, 1,1,6,1 );
#endif #endif
l->addWidget( genderbox, 1, 2 ); l->addWidget( genderbox, 1, 2 );
l->addWidget( alignbox, 2, 2 ); l->addWidget( alignbox, 2, 2 );
l->addWidget( logo, 3, 2, Qt::AlignCenter ); l->addWidget( logo, 3, 2, Qt::AlignCenter );
l->setRowStretch( 3, 5 ); l->setRowStretch( 3, 6 );
int i; int i;
int nrole; int nrole;
chosen_gend = flags.initgend;
chosen_align = flags.initalign;
// XXX QListView unsorted goes in rev. // XXX QListView unsorted goes in rev.
for (nrole=0; roles[nrole].name.m; nrole++) for (nrole=0; roles[nrole].name.m; nrole++)
; ;
@@ -254,15 +257,46 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
} }
connect( aligngroup, SIGNAL(buttonPressed(int)), this, SLOT(selectAlignment(int)) ); connect( aligngroup, SIGNAL(buttonPressed(int)), this, SLOT(selectAlignment(int)) );
QPushButton* rnd = new QPushButton("Random",this);
l->addWidget( rnd, 4, 2 );
rnd->setDefault(false);
connect( rnd, SIGNAL(clicked()), this, SLOT(Randomize()) );
QPushButton* ok = new QPushButton("Play",this); QPushButton* ok = new QPushButton("Play",this);
l->addWidget( ok, 4, 2 ); l->addWidget( ok, 5, 2 );
ok->setDefault(true); ok->setDefault(true);
connect( ok, SIGNAL(clicked()), this, SLOT(accept()) ); connect( ok, SIGNAL(clicked()), this, SLOT(accept()) );
QPushButton* cancel = new QPushButton("Quit",this); QPushButton* cancel = new QPushButton("Quit",this);
l->addWidget( cancel, 5, 2 ); l->addWidget( cancel, 6, 2 );
connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) ); connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) );
Randomize();
}
void NetHackQtPlayerSelector::Randomize()
{
int nrole = role->rowCount();
int nrace = race->rowCount();
boolean picksomething = (flags.initrole == ROLE_NONE
|| flags.initrace == ROLE_NONE
|| flags.initgend == ROLE_NONE
|| flags.initalign == ROLE_NONE);
if (flags.randomall && picksomething) {
if (flags.initrole == ROLE_NONE)
flags.initrole = ROLE_RANDOM;
if (flags.initrace == ROLE_NONE)
flags.initrace = ROLE_RANDOM;
if (flags.initgend == ROLE_NONE)
flags.initgend = ROLE_RANDOM;
if (flags.initalign == ROLE_NONE)
flags.initalign = ROLE_RANDOM;
}
rigid_role_checks();
// Randomize race and role, unless specified in config // Randomize race and role, unless specified in config
int ro = flags.initrole; int ro = flags.initrole;
if (ro == ROLE_NONE || ro == ROLE_RANDOM) { if (ro == ROLE_NONE || ro == ROLE_RANDOM) {
@@ -279,7 +313,7 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
} }
} }
// make sure we have a valid combination, honoring // make sure we have a valid combination, honoring
// the users request if possible. // the users request if possible.
bool choose_race_first; bool choose_race_first;
#ifdef QT_CHOOSE_RACE_FIRST #ifdef QT_CHOOSE_RACE_FIRST
@@ -332,12 +366,8 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
role->setCurrentCell(ro, 0); role->setCurrentCell(ro, 0);
race->setCurrentCell(ra, 0); race->setCurrentCell(ra, 0);
flags.initrace = race->currentRow();
flags.initrole = role->currentRow();
} }
void NetHackQtPlayerSelector::selectName(const QString& n) void NetHackQtPlayerSelector::selectName(const QString& n)
{ {
str_copy(plname,n.toLatin1().constData(),SIZE(plname)); str_copy(plname,n.toLatin1().constData(),SIZE(plname));
@@ -378,7 +408,7 @@ void NetHackQtPlayerSelector::selectRole(int crow, int ccol, int prow, int pcol)
} }
#endif #endif
flags.initrole = role->currentRow(); //flags.initrole = role->currentRow();
setupOthers(); setupOthers();
} }
@@ -416,7 +446,7 @@ void NetHackQtPlayerSelector::selectRace(int crow, int ccol, int prow, int pcol)
} }
#endif #endif
flags.initrace = race->currentRow(); //flags.initrace = race->currentRow();
setupOthers(); setupOthers();
} }
@@ -460,12 +490,12 @@ void NetHackQtPlayerSelector::setupOthers()
void NetHackQtPlayerSelector::selectGender(int i) void NetHackQtPlayerSelector::selectGender(int i)
{ {
flags.initgend = i; chosen_gend = i;
} }
void NetHackQtPlayerSelector::selectAlignment(int i) void NetHackQtPlayerSelector::selectAlignment(int i)
{ {
flags.initalign = i; chosen_align = i;
} }
void NetHackQtPlayerSelector::Quit() void NetHackQtPlayerSelector::Quit()
@@ -493,6 +523,10 @@ bool NetHackQtPlayerSelector::Choose()
} }
if ( exec() ) { if ( exec() ) {
flags.initrace = race->currentRow();
flags.initrole = role->currentRow();
flags.initgend = chosen_gend;
flags.initalign = chosen_align;
return true; return true;
} else { } else {
return false; return false;

View File

@@ -21,6 +21,7 @@ public:
public slots: public slots:
void Quit(); void Quit();
void Random(); void Random();
void Randomize();
void selectName(const QString& n); void selectName(const QString& n);
void selectRole(int current, int, int previous, int); void selectRole(int current, int, int previous, int);
@@ -38,6 +39,8 @@ private:
QRadioButton **gender; QRadioButton **gender;
QRadioButton **alignment; QRadioButton **alignment;
bool fully_specified_role; bool fully_specified_role;
int chosen_gend;
int chosen_align;
}; };
} // namespace nethack_qt4 } // namespace nethack_qt4

View File

@@ -4,7 +4,8 @@
#define NETHACK_CLR_FG grey #define NETHACK_CLR_FG grey
#define NETHACK_CLR_BG black #define NETHACK_CLR_BG black
#define NETHACK_CLR_QUIT red #define NETHACK_CLR_QUIT red
#define NETHACK_CLR_RANDOM green #define NETHACK_CLR_RANDOM yellow
#define NETHACK_CLR_PLAY green
#define NETHACK_CLR_HELP green #define NETHACK_CLR_HELP green
#define NETHACK_BTN_SHAPE roundedRectangle #define NETHACK_BTN_SHAPE roundedRectangle
#define NETHACK_BTN_ROUND 20 #define NETHACK_BTN_ROUND 20
@@ -119,12 +120,54 @@ NetHack*showGrip: False
! text input prompt window ! text input prompt window
NetHack*response*textSink*background: red NetHack*response*textSink*background: red
NetHack*textSink*background: red
NetHack*response*foreground: NETHACK_CLR_FG NetHack*response*foreground: NETHACK_CLR_FG
NetHack*response*background: NETHACK_CLR_BG NetHack*response*background: NETHACK_CLR_BG
NetHack*response*borderColor: NETHACK_CLR_FG NetHack*response*borderColor: NETHACK_CLR_FG
NetHack*response*borderWidth: 1 NetHack*response*borderWidth: 1
! role selection window ! player selection dialog (OPTIONS=player_selection:dialog)
!NetHack*player_selection_dialog.height: 420
!NetHack*player_selection_dialog.width: 403
!NetHack*player_selection_dialog*foreground: black
!NetHack*player_selection_dialog*background: white
NetHack*player_selection_dialog*name_label.borderWidth: 0
NetHack*player_selection_dialog*race_label.borderWidth: 0
NetHack*player_selection_dialog*role_label.borderWidth: 0
NetHack*player_selection_dialog*gender_label.borderWidth: 0
NetHack*player_selection_dialog*align_label.borderWidth: 0
NetHack*player_selection_dialog*button_vp.borderWidth: 0
NetHack*player_selection_dialog*name_input.borderWidth: 1
NetHack*player_selection_dialog*name_input.borderColor: NETHACK_CLR_FG
NetHack*player_selection_dialog*role_vp.borderColor: NETHACK_CLR_FG
NetHack*player_selection_dialog*race_vp.borderColor: NETHACK_CLR_FG
NetHack*player_selection_dialog*gender_vp.borderColor: NETHACK_CLR_FG
NetHack*player_selection_dialog*align_vp.borderColor: NETHACK_CLR_FG
NetHack*player_selection_dialog*random.foreground: NETHACK_CLR_RANDOM
NetHack*player_selection_dialog*random.borderColor: NETHACK_CLR_RANDOM
NetHack*player_selection_dialog*random.borderWidth: 1
NetHack*player_selection_dialog*random.shapeStyle: NETHACK_BTN_SHAPE
NetHack*player_selection_dialog*random.cornerRoundPercent: NETHACK_BTN_ROUND
NetHack*player_selection_dialog*quit.foreground: NETHACK_CLR_QUIT
NetHack*player_selection_dialog*quit.borderColor: NETHACK_CLR_QUIT
NetHack*player_selection_dialog*quit.borderWidth: 1
NetHack*player_selection_dialog*quit.shapeStyle: NETHACK_BTN_SHAPE
NetHack*player_selection_dialog*quit.cornerRoundPercent: NETHACK_BTN_ROUND
NetHack*player_selection_dialog*play.foreground: NETHACK_CLR_PLAY
NetHack*player_selection_dialog*play.borderColor: NETHACK_CLR_PLAY
NetHack*player_selection_dialog*play.borderWidth: 1
NetHack*player_selection_dialog*play.shapeStyle: NETHACK_BTN_SHAPE
NetHack*player_selection_dialog*play.cornerRoundPercent: NETHACK_BTN_ROUND
! role selection window (OPTIONS=player_selection:prompts)
NetHack*player_selection*random.foreground: NETHACK_CLR_RANDOM NetHack*player_selection*random.foreground: NETHACK_CLR_RANDOM
NetHack*player_selection*random.background: black NetHack*player_selection*random.background: black
NetHack*player_selection*random.borderColor: NETHACK_CLR_RANDOM NetHack*player_selection*random.borderColor: NETHACK_CLR_RANDOM

View File

@@ -121,7 +121,7 @@ Region region; /* unused */
nhUse(region); nhUse(region);
/* This isn't correct - we need to call the callback with region. */ /* This isn't correct - we need to call the callback with region. */
XtCallCallbacks(w, XtNexposeCallback, (caddr_t) event); XtCallCallbacks(w, XtNexposeCallback, (XtPointer)event);
} }
/* ARGSUSED */ /* ARGSUSED */
@@ -129,7 +129,7 @@ static void
Resize(w) Resize(w)
Widget w; Widget w;
{ {
XtCallCallbacks(w, XtNresizeCallback, (caddr_t) 0); XtCallCallbacks(w, XtNresizeCallback, (XtPointer) 0);
} }
WindowClassRec windowClassRec = { WindowClassRec windowClassRec = {

View File

@@ -91,7 +91,7 @@ merge_text_colormap()
if (j == header.ncolors) { /* couldn't find it */ if (j == header.ncolors) { /* couldn't find it */
#ifdef PRINT_COLORMAP #ifdef PRINT_COLORMAP
printf("color %2d: %3d %3d %3d\n", header.ncolors, Fprintf(stdout, "color %2d: %3d %3d %3d\n", header.ncolors,
ColorMap[CM_RED][i], ColorMap[CM_GREEN][i], ColorMap[CM_RED][i], ColorMap[CM_GREEN][i],
ColorMap[CM_BLUE][i]); ColorMap[CM_BLUE][i]);
#endif #endif
@@ -117,7 +117,7 @@ char *fname;
} }
merge_text_colormap(); merge_text_colormap();
count = convert_tiles(&curr_tb, header.ntiles); count = convert_tiles(&curr_tb, header.ntiles);
Fprintf(stderr, "%s: %lu tiles\n", fname, count); Fprintf(stdout, "%s: %lu tiles\n", fname, count);
header.ntiles += count; header.ntiles += count;
fclose_text_file(); fclose_text_file();
} }
@@ -157,7 +157,7 @@ FILE *fp;
Fprintf(fp, "\",\n"); Fprintf(fp, "\",\n");
} }
return fprintf(fp, "};\n") >= 0; return Fprintf(fp, "};\n") >= 0;
} }
#endif /* USE_XPM */ #endif /* USE_XPM */
@@ -199,7 +199,7 @@ char **argv;
} }
process_file(argv[i]); process_file(argv[i]);
} }
Fprintf(stderr, "Total tiles: %ld\n", header.ntiles); Fprintf(stdout, "Total tiles: %ld\n", header.ntiles);
/* round size up to the end of the row */ /* round size up to the end of the row */
if ((header.ntiles % header.per_row) != 0) { if ((header.ntiles % header.per_row) != 0) {

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winX.c $NHDT-Date: 1457079197 2016/03/04 08:13:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.41 $ */ /* NetHack 3.6 winX.c $NHDT-Date: 1507846693 2017/10/12 22:18:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */
/* 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. */
@@ -97,7 +97,11 @@ extern NEARDATA winid WIN_STATUS;
/* Interface definition, for windows.c */ /* Interface definition, for windows.c */
struct window_procs X11_procs = { struct window_procs X11_procs = {
"X11", WC_COLOR | WC_HILITE_PET | WC_TILED_MAP, 0L, X11_init_nhwindows, "X11",
(WC_COLOR | WC_HILITE_PET | WC_ASCII_MAP | WC_TILED_MAP
| WC_PLAYER_SELECTION | WC_PERM_INVENT | WC_MOUSE_SUPPORT),
0L, /* WC2 flag mask */
X11_init_nhwindows,
X11_player_selection, X11_askname, X11_get_nh_event, X11_exit_nhwindows, X11_player_selection, X11_askname, X11_get_nh_event, X11_exit_nhwindows,
X11_suspend_nhwindows, X11_resume_nhwindows, X11_create_nhwindow, X11_suspend_nhwindows, X11_resume_nhwindows, X11_create_nhwindow,
X11_clear_nhwindow, X11_display_nhwindow, X11_destroy_nhwindow, X11_curs, X11_clear_nhwindow, X11_display_nhwindow, X11_destroy_nhwindow, X11_curs,
@@ -136,6 +140,7 @@ struct window_procs X11_procs = {
static winid NDECL(find_free_window); static winid NDECL(find_free_window);
static void FDECL(nhFreePixel, (XtAppContext, XrmValuePtr, XtPointer, static void FDECL(nhFreePixel, (XtAppContext, XrmValuePtr, XtPointer,
XrmValuePtr, Cardinal *)); XrmValuePtr, Cardinal *));
static boolean FDECL(new_resource_macro, (String, unsigned));
static void NDECL(load_default_resources); static void NDECL(load_default_resources);
static void NDECL(release_default_resources); static void NDECL(release_default_resources);
#ifdef X11_HANGUP_SIGNAL #ifdef X11_HANGUP_SIGNAL
@@ -480,7 +485,43 @@ Widget w;
#endif #endif
} }
static String *default_resource_data = 0; /* NULL-terminated array */ static String *default_resource_data = 0, /* NULL-terminated arrays */
*def_rsrc_macr = 0, /* macro names */
*def_rsrc_valu = 0; /* macro values */
/* caller found "#define"; parse into macro name and its expansion value */
static boolean
new_resource_macro(inbuf, numdefs)
String inbuf; /* points past '#define' rather than to start of buffer */
unsigned numdefs; /* array slot to fill */
{
String p, q;
/* we expect inbuf to be terminated by newline; get rid of it */
q = eos(inbuf);
if (q > inbuf && q[-1] == '\n')
q[-1] = '\0';
/* figure out macro's name */
for (p = inbuf; *p == ' ' || *p == '\t'; ++p)
continue; /* skip whitespace */
for (q = p; *q && *q != ' ' && *q != '\t'; ++q)
continue; /* token consists of non-whitespace */
Strcat(q, " "); /* guarantee something beyond '#define FOO' */
*q++ = '\0'; /* p..(q-1) contains macro name */
if (!*p) /* invalid definition: '#define' followed by nothing */
return FALSE;
def_rsrc_macr[numdefs] = dupstr(p);
/* figure out macro's value; empty value is supported but not expected */
while (*q == ' ' || *q == '\t')
++q; /* skip whitespace between name and value */
for (p = eos(q); --p > q && (*p == ' ' || *p == '\t'); )
continue; /* discard trailing whitespace */
*++p = '\0'; /* q..p containes macro value */
def_rsrc_valu[numdefs] = dupstr(q);
return TRUE;
}
/* read the template NetHack.ad into default_resource_data[] to supply /* read the template NetHack.ad into default_resource_data[] to supply
fallback resources to XtAppInitialize() */ fallback resources to XtAppInitialize() */
@@ -489,8 +530,8 @@ load_default_resources()
{ {
FILE *fp; FILE *fp;
String inbuf; String inbuf;
unsigned insiz, linelen, longlen, numlines; unsigned insiz, linelen, longlen, numlines, numdefs, midx;
boolean comment = FALSE; /* lint suppression */ boolean comment, isdef;
/* /*
* Running nethack via the shell script adds $HACKDIR to the path used * Running nethack via the shell script adds $HACKDIR to the path used
@@ -499,7 +540,11 @@ load_default_resources()
* load its contents into memory so that the application startup call * load its contents into memory so that the application startup call
* in X11_init_nhwindows() can use them as fallback resources. * in X11_init_nhwindows() can use them as fallback resources.
* *
* No attempt to support the 'include' directive has been made. * No attempt to support the 'include' directive has been made, nor
* backslash+newline continuation lines. Macro expansion (at most
* one substitution per line) is supported. '#define' to introduce
* a macro must be at start of line (no whitespace before or after
* the '#' character).
*/ */
fp = fopen("./NetHack.ad", "r"); fp = fopen("./NetHack.ad", "r");
if (!fp) if (!fp)
@@ -509,35 +554,84 @@ load_default_resources()
insiz = BUFSIZ; /* stdio BUFSIZ, not nethack BUFSZ */ insiz = BUFSIZ; /* stdio BUFSIZ, not nethack BUFSZ */
inbuf = (String) alloc(insiz); inbuf = (String) alloc(insiz);
linelen = longlen = 0; linelen = longlen = 0;
numlines = 0; numlines = numdefs = 0;
comment = isdef = FALSE; /* lint suppression */
while (fgets(inbuf, insiz, fp)) { while (fgets(inbuf, insiz, fp)) {
if (!linelen) /* inbuf has start of record; treat empty as comment */ if (!linelen) {
/* !linelen: inbuf has start of record; treat empty as comment */
comment = (*inbuf == '!' || *inbuf == '\n'); comment = (*inbuf == '!' || *inbuf == '\n');
isdef = !strncmp(inbuf, "#define", 7);
++numdefs;
}
linelen += strlen(inbuf); linelen += strlen(inbuf);
if (!index(inbuf, '\n')) if (!index(inbuf, '\n'))
continue; continue;
if (linelen > longlen) if (linelen > longlen)
longlen = linelen; longlen = linelen;
linelen = 0; linelen = 0;
if (!comment) if (!comment && !isdef)
++numlines; ++numlines;
} }
free((genericptr_t) inbuf);
insiz = longlen + 1; insiz = longlen + 1;
inbuf = (String) alloc(insiz); if (numdefs) { /* don't alloc if 0; no need for any terminator */
def_rsrc_macr = (String *) alloc(numdefs * sizeof (String));
def_rsrc_valu = (String *) alloc(numdefs * sizeof (String));
insiz += BUFSIZ; /* include room for macro expansion within buffer */
}
if (insiz > BUFSIZ) {
free((genericptr_t) inbuf);
inbuf = (String) alloc(insiz);
}
++numlines; /* room for terminator */ ++numlines; /* room for terminator */
default_resource_data = (String *) alloc(numlines * sizeof (String)); default_resource_data = (String *) alloc(numlines * sizeof (String));
/* now read the file into the array */ /* now re-read the file, storing its contents into the allocated array
after performing macro substitutions */
(void) rewind(fp); (void) rewind(fp);
numlines = 0; numlines = numdefs = 0;
while (fgets(inbuf, insiz, fp)) { while (fgets(inbuf, insiz, fp)) {
if (*inbuf != '!' && *inbuf != '\n') if (!strncmp(inbuf, "#define", 7)) {
if (new_resource_macro(&inbuf[7], numdefs))
++numdefs;
} else if (*inbuf != '!' && *inbuf != '\n') {
if (numdefs) {
/*
* Macro expansion: we assume at most one substitution
* per line. That's all that our sample NetHack.ad uses.
*
* If we ever need more, this will have to become a lot
* more sophisticated. It will need to find the first
* instance within inbuf[] rather than first macro which
* appears, and to avoid finding names within substituted
* expansion values.
*
* Any substitution which would exceed the buffer size is
* skipped. A sophisticated implementation would need to
* be prepared to allocate a bigger buffer when needed.
*/
linelen = strlen(inbuf);
for (midx = 0; midx < numdefs; ++midx) {
if ((linelen + strlen(def_rsrc_valu[midx])
< insiz - strlen(def_rsrc_macr[midx]))
&& strNsubst(inbuf, def_rsrc_macr[midx],
def_rsrc_valu[midx], 1))
break;
}
}
default_resource_data[numlines++] = dupstr(inbuf); default_resource_data[numlines++] = dupstr(inbuf);
}
} }
default_resource_data[numlines] = (String) 0; default_resource_data[numlines] = (String) 0;
(void) fclose(fp); (void) fclose(fp);
free((genericptr_t) inbuf); free((genericptr_t) inbuf);
if (def_rsrc_macr) { /* implies def_rsrc_valu is non-Null too */
for (midx = 0; midx < numdefs; ++midx) {
free((genericptr_t) def_rsrc_macr[midx]);
free((genericptr_t) def_rsrc_valu[midx]);
}
free((genericptr_t) def_rsrc_macr), def_rsrc_macr = 0;
free((genericptr_t) def_rsrc_valu), def_rsrc_valu = 0;
}
} }
static void static void
@@ -550,6 +644,7 @@ release_default_resources()
free((genericptr_t) default_resource_data[idx]); free((genericptr_t) default_resource_data[idx]);
free((genericptr_t) default_resource_data), default_resource_data = 0; free((genericptr_t) default_resource_data), default_resource_data = 0;
} }
/* def_rsrc_macr[] and def_rsrc_valu[] have already been released */
} }
/* Global Functions ======================================================= */ /* Global Functions ======================================================= */
@@ -1031,6 +1126,9 @@ static XtActionsRec actions[] = {
{ nhStr("ec_key"), ec_key }, /* extended commands */ { nhStr("ec_key"), ec_key }, /* extended commands */
{ nhStr("ec_delete"), ec_delete }, /* ext-com menu delete */ { nhStr("ec_delete"), ec_delete }, /* ext-com menu delete */
{ nhStr("ps_key"), ps_key }, /* player selection */ { nhStr("ps_key"), ps_key }, /* player selection */
{ nhStr("plsel_quit"), plsel_quit }, /* player selection dialog */
{ nhStr("plsel_play"), plsel_play }, /* player selection dialog */
{ nhStr("plsel_rnd"), plsel_randomize }, /* player selection dialog */
{ nhStr("race_key"), race_key }, /* race selection */ { nhStr("race_key"), race_key }, /* race selection */
{ nhStr("gend_key"), gend_key }, /* gender selection */ { nhStr("gend_key"), gend_key }, /* gender selection */
{ nhStr("algn_key"), algn_key }, /* alignment selection */ { nhStr("algn_key"), algn_key }, /* alignment selection */
@@ -1176,6 +1274,7 @@ char **argv;
(void) seteuid(savuid); (void) seteuid(savuid);
x_inited = TRUE; /* X is now initialized */ x_inited = TRUE; /* X is now initialized */
plsel_ask_name = FALSE;
release_default_resources(); release_default_resources();
@@ -1374,6 +1473,20 @@ X11_askname()
{ {
Widget popup, dialog; Widget popup, dialog;
Arg args[1]; Arg args[1];
char *defplname = (char *)0;
#ifdef UNIX
defplname = get_login_name();
#endif
(void) strncpy(plname, defplname ? defplname : "Mumbles",
sizeof plname - 1);
plname[sizeof plname - 1] = '\0';
if (iflags.wc_player_selection == VIA_DIALOG) {
/* X11_player_selection_dialog() handles name query */
plsel_ask_name = TRUE;
return;
} /* else iflags.wc_player_selection == VIA_PROMPTS */
XtSetArg(args[0], XtNallowShellResize, True); XtSetArg(args[0], XtNallowShellResize, True);
@@ -1386,7 +1499,7 @@ X11_askname()
(XtCallbackProc) 0); (XtCallbackProc) 0);
SetDialogPrompt(dialog, nhStr("What is your name?")); /* set prompt */ SetDialogPrompt(dialog, nhStr("What is your name?")); /* set prompt */
SetDialogResponse(dialog, nhStr(""), PL_NSIZ); /* set default answer */ SetDialogResponse(dialog, plname, PL_NSIZ); /* set default answer */
XtRealizeWidget(popup); XtRealizeWidget(popup);
positionpopup(popup, TRUE); /* center,bottom */ positionpopup(popup, TRUE); /* center,bottom */

View File

@@ -18,9 +18,12 @@
#include <X11/Xaw/Command.h> #include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h> #include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h> #include <X11/Xaw/Label.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Scrollbar.h> #include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Viewport.h> #include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Cardinals.h> #include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/List.h>
#include <X11/Xos.h> /* for index() */ #include <X11/Xos.h> /* for index() */
#include <X11/Xatom.h> #include <X11/Xatom.h>
@@ -52,6 +55,17 @@ static int ec_nchars = 0;
static char ec_chars[EC_NCHARS]; static char ec_chars[EC_NCHARS];
static Time ec_time; static Time ec_time;
boolean plsel_ask_name;
static const char plsel_dialog_translations[] = "#override\n\
<Key>Escape: plsel_quit()\n\
<Key>Return: plsel_play()";
static const char plsel_input_accelerators[] = "#override\n\
<Key>Escape: plsel_quit()\n\
<Key>Return: plsel_play()\n\
<Key>Tab: \n";
static const char extended_command_translations[] = "#override\n\ static const char extended_command_translations[] = "#override\n\
<Key>Left: scroll(4)\n\ <Key>Left: scroll(4)\n\
<Key>Right: scroll(6)\n\ <Key>Right: scroll(6)\n\
@@ -83,6 +97,23 @@ static Widget FDECL(make_menu, (const char *, const char *, const char *,
XtCallbackProc, int, const char **, XtCallbackProc, int, const char **,
Widget **, XtCallbackProc, Widget *)); Widget **, XtCallbackProc, Widget *));
void NDECL(X11_player_selection_setupOthers);
void NDECL(X11_player_selection_randomize);
/* Bad Hack alert. Using integers instead of XtPointers */
XtPointer
i2xtp(i)
int i;
{
return (XtPointer)(long)i;
}
int
xtp2i(x)
XtPointer x;
{
return (long)x;
}
/* Player Selection -------------------------------------------------------- /* Player Selection --------------------------------------------------------
*/ */
/* ARGSUSED */ /* ARGSUSED */
@@ -298,10 +329,911 @@ Cardinal *num_params;
exit_x_event = TRUE; exit_x_event = TRUE;
} }
int plsel_n_races, plsel_n_roles;
Widget *plsel_race_radios = (Widget *) 0;
Widget *plsel_role_radios = (Widget *) 0;
Widget *plsel_gend_radios = (Widget *) 0;
Widget *plsel_align_radios = (Widget *) 0;
Widget plsel_name_input;
Widget plsel_btn_play;
void
plsel_dialog_acceptvalues()
{
Arg args[2];
String s;
flags.initrace = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
flags.initrole = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
flags.initgend = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0]))-1;
flags.initalign = xtp2i(XawToggleGetCurrent(plsel_align_radios[0]))-1;
XtSetArg(args[0], nhStr(XtNstring), &s);
XtGetValues(plsel_name_input, args, ONE);
(void) strncpy(plname, (char *) s, sizeof plname - 1);
plname[sizeof plname - 1] = '\0';
}
/* ARGSUSED */
void
plsel_quit(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
nhUse(w);
nhUse(event);
nhUse(params);
nhUse(num_params);
ps_selected = PS_QUIT;
exit_x_event = TRUE; /* leave event loop */
}
/* ARGSUSED */
void
plsel_play(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
Arg args[2];
Boolean state;
nhUse(w);
nhUse(event);
nhUse(params);
nhUse(num_params);
XtSetArg(args[0], nhStr(XtNsensitive), &state);
XtGetValues(plsel_btn_play, args, ONE);
if (state) {
plsel_dialog_acceptvalues();
exit_x_event = TRUE; /* leave event loop */
} else {
X11_nhbell();
}
}
/* ARGSUSED */
void
plsel_randomize(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
nhUse(w);
nhUse(event);
nhUse(params);
nhUse(num_params);
X11_player_selection_randomize();
}
/* enable or disable the Play button */
void
plsel_set_play_button(state)
boolean state;
{
Arg args[2];
XtSetArg(args[0], nhStr(XtNsensitive), !state);
XtSetValues(plsel_btn_play, args, ONE);
}
void
plsel_set_sensitivities(setcurr)
boolean setcurr;
{
Arg args[2];
int j, valid;
int c = 0;
int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
plsel_set_play_button(ra < 0 || ro < 0);
if (ra < 0 || ro < 0)
return;
valid = -1;
for (j = 0; roles[j].name.m; j++) {
boolean v = validrace(j, ra);
if (j == ro)
c = j;
XtSetArg(args[0], nhStr(XtNsensitive), v);
XtSetValues(plsel_role_radios[j], args, ONE);
if (valid < 0 && v)
valid = j;
}
if (!validrace(ro, c))
c = valid;
if (setcurr) {
int tmpc = c+1;
XawToggleSetCurrent(plsel_role_radios[0], i2xtp(tmpc));
}
valid = -1;
for (j = 0; races[j].noun; j++) {
boolean v = validrace(ro, j);
if (j == ra)
c = j;
XtSetArg(args[0], nhStr(XtNsensitive), v);
XtSetValues(plsel_race_radios[j], args, ONE);
if (valid < 0 && v)
valid = j;
}
if (!validrace(ro, c))
c = valid;
if (setcurr) {
int tmpc = c+1;
XawToggleSetCurrent(plsel_race_radios[0], i2xtp(tmpc));
}
X11_player_selection_setupOthers();
}
void
X11_player_selection_randomize()
{
int nrole = plsel_n_roles;
int nrace = plsel_n_races;
int ro, ra;
boolean fully_specified_role;
boolean choose_race_first;
int a, g;
int tmpx;
boolean picksomething = (flags.initrole == ROLE_NONE
|| flags.initrace == ROLE_NONE
|| flags.initgend == ROLE_NONE
|| flags.initalign == ROLE_NONE);
if (flags.randomall && picksomething) {
if (flags.initrole == ROLE_NONE)
flags.initrole = ROLE_RANDOM;
if (flags.initrace == ROLE_NONE)
flags.initrace = ROLE_RANDOM;
if (flags.initgend == ROLE_NONE)
flags.initgend = ROLE_RANDOM;
if (flags.initalign == ROLE_NONE)
flags.initalign = ROLE_RANDOM;
}
rigid_role_checks();
/* Randomize race and role, unless specified in config */
ro = flags.initrole;
if (ro == ROLE_NONE || ro == ROLE_RANDOM) {
ro = rn2(nrole);
if (flags.initrole != ROLE_RANDOM) {
fully_specified_role = FALSE;
}
}
ra = flags.initrace;
if (ra == ROLE_NONE || ra == ROLE_RANDOM) {
ra = rn2(nrace);
if (flags.initrace != ROLE_RANDOM) {
fully_specified_role = FALSE;
}
}
/* make sure we have a valid combination, honoring
the users request if possible. */
choose_race_first = FALSE;
if (flags.initrace >= 0 && flags.initrole < 0) {
choose_race_first = TRUE;
}
while (!validrace(ro,ra)) {
if (choose_race_first) {
ro = rn2(nrole);
if (flags.initrole != ROLE_RANDOM) {
fully_specified_role = FALSE;
}
} else {
ra = rn2(nrace);
if (flags.initrace != ROLE_RANDOM) {
fully_specified_role = FALSE;
}
}
}
g = flags.initgend;
if (g == ROLE_NONE) {
g = rn2(ROLE_GENDERS);
fully_specified_role = FALSE;
}
while (!validgend(ro,ra,g)) {
g = rn2(ROLE_GENDERS);
}
a = flags.initalign;
if (a == ROLE_NONE) {
a = rn2(ROLE_ALIGNS);
fully_specified_role = FALSE;
}
while (!validalign(ro,ra,a)) {
a = rn2(ROLE_ALIGNS);
}
tmpx = g+1; XawToggleSetCurrent(plsel_gend_radios[0], i2xtp(tmpx));
tmpx = a+1; XawToggleSetCurrent(plsel_align_radios[0], i2xtp(tmpx));
tmpx = ra+1; XawToggleSetCurrent(plsel_race_radios[0], i2xtp(tmpx));
tmpx = ro+1; XawToggleSetCurrent(plsel_role_radios[0], i2xtp(tmpx));
plsel_set_sensitivities(FALSE);
}
void
X11_player_selection_setupOthers()
{
Arg args[2];
int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
int valid = -1;
int c = 0;
int j;
int k;
int gchecked = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0]))-1;
int achecked = xtp2i(XawToggleGetCurrent(plsel_align_radios[0]))-1;
if (ro < 0 || ra < 0)
return;
for (j = 0; j < ROLE_GENDERS; j++) {
boolean v = validgend(ro, ra, j);
if (j == gchecked)
c = j;
XtSetArg(args[0], nhStr(XtNsensitive), v);
XtSetValues(plsel_gend_radios[j], args, ONE);
if (valid < 0 && v)
valid = j;
}
if (!validgend(ro, ra, c))
c = valid;
k = c+1;
XawToggleSetCurrent(plsel_gend_radios[0], i2xtp(k));
valid = -1;
for (j = 0; j < ROLE_ALIGNS; j++) {
boolean v = validalign(ro, ra, j);
if (j == achecked)
c = j;
XtSetArg(args[0], nhStr(XtNsensitive), v);
XtSetValues(plsel_align_radios[j], args, ONE);
if (valid < 0 && v)
valid = j;
}
if (!validalign(ro, ra, c))
c = valid;
k = c+1;
XawToggleSetCurrent(plsel_align_radios[0], i2xtp(k));
}
static void
racetoggleCallback(w, client, call)
Widget w;
XtPointer client, call;
{
Arg args[2];
int j, valid;
int c = 0;
int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
nhUse(w);
nhUse(client);
nhUse(call);
plsel_set_play_button(ra < 0 || ro < 0);
if (ra < 0 || ro < 0)
return;
valid = -1;
for (j = 0; roles[j].name.m; j++) {
boolean v = validrace(j, ra);
if (j == ro)
c = j;
XtSetArg(args[0], nhStr(XtNsensitive), v);
XtSetValues(plsel_role_radios[j], args, ONE);
if (valid < 0 && v)
valid = j;
}
if (!validrace(c, ra))
c = valid;
j = c+1;
XawToggleSetCurrent(plsel_role_radios[0], i2xtp(j));
X11_player_selection_setupOthers();
}
static void
roletoggleCallback(w, client, call)
Widget w;
XtPointer client, call;
{
Arg args[2];
int j, valid;
int c = 0;
int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
nhUse(w);
nhUse(client);
nhUse(call);
plsel_set_play_button(ra < 0 || ro < 0);
if (ra < 0 || ro < 0)
return;
valid = -1;
for (j = 0; races[j].noun; j++) {
boolean v = validrace(ro, j);
if (j == ra)
c = j;
XtSetArg(args[0], nhStr(XtNsensitive), v);
XtSetValues(plsel_race_radios[j], args, ONE);
if (valid < 0 && v)
valid = j;
}
if (!validrace(ro, c))
c = valid;
j = c + 1;
XawToggleSetCurrent(plsel_race_radios[0], i2xtp(j));
X11_player_selection_setupOthers();
}
static void
gendertoggleCallback(w, client, call)
Widget w;
XtPointer client, call;
{
int r = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
nhUse(w);
nhUse(client);
nhUse(call);
plsel_set_play_button(r < 0);
}
static void
aligntoggleCallback(w, client, call)
Widget w;
XtPointer client, call;
{
int r = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
nhUse(w);
nhUse(client);
nhUse(call);
plsel_set_play_button(r < 0);
}
static void
plsel_random_btn_callback(w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
nhUse(w);
nhUse(client);
nhUse(call);
X11_player_selection_randomize();
}
static void
plsel_play_btn_callback(w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
nhUse(w);
nhUse(client);
nhUse(call);
plsel_dialog_acceptvalues();
exit_x_event = TRUE; /* leave event loop */
}
static void
plsel_quit_btn_callback(w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
nhUse(w);
nhUse(client);
nhUse(call);
ps_selected = PS_QUIT;
exit_x_event = TRUE; /* leave event loop */
}
Widget
X11_create_player_selection_name(form)
Widget form;
{
Widget namelabel, name_vp, name_form;
Arg args[10];
Cardinal num_args;
/* name viewport */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, False); num_args++;
XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
name_vp = XtCreateManagedWidget("name_vp", viewportWidgetClass, form,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
name_form = XtCreateManagedWidget("name_form", formWidgetClass, name_vp,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Name"); num_args++;
XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
namelabel = XtCreateManagedWidget("name_label",
labelWidgetClass, name_form,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), namelabel); 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(XtNresizable), True); num_args++;
XtSetArg(args[num_args], nhStr(XtNeditType),
!plsel_ask_name ? XawtextRead : XawtextEdit); num_args++;
XtSetArg(args[num_args], nhStr(XtNresize), XawtextResizeWidth); num_args++;
XtSetArg(args[num_args], nhStr(XtNstring), plname); num_args++;
XtSetArg(args[num_args], XtNinsertPosition, strlen(plname)); num_args++;
XtSetArg(args[num_args], nhStr(XtNaccelerators),
XtParseAcceleratorTable(plsel_input_accelerators)); num_args++;
plsel_name_input = XtCreateManagedWidget("name_input",
asciiTextWidgetClass, name_form,
args, num_args);
XtInstallAccelerators(plsel_name_input, plsel_name_input);
if (plsel_ask_name) {
XtSetKeyboardFocus(form, plsel_name_input);
} else {
XtSetArg(args[0], nhStr(XtNdisplayCaret), False);
XtSetValues(plsel_name_input, args, ONE);
}
return name_vp;
}
void
X11_player_selection_dialog()
{
Widget popup, popup_vp;
Widget form;
Widget name_vp;
Widget racelabel, race_form, race_vp, race_form2;
Widget rolelabel, role_form, role_vp, role_form2;
Widget gendlabel, gend_form,
gend_radio_m, gend_radio_f, gend_vp, gend_form2;
Widget alignlabel, align_form,
align_radio_l, align_radio_n, align_radio_c, align_vp, align_form2;
Widget btn_vp, btn_form, random_btn, play_btn, quit_btn;
Widget tmpwidget;
Arg args[10];
Cardinal num_args;
int i;
int winwid = 400;
int cwid = (winwid / 3) - 14;
num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
XtSetArg(args[num_args], XtNtitle, "Player Selection"); num_args++;
popup = XtCreatePopupShell("player_selection_dialog",
transientShellWidgetClass,
toplevel, args, num_args);
num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(plsel_dialog_translations)); num_args++;
popup_vp = XtCreateManagedWidget("plsel_vp", viewportWidgetClass,
popup, args, num_args);
num_args = 0;
XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(plsel_dialog_translations)); num_args++;
form = XtCreateManagedWidget("plsel_form", formWidgetClass, popup_vp,
args, num_args);
name_vp = X11_create_player_selection_name(form);
num_args = 0;
XtSetArg(args[num_args], XtNwidth, winwid); num_args++;
XtSetValues(name_vp, args, num_args);
/********************************************/
/* Race */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
race_form = XtCreateManagedWidget("race_form", formWidgetClass, form,
args, num_args);
/* race label */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Race"); num_args++;
racelabel = XtCreateManagedWidget("race_label",
labelWidgetClass, race_form,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromVert), racelabel); num_args++;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
race_vp = XtCreateManagedWidget("race_vp", viewportWidgetClass, race_form,
args, num_args);
num_args = 0;
race_form2 = XtCreateManagedWidget("race_form2", formWidgetClass, race_vp,
args, num_args);
for (i = 0; races[i].noun; i++)
continue;
plsel_n_races = i;
plsel_race_radios = (Widget *) alloc(sizeof (Widget) * plsel_n_races);
/* race radio buttons */
for (i = 0; races[i].noun; i++) {
Widget racewidget;
num_args = 0;
if (i > 0)
XtSetArg(args[num_args], nhStr(XtNfromVert),
tmpwidget); num_args++;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
if (i > 0)
XtSetArg(args[num_args], nhStr(XtNradioGroup),
plsel_race_radios[0]); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), (i + 1)); num_args++;
racewidget = XtCreateManagedWidget(races[i].noun,
toggleWidgetClass,
race_form2,
args, num_args);
XtAddCallback(racewidget, XtNcallback, racetoggleCallback, i2xtp(i));
tmpwidget = racewidget;
plsel_race_radios[i] = racewidget;
}
XawToggleUnsetCurrent(plsel_race_radios[0]);
/********************************************/
/* Role */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromHoriz), race_form); num_args++;
role_form = XtCreateManagedWidget("role_form", formWidgetClass, form,
args, num_args);
/* role label */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Role"); num_args++;
rolelabel = XtCreateManagedWidget("role_label",
labelWidgetClass, role_form,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromVert), rolelabel); num_args++;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
role_vp = XtCreateManagedWidget("role_vp", viewportWidgetClass, role_form,
args, num_args);
num_args = 0;
role_form2 = XtCreateManagedWidget("role_form2", formWidgetClass, role_vp,
args, num_args);
for (i = 0; roles[i].name.m; i++)
continue;
plsel_n_roles = i;
plsel_role_radios = (Widget *)alloc(sizeof(Widget) * plsel_n_roles);
/* role radio buttons */
for (i = 0; roles[i].name.m; i++) {
Widget rolewidget;
num_args = 0;
if (i > 0)
XtSetArg(args[num_args], nhStr(XtNfromVert),
tmpwidget); num_args++;
XtSetArg(args[num_args], nhStr(XtNwidth), cwid); num_args++;
if (i > 0)
XtSetArg(args[num_args], nhStr(XtNradioGroup),
plsel_role_radios[0]); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), (i + 1)); num_args++;
rolewidget = XtCreateManagedWidget(roles[i].name.m,
toggleWidgetClass,
role_form2,
args, num_args);
XtAddCallback(rolewidget, XtNcallback, roletoggleCallback, i2xtp(i));
tmpwidget = rolewidget;
plsel_role_radios[i] = rolewidget;
}
XawToggleUnsetCurrent(plsel_role_radios[0]);
/********************************************/
/* Gender*/
plsel_gend_radios = (Widget *)alloc(sizeof(Widget) * ROLE_GENDERS);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
gend_form = XtCreateManagedWidget("gender_form", formWidgetClass, form,
args, num_args);
/* gender label */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Gender"); num_args++;
gendlabel = XtCreateManagedWidget("gender_label",
labelWidgetClass, gend_form,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromVert), gendlabel); num_args++;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
gend_vp = XtCreateManagedWidget("gender_vp", viewportWidgetClass,
gend_form, args, num_args);
num_args = 0;
gend_form2 = XtCreateManagedWidget("gender_form2", formWidgetClass,
gend_vp, args, num_args);
/* gender radio buttons */
num_args = 0;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), 1); num_args++;
plsel_gend_radios[0] = gend_radio_m
= XtCreateManagedWidget("Male", toggleWidgetClass,
gend_form2, args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), gend_radio_m); num_args++;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioGroup), plsel_gend_radios[0]); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), 2); num_args++;
plsel_gend_radios[1] = gend_radio_f
= XtCreateManagedWidget("Female", toggleWidgetClass,
gend_form2, args, num_args);
XawToggleUnsetCurrent(plsel_gend_radios[0]);
XtAddCallback(gend_radio_m, XtNcallback,
gendertoggleCallback, (XtPointer) (1));
XtAddCallback(gend_radio_f, XtNcallback,
gendertoggleCallback, (XtPointer) (2));
/********************************************/
/* Alignment */
plsel_align_radios = (Widget *)alloc(sizeof(Widget) * ROLE_ALIGNS);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), gend_form); num_args++;
XtSetArg(args[num_args], nhStr(XtNvertDistance), 30); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
align_form = XtCreateManagedWidget("align_form", formWidgetClass, form,
args, num_args);
/* align label */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Alignment"); num_args++;
alignlabel = XtCreateManagedWidget("align_label",
labelWidgetClass, align_form,
args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromVert), alignlabel); num_args++;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
align_vp = XtCreateManagedWidget("align_vp", viewportWidgetClass,
align_form, args, num_args);
num_args = 0;
align_form2 = XtCreateManagedWidget("align_form2", formWidgetClass,
align_vp, args, num_args);
num_args = 0;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), 1); num_args++;
plsel_align_radios[0] = align_radio_l
= XtCreateManagedWidget("Lawful", toggleWidgetClass,
align_form2, args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), align_radio_l); num_args++;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioGroup), plsel_align_radios[0]); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), 2); num_args++;
plsel_align_radios[1] = align_radio_n
= XtCreateManagedWidget("Neutral", toggleWidgetClass,
align_form2, args, num_args);
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), align_radio_n); num_args++;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioGroup), plsel_align_radios[0]); num_args++;
XtSetArg(args[num_args], nhStr(XtNradioData), 3); num_args++;
plsel_align_radios[2] = align_radio_c = XtCreateManagedWidget("Chaotic",
toggleWidgetClass,
align_form2,
args, num_args);
XawToggleUnsetCurrent(plsel_align_radios[0]);
XtAddCallback(align_radio_l, XtNcallback,
aligntoggleCallback, (XtPointer) (1));
XtAddCallback(align_radio_n, XtNcallback,
aligntoggleCallback, (XtPointer) (2));
XtAddCallback(align_radio_c, XtNcallback,
aligntoggleCallback, (XtPointer) (3));
/********************************************/
/* Buttons! */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), align_form); num_args++;
XtSetArg(args[num_args], nhStr(XtNvertDistance), 30); num_args++;
XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
XtSetArg(args[num_args], XtNforceBars, False); num_args++;
XtSetArg(args[num_args], XtNallowVert, False); num_args++;
XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
btn_vp = XtCreateManagedWidget("btn_vp", viewportWidgetClass, form,
args, num_args);
num_args = 0;
btn_form = XtCreateManagedWidget("btn_form", formWidgetClass, btn_vp,
args, num_args);
/* "Random" button */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Random"); num_args++;
random_btn = XtCreateManagedWidget("random", commandWidgetClass, btn_form,
args, num_args);
XtAddCallback(random_btn, XtNcallback, plsel_random_btn_callback, form);
/* "Play" button */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), random_btn); num_args++;
XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Play"); num_args++;
plsel_btn_play = play_btn
= XtCreateManagedWidget("play", commandWidgetClass, btn_form,
args, num_args);
XtAddCallback(play_btn, XtNcallback, plsel_play_btn_callback, form);
/* "Quit" button */
num_args = 0;
XtSetArg(args[num_args], nhStr(XtNfromVert), play_btn); 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], XtNwidth, cwid); num_args++;
XtSetArg(args[num_args], nhStr(XtNlabel), "Quit"); num_args++;
quit_btn = XtCreateManagedWidget("quit", commandWidgetClass, btn_form,
args, num_args);
XtAddCallback(quit_btn, XtNcallback, plsel_quit_btn_callback, form);
/********************************************/
XtRealizeWidget(popup);
X11_player_selection_randomize();
ps_selected = -1;
nh_XtPopup(popup, (int) XtGrabExclusive, form);
/* The callback will enable the event loop exit. */
(void) x_event(EXIT_ON_EXIT);
nh_XtPopdown(popup);
XtDestroyWidget(popup);
if (plsel_race_radios)
free(plsel_race_radios);
if (plsel_role_radios)
free(plsel_role_radios);
if (plsel_gend_radios)
free(plsel_gend_radios);
if (plsel_align_radios)
free(plsel_align_radios);
if (ps_selected == PS_QUIT || program_state.done_hup) {
clearlocks();
X11_exit_nhwindows((char *) 0);
nh_terminate(0);
}
}
/* Global functions ========================================================= /* Global functions =========================================================
*/ */
void void
X11_player_selection() X11_player_selection_prompts()
{ {
int num_roles, num_races, num_gends, num_algns, i, availcount, availindex; int num_roles, num_races, num_gends, num_algns, i, availcount, availindex;
Widget popup, player_form; Widget popup, player_form;
@@ -586,6 +1518,16 @@ X11_player_selection()
} }
} }
void
X11_player_selection()
{
if (iflags.wc_player_selection == VIA_DIALOG) {
X11_player_selection_dialog();
} else { /* iflags.wc_player_selection == VIA_PROMPTS */
X11_player_selection_prompts();
}
}
int int
X11_get_ext_cmd() X11_get_ext_cmd()
{ {

View File

@@ -104,7 +104,7 @@ register_main_window_class()
wcex.hInstance = GetNHApp()->hApp; wcex.hInstance = GetNHApp()->hApp;
wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR) IDI_NETHACKW); wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR) IDI_NETHACKW);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wcex.lpszMenuName = (TCHAR *) IDC_NETHACKW; wcex.lpszMenuName = (TCHAR *) IDC_NETHACKW;
wcex.lpszClassName = szMainWindowClass; wcex.lpszClassName = szMainWindowClass;

View File

@@ -254,6 +254,8 @@ mswin_menu_window_select_menu(HWND hWnd, int how, MENU_ITEM_P **_selected,
&& how != PICK_NONE) { && how != PICK_NONE) {
data->menu.prompt[0] = '\0'; data->menu.prompt[0] = '\0';
SetMenuListType(hWnd, PICK_NONE); SetMenuListType(hWnd, PICK_NONE);
for (i = 0; i < data->menu.size; i++)
data->menu.items[i].count = 0;
LayoutMenu(hWnd); LayoutMenu(hWnd);
} }
} }

View File

@@ -12,6 +12,52 @@
extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */ extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
typedef struct back_buffer {
HWND hWnd;
HDC hdc;
HBITMAP bm;
HBITMAP orig_bm;
int width;
int height;
} back_buffer_t;
void back_buffer_free(back_buffer_t * back_buffer)
{
if (back_buffer->bm != NULL) {
SelectObject(back_buffer->hdc, back_buffer->orig_bm);
DeleteObject(back_buffer->bm);
back_buffer->bm = NULL;
}
}
void back_buffer_allocate(back_buffer_t * back_buffer, int width, int height)
{
HDC hdc = GetDC(back_buffer->hWnd);
back_buffer->bm = CreateCompatibleBitmap(hdc, width, height);
back_buffer->orig_bm = SelectObject(back_buffer->hdc, back_buffer->bm);
back_buffer->width = width;
back_buffer->height = height;
ReleaseDC(back_buffer->hWnd, hdc);
}
void back_buffer_size(back_buffer_t * back_buffer, int width, int height)
{
if (back_buffer->bm == NULL || back_buffer->width != width
|| back_buffer->height != height) {
back_buffer_free(back_buffer);
back_buffer_allocate(back_buffer, width, height);
}
}
void back_buffer_init(back_buffer_t * back_buffer, HWND hWnd, int width, int height)
{
back_buffer->hWnd = hWnd;
back_buffer->hdc = CreateCompatibleDC(NULL);
back_buffer->bm = NULL;
back_buffer_size(back_buffer, width, height);
}
typedef struct mswin_nethack_status_window { typedef struct mswin_nethack_status_window {
int index; int index;
char window_text[NHSW_LINES][MAXWINDOWTEXT + 1]; char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
@@ -20,6 +66,7 @@ typedef struct mswin_nethack_status_window {
boolean *activefields; boolean *activefields;
int *percents; int *percents;
int *colors; int *colors;
back_buffer_t back_buffer;
} NHStatusWindow, *PNHStatusWindow; } NHStatusWindow, *PNHStatusWindow;
static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN,
@@ -45,6 +92,7 @@ mswin_init_status_window()
HWND ret; HWND ret;
NHStatusWindow *data; NHStatusWindow *data;
RECT rt; RECT rt;
int width, height;
if (!run_once) { if (!run_once) {
register_status_window_class(); register_status_window_class();
@@ -59,12 +107,14 @@ mswin_init_status_window()
} }
/* create status window object */ /* create status window object */
width = rt.right - rt.left;
height = rt.bottom - rt.top;
ret = CreateWindow(szStatusWindowClass, NULL, ret = CreateWindow(szStatusWindowClass, NULL,
WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX, WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX,
rt.left, /* horizontal position of window */ rt.left, /* horizontal position of window */
rt.top, /* vertical position of window */ rt.top, /* vertical position of window */
rt.right - rt.left, /* window width */ width, /* window width */
rt.bottom - rt.top, /* window height */ height, /* window height */
GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL); GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL);
if (!ret) if (!ret)
panic("Cannot create status window"); panic("Cannot create status window");
@@ -80,8 +130,20 @@ mswin_init_status_window()
ZeroMemory(data, sizeof(NHStatusWindow)); ZeroMemory(data, sizeof(NHStatusWindow));
SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data); SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
back_buffer_init(&data->back_buffer, ret, width, height);
mswin_apply_window_style(ret); mswin_apply_window_style(ret);
if (status_bg_brush == NULL) {
status_bg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS);
status_bg_brush = CreateSolidBrush(status_bg_color);
}
if (status_fg_brush == NULL) {
status_fg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS);
status_fg_brush = CreateSolidBrush(status_fg_color);
}
return ret; return ret;
} }
@@ -98,9 +160,7 @@ register_status_window_class()
wcex.hInstance = GetNHApp()->hApp; wcex.hInstance = GetNHApp()->hApp;
wcex.hIcon = NULL; wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = status_bg_brush wcex.hbrBackground = NULL;
? status_bg_brush
: SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_STATUS);
wcex.lpszMenuName = NULL; wcex.lpszMenuName = NULL;
wcex.lpszClassName = szStatusWindowClass; wcex.lpszClassName = szStatusWindowClass;
@@ -216,30 +276,35 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
int *f; int *f;
int **fop; int **fop;
SIZE sz; SIZE sz;
HGDIOBJ oldFont, normalFont, boldFont; HGDIOBJ normalFont, boldFont;
TCHAR wbuf[BUFSZ]; TCHAR wbuf[BUFSZ];
COLORREF OldBg, OldFg, Bg, Fg;
RECT rt; RECT rt;
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hdc; HDC hdc;
PNHStatusWindow data; PNHStatusWindow data;
int width, height;
RECT clear_rect;
HDC front_buffer_hdc;
data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
hdc = BeginPaint(hWnd, &ps); front_buffer_hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rt); GetClientRect(hWnd, &rt);
width = rt.right - rt.left;
height = rt.bottom - rt.top;
back_buffer_size(&data->back_buffer, width, height);
hdc = data->back_buffer.hdc;
normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE); normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE);
boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE); boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE);
oldFont = SelectObject(hdc, normalFont);
Bg = status_bg_brush ? status_bg_color SelectObject(hdc, normalFont);
: (COLORREF) GetSysColor(DEFAULT_COLOR_BG_STATUS);
OldBg = SetBkColor(hdc, Bg);
Fg = status_fg_brush ? status_fg_color SetBkColor(hdc, status_bg_color);
: (COLORREF) GetSysColor(DEFAULT_COLOR_FG_STATUS); SetTextColor(hdc, status_fg_color);
OldFg = SetTextColor(hdc, Fg);
if (iflags.wc2_hitpointbar && BL_HP < data->n_fields if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
&& data->activefields[BL_HP]) { && data->activefields[BL_HP]) {
@@ -247,6 +312,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
hpbar_color = data->colors[BL_HP] & 0x00ff; hpbar_color = data->colors[BL_HP] & 0x00ff;
} }
clear_rect.left = 0;
clear_rect.top = 0;
clear_rect.right = width;
clear_rect.bottom = height;
FillRect(hdc, &clear_rect, status_bg_brush);
for (fop = fieldorders; *fop; fop++) { for (fop = fieldorders; *fop; fop++) {
LONG left = rt.left; LONG left = rt.left;
LONG cy = 0; LONG cy = 0;
@@ -275,8 +347,10 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
else if (atr & HL_DIM) else if (atr & HL_DIM)
fntatr = ATR_DIM; fntatr = ATR_DIM;
fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE); fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
nFg = (clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr) : Fg; nFg = (clr == NO_COLOR ? status_fg_color
nBg = Bg; : ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr)
: status_fg_color));
nBg = status_bg_color;
GetTextExtentPoint32(hdc, wbuf, vlen, &sz); GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
if (*f == BL_TITLE && iflags.wc2_hitpointbar) { if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
@@ -286,7 +360,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
/* first draw title normally */ /* first draw title normally */
SelectObject(hdc, fnt); SelectObject(hdc, fnt);
SetBkMode(hdc, OPAQUE); SetBkMode(hdc, OPAQUE);
SetBkColor(hdc, Bg); SetBkColor(hdc, status_bg_color);
SetTextColor(hdc, nhcolor_to_RGB(hpbar_color)); SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
DrawText(hdc, wbuf, vlen, &rt, DT_LEFT); DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
@@ -322,13 +396,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
rt.left += sz.cx; rt.left += sz.cx;
cy = max(cy, sz.cy); cy = max(cy, sz.cy);
} }
rt.left = left; rt.left = left;
rt.top += cy; rt.top += cy;
} }
SelectObject(hdc, oldFont); BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
SetTextColor(hdc, OldFg);
SetBkColor(hdc, OldBg);
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
return 0; return 0;