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
+5
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 ';'.
.lp #help
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
Show long version and game history. Default key is 'V'.
.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
``More info?'' prompt, but it also means that you might miss some
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
Visually distinguish pets from similar animals (default off).
The behavior of this option depends on the type of windowing you use.
+4
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
might miss some interesting and/or important information. Persistent.
%.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}]
Visually distinguish pets from similar animals (default off).
The behavior of this option depends on the type of windowing you use.
+8
View File
@@ -451,6 +451,8 @@ give feedback when released from a bear trap
depending upon how the dynamically inserted pattern-match phrase fit
#version output left out "pattern matching via <method>" if the basic NetHack
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
@@ -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
far side of a closed door shifted shape to pass under that door
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
@@ -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
"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
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
@@ -703,6 +709,8 @@ X11: status display split into three columns to accomodate Stone/Deaf/Lev/&c;
resources replaced by status_condition[1-3].*
X11: more terminal-like default resources
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
+3 -2
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(breaks, (struct obj *, XCHAR_P, XCHAR_P));
E void FDECL(release_camera_demon, (struct obj *, XCHAR_P, XCHAR_P));
E void FDECL(breakobj,
(struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P, BOOLEAN_P));
E void FDECL(breakobj, (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P, BOOLEAN_P));
E boolean FDECL(breaktest, (struct obj *));
E boolean FDECL(walk_path, (coord *, coord *,
boolean (*)(genericptr, int, int), genericptr_t));
E boolean FDECL(hurtle_jump, (genericptr_t, int, int));
E boolean FDECL(hurtle_step, (genericptr_t, int, int));
/* ### drawing.c ### */
@@ -2487,6 +2487,7 @@ E void NDECL(port_help);
E void FDECL(sethanguphandler, (void (*)(int)));
E boolean NDECL(authorize_wizard_mode);
E boolean FDECL(check_user_string, (char *));
E char *NDECL(get_login_name);
#endif /* UNIX */
/* ### unixtty.c ### */
+1
View File
@@ -191,6 +191,7 @@ struct instance_flags {
* behaviour of various NetHack functions and probably warrant
* a structure of their own elsewhere some day.
*/
boolean herecmd_menu; /* use menu when mouseclick on yourself */
boolean invis_goldsym; /* gold symbol is ' '? */
int parse_config_file_src; /* hack for parse_config_line() */
int in_lava_effects; /* hack for Boots_off() */
+14
View File
@@ -946,6 +946,20 @@ static const char *pet_mark_small_xpm[] = {
"..X.."
};
/* 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[] = {
/* width height ncolors chars_per_pixel */
"40 40 23 1",
+7
View File
@@ -242,6 +242,7 @@ E boolean exit_x_event; /* exit condition for event loop */
#define EXIT_ON_EXIT 2
#define EXIT_ON_SENT_EVENT 3
E int click_x, click_y, click_button, updated_inventory;
E boolean plsel_ask_name;
typedef struct {
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_key, (Widget, XEvent *, String *,
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);
/* ### winstatus.c ### */
+4
View File
@@ -15,6 +15,7 @@ typedef union any {
int a_int;
char a_char;
schar a_schar;
uchar a_uchar;
unsigned int a_uint;
long a_long;
unsigned long a_ulong;
@@ -23,6 +24,8 @@ typedef union any {
unsigned long *a_ulptr;
unsigned *a_uptr;
const char *a_string;
int NDECL((*a_nfunc));
unsigned long a_mask32; /* used by status highlighting */
/* add types as needed */
} anything;
#define ANY_P union any /* avoid typedef in prototypes */
@@ -45,6 +48,7 @@ enum any_types {
ANY_LPTR, /* pointer to long */
ANY_ULPTR, /* pointer to unsigned long */
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) */
};
+2 -1
View File
@@ -227,7 +227,8 @@
&& !BFlying)
/* 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 */
/* Wwalking is meaningless on water level */
+6 -7
View File
@@ -1769,10 +1769,10 @@ int magic; /* 0=Physical, otherwise skill level */
temp = -temp;
if (range < temp)
range = temp;
(void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
/* hurtle_step results in (u.ux, u.uy) == (cc.x, cc.y) and usually
* moves the ball if punished, but does not handle all the effects
* of landing on the final position.
(void) walk_path(&uc, &cc, hurtle_jump, (genericptr_t) &range);
/* hurtle_jump -> hurtle_step results in <u.ux,u.uy> == <cc.x,cc.y>
* and usually moves the ball if punished, but does not handle all
* the effects of landing on the final position.
*/
teleds(cc.x, cc.y, FALSE);
sokoban_guilt();
@@ -1951,9 +1951,8 @@ struct obj *obj;
if (ABASE(idx) >= AMAX(idx))
continue;
val_limit = AMAX(idx);
/* don't recover strength lost from hunger */
if (idx == A_STR && u.uhs >= WEAK)
val_limit--;
/* this used to adjust 'val_limit' for A_STR when u.uhs was
WEAK or worse, but that's handled via ATEMP(A_STR) now */
if (Fixed_abil) {
/* potion/spell of restore ability override sustain ability
intrinsic but unicorn horn usage doesn't */
+13 -6
View File
@@ -366,20 +366,27 @@ set_moreluck()
void
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 */
if (ATEMP(i) && ATIME(i)) {
equilibrium = (i == A_STR && u.uhs >= WEAK) ? -1 : 0;
if (ATEMP(i) != equilibrium && ATIME(i) != 0) {
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 */
ATIME(i) = 100 / ACURR(A_CON);
}
}
}
(void) encumber_msg();
if (context.botl)
(void) encumber_msg();
}
#define AVAL 50 /* tune value for exercise gains */
+269
View File
@@ -114,6 +114,8 @@ static int NDECL(dosuspend_core); /**/
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(timed_occupation);
STATIC_PTR int NDECL(doextcmd);
@@ -181,6 +183,10 @@ STATIC_DCL void FDECL(attributes_enlightenment, (int, int));
static const char *readchar_queue = "";
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 void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P));
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",
doquickwhatis, 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",
dohistory, IFBURIED | GENERALCMD },
{ '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 },
{ '\0', "terrain", "show map without obstructions",
doterrain, IFBURIED | AUTOCOMPLETE },
{ '\0', "therecmdmenu",
"show menu of commands you can do from here to adjacent spot",
dotherecmdmenu },
{ 't', "throw", "throw something", dothrow },
{ '\0', "timeout", "look at timeout queue and hero's timed intrinsics",
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;
}
/* #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;
/*
@@ -4692,6 +4948,11 @@ int x, y, mod;
}
if (x == 0 && y == 0) {
if (iflags.herecmd_menu) {
cmd[0] = here_cmd_menu(FALSE);
return cmd;
}
/* here */
if (IS_FOUNTAIN(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)) {
cmd[1] = Cmd.dirchars[dir];
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)) {
/* slight assistance to the player: choose kick/open for them
*/
@@ -5096,6 +5364,7 @@ wiz_port_debug()
num_menu_selections = SIZE(menu_selections) - 1;
if (num_menu_selections > 0) {
menu_item *pick_list;
win = create_nhwindow(NHW_MENU);
start_menu(win);
for (k = 0; k < num_menu_selections; ++k) {
+54 -6
View File
@@ -519,6 +519,25 @@ genericptr_t arg;
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,
* 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)
&& bad_rock(youmonst.data, x, u.uy)) {
boolean too_much =
(invent && (inv_weight() + weight_cap() > 600));
boolean too_much = (invent && (inv_weight() + weight_cap() > 600));
/* Move at a diagonal. */
if (bigmonst(youmonst.data) || too_much) {
You("%sget forcefully wedged into a crevice.",
@@ -621,14 +640,43 @@ int x, y;
}
}
if ((mon = m_at(x, y)) != 0) {
You("bump into %s.", a_monnam(mon));
if ((mon = m_at(x, y)) != 0
#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);
if (!canspotmon(mon))
map_invisible(mon->mx, mon->my);
setmangry(mon, FALSE);
wake_nearto(x,y, 10);
wake_nearto(x, y, 10);
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)) {
/* Move at a diagonal. */
if (Sokoban) {
+43 -14
View File
@@ -112,8 +112,11 @@ register struct obj *obj;
void
init_uhunger()
{
context.botl = (u.uhs != NOT_HUNGRY || ATEMP(A_STR) < 0);
u.uhunger = 900;
u.uhs = NOT_HUNGRY;
if (ATEMP(A_STR) < 0)
ATEMP(A_STR) = 0;
}
/* 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
* metallic meal, etc....
*/
if (!(carried(otmp) ? retouch_object(&otmp, FALSE)
: touch_artifact(otmp, &youmonst))) {
return 1;
} else if (!is_edible(otmp)) {
if (!is_edible(otmp)) {
You("cannot eat that!");
return 0;
} else if ((otmp->owornmask & (W_ARMOR | W_TOOL | W_AMUL | W_SADDLE))
@@ -2451,6 +2451,9 @@ doeat()
/* let them eat rings */
You_cant("eat %s you're wearing.", something);
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
&& otmp->oerodeproof) {
@@ -2465,13 +2468,26 @@ doeat()
/* The regurgitated object's rustproofing is gone now */
otmp->oerodeproof = 0;
make_stunned((HStun & TIMEOUT) + (long) rn2(10), TRUE);
You("spit %s out onto the %s.", the(xname(otmp)),
surface(u.ux, u.uy));
if (carried(otmp)) {
freeinv(otmp);
dropy(otmp);
/*
* We don't expect rust monsters to be wielding welded weapons
* or wearing cursed rings which were rustproofed, but guard
* against the possibility just in case.
*/
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;
}
/* KMH -- Slow digestion is... indigestible */
@@ -2961,10 +2977,23 @@ boolean incr;
}
if (newhs != u.uhs) {
if (newhs >= WEAK && u.uhs < WEAK)
losestr(1); /* this may kill you -- see below */
else if (newhs < WEAK && u.uhs >= WEAK)
losestr(-1);
if (newhs >= WEAK && u.uhs < WEAK) {
/* this used to be losestr(1) which had the potential to
be fatal (still handled below) by reducing HP if it
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) {
case HUNGRY:
if (Hallucination) {
+1
View File
@@ -763,6 +763,7 @@ time_t when; /* date+time at end of game */
dump_redirect(FALSE);
#else
nhUse(how);
nhUse(when);
#endif
}
+26 -16
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. */
/* 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 },
{ "goldX", &iflags.goldX, FALSE, 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_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
{ "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/
@@ -3719,8 +3720,19 @@ boolean tinitial, tfrom_file;
vision_full_recalc = 1; /* delayed recalc */
if (iflags.use_color)
need_redraw = TRUE; /* darkroom refresh */
} else if (boolopt[i].addr == &iflags.wc_tiled_map
|| boolopt[i].addr == &flags.showrace
} else if (boolopt[i].addr == &iflags.wc_ascii_map) {
/* 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.hilite_pile
|| boolopt[i].addr == &iflags.hilite_pet) {
@@ -5523,7 +5535,8 @@ const char *mapping;
ape = (struct autopickup_exception *) alloc(sizeof *ape);
ape->regex = regex_init();
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);
free((genericptr_t) ape);
return 0;
@@ -6182,13 +6195,11 @@ STATIC_OVL boolean
wc_supported(optnam)
const char *optnam;
{
int k = 0;
int k;
while (wc_options[k].wc_name) {
if (!strcmp(wc_options[k].wc_name, optnam)
&& (windowprocs.wincap & wc_options[k].wc_bit))
return TRUE;
k++;
for (k = 0; wc_options[k].wc_name; ++k) {
if (!strcmp(wc_options[k].wc_name, optnam))
return (windowprocs.wincap & wc_options[k].wc_bit) ? TRUE : FALSE;
}
return FALSE;
}
@@ -6242,13 +6253,12 @@ STATIC_OVL boolean
wc2_supported(optnam)
const char *optnam;
{
int k = 0;
int k;
while (wc2_options[k].wc_name) {
if (!strcmp(wc2_options[k].wc_name, optnam)
&& (windowprocs.wincap2 & wc2_options[k].wc_bit))
return TRUE;
k++;
for (k = 0; wc2_options[k].wc_name; ++k) {
if (!strcmp(wc2_options[k].wc_name, optnam))
return (windowprocs.wincap2 & wc2_options[k].wc_bit) ? TRUE
: FALSE;
}
return FALSE;
}
+2 -2
View File
@@ -565,8 +565,8 @@ register struct obj *otmp;
i = rn2(A_MAX); /* start at a random point */
for (ii = 0; ii < A_MAX; ii++) {
lim = AMAX(i);
if (i == A_STR && u.uhs >= 3)
--lim; /* WEAK */
/* this used to adjust 'lim' for A_STR when u.uhs was
WEAK or worse, but that's handled via ATEMP(A_STR) now */
if (ABASE(i) < lim) {
ABASE(i) = lim;
context.botl = 1;
+1 -1
View File
@@ -343,7 +343,7 @@ int trouble;
u.utrap = 0;
break;
case TROUBLE_STARVING:
losestr(-1);
/* temporarily lost strength recovery now handled by init_uhunger() */
/*FALLTHRU*/
case TROUBLE_HUNGRY:
Your("%s feels content.", body_part(STOMACH));
+4
View File
@@ -1714,6 +1714,7 @@ boolean confused, helmet_protects, byu, skip_uswallow;
}
} else
dmg = 0;
wake_nearto(u.ux, u.uy, 4 * 4);
/* Must be before the losehp(), for bones files */
if (!flooreffects(otmp2, u.ux, u.uy, "fall")) {
place_object(otmp2, u.ux, u.uy);
@@ -1779,7 +1780,10 @@ boolean confused, byu;
pline("%s is killed.", Monnam(mtmp));
mondied(mtmp);
}
} else {
wakeup(mtmp, byu);
}
wake_nearto(x, y, 4 * 4);
} else if (u.uswallow && mtmp == u.ustuck) {
obfree(otmp2, (struct obj *) 0);
/* fall through to player */
+18 -1
View File
@@ -332,6 +332,9 @@ RANDOBJ =
# used by `make depend' to reconstruct this Makefile; you shouldn't need this
AWK = nawk
#VERBOSEMAKE = 1
# ----------------------------------------
#
# 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,
# {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
# timestamp files to reduce `make' overhead and shorten .o dependency lists
@@ -438,7 +455,7 @@ $(GAME): $(SYSTEM)
Sysunix: $(HOBJ) Makefile
@echo "Loading ..."
$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
@$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
@touch Sysunix
Sys3B2: $(HOBJ) Makefile
+16 -4
View File
@@ -130,6 +130,20 @@ LEXYYC = lex.yy.c
#
# 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
CONFIG_H = ../src/config.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
# is one "_cplusplus" inside a comment
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
../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
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
../include/dgn_comp.h: dgn_yacc.c
+1 -1
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+= 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+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\"
CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
+5
View File
@@ -26,6 +26,11 @@ x) hints=/dev/null
;;
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.dat DAT ../../dat/Makefile $hints $hfile
/bin/sh ./mkmkfile.sh Makefile.doc DOC ../../doc/Makefile $hints $hfile
+14
View File
@@ -696,4 +696,18 @@ get_unix_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*/
+96 -37
View File
@@ -18,6 +18,7 @@ extern "C" {
#undef max
#include <QtGui/QtGui>
#include <QStringList>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#include <QtMultimedia/QSound>
@@ -119,6 +120,9 @@ NetHackQtBind::NetHackQtBind(int& argc, char** argv) :
main = new NetHackQtMainWindow(keybuffer);
connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
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)
@@ -493,51 +497,48 @@ int NetHackQtBind::qt_doprev_message()
char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, CHAR_P def)
{
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) {
// Similar to X11 windowport `slow' feature.
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;
}
int result = -1;
#ifdef USE_POPUPS
// Improve some special-cases (DIRKS 08/02/23)
if (strcmp (choices,"ynq") == 0) {
switch (QMessageBox::information (NetHackQtBind::mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2))
{
case 0: return 'y';
case 1: return 'n';
case 2: return 'q';
}
}
if (choices) {
if (!strcmp(choices,"ynq"))
result = QMessageBox::information (NetHackQtBind::mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2);
else if (!strcmp(choices,"yn"))
result = QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Yes", "&No",0,1);
else if (!strcmp(choices, "rl"))
result = QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Right", "&Left",0,1);
if (strcmp (choices,"yn") == 0) {
switch (QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Yes", "&No",0,1))
{
case 0: return 'y';
case 1: return 'n';
}
}
if (result >= 0 && result < strlen(choices)) {
char yn_resp = choices[result];
message += QString(" %1").arg(yn_resp);
result = yn_resp;
}
}
#endif
NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message);
int result=-1;
while (result<0) {
while (result < 0) {
char ch=NetHackQtBind::qt_nhgetch();
if (ch=='\033') {
result=yn_esc_map;
@@ -558,7 +559,12 @@ char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, C
return result;
} else {
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);
}
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)
{
// Ignore Alt-key navigation to menubar, it's annoying when you
@@ -658,6 +713,9 @@ NetHackQtKeyBuffer NetHackQtBind::keybuffer;
NetHackQtClickBuffer NetHackQtBind::clickbuffer;
NetHackQtMainWindow* NetHackQtBind::main=0;
QFrame* NetHackQtBind::splash=0;
QStringList *NetHackQtBind::msgs_strings;
boolean NetHackQtBind::msgs_saved = false;
boolean NetHackQtBind::msgs_initd = false;
static void Qt_positionbar(char *) {}
@@ -683,7 +741,7 @@ struct window_procs Qt_procs = {
nethack_qt4::NetHackQtBind::qt_destroy_nhwindow,
nethack_qt4::NetHackQtBind::qt_curs,
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_start_menu,
nethack_qt4::NetHackQtBind::qt_add_menu,
@@ -728,7 +786,8 @@ struct window_procs Qt_procs = {
#endif
genl_preference_update,
genl_getmsghistory, genl_putmsghistory,
nethack_qt4::NetHackQtBind::qt_getmsghistory,
nethack_qt4::NetHackQtBind::qt_putmsghistory,
genl_status_init,
genl_status_finish, genl_status_enablefield,
#ifdef STATUS_HILITES
+7
View File
@@ -78,6 +78,9 @@ public:
static void qt_start_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 int qt_kbhit();
@@ -85,6 +88,10 @@ public:
private:
virtual bool notify(QObject *receiver, QEvent *event);
static QStringList *msgs_strings;
static boolean msgs_saved;
static boolean msgs_initd;
};
} // namespace nethack_qt4
-5
View File
@@ -73,13 +73,8 @@ void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
drawWorn(painter,uarms,0,1); // Shield
drawWorn(painter,uarmg,0,2); // Gloves - repeated
drawWorn(painter,uarmg,2,2); // Gloves - repeated
#ifdef TOURIST
drawWorn(painter,uarmf,1,5); // Shoes (feet)
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,uright,2,3); // RingR
+12 -3
View File
@@ -861,14 +861,22 @@ void NetHackQtMainWindow::doKeys(const QString& k)
void NetHackQtMainWindow::AddMessageWindow(NetHackQtMessageWindow* window)
{
message=window;
hsplitter->insertWidget(0, message->Widget());
if (!qt_compact_mode)
hsplitter->insertWidget(0, message->Widget());
ShowIfReady();
}
NetHackQtMessageWindow * NetHackQtMainWindow::GetMessageWindow()
{
return message;
}
void NetHackQtMainWindow::AddMapWindow(NetHackQtMapWindow2* window)
{
map=window;
vsplitter->insertWidget(1, map->Widget());
if (!qt_compact_mode)
vsplitter->insertWidget(1, map->Widget());
ShowIfReady();
connect(map,SIGNAL(resized()),this,SLOT(layout()));
}
@@ -876,7 +884,8 @@ void NetHackQtMainWindow::AddMapWindow(NetHackQtMapWindow2* window)
void NetHackQtMainWindow::AddStatusWindow(NetHackQtStatusWindow* window)
{
status=window;
hsplitter->insertWidget(2, status->Widget());
if (!qt_compact_mode)
hsplitter->insertWidget(2, status->Widget());
ShowIfReady();
}
+1
View File
@@ -41,6 +41,7 @@ public:
NetHackQtMainWindow(NetHackQtKeyBuffer&);
void AddMessageWindow(NetHackQtMessageWindow* window);
NetHackQtMessageWindow * GetMessageWindow();
void AddMapWindow(NetHackQtMapWindow2* window);
void AddStatusWindow(NetHackQtStatusWindow* window);
void RemoveWindow(NetHackQtWindow* window);
+32 -22
View File
@@ -71,6 +71,7 @@ NetHackQtMapViewport::NetHackQtMapViewport(NetHackQtClickBuffer& click_sink) :
change(10)
{
pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
pile_annotation = QPixmap(pile_mark_xpm);
Clear();
cursor.setX(0);
@@ -157,29 +158,33 @@ void NetHackQtMapViewport::paintEvent(QPaintEvent* event)
QString(QChar(ch)).left(1)
);
}
if (glyph_is_pet(g)
#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
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
}
}
}
}
painter.setFont(font());
} else {
for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) {
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);
if (glyph_is_pet(g)
#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
) {
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);
pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
pile_annotation = QPixmap(pile_mark_xpm);
cursor.setX(0);
cursor.setY(0);
@@ -835,13 +841,13 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
Qt::AlignCenter,
QString(QChar(ch)).left(1)
);
if (glyph_is_pet(g)
#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
) {
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 i=garea.left(); i<=garea.right(); i++) {
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);
if (glyph_is_pet(g)
#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
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
}
}
}
+1
View File
@@ -33,6 +33,7 @@ private:
unsigned short& Glyph(int x, int y) { return glyph[y][x]; }
QPoint cursor;
QPixmap pet_annotation;
QPixmap pile_annotation;
NetHackQtClickBuffer& clicksink;
Clusterizer change;
+21 -3
View File
@@ -132,6 +132,7 @@ NetHackQtMenuWindow::NetHackQtMenuWindow(QWidget *parent) :
grid->setRowStretch(2, 1);
setFocusPolicy(Qt::StrongFocus);
table->setFocusPolicy(Qt::NoFocus);
connect(table, SIGNAL(cellClicked(int,int)), this, SLOT(cellToggleSelect(int,int)));
setLayout(grid);
}
@@ -482,11 +483,11 @@ void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
accept();
else if (key==MENU_SEARCH)
Search();
else if (key==MENU_SELECT_ALL)
else if (key==MENU_SELECT_ALL || key==MENU_SELECT_PAGE)
All();
else if (key==MENU_INVERT_ALL)
else if (key==MENU_INVERT_ALL || key==MENU_INVERT_PAGE)
Invert();
else if (key==MENU_UNSELECT_ALL)
else if (key==MENU_UNSELECT_ALL || key==MENU_UNSELECT_PAGE)
ChooseNone();
else if (('0' <= key && key <= '9') || key == '\b')
InputCount(key);
@@ -501,6 +502,9 @@ void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
void NetHackQtMenuWindow::All()
{
if (how != PICK_ANY)
return;
for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText("");
@@ -511,6 +515,9 @@ void NetHackQtMenuWindow::All()
}
void NetHackQtMenuWindow::ChooseNone()
{
if (how != PICK_ANY)
return;
for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText("");
@@ -521,6 +528,9 @@ void NetHackQtMenuWindow::ChooseNone()
}
void NetHackQtMenuWindow::Invert()
{
if (how != PICK_ANY)
return;
for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText("");
@@ -531,6 +541,9 @@ void NetHackQtMenuWindow::Invert()
}
void NetHackQtMenuWindow::Search()
{
if (how == PICK_NONE)
return;
NetHackQtStringRequestor requestor(this, "Search for:");
char line[256];
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)
{
if (how == PICK_ONE) {
+1
View File
@@ -66,6 +66,7 @@ public slots:
void Search();
void ToggleSelect(int);
void cellToggleSelect(int, int);
void DoSelection(bool);
protected:
+21
View File
@@ -35,6 +35,7 @@ NetHackQtMessageWindow::NetHackQtMessageWindow() :
list->setFocusPolicy(Qt::NoFocus);
::iflags.window_inited = 1;
map = 0;
currgetmsg = 0;
connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(updateFont()));
updateFont();
}
@@ -72,6 +73,12 @@ void NetHackQtMessageWindow::Clear()
map->clearMessages();
}
void NetHackQtMessageWindow::ClearMessages()
{
if (list)
list->clear();
}
void NetHackQtMessageWindow::Display(bool block)
{
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)
{
#ifdef USER_SOUNDS
+3
View File
@@ -22,15 +22,18 @@ public:
virtual QWidget* Widget();
virtual void Clear();
virtual void Display(bool block);
virtual const char *GetStr(bool init);
virtual void PutStr(int attr, const QString& text);
void Scroll(int dx, int dy);
void ClearMessages();
void setMap(NetHackQtMapWindow2*);
private:
QListWidget* list;
bool changed;
int currgetmsg;
NetHackQtMapWindow2* map;
private slots:
+57 -23
View File
@@ -37,7 +37,7 @@ namespace nethack_qt4 {
void centerOnMain( QWidget* w );
// 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>";
class NhPSListViewItem : public QTableWidgetItem {
@@ -158,8 +158,9 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
| | | | +--------------+
3 | | | | ...stretch...
| | | |
4 | | | | [ Play ]
5 | | | | [ Quit ]
4 | | | | [ Random ]
5 | | | | [ Play ]
6 | | | | [ Quit ]
+---------+ +---------+
*/
@@ -177,37 +178,39 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
connect(name, SIGNAL(textChanged(const QString&)),
this, SLOT(selectName(const QString&)) );
name->setFocus();
QGroupBox* genderbox = new QGroupBox("Sex",this);
QGroupBox* genderbox = new QGroupBox("Gender",this);
QButtonGroup *gendergroup = new QButtonGroup(this);
QGroupBox* alignbox = new QGroupBox("Alignment",this);
QButtonGroup *aligngroup = new QButtonGroup(this);
QVBoxLayout* vbgb = new QVBoxLayout(genderbox);
vbgb->addSpacing(fontMetrics().height()*3/4);
QVBoxLayout* vbab = new QVBoxLayout(alignbox);
vbab->addSpacing(fontMetrics().height());
QLabel* logo = new QLabel(nh_attribution, this);
char versionbuf[QBUFSZ];
QLabel* logo = new QLabel(QString(nh_attribution).arg(version_string(versionbuf)), this);
l->addWidget( namebox, 0,0,1,3 );
#ifdef QT_CHOOSE_RACE_FIRST
race = new NhPSListView(this);
role = new NhPSListView(this);
l->addWidget( race, 1,0,5,1 );
l->addWidget( role, 1,1,5,1 );
l->addWidget( race, 1,0,6,1 );
l->addWidget( role, 1,1,6,1 );
#else
role = new NhPSListView(this);
race = new NhPSListView(this);
l->addWidget( role, 1,0,5,1 );
l->addWidget( race, 1,1,5,1 );
l->addWidget( role, 1,0,6,1 );
l->addWidget( race, 1,1,6,1 );
#endif
l->addWidget( genderbox, 1, 2 );
l->addWidget( alignbox, 2, 2 );
l->addWidget( logo, 3, 2, Qt::AlignCenter );
l->setRowStretch( 3, 5 );
l->setRowStretch( 3, 6 );
int i;
int nrole;
chosen_gend = flags.initgend;
chosen_align = flags.initalign;
// XXX QListView unsorted goes in rev.
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)) );
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);
l->addWidget( ok, 4, 2 );
l->addWidget( ok, 5, 2 );
ok->setDefault(true);
connect( ok, SIGNAL(clicked()), this, SLOT(accept()) );
QPushButton* cancel = new QPushButton("Quit",this);
l->addWidget( cancel, 5, 2 );
l->addWidget( cancel, 6, 2 );
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
int ro = flags.initrole;
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.
bool choose_race_first;
#ifdef QT_CHOOSE_RACE_FIRST
@@ -332,12 +366,8 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
role->setCurrentCell(ro, 0);
race->setCurrentCell(ra, 0);
flags.initrace = race->currentRow();
flags.initrole = role->currentRow();
}
void NetHackQtPlayerSelector::selectName(const QString& n)
{
str_copy(plname,n.toLatin1().constData(),SIZE(plname));
@@ -378,7 +408,7 @@ void NetHackQtPlayerSelector::selectRole(int crow, int ccol, int prow, int pcol)
}
#endif
flags.initrole = role->currentRow();
//flags.initrole = role->currentRow();
setupOthers();
}
@@ -416,7 +446,7 @@ void NetHackQtPlayerSelector::selectRace(int crow, int ccol, int prow, int pcol)
}
#endif
flags.initrace = race->currentRow();
//flags.initrace = race->currentRow();
setupOthers();
}
@@ -460,12 +490,12 @@ void NetHackQtPlayerSelector::setupOthers()
void NetHackQtPlayerSelector::selectGender(int i)
{
flags.initgend = i;
chosen_gend = i;
}
void NetHackQtPlayerSelector::selectAlignment(int i)
{
flags.initalign = i;
chosen_align = i;
}
void NetHackQtPlayerSelector::Quit()
@@ -493,6 +523,10 @@ bool NetHackQtPlayerSelector::Choose()
}
if ( exec() ) {
flags.initrace = race->currentRow();
flags.initrole = role->currentRow();
flags.initgend = chosen_gend;
flags.initalign = chosen_align;
return true;
} else {
return false;
+3
View File
@@ -21,6 +21,7 @@ public:
public slots:
void Quit();
void Random();
void Randomize();
void selectName(const QString& n);
void selectRole(int current, int, int previous, int);
@@ -38,6 +39,8 @@ private:
QRadioButton **gender;
QRadioButton **alignment;
bool fully_specified_role;
int chosen_gend;
int chosen_align;
};
} // namespace nethack_qt4
+45 -2
View File
@@ -4,7 +4,8 @@
#define NETHACK_CLR_FG grey
#define NETHACK_CLR_BG black
#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_BTN_SHAPE roundedRectangle
#define NETHACK_BTN_ROUND 20
@@ -119,12 +120,54 @@ NetHack*showGrip: False
! text input prompt window
NetHack*response*textSink*background: red
NetHack*textSink*background: red
NetHack*response*foreground: NETHACK_CLR_FG
NetHack*response*background: NETHACK_CLR_BG
NetHack*response*borderColor: NETHACK_CLR_FG
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.background: black
NetHack*player_selection*random.borderColor: NETHACK_CLR_RANDOM
+2 -2
View File
@@ -121,7 +121,7 @@ Region region; /* unused */
nhUse(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 */
@@ -129,7 +129,7 @@ static void
Resize(w)
Widget w;
{
XtCallCallbacks(w, XtNresizeCallback, (caddr_t) 0);
XtCallCallbacks(w, XtNresizeCallback, (XtPointer) 0);
}
WindowClassRec windowClassRec = {
+4 -4
View File
@@ -91,7 +91,7 @@ merge_text_colormap()
if (j == header.ncolors) { /* couldn't find it */
#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_BLUE][i]);
#endif
@@ -117,7 +117,7 @@ char *fname;
}
merge_text_colormap();
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;
fclose_text_file();
}
@@ -157,7 +157,7 @@ FILE *fp;
Fprintf(fp, "\",\n");
}
return fprintf(fp, "};\n") >= 0;
return Fprintf(fp, "};\n") >= 0;
}
#endif /* USE_XPM */
@@ -199,7 +199,7 @@ char **argv;
}
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 */
if ((header.ntiles % header.per_row) != 0) {
+128 -15
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 */
/* NetHack may be freely redistributed. See license for details. */
@@ -97,7 +97,11 @@ extern NEARDATA winid WIN_STATUS;
/* Interface definition, for windows.c */
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_suspend_nhwindows, X11_resume_nhwindows, X11_create_nhwindow,
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 void FDECL(nhFreePixel, (XtAppContext, XrmValuePtr, XtPointer,
XrmValuePtr, Cardinal *));
static boolean FDECL(new_resource_macro, (String, unsigned));
static void NDECL(load_default_resources);
static void NDECL(release_default_resources);
#ifdef X11_HANGUP_SIGNAL
@@ -480,7 +485,43 @@ Widget w;
#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
fallback resources to XtAppInitialize() */
@@ -489,8 +530,8 @@ load_default_resources()
{
FILE *fp;
String inbuf;
unsigned insiz, linelen, longlen, numlines;
boolean comment = FALSE; /* lint suppression */
unsigned insiz, linelen, longlen, numlines, numdefs, midx;
boolean comment, isdef;
/*
* 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
* 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");
if (!fp)
@@ -509,35 +554,84 @@ load_default_resources()
insiz = BUFSIZ; /* stdio BUFSIZ, not nethack BUFSZ */
inbuf = (String) alloc(insiz);
linelen = longlen = 0;
numlines = 0;
numlines = numdefs = 0;
comment = isdef = FALSE; /* lint suppression */
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');
isdef = !strncmp(inbuf, "#define", 7);
++numdefs;
}
linelen += strlen(inbuf);
if (!index(inbuf, '\n'))
continue;
if (linelen > longlen)
longlen = linelen;
linelen = 0;
if (!comment)
if (!comment && !isdef)
++numlines;
}
free((genericptr_t) inbuf);
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 */
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);
numlines = 0;
numlines = numdefs = 0;
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] = (String) 0;
(void) fclose(fp);
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
@@ -550,6 +644,7 @@ release_default_resources()
free((genericptr_t) default_resource_data[idx]);
free((genericptr_t) default_resource_data), default_resource_data = 0;
}
/* def_rsrc_macr[] and def_rsrc_valu[] have already been released */
}
/* Global Functions ======================================================= */
@@ -1031,6 +1126,9 @@ static XtActionsRec actions[] = {
{ nhStr("ec_key"), ec_key }, /* extended commands */
{ nhStr("ec_delete"), ec_delete }, /* ext-com menu delete */
{ 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("gend_key"), gend_key }, /* gender selection */
{ nhStr("algn_key"), algn_key }, /* alignment selection */
@@ -1176,6 +1274,7 @@ char **argv;
(void) seteuid(savuid);
x_inited = TRUE; /* X is now initialized */
plsel_ask_name = FALSE;
release_default_resources();
@@ -1374,6 +1473,20 @@ X11_askname()
{
Widget popup, dialog;
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);
@@ -1386,7 +1499,7 @@ X11_askname()
(XtCallbackProc) 0);
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);
positionpopup(popup, TRUE); /* center,bottom */
+943 -1
View File
@@ -18,9 +18,12 @@
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/List.h>
#include <X11/Xos.h> /* for index() */
#include <X11/Xatom.h>
@@ -52,6 +55,17 @@ static int ec_nchars = 0;
static char ec_chars[EC_NCHARS];
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\
<Key>Left: scroll(4)\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 **,
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 --------------------------------------------------------
*/
/* ARGSUSED */
@@ -298,10 +329,911 @@ Cardinal *num_params;
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 =========================================================
*/
void
X11_player_selection()
X11_player_selection_prompts()
{
int num_roles, num_races, num_gends, num_algns, i, availcount, availindex;
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
X11_get_ext_cmd()
{
+1 -1
View File
@@ -104,7 +104,7 @@ register_main_window_class()
wcex.hInstance = GetNHApp()->hApp;
wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR) IDI_NETHACKW);
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.lpszClassName = szMainWindowClass;
+2
View File
@@ -254,6 +254,8 @@ mswin_menu_window_select_menu(HWND hWnd, int how, MENU_ITEM_P **_selected,
&& how != PICK_NONE) {
data->menu.prompt[0] = '\0';
SetMenuListType(hWnd, PICK_NONE);
for (i = 0; i < data->menu.size; i++)
data->menu.items[i].count = 0;
LayoutMenu(hWnd);
}
}
+97 -23
View File
@@ -12,6 +12,52 @@
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 {
int index;
char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
@@ -20,6 +66,7 @@ typedef struct mswin_nethack_status_window {
boolean *activefields;
int *percents;
int *colors;
back_buffer_t back_buffer;
} NHStatusWindow, *PNHStatusWindow;
static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN,
@@ -45,6 +92,7 @@ mswin_init_status_window()
HWND ret;
NHStatusWindow *data;
RECT rt;
int width, height;
if (!run_once) {
register_status_window_class();
@@ -59,12 +107,14 @@ mswin_init_status_window()
}
/* create status window object */
width = rt.right - rt.left;
height = rt.bottom - rt.top;
ret = CreateWindow(szStatusWindowClass, NULL,
WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX,
rt.left, /* horizontal position of window */
rt.top, /* vertical position of window */
rt.right - rt.left, /* window width */
rt.bottom - rt.top, /* window height */
rt.left, /* horizontal position of window */
rt.top, /* vertical position of window */
width, /* window width */
height, /* window height */
GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL);
if (!ret)
panic("Cannot create status window");
@@ -80,8 +130,20 @@ mswin_init_status_window()
ZeroMemory(data, sizeof(NHStatusWindow));
SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
back_buffer_init(&data->back_buffer, ret, width, height);
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;
}
@@ -98,9 +160,7 @@ register_status_window_class()
wcex.hInstance = GetNHApp()->hApp;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = status_bg_brush
? status_bg_brush
: SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_STATUS);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szStatusWindowClass;
@@ -216,30 +276,35 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
int *f;
int **fop;
SIZE sz;
HGDIOBJ oldFont, normalFont, boldFont;
HGDIOBJ normalFont, boldFont;
TCHAR wbuf[BUFSZ];
COLORREF OldBg, OldFg, Bg, Fg;
RECT rt;
PAINTSTRUCT ps;
HDC hdc;
PNHStatusWindow data;
int width, height;
RECT clear_rect;
HDC front_buffer_hdc;
data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
hdc = BeginPaint(hWnd, &ps);
front_buffer_hdc = BeginPaint(hWnd, &ps);
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);
boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE);
oldFont = SelectObject(hdc, normalFont);
Bg = status_bg_brush ? status_bg_color
: (COLORREF) GetSysColor(DEFAULT_COLOR_BG_STATUS);
OldBg = SetBkColor(hdc, Bg);
SelectObject(hdc, normalFont);
Fg = status_fg_brush ? status_fg_color
: (COLORREF) GetSysColor(DEFAULT_COLOR_FG_STATUS);
OldFg = SetTextColor(hdc, Fg);
SetBkColor(hdc, status_bg_color);
SetTextColor(hdc, status_fg_color);
if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
&& data->activefields[BL_HP]) {
@@ -247,6 +312,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
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++) {
LONG left = rt.left;
LONG cy = 0;
@@ -275,8 +347,10 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
else if (atr & HL_DIM)
fntatr = ATR_DIM;
fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
nFg = (clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr) : Fg;
nBg = Bg;
nFg = (clr == NO_COLOR ? status_fg_color
: ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr)
: status_fg_color));
nBg = status_bg_color;
GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
@@ -286,7 +360,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
/* first draw title normally */
SelectObject(hdc, fnt);
SetBkMode(hdc, OPAQUE);
SetBkColor(hdc, Bg);
SetBkColor(hdc, status_bg_color);
SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
@@ -322,13 +396,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
rt.left += sz.cx;
cy = max(cy, sz.cy);
}
rt.left = left;
rt.top += cy;
}
SelectObject(hdc, oldFont);
SetTextColor(hdc, OldFg);
SetBkColor(hdc, OldBg);
BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
return 0;