diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 15d5b2d6d..4073cef20 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -236,6 +236,12 @@ to emphasize that it's not a light source, change description of wielded Sting from "(glowing)" to nothing (not warm enough to feel) when blind glowing Sting quivers if hero becomes blind and quivering Sting glows if blindness ends; it worked for timed blindness but not for blindfold +weapon (wielded pie, egg, potion, boomerang) might be destroyed when hitting a + long worm, then freed memory was accessed to decide whether to cut it +level change after being interruped locking or unlocking a container might + access freed memory +if a restore attempt failed and a new game was started instead, it would use + stale context from old game if restoration got far enough to load that Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository @@ -258,6 +264,8 @@ buliding with EXTRA_SANITY_CHECKS enabled would issue "no monster to remove" changing Sting's description to be "(weapon in hand) (light blue aura)" was too close to feedback when objects become blessed; change it again, to "(weapon in hand, flickering/glimmering/gleaming light blue)" +fix bit-use collision between WC2_TERM_SIZE and WC2_RESET_STATUS in + include/winprocs.h following a recent merge tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status @@ -275,6 +283,8 @@ Platform- and/or Interface-Specific Fixes or Features ----------------------------------------------------- move 'perm_invent' value from flags to iflags to keep it out of save files; affects X11, win32, and curses +always define shell and suspend commands so that key bindings copied from one + platform to another work even if second one disables those commands windows-gui: In nethackw, there could be conflicts between menu accelerators and an extra choice accelerator to fix H7132. windows-gui: recognize new BL_RESET in status_update; no change in behavior yet diff --git a/include/extern.h b/include/extern.h index dd703e101..5d0ddd2ff 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1543745352 2018/12/02 10:09:12 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.664 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1543892214 2018/12/04 02:56:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.665 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2837,7 +2837,7 @@ E void FDECL(worm_move, (struct monst *)); E void FDECL(worm_nomove, (struct monst *)); E void FDECL(wormgone, (struct monst *)); E void FDECL(wormhitu, (struct monst *)); -E void FDECL(cutworm, (struct monst *, XCHAR_P, XCHAR_P, struct obj *)); +E void FDECL(cutworm, (struct monst *, XCHAR_P, XCHAR_P, BOOLEAN_P)); E void FDECL(see_wsegs, (struct monst *)); E void FDECL(detect_wsegs, (struct monst *, BOOLEAN_P)); E void FDECL(save_worm, (int, int)); diff --git a/include/flag.h b/include/flag.h index 956de39f0..0623ec526 100644 --- a/include/flag.h +++ b/include/flag.h @@ -369,8 +369,6 @@ struct instance_flags { boolean wizweight; /* display weight of everything in wizard mode */ boolean cmdassist; /* provide detailed assistance for some commands */ boolean clicklook; /* allow right-clicking for look */ - boolean msg_is_alert; /* suggest windowport should grab player's attention - * and request acknowlegement */ int statuslines; /* default = 2, code support for alternative 3 */ /* * Window capability support. diff --git a/include/func_tab.h b/include/func_tab.h index 14460c926..79daef1de 100644 --- a/include/func_tab.h +++ b/include/func_tab.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 func_tab.h $NHDT-Date: 1432512775 2015/05/25 00:12:55 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */ +/* NetHack 3.6 func_tab.h $NHDT-Date: 1543797823 2018/12/03 00:43:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.11 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2016. */ /* NetHack may be freely redistributed. See license for details. */ @@ -11,6 +11,7 @@ #define AUTOCOMPLETE 0x02 /* command autocompletes */ #define WIZMODECMD 0x04 /* wizard-mode command */ #define GENERALCMD 0x08 /* general command, does not take game time */ +#define CMD_NOT_AVAILABLE 0x10 /* recognized but non-functional (!SHELL,&c) */ struct ext_func_tab { uchar key; diff --git a/include/winprocs.h b/include/winprocs.h index 316af5171..ddfef409d 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -216,10 +216,10 @@ extern after updating status window fields */ #define WC2_RESET_STATUS 0x0100L /* 09 call status_update(BL_RESET) to indicate draw everything */ -#define WC2_TERM_SIZE 0x0100L /* 10 support setting terminal size */ -#define WC2_WINDOWBORDERS 0x0200L /* 11 display borders on nh windows */ -#define WC2_PETATTR 0x0400L /* 12 attributes for hilite_pet */ -#define WC2_GUICOLOR 0x0800L /* 13 display colours outside map win */ +#define WC2_TERM_SIZE 0x0200L /* 10 support setting terminal size */ +#define WC2_WINDOWBORDERS 0x0400L /* 11 display borders on nh windows */ +#define WC2_PETATTR 0x0800L /* 12 attributes for hilite_pet */ +#define WC2_GUICOLOR 0x1000L /* 13 display colours outside map win */ /* 19 free bits */ #define ALIGN_LEFT 1 diff --git a/src/cmd.c b/src/cmd.c index 20327366c..8924923da 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1543711385 2018/12/02 00:43:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.309 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1543972186 2018/12/05 01:09:46 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.313 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -126,10 +126,10 @@ extern int NDECL(dozap); /**/ extern int NDECL(doorganize); /**/ #endif /* DUMB */ -static int NDECL(dosuspend_core); /**/ - static int NDECL((*timed_occ_fn)); +STATIC_PTR int NDECL(dosuspend_core); +STATIC_PTR int NDECL(dosh_core); STATIC_PTR int NDECL(doherecmdmenu); STATIC_PTR int NDECL(dotherecmdmenu); STATIC_PTR int NDECL(doprev_message); @@ -194,9 +194,6 @@ STATIC_DCL void FDECL(one_characteristic, (int, int, int)); STATIC_DCL void FDECL(status_enlightenment, (int, int)); 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)); @@ -205,6 +202,13 @@ 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 *)); +static const char *readchar_queue = ""; +static coord clicklook_cc; +/* for rejecting attempts to use wizard mode commands */ +static const char unavailcmd[] = "Unavailable command '%s'."; +/* for rejecting #if !SHELL, !SUSPEND */ +static const char cmdnotavail[] = "'%s' command not available."; + STATIC_PTR int doprev_message(VOID_ARGS) { @@ -438,6 +442,8 @@ doextlist(VOID_ARGS) for (efp = extcmdlist; efp->ef_txt; efp++) { int wizc; + if ((efp->flags & CMD_NOT_AVAILABLE) != 0) + continue; /* if hiding non-autocomplete commands, skip such */ if (menumode == 1 && (efp->flags & AUTOCOMPLETE) == 0) continue; @@ -567,7 +573,8 @@ extcmd_via_menu() any = zeroany; /* populate choices */ for (efp = extcmdlist; efp->ef_txt; efp++) { - if (!(efp->flags & AUTOCOMPLETE) + if ((efp->flags & CMD_NOT_AVAILABLE) + || !(efp->flags & AUTOCOMPLETE) || (!wizard && (efp->flags & WIZMODECMD))) continue; if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) { @@ -763,8 +770,7 @@ wiz_wish(VOID_ARGS) /* Unlimited wishes for debug mode by Paul Polderman */ flags.verbose = save_verbose; (void) encumber_msg(); } else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_wish))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_wish))); return 0; } @@ -784,8 +790,7 @@ wiz_identify(VOID_ARGS) (void) display_inventory((char *) 0, FALSE); iflags.override_ID = 0; } else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_identify))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_identify))); return 0; } @@ -840,8 +845,7 @@ wiz_map(VOID_ARGS) HConfusion = save_Hconf; HHallucination = save_Hhallu; } else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_map))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_map))); return 0; } @@ -852,8 +856,7 @@ wiz_genesis(VOID_ARGS) if (wizard) (void) create_particular(); else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_genesis))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_genesis))); return 0; } @@ -864,8 +867,7 @@ wiz_where(VOID_ARGS) if (wizard) (void) print_dungeon(FALSE, (schar *) 0, (xchar *) 0); else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_where))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_where))); return 0; } @@ -876,8 +878,7 @@ wiz_detect(VOID_ARGS) if (wizard) (void) findit(); else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_detect))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_detect))); return 0; } @@ -888,8 +889,7 @@ wiz_level_tele(VOID_ARGS) if (wizard) level_tele(); else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_level_tele))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_level_tele))); return 0; } @@ -1444,8 +1444,7 @@ wiz_intrinsic(VOID_ARGS) free((genericptr_t) pick_list); doredraw(); } else - pline("Unavailable command '%s'.", - visctrl((int) cmd_from_func(wiz_intrinsic))); + pline(unavailcmd, visctrl((int) cmd_from_func(wiz_intrinsic))); return 0; } @@ -3304,16 +3303,21 @@ struct ext_func_tab extcmdlist[] = { { '^', "seetrap", "show the type of adjacent trap", doidtrap, IFBURIED }, { WEAPON_SYM, "seeweapon", "show the weapon currently wielded", doprwep, IFBURIED }, -#ifdef SHELL - { '!', "shell", "do a shell escape", dosh, IFBURIED | GENERALCMD }, + { '!', "shell", "do a shell escape", + dosh_core, IFBURIED | GENERALCMD +#ifndef SHELL + | CMD_NOT_AVAILABLE #endif /* SHELL */ + }, { M('s'), "sit", "sit down", dosit, AUTOCOMPLETE }, { '\0', "stats", "show memory statistics", wiz_show_stats, IFBURIED | AUTOCOMPLETE | WIZMODECMD }, -#ifdef SUSPEND { C('z'), "suspend", "suspend the game", - dosuspend_core, IFBURIED | GENERALCMD }, + dosuspend_core, IFBURIED | GENERALCMD +#ifndef SUSPEND + | CMD_NOT_AVAILABLE #endif /* SUSPEND */ + }, { 'x', "swap", "swap wielded and secondary weapons", doswapweapon }, { 'T', "takeoff", "take off one piece of armor", dotakeoff }, { 'A', "takeoffall", "remove all armor", doddoremarm }, @@ -3407,6 +3411,14 @@ const char *command; if (strcmp(command, extcmd->ef_txt)) continue; Cmd.commands[key] = extcmd; +#if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */ + if ((extcmd->flags & CMD_NOT_AVAILABLE) != 0) { + char buf[BUFSZ]; + + Sprintf(buf, cmdnotavail, extcmd->ef_txt); + config_error_add("%s", buf); + } +#endif return TRUE; } @@ -5504,10 +5516,7 @@ parse() if (iflags.debug_fuzzer /* if fuzzing, override '!' and ^Z */ && (Cmd.commands[foo & 0x0ff] && (Cmd.commands[foo & 0x0ff]->ef_funct == dosuspend_core -#ifdef SHELL - || Cmd.commands[foo & 0x0ff]->ef_funct == dosh -#endif - ))) + || Cmd.commands[foo & 0x0ff]->ef_funct == dosh_core))) foo = Cmd.spkeys[NHKF_ESC]; if (foo == Cmd.spkeys[NHKF_ESC]) { /* esc cancels count (TH) */ @@ -5666,19 +5675,26 @@ readchar() return (char) sym; } +/* '_' command, #travel, via keyboard rather than mouse click */ STATIC_PTR int dotravel(VOID_ARGS) { - /* Keyboard travel command */ static char cmd[2]; coord cc; + /* [FIXME? Supporting the ability to disable traveling via mouse + click makes some sense, depending upon overall mouse usage. + Disabling '_' on a user by user basis makes no sense at all since + even if it is typed by accident, aborting when picking a target + destination is trivial. Travel via mouse predates travel via '_', + and this use of OPTION=!travel is probably just a mistake....] */ if (!flags.travelcmd) return 0; + cmd[1] = 0; cc.x = iflags.travelcc.x; cc.y = iflags.travelcc.y; - if (cc.x == -1 && cc.y == -1) { + if (cc.x == 0 && cc.y == 0) { /* No cached destination, start attempt from current position */ cc.x = u.ux; cc.y = u.uy; @@ -5789,8 +5805,9 @@ const char *prompt; return confirmed_ok; } -int -dosuspend_core() +/* ^Z command, #suspend */ +STATIC_PTR int +dosuspend_core(VOID_ARGS) { #ifdef SUSPEND /* Does current window system support suspend? */ @@ -5799,7 +5816,20 @@ dosuspend_core() dosuspend(); } else #endif - Norep("Suspend command not available."); + Norep(cmdnotavail, "#suspend"); + return 0; +} + +/* '!' command, #shell */ +STATIC_PTR int +dosh_core(VOID_ARGS) +{ +#ifdef SHELL + /* access restrictions, if any, are handled in port code */ + dosh(); +#else + Norep(cmdnotavail, "#shell"); +#endif return 0; } diff --git a/src/do.c b/src/do.c index 2d7150555..2dbe2b5cb 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1543052696 2018/11/24 09:44:56 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.175 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1543972190 2018/12/05 01:09:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.176 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1244,6 +1244,17 @@ boolean at_stairs, falling, portal; if(dropleveltempsfn) (*dropleveltempsfn)(); #endif + /* discard context which applies to the level we're leaving; + for lock-picking, container may be carried, in which case we + keep context; if on the floor, it's about to be saved+freed and + maybe_reset_pick() needs to do its carried() check before that */ + maybe_reset_pick(); + reset_trapset(); /* even if to-be-armed trap obj is accompanying hero */ + iflags.travelcc.x = iflags.travelcc.y = 0; /* travel destination cache */ + context.polearm.hitmon = (struct monst *) 0; /* polearm target */ + /* digging context is level-aware and can actually be resumed if + hero returns to the previous level without any intervening dig */ + if (falling) /* assuming this is only trap door or hole */ impact_drop((struct obj *) 0, u.ux, u.uy, newlevel->dlevel); @@ -1600,14 +1611,6 @@ boolean at_stairs, falling, portal; /* assume this will always return TRUE when changing level */ (void) in_out_region(u.ux, u.uy); (void) pickup(1); - - /* discard context which applied to previous level */ - maybe_reset_pick(); /* for door or for box not accompanying hero */ - reset_trapset(); /* even if to-be-armed trap obj is accompanying hero */ - iflags.travelcc.x = iflags.travelcc.y = -1; /* travel destination cache */ - context.polearm.hitmon = (struct monst *) 0; /* polearm target */ - /* digging context is level-aware and can actually be resumed if - hero returns to the previous level without any intervening dig */ } STATIC_OVL void diff --git a/src/dothrow.c b/src/dothrow.c index d40857447..e55c9b7d6 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1525012611 2018/04/29 14:36:51 $ $NHDT-Branch: master $:$NHDT-Revision: 1.137 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1543892215 2018/12/04 02:56:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.152 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1652,13 +1652,16 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */ } if (tmp >= dieroll) { - boolean wasthrown = (thrownobj != 0); + boolean wasthrown = (thrownobj != 0), + /* remember weapon attribute; hmon() might destroy obj */ + chopper = is_axe(obj); /* attack hits mon */ if (hmode == HMON_APPLIED) u.uconduct.weaphit++; if (hmon(mon, obj, hmode, dieroll)) { /* mon still alive */ - cutworm(mon, bhitpos.x, bhitpos.y, obj); + if (mon->wormno) + cutworm(mon, bhitpos.x, bhitpos.y, chopper); } exercise(A_DEX, TRUE); /* if hero was swallowed and projectile killed the engulfer, @@ -1668,8 +1671,9 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */ if (wasthrown && !thrownobj) return 1; - /* projectiles other than magic stones - sometimes disappear when thrown */ + /* projectiles other than magic stones sometimes disappear + when thrown; projectiles aren't among the types of weapon + that hmon() might have destroyed so obj is intact */ if (objects[otyp].oc_skill < P_NONE && objects[otyp].oc_skill > -P_BOOMERANG && !objects[otyp].oc_magic) { diff --git a/src/hack.c b/src/hack.c index 7a5e48116..c0c0313f2 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1540591769 2018/10/26 22:09:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.194 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1543972190 2018/12/05 01:09:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.200 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -923,7 +923,7 @@ int mode; u.dx = u.tx - u.ux; u.dy = u.ty - u.uy; nomul(0); - iflags.travelcc.x = iflags.travelcc.y = -1; + iflags.travelcc.x = iflags.travelcc.y = 0; } return TRUE; } @@ -1045,7 +1045,7 @@ int mode; nomul(0); /* reset run so domove run checks work */ context.run = 8; - iflags.travelcc.x = iflags.travelcc.y = -1; + iflags.travelcc.x = iflags.travelcc.y = 0; } return TRUE; } diff --git a/src/options.c b/src/options.c index 8be8cfcd3..d4b7daf4d 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1543395749 2018/11/28 09:02:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.334 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1543972192 2018/12/05 01:09:52 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.335 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -747,8 +747,6 @@ initoptions_init() warnsyms[i] = def_warnsyms[i].sym; iflags.bouldersym = 0; - iflags.travelcc.x = iflags.travelcc.y = -1; - /* for "special achievement" tracking (see obj.h, create_object(sp_lev.c), addinv_core1(invent.c) */ iflags.mines_prize_type = LUCKSTONE; diff --git a/src/restore.c b/src/restore.c index 25604f10d..e9f25d72c 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 restore.c $NHDT-Date: 1542798626 2018/11/21 11:10:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.109 $ */ +/* NetHack 3.6 restore.c $NHDT-Date: 1543972193 2018/12/05 01:09:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.128 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -539,6 +539,7 @@ unsigned int *stuckid, *steedid; #ifdef SYSFLAGS struct sysflag newgamesysflags; #endif + struct context_info newgamecontext; /* all 0, but has some pointers */ struct obj *otmp, *tmp_bc; char timebuf[15]; unsigned long uid; @@ -553,9 +554,15 @@ unsigned int *stuckid, *steedid; if (!wizard) return FALSE; } + + newgamecontext = context; /* copy statically init'd context */ mread(fd, (genericptr_t) &context, sizeof (struct context_info)); - if (context.warntype.speciesidx >= LOW_PM) - context.warntype.species = &mons[context.warntype.speciesidx]; + context.warntype.species = (context.warntype.speciesidx >= LOW_PM) + ? &mons[context.warntype.speciesidx] + : (struct permonst *) 0; + /* context.victual.piece, .tin.tin, .spellbook.book, and .polearm.hitmon + are pointers which get set to Null during save and will be recovered + via corresponding o_id or m_id while objs or mons are being restored */ /* we want to be able to revert to command line/environment/config file option values instead of keeping old save file option values @@ -625,6 +632,7 @@ unsigned int *stuckid, *steedid; #ifdef SYSFLAGS sysflags = newgamesysflags; #endif + context = newgamecontext; return FALSE; } /* in case hangup save occurred in midst of level change */ diff --git a/src/save.c b/src/save.c index 095890f05..18465966d 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 save.c $NHDT-Date: 1489192905 2017/03/11 00:41:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.101 $ */ +/* NetHack 3.6 save.c $NHDT-Date: 1543972194 2018/12/05 01:09:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.115 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1035,37 +1035,22 @@ register struct obj *otmp; if (Has_contents(otmp)) saveobjchn(fd, otmp->cobj, mode); if (release_data(mode)) { - /* if (otmp->oclass == FOOD_CLASS) - * food_disappears(otmp); - */ /* - * If these are on the floor, the discarding could - * be because of a game save, or we could just be changing levels. + * If these are on the floor, the discarding could be + * due to game save, or we could just be changing levels. * Always invalidate the pointer, but ensure that we have * the o_id in order to restore the pointer on reload. */ if (otmp == context.victual.piece) { - /* Store the o_id of the victual if mismatched */ - if (context.victual.o_id != otmp->o_id) - context.victual.o_id = otmp->o_id; - /* invalidate the pointer; on reload it will get restored */ + context.victual.o_id = otmp->o_id; context.victual.piece = (struct obj *) 0; } if (otmp == context.tin.tin) { - /* Store the o_id of your tin */ - if (context.tin.o_id != otmp->o_id) - context.tin.o_id = otmp->o_id; - /* invalidate the pointer; on reload it will get restored */ + context.tin.o_id = otmp->o_id; context.tin.tin = (struct obj *) 0; } - /* if (otmp->oclass == SPBOOK_CLASS) - * book_disappears(otmp); - */ if (otmp == context.spbook.book) { - /* Store the o_id of your spellbook */ - if (context.spbook.o_id != otmp->o_id) - context.spbook.o_id = otmp->o_id; - /* invalidate the pointer; on reload it will get restored */ + context.spbook.o_id = otmp->o_id; context.spbook.book = (struct obj *) 0; } otmp->where = OBJ_FREE; /* set to free so dealloc will work */ diff --git a/src/uhitm.c b/src/uhitm.c index a14218543..0412bb599 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 uhitm.c $NHDT-Date: 1542765366 2018/11/21 01:56:06 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.185 $ */ +/* NetHack 3.6 uhitm.c $NHDT-Date: 1543892215 2018/12/04 02:56:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.195 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -449,7 +449,9 @@ int rollneeded, armorpenalty; /* for monks */ struct attack *uattk; int dieroll; { - register boolean malive = TRUE; + boolean malive = TRUE, + /* hmon() might destroy weapon; remember aspect for cutworm */ + slice_or_chop = (weapon && (is_blade(weapon) || is_axe(weapon))); if (override_confirmation) { /* this may need to be generalized if weapons other than @@ -490,7 +492,7 @@ int dieroll; u.uconduct.weaphit = oldweaphit; } if (mon->wormno && *mhit) - cutworm(mon, x, y, weapon); + cutworm(mon, x, y, slice_or_chop); } } return malive; diff --git a/src/worm.c b/src/worm.c index 4e9d144b1..faf257710 100644 --- a/src/worm.c +++ b/src/worm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 worm.c $NHDT-Date: 1456528599 2016/02/26 23:16:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */ +/* NetHack 3.6 worm.c $NHDT-Date: 1543892216 2018/12/04 02:56:56 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.28 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -314,10 +314,10 @@ register struct monst *worm; * that both halves will survive. */ void -cutworm(worm, x, y, weap) +cutworm(worm, x, y, cuttier) struct monst *worm; xchar x, y; -struct obj *weap; +boolean cuttier; /* hit is by wielded blade or axe or by thrown axe */ { register struct wseg *curr, *new_tail; register struct monst *new_worm; @@ -330,12 +330,10 @@ struct obj *weap; if (x == worm->mx && y == worm->my) return; /* hit on head */ - /* cutting goes best with a bladed weapon */ - cut_chance = rnd(20); /* Normally 1-16 does not cut */ - /* Normally 17-20 does */ - - if (weap && is_blade(weap)) /* With a blade 1- 6 does not cut */ - cut_chance += 10; /* 7-20 does */ + /* cutting goes best with a cuttier weapon */ + cut_chance = rnd(20); /* Normally 1-16 does not cut, 17-20 does, */ + if (cuttier) + cut_chance += 10; /* with a blade 1- 6 does not cut, 7-20 does. */ if (cut_chance < 17) return; /* not good enough */ diff --git a/sys/winnt/win10.c b/sys/winnt/win10.c index 3ec62a943..48f5bb98a 100644 --- a/sys/winnt/win10.c +++ b/sys/winnt/win10.c @@ -45,17 +45,6 @@ void win10_init() } -void win10_monitor_size(HWND hWnd, int * width, int * height) -{ - HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); - MONITORINFO info; - info.cbSize = sizeof(MONITORINFO); - BOOL success = GetMonitorInfo(monitor, &info); - nhassert(success); - *width = info.rcMonitor.right - info.rcMonitor.left; - *height = info.rcMonitor.bottom - info.rcMonitor.top; -} - int win10_monitor_dpi(HWND hWnd) { UINT monitorDpi = 96; @@ -79,5 +68,14 @@ double win10_monitor_scale(HWND hWnd) void win10_monitor_info(HWND hWnd, MonitorInfo * monitorInfo) { monitorInfo->scale = win10_monitor_scale(hWnd); - win10_monitor_size(hWnd, &monitorInfo->width, &monitorInfo->height); + + HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + BOOL success = GetMonitorInfo(monitor, &info); + nhassert(success); + monitorInfo->width = info.rcMonitor.right - info.rcMonitor.left; + monitorInfo->height = info.rcMonitor.bottom - info.rcMonitor.top; + monitorInfo->left = info.rcMonitor.left; + monitorInfo->top = info.rcMonitor.top; } diff --git a/sys/winnt/win10.h b/sys/winnt/win10.h index 1bf4fce33..458e6991d 100644 --- a/sys/winnt/win10.h +++ b/sys/winnt/win10.h @@ -23,6 +23,8 @@ typedef struct { double scale; // dpi of monitor / 96 int width; // in pixels int height; // in pixels + int top; // in desktop coordinate pixel space + int left; // in desktop coordinate pixel space } MonitorInfo; extern Win10 gWin10; diff --git a/win/X11/winmisc.c b/win/X11/winmisc.c index 567f2ba84..59883cdaf 100644 --- a/win/X11/winmisc.c +++ b/win/X11/winmisc.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 winmisc.c $NHDT-Date: 1539892610 2018/10/18 19:56:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.39 $ */ +/* NetHack 3.6 winmisc.c $NHDT-Date: 1543830350 2018/12/03 09:45:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.42 $ */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -1890,6 +1890,8 @@ Cardinal *num_params; ec_nchars = 1; } for (i = 0; extcmdlist[i].ef_txt; i++) { + if (extcmdlist[i].flags & CMD_NOT_AVAILABLE) + continue; if (extcmdlist[i].ef_txt[0] == '?') continue; @@ -1926,22 +1928,27 @@ Cardinal *num_params; static void init_extended_commands_popup() { - int i, num_commands; + int i, j, num_commands, ignore_cmds = 0; const char **command_list; /* count commands */ for (num_commands = 0; extcmdlist[num_commands].ef_txt; num_commands++) - ; /* do nothing */ + if (extcmdlist[num_commands].flags & CMD_NOT_AVAILABLE) + ++ignore_cmds; /* If the last entry is "help", don't use it. */ if (strcmp(extcmdlist[num_commands - 1].ef_txt, "?") == 0) --num_commands; - command_list = - (const char **) alloc((unsigned) num_commands * sizeof(char *)); + j = num_commands - ignore_cmds; + command_list = (const char **) alloc((unsigned) j * sizeof (char *)); - for (i = 0; i < num_commands; i++) - command_list[i] = extcmdlist[i].ef_txt; + for (i = j = 0; i < num_commands; i++) { + if (extcmdlist[i].flags & CMD_NOT_AVAILABLE) + continue; + command_list[j++] = extcmdlist[i].ef_txt; + } + num_commands = j; extended_command_popup = make_menu("extended_commands", "Extended Commands", diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index 7393610bd..99e5eb830 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -419,6 +419,8 @@ curses_ext_cmd() ret = -1; } for (count = 0; extcmdlist[count].ef_txt; count++) { + if (!wizard && (extcmdlist[count].flags & WIZMODECMD)) + continue; if (!(extcmdlist[count].flags & AUTOCOMPLETE)) continue; if (strlen(extcmdlist[count].ef_txt) > (size_t) prompt_width) { @@ -508,6 +510,12 @@ curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier, nhmenu_item *new_item, *current_items, *menu_item_ptr; nhmenu *current_menu = get_menu(wid); + if (current_menu == NULL) { + impossible + ("curses_add_nhmenu_item: attempt to add item to nonexistent menu"); + return; + } + if (str == NULL) { return; } @@ -530,11 +538,6 @@ curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier, new_item->count = -1; new_item->next_item = NULL; - if (current_menu == NULL) { - panic - ("curses_add_nhmenu_item: attempt to add item to nonexistant menu"); - } - current_items = current_menu->entries; menu_item_ptr = current_items; @@ -559,12 +562,13 @@ curses_finalize_nhmenu(winid wid, const char *prompt) { int count = 0; nhmenu *current_menu = get_menu(wid); - nhmenu_item *menu_item_ptr = current_menu->entries; if (current_menu == NULL) { - panic("curses_finalize_nhmenu: attempt to finalize nonexistant menu"); + impossible("curses_finalize_nhmenu: attempt to finalize nonexistent menu"); + return; } + nhmenu_item *menu_item_ptr = current_menu->entries; while (menu_item_ptr != NULL) { menu_item_ptr = menu_item_ptr->next_item; count++; @@ -590,13 +594,15 @@ curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected) *_selected = NULL; if (current_menu == NULL) { - panic("curses_display_nhmenu: attempt to display nonexistant menu"); + impossible("curses_display_nhmenu: attempt to display nonexistent menu"); + return '\033'; } menu_item_ptr = current_menu->entries; if (menu_item_ptr == NULL) { - panic("curses_display_nhmenu: attempt to display empty menu"); + impossible("curses_display_nhmenu: attempt to display empty menu"); + return '\033'; } /* Reset items to unselected to clear out selections from previous @@ -631,8 +637,9 @@ curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected) while (menu_item_ptr != NULL) { if (menu_item_ptr->selected) { if (count == num_chosen) { - panic("curses_display_nhmenu: Selected items " + impossible("curses_display_nhmenu: Selected items " "exceeds expected number"); + break; } selected[count].item = menu_item_ptr->identifier; selected[count].count = menu_item_ptr->count; @@ -642,7 +649,7 @@ curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected) } if (count != num_chosen) { - panic("curses_display_nhmenu: Selected items less than " + impossible("curses_display_nhmenu: Selected items less than " "expected number"); } } @@ -949,7 +956,8 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num) } if (menu_item_ptr == NULL) { /* Page not found */ - panic("menu_display_page: attempt to display nonexistant page"); + impossible("menu_display_page: attempt to display nonexistent page"); + return; } werase(win); @@ -1343,7 +1351,8 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op } if (menu_item_ptr == NULL) { /* Page not found */ - panic("menu_display_page: attempt to display nonexistant page"); + impossible("menu_display_page: attempt to display nonexistent page"); + return 0; } while (menu_item_ptr != NULL) { diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index df45d07b8..ef351a27a 100644 --- a/win/curses/cursmesg.c +++ b/win/curses/cursmesg.c @@ -148,18 +148,13 @@ curses_block(boolean noscroll) curses_get_window_size(MESSAGE_WIN, &height, &width); curses_toggle_color_attr(win, MORECOLOR, NONE, ON); - mvwprintw(win, my, mx, iflags.msg_is_alert ? "" : ">>"); + mvwprintw(win, my, mx, ">>"); curses_toggle_color_attr(win, MORECOLOR, NONE, OFF); - if (iflags.msg_is_alert) - curses_alert_main_borders(TRUE); wrefresh(win); - while (iflags.msg_is_alert && (ret = wgetch(win) != '\t')); /* msgtype=stop should require space/enter rather than * just any key, as we want to prevent YASD from * riding direction keys. */ - while (!iflags.msg_is_alert && (ret = wgetch(win)) && !index(resp,(char)ret)); - if (iflags.msg_is_alert) - curses_alert_main_borders(FALSE); + while ((ret = wgetch(win)) && !index(resp,(char)ret)); if (height == 1) { curses_clear_unhighlight_message_window(); } else { @@ -298,8 +293,8 @@ curses_prev_mesg() } -/* Shows Count: in a separate window, or at the bottom of the message -window, depending on the user's settings */ +/* Shows Count: at the bottom of the message window, + popup_dialog is not currently implemented for this function */ void curses_count_window(const char *count_text) @@ -317,43 +312,31 @@ curses_count_window(const char *count_text) counting = TRUE; - if (iflags.wc_popup_dialog) { /* Display count in popup window */ - startx = 1; - starty = 1; + curses_get_window_xy(MESSAGE_WIN, &winx, &winy); + curses_get_window_size(MESSAGE_WIN, &messageh, &messagew); - if (countwin == NULL) { - countwin = curses_create_window(25, 1, UP); - } - - } else { /* Display count at bottom of message window */ - - curses_get_window_xy(MESSAGE_WIN, &winx, &winy); - curses_get_window_size(MESSAGE_WIN, &messageh, &messagew); - - if (curses_window_has_border(MESSAGE_WIN)) { - winx++; - winy++; - } - - winy += messageh - 1; - - if (countwin == NULL) { - pline("#"); -#ifndef PDCURSES - countwin = newwin(1, 25, winy, winx); -#endif /* !PDCURSES */ - } -#ifdef PDCURSES - else { - curses_destroy_win(countwin); - } - - countwin = newwin(1, 25, winy, winx); -#endif /* PDCURSES */ - startx = 0; - starty = 0; + if (curses_window_has_border(MESSAGE_WIN)) { + winx++; + winy++; } + winy += messageh - 1; + + if (countwin == NULL) { +#ifndef PDCURSES + countwin = newwin(1, 25, winy, winx); +#endif /* !PDCURSES */ + } +#ifdef PDCURSES + else { + curses_destroy_win(countwin); + } + + countwin = newwin(1, 25, winy, winx); +#endif /* PDCURSES */ + startx = 0; + starty = 0; + mvwprintw(countwin, starty, startx, "%s", count_text); wrefresh(countwin); } diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index 00e055c10..8ee1f68fe 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -92,9 +92,9 @@ curses_toggle_color_attr(WINDOW * win, int color, int attr, int onoff) } /* GUI color disabled */ - /* if ((!iflags.wc2_guicolor) && (win != mapwin)) { - return; - } */ + if ((!iflags.wc2_guicolor) && (win != mapwin)) { + return; + } if (color == 0) { /* make black fg visible */ # ifdef USE_DARKGRAY @@ -102,7 +102,6 @@ curses_toggle_color_attr(WINDOW * win, int color, int attr, int onoff) if (can_change_color() && (COLORS > 16)) { /* colorpair for black is already darkgray */ } else { /* Use bold for a bright black */ - wattron(win, A_BOLD); } } else @@ -188,8 +187,8 @@ curses_get_wid(int type) ret = text_wid; break; default: - panic("curses_get_wid: unsupported window type"); - ret = -1; /* Not reached */ + impossible("curses_get_wid: unsupported window type"); + ret = -1; } while (curses_window_exists(ret)) { diff --git a/win/curses/curswins.c b/win/curses/curswins.c index 4eaafa207..017450830 100644 --- a/win/curses/curswins.c +++ b/win/curses/curswins.c @@ -78,9 +78,15 @@ curses_create_window(int width, int height, orient orientation) width += 2; /* leave room for bounding box */ height += 2; - if ((width > term_cols) || (height > term_rows)) - panic("curses_create_window: Terminal too small for dialog window"); + if ((width > term_cols) || (height > term_rows)) { + impossible("curses_create_window: Terminal too small for dialog window"); + width = term_cols; + height = term_rows; + } switch (orientation) { + default: + impossible("curses_create_window: Bad orientation"); + /* fall through to centre */ case CENTER: startx = (term_cols / 2) - (width / 2); starty = (term_rows / 2) - (height / 2); @@ -119,9 +125,6 @@ curses_create_window(int width, int height, orient orientation) starty = 0; break; - default: - panic("curses_create_window: Bad orientation"); - break; } if (startx < 0) { @@ -190,7 +193,8 @@ WINDOW * curses_get_nhwin(winid wid) { if (!is_main_window(wid)) { - panic("curses_get_nhwin: wid out of range. Not a main window."); + impossible("curses_get_nhwin: wid %d out of range. Not a main window.", wid); + return NULL; } return nhwins[wid].curwin; @@ -208,7 +212,8 @@ curses_add_nhwin(winid wid, int height, int width, int y, int x, int real_height = height; if (!is_main_window(wid)) { - panic("curses_add_nhwin: wid out of range. Not a main window."); + impossible("curses_add_nhwin: wid %d out of range. Not a main window.", wid); + return; } nhwins[wid].nhwin = wid; @@ -300,7 +305,8 @@ curses_del_nhwin(winid wid) } if (!is_main_window(wid)) { - panic("curses_del_nhwin: wid out of range. Not a main window."); + impossible("curses_del_nhwin: wid %d out of range. Not a main window.", wid); + return; } nhwins[wid].curwin = NULL; @@ -390,7 +396,10 @@ void curses_get_window_xy(winid wid, int *x, int *y) { if (!is_main_window(wid)) { - panic("curses_get_window_xy: wid out of range. Not a main window."); + impossible("curses_get_window_xy: wid %d out of range. Not a main window.", wid); + *x = 0; + *y = 0; + return; } *x = nhwins[wid].x; @@ -442,8 +451,9 @@ int curses_get_window_orientation(winid wid) { if (!is_main_window(wid)) { - panic - ("curses_get_window_orientation: wid out of range. Not a main window."); + impossible + ("curses_get_window_orientation: wid %d out of range. Not a main window.", wid); + return CENTER; } return nhwins[wid].orientation; @@ -480,7 +490,8 @@ curses_puts(winid wid, int attr, const char *text) if (curses_is_menu(wid) || curses_is_text(wid)) { if (!curses_menu_exists(wid)) { - panic("curses_puts: Attempted write to nonexistant window!"); + impossible("curses_puts: Attempted write to nonexistant window %d!", wid); + return; } identifier = malloc(sizeof (anything)); identifier->a_void = NULL; diff --git a/win/tty/getline.c b/win/tty/getline.c index eea05fd39..f4894a950 100644 --- a/win/tty/getline.c +++ b/win/tty/getline.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 getline.c $NHDT-Date: 1523619111 2018/04/13 11:31:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.35 $ */ +/* NetHack 3.6 getline.c $NHDT-Date: 1543830347 2018/12/03 09:45:47 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.37 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -260,6 +260,8 @@ char *base; com_index = -1; for (oindex = 0; extcmdlist[oindex].ef_txt != (char *) 0; oindex++) { + if (extcmdlist[oindex].flags & CMD_NOT_AVAILABLE) + continue; if ((extcmdlist[oindex].flags & AUTOCOMPLETE) && !(!wizard && (extcmdlist[oindex].flags & WIZMODECMD)) && !strncmpi(base, extcmdlist[oindex].ef_txt, strlen(base))) { diff --git a/win/win32/mhfont.c b/win/win32/mhfont.c index e8296cc8d..18e09082e 100644 --- a/win/win32/mhfont.c +++ b/win/win32/mhfont.c @@ -8,23 +8,18 @@ #include "winos.h" #include "mhfont.h" +/* font table - 64 fonts ought to be enough */ #define MAXFONTS 64 -/* font table - 64 fonts ought to be enough */ -static struct font_table_entry { - int code; - HFONT hFont; - BOOL supportsUnicode; -} font_table[MAXFONTS]; +static cached_font font_table[MAXFONTS]; static int font_table_size = 0; -HFONT version_splash_font; #define NHFONT_CODE(win, attr) (((attr & 0xFF) << 8) | (win_type & 0xFF)) static void __cdecl font_table_cleanup(void); -void -mswin_init_splashfonts(HWND hWnd) +HFONT +mswin_create_splashfont(HWND hWnd) { HDC hdc = GetDC(hWnd); double scale = win10_monitor_scale(hWnd); @@ -44,14 +39,10 @@ mswin_init_splashfonts(HWND hWnd) lgfnt.lfQuality = DEFAULT_QUALITY; // output quality lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family NH_A2W("Times New Roman", lgfnt.lfFaceName, LF_FACESIZE); - version_splash_font = CreateFontIndirect(&lgfnt); + HFONT font = CreateFontIndirect(&lgfnt); ReleaseDC(hWnd, hdc); -} -void -mswin_destroy_splashfonts() -{ - DeleteObject(version_splash_font); + return font; } BOOL @@ -66,7 +57,7 @@ mswin_font_supports_unicode(HFONT hFont) /* create font based on window type, charater attributes and window device context */ -HGDIOBJ +cached_font * mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace) { HFONT fnt = NULL; @@ -88,7 +79,7 @@ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace) break; if (!replace && font_index < font_table_size) - return font_table[font_index].hFont; + return &font_table[font_index]; switch (win_type) { case NHW_STATUS: @@ -102,7 +93,7 @@ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace) lgfnt.lfWeight = (attr == ATR_BOLD) ? FW_BOLD : FW_NORMAL; // font weight lgfnt.lfItalic = FALSE; // italic attribute option - lgfnt.lfUnderline = FALSE; // underline attribute option + lgfnt.lfUnderline = (attr == ATR_ULINE); // underline attribute option lgfnt.lfStrikeOut = FALSE; // strikeout attribute option lgfnt.lfCharSet = mswin_charset(); // character set identifier lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision @@ -214,7 +205,15 @@ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace) font_table[font_index].hFont = fnt; font_table[font_index].supportsUnicode = winos_font_support_cp437(fnt); - return fnt; + HGDIOBJ savedFont = SelectObject(hdc, fnt); + SIZE size; + GetTextExtentPoint32A(hdc, " ", 1, &size); + SelectObject(hdc, savedFont); + + font_table[font_index].height = size.cy; + font_table[font_index].width = size.cx; + + return &font_table[font_index]; } UINT diff --git a/win/win32/mhfont.h b/win/win32/mhfont.h index 76e651215..20b5d1400 100644 --- a/win/win32/mhfont.h +++ b/win/win32/mhfont.h @@ -9,10 +9,17 @@ #include "winMS.h" +typedef struct cached_font { + int code; + HFONT hFont; + BOOL supportsUnicode; + int width; + int height; +} cached_font; + BOOL mswin_font_supports_unicode(HFONT hFont); -HGDIOBJ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace); -void mswin_init_splashfonts(HWND hWnd); -void mswin_destroy_splashfonts(void); +cached_font * mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace); +HFONT mswin_create_splashfont(HWND hWnd); UINT mswin_charset(void); #endif /* MSWINFont_h */ diff --git a/win/win32/mhmain.c b/win/win32/mhmain.c index 8645a5d19..a71534703 100644 --- a/win/win32/mhmain.c +++ b/win/win32/mhmain.c @@ -501,6 +501,10 @@ MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) exit(1); break; + case WM_DPICHANGED: { + mswin_layout_main_window(NULL); + } break; + default: return DefWindowProc(hWnd, message, wParam, lParam); } diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index 49c2a4e4e..d401c4c3c 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -576,6 +576,13 @@ MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) dirty(data, data->xCur, data->yCur); break; + case WM_DPICHANGED: { + RECT rt; + GetWindowRect(hWnd, &rt); + ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT)&rt); + ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT)&rt) + 1); + mswin_update_window_placement(NHW_MAP, &rt); + } break; default: return DefWindowProc(hWnd, message, wParam, lParam); @@ -722,8 +729,6 @@ onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) data->tileDC = CreateCompatibleDC(hDC); ReleaseDC(hWnd, hDC); - SelectObject(data->tileDC, GetNHApp()->bmpMapTiles); - SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data); clearAll(data); @@ -982,11 +987,15 @@ onPaint(HWND hWnd) PNHMapWindow data = (PNHMapWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); /* update back buffer */ + HBITMAP savedBitmap = SelectObject(data->tileDC, GetNHApp()->bmpMapTiles); + for (int i = 0; i < COLNO; i++) for (int j = 0; j < ROWNO; j++) if (data->mapDirty[i][j]) paint(data, i, j); + SelectObject(data->tileDC, savedBitmap); + PAINTSTRUCT ps; HDC hFrontBufferDC = BeginPaint(hWnd, &ps); diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c index d35c5ef2e..5e38d0235 100644 --- a/win/win32/mhmenu.c +++ b/win/win32/mhmenu.c @@ -297,8 +297,9 @@ MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data); /* set font for the text cotrol */ + cached_font * font = mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE); SendMessage(control, WM_SETFONT, - (WPARAM) mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE), + (WPARAM) font->hFont, (LPARAM) 0); ReleaseDC(control, hdc); @@ -564,8 +565,8 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) /* calculate dimensions of the added line of text */ hdc = GetDC(text_view); - saveFont = - SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE)); + cached_font * font = mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE); + saveFont = SelectObject(hdc, font->hFont); SetRect(&text_rt, 0, 0, 0, 0); DrawTextA(hdc, msg_data->text, strlen(msg_data->text), &text_rt, DT_CALCRECT | DT_TOP | DT_LEFT | DT_NOPREFIX @@ -629,8 +630,8 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) /* calculate tabstop size */ hDC = GetDC(hWnd); - saveFont = SelectObject( - hDC, mswin_get_font(NHW_MENU, msg_data->attr, hDC, FALSE)); + cached_font * font = mswin_get_font(NHW_MENU, msg_data->attr, hDC, FALSE); + saveFont = SelectObject(hDC, font->hFont); GetTextMetrics(hDC, &tm); p1 = data->menu.items[new_item].str; p = strchr(data->menu.items[new_item].str, '\t'); @@ -936,8 +937,8 @@ onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam) GetClientRect(GetMenuControl(hWnd), &list_rect); hdc = GetDC(GetMenuControl(hWnd)); - saveFont = - SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, FALSE)); + cached_font * font = mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, FALSE); + saveFont = SelectObject(hdc, font->hFont); GetTextMetrics(hdc, &tm); /* Set the height of the list box items to max height of the individual @@ -1000,8 +1001,8 @@ onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) item = &data->menu.items[lpdis->itemID]; tileDC = CreateCompatibleDC(lpdis->hDC); - saveFont = SelectObject( - lpdis->hDC, mswin_get_font(NHW_MENU, item->attr, lpdis->hDC, FALSE)); + cached_font * font = mswin_get_font(NHW_MENU, item->attr, lpdis->hDC, FALSE); + saveFont = SelectObject(lpdis->hDC, font->hFont); NewBg = menu_bg_brush ? menu_bg_color : (COLORREF) GetSysColor(DEFAULT_COLOR_BG_MENU); OldBg = SetBkColor(lpdis->hDC, NewBg); @@ -1050,8 +1051,8 @@ onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) if (iflags.use_menu_color && (menucolr = get_menu_coloring(item->str, &color, &attr))) { - SelectObject(lpdis->hDC, - mswin_get_font(NHW_MENU, attr, lpdis->hDC, FALSE)); + cached_font * menu_font = mswin_get_font(NHW_MENU, attr, lpdis->hDC, FALSE); + SelectObject(lpdis->hDC, menu_font->hFont); if (color != NO_COLOR) SetTextColor(lpdis->hDC, nhcolor_to_RGB(color)); } @@ -1165,8 +1166,10 @@ onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) data->menu.items[lpdis->itemID].count); } - SelectObject(lpdis->hDC, mswin_get_font(NHW_MENU, ATR_BLINK, - lpdis->hDC, FALSE)); + /* TOOD: add blinking for blink text */ + + cached_font * blink_font = mswin_get_font(NHW_MENU, ATR_BLINK, lpdis->hDC, FALSE); + SelectObject(lpdis->hDC, blink_font->hFont); /* calculate text rectangle */ SetRect(&drawRect, client_rt.left, lpdis->rcItem.top, diff --git a/win/win32/mhmsgwnd.c b/win/win32/mhmsgwnd.c index febe88143..505b40f36 100644 --- a/win/win32/mhmsgwnd.c +++ b/win/win32/mhmsgwnd.c @@ -635,9 +635,9 @@ onPaint(HWND hWnd) draw_rt.top = y - data->yChar; draw_rt.bottom = y; - oldFont = SelectObject( - hdc, mswin_get_font(NHW_MESSAGE, data->window_text[i].attr, - hdc, FALSE)); + cached_font * font = mswin_get_font(NHW_MESSAGE, + data->window_text[i].attr, hdc, FALSE); + oldFont = SelectObject(hdc, font->hFont); /* convert to UNICODE stripping newline */ strcpy(tmptext, data->window_text[i].text); @@ -746,8 +746,8 @@ mswin_message_window_size(HWND hWnd, LPSIZE sz) /* -- Calculate the font size -- */ /* Get the handle to the client area's device context. */ hdc = GetDC(hWnd); - saveFont = - SelectObject(hdc, mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE)); + cached_font * font = mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE); + saveFont = SelectObject(hdc, font->hFont); /* Extract font dimensions from the text metrics. */ GetTextMetrics(hdc, &tm); @@ -813,10 +813,9 @@ can_append_text(HWND hWnd, int attr, const char *text) strcat(tmptext, MORE); hdc = GetDC(hWnd); - saveFont = SelectObject( - hdc, - mswin_get_font(NHW_MESSAGE, data->window_text[MSG_LINES - 1].attr, - hdc, FALSE)); + cached_font * font = mswin_get_font(NHW_MESSAGE, + data->window_text[MSG_LINES - 1].attr, hdc, FALSE); + saveFont = SelectObject(hdc, font->hFont); GetClientRect(hWnd, &draw_rt); draw_rt.left += LINE_PADDING_LEFT(data); draw_rt.right -= LINE_PADDING_RIGHT(data); @@ -860,17 +859,16 @@ more_prompt_check(HWND hWnd) remaining_height = client_rt.bottom - client_rt.top; hdc = GetDC(hWnd); - saveFont = - SelectObject(hdc, mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE)); + cached_font * font = mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE); + saveFont = SelectObject(hdc, font->hFont); for (i = 0; i < data->lines_not_seen; i++) { /* we only need width for the DrawText */ SetRect(&draw_rt, client_rt.left + LINE_PADDING_LEFT(data), client_rt.top, client_rt.right - LINE_PADDING_RIGHT(data), client_rt.top); - SelectObject(hdc, - mswin_get_font(NHW_MESSAGE, - data->window_text[MSG_LINES - i - 1].attr, - hdc, FALSE)); + font = mswin_get_font(NHW_MESSAGE, + data->window_text[MSG_LINES - i - 1].attr, hdc, FALSE); + SelectObject(hdc, font->hFont); strcpy(tmptext, data->window_text[MSG_LINES - i - 1].text); strip_newline(tmptext); diff --git a/win/win32/mhrip.c b/win/win32/mhrip.c index ed826704b..79ad05342 100644 --- a/win/win32/mhrip.c +++ b/win/win32/mhrip.c @@ -69,7 +69,6 @@ mswin_display_RIP_window(HWND hWnd) RECT riprt; RECT clientrect; RECT textrect; - HDC hdc; HFONT OldFont; MonitorInfo monitorInfo; @@ -98,8 +97,8 @@ mswin_display_RIP_window(HWND hWnd) textrect.left += data->x; textrect.right -= data->x; if (data->window_text) { - hdc = GetDC(hWnd); - OldFont = SelectObject(hdc, mswin_get_font(NHW_TEXT, 0, hdc, FALSE)); + HDC hdc = GetDC(hWnd); + OldFont = SelectObject(hdc, mswin_get_font(NHW_TEXT, 0, hdc, FALSE)->hFont); DrawText(hdc, data->window_text, strlen(data->window_text), &textrect, DT_LEFT | DT_NOPREFIX | DT_CALCRECT); SelectObject(hdc, OldFont); @@ -144,21 +143,18 @@ mswin_display_RIP_window(HWND hWnd) INT_PTR CALLBACK NHRIPWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - HDC hdc; - PNHRIPWindow data; - - data = (PNHRIPWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); + PNHRIPWindow data = (PNHRIPWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); switch (message) { - case WM_INITDIALOG: + case WM_INITDIALOG: { + HDC hdc = GetDC(hWnd); + cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE); + /* set text control font */ - hdc = GetDC(hWnd); - SendMessage(hWnd, WM_SETFONT, - (WPARAM) mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE), - 0); + SendMessage(hWnd, WM_SETFONT, (WPARAM)font->hFont, 0); ReleaseDC(hWnd, hdc); SetFocus(GetDlgItem(hWnd, IDOK)); - return FALSE; + } break; case WM_MSNH_COMMAND: onMSNHCommand(hWnd, wParam, lParam); @@ -172,9 +168,10 @@ NHRIPWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) HANDLE OldBitmap; PAINTSTRUCT ps; HFONT OldFont; + HDC hdc = BeginPaint(hWnd, &ps); + cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE); - hdc = BeginPaint(hWnd, &ps); - OldFont = SelectObject(hdc, mswin_get_font(NHW_TEXT, 0, hdc, FALSE)); + OldFont = SelectObject(hdc, font->hFont); hdcBitmap = CreateCompatibleDC(hdc); SetBkMode(hdc, TRANSPARENT); GetClientRect(hWnd, &clientrect); diff --git a/win/win32/mhsplash.c b/win/win32/mhsplash.c index 0b0e313cd..0271c8081 100644 --- a/win/win32/mhsplash.c +++ b/win/win32/mhsplash.c @@ -25,26 +25,97 @@ INT_PTR CALLBACK NHSplashWndProc(HWND, UINT, WPARAM, LPARAM); #define SPLASH_VERSION_X_96DPI 280 #define SPLASH_VERSION_Y_96DPI 0 -extern HFONT version_splash_font; - typedef struct { + int boarder_width; + int boarder_height; + int client_width; + int client_height; + int ok_control_width; + int ok_control_height; + int ok_control_offset_x; + int ok_control_offset_y; + int text_control_width; + int text_control_height; + int text_control_offset_x; + int text_control_offset_y; + int window_width; + int window_height; int width; int height; - int offsetX; - int offsetY; - int versionX; - int versionY; + int offset_x; + int offset_y; + int version_x; + int version_y; + HFONT hFont; } SplashData; +static void +mswin_set_splash_data(HWND hWnd, SplashData * sd, double scale) +{ + RECT client_rect; + RECT window_rect; + RECT ok_control_rect; + RECT text_control_rect; + + GetClientRect(hWnd, &client_rect); + GetWindowRect(hWnd, &window_rect); + GetWindowRect(GetDlgItem(hWnd, IDOK), &ok_control_rect); + GetWindowRect(GetDlgItem(hWnd, IDC_EXTRAINFO), &text_control_rect); + + sd->boarder_width = (window_rect.right - window_rect.left) - + (client_rect.right - client_rect.left); + sd->boarder_height = (window_rect.bottom - window_rect.top) - + (client_rect.bottom - client_rect.top); + + sd->ok_control_width = ok_control_rect.right - ok_control_rect.left; + sd->ok_control_height = ok_control_rect.bottom - ok_control_rect.top; + + sd->width = (int)(scale * SPLASH_WIDTH_96DPI); + sd->height = (int)(scale * SPLASH_HEIGHT_96DPI); + sd->offset_x = (int)(scale * SPLASH_OFFSET_X_96DPI); + sd->offset_y = (int)(scale * SPLASH_OFFSET_Y_96DPI); + sd->version_x = (int)(scale * SPLASH_VERSION_X_96DPI); + sd->version_y = (int)(scale * SPLASH_VERSION_Y_96DPI); + + sd->client_width = sd->width + sd->offset_x * 2; + sd->client_height = sd->height + sd->ok_control_height + + sd->offset_y * 3; + + sd->window_width = sd->client_width + sd->boarder_width; + sd->window_height = sd->client_height + sd->boarder_height; + + sd->ok_control_offset_x = (sd->client_width - sd->ok_control_width) / 2; + sd->ok_control_offset_y = sd->client_height - sd->ok_control_height - sd->offset_y; + + sd->text_control_width = sd->client_width - sd->offset_x * 2; + sd->text_control_height = text_control_rect.bottom - text_control_rect.top; + + sd->text_control_offset_x = sd->offset_x; + sd->text_control_offset_y = sd->ok_control_offset_y - sd->offset_y - + sd->text_control_height; + + if (sd->hFont != NULL) + DeleteObject(sd->hFont); + + sd->hFont = mswin_create_splashfont(hWnd); + + MoveWindow(hWnd, window_rect.left, window_rect.top, + sd->window_width, sd->window_height, TRUE); + + MoveWindow(GetDlgItem(hWnd, IDOK), + sd->ok_control_offset_x, sd->ok_control_offset_y, + sd->ok_control_width, sd->ok_control_height, TRUE); + + MoveWindow(GetDlgItem(hWnd, IDC_EXTRAINFO), + sd->text_control_offset_x, sd->text_control_offset_y, + sd->text_control_width, sd->text_control_height, TRUE); + +} + void mswin_display_splash_window(BOOL show_ver) { MSG msg; - int left, top; - RECT splashrt; - RECT clientrt; - RECT controlrt; - int buttop; strbuf_t strbuf; strbuf_init(&strbuf); @@ -56,57 +127,18 @@ mswin_display_splash_window(BOOL show_ver) MonitorInfo monitorInfo; win10_monitor_info(hWnd, &monitorInfo); - - SplashData splashData; - splashData.width = (int) (monitorInfo.scale * SPLASH_WIDTH_96DPI); - splashData.height = (int) (monitorInfo.scale * SPLASH_HEIGHT_96DPI); - splashData.offsetX = (int) (monitorInfo.scale * SPLASH_OFFSET_X_96DPI); - splashData.offsetY = (int) (monitorInfo.scale * SPLASH_OFFSET_Y_96DPI); - splashData.versionX = (int) (monitorInfo.scale * SPLASH_VERSION_X_96DPI); - splashData.versionY = (int) (monitorInfo.scale * SPLASH_VERSION_Y_96DPI); + SplashData splashData; + memset(&splashData, 0, sizeof(splashData)); + mswin_set_splash_data(hWnd, &splashData, monitorInfo.scale); SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) &splashData); - mswin_init_splashfonts(hWnd); GetNHApp()->hPopupWnd = hWnd; - /* Get control size */ - GetWindowRect(GetDlgItem(hWnd, IDOK), &controlrt); - controlrt.right -= controlrt.left; - controlrt.bottom -= controlrt.top; - /* Get current client area */ - GetClientRect(hWnd, &clientrt); - /* Get window size */ - GetWindowRect(hWnd, &splashrt); - splashrt.right -= splashrt.left; - splashrt.bottom -= splashrt.top; - /* Get difference between requested client area and current value */ - splashrt.right += splashData.width + splashData.offsetX * 2 - - clientrt.right; - splashrt.bottom += splashData.height + controlrt.bottom - + splashData.offsetY * 3 - - clientrt.bottom; - /* Place the window centered */ - /* On the screen, not on the parent window */ - left = (monitorInfo.width - splashrt.right) / 2; - top = (monitorInfo.height - splashrt.bottom) / 2; - MoveWindow(hWnd, left, top, splashrt.right, splashrt.bottom, TRUE); - /* Place the OK control */ - GetClientRect(hWnd, &clientrt); - MoveWindow(GetDlgItem(hWnd, IDOK), - (clientrt.right - clientrt.left - controlrt.right) / 2, - clientrt.bottom - controlrt.bottom - splashData.offsetY, - controlrt.right, controlrt.bottom, TRUE); - buttop = clientrt.bottom - controlrt.bottom - splashData.offsetY; - /* Place the text control */ - GetWindowRect(GetDlgItem(hWnd, IDC_EXTRAINFO), &controlrt); - controlrt.right -= controlrt.left; - controlrt.bottom -= controlrt.top; - GetClientRect(hWnd, &clientrt); - MoveWindow(GetDlgItem(hWnd, IDC_EXTRAINFO), - clientrt.left + splashData.offsetX, - buttop - controlrt.bottom - splashData.offsetY, - clientrt.right - 2 * splashData.offsetX, controlrt.bottom, TRUE); + + int left = monitorInfo.left + (monitorInfo.width - splashData.window_width) / 2; + int top = monitorInfo.top + (monitorInfo.height - splashData.window_height) / 2; + MoveWindow(hWnd, left, top, splashData.window_width, splashData.window_height, TRUE); /* Fill the text control */ strbuf_reserve(&strbuf, BUFSIZ); @@ -164,27 +196,24 @@ mswin_display_splash_window(BOOL show_ver) } GetNHApp()->hPopupWnd = NULL; - mswin_destroy_splashfonts(); + DeleteObject(splashData.hFont); } INT_PTR CALLBACK NHSplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - HDC hdc; - UNREFERENCED_PARAMETER(lParam); switch (message) { - case WM_INITDIALOG: + case WM_INITDIALOG: { + HDC hdc = GetDC(hWnd); + cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE); /* set text control font */ - hdc = GetDC(hWnd); - SendMessage(hWnd, WM_SETFONT, - (WPARAM) mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE), - 0); + SendMessage(hWnd, WM_SETFONT, (WPARAM)font->hFont, 0); ReleaseDC(hWnd, hdc); SetFocus(GetDlgItem(hWnd, IDOK)); - return FALSE; + } break; case WM_PAINT: { char VersionString[BUFSZ]; @@ -196,14 +225,14 @@ NHSplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SplashData *splashData = (SplashData *) GetWindowLongPtr(hWnd, GWLP_USERDATA); - hdc = BeginPaint(hWnd, &ps); + HDC hdc = BeginPaint(hWnd, &ps); /* Show splash graphic */ hdcBitmap = CreateCompatibleDC(hdc); SetBkMode(hdc, OPAQUE); OldBitmap = SelectObject(hdcBitmap, GetNHApp()->bmpSplash); (*GetNHApp()->lpfnTransparentBlt)(hdc, - splashData->offsetX, splashData->offsetY, + splashData->offset_x, splashData->offset_y, splashData->width, splashData->height, hdcBitmap, 0, 0, SPLASH_WIDTH_96DPI, SPLASH_HEIGHT_96DPI, TILE_BK_COLOR); @@ -215,11 +244,11 @@ NHSplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* Print version number */ SetTextColor(hdc, RGB(0, 0, 0)); - rt.right = rt.left = splashData->offsetX + splashData->versionX; - rt.bottom = rt.top = splashData->offsetY + splashData->versionY; + rt.right = rt.left = splashData->offset_x + splashData->version_x; + rt.bottom = rt.top = splashData->offset_y + splashData->version_y; Sprintf(VersionString, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL); - OldFont = SelectObject(hdc, version_splash_font); + OldFont = SelectObject(hdc, splashData->hFont); DrawText(hdc, VersionString, strlen(VersionString), &rt, DT_LEFT | DT_NOPREFIX | DT_CALCRECT); DrawText(hdc, VersionString, strlen(VersionString), &rt, @@ -238,6 +267,18 @@ NHSplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } break; + + case WM_DPICHANGED: { + SplashData *splashData = (SplashData *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + MonitorInfo monitorInfo; + win10_monitor_info(hWnd, &monitorInfo); + + mswin_set_splash_data(hWnd, splashData, monitorInfo.scale); + + InvalidateRect(hWnd, NULL, TRUE); + } break; + } return FALSE; } diff --git a/win/win32/mhstatus.c b/win/win32/mhstatus.c index 57c70b436..d5bfda092 100644 --- a/win/win32/mhstatus.c +++ b/win/win32/mhstatus.c @@ -9,8 +9,15 @@ #include "mhmsg.h" #include "mhfont.h" +#ifndef STATUS_HILITES +#error STATUS_HILITES not defined +#endif + #define MAXWINDOWTEXT BUFSZ +#define STATUS_BLINK_INTERVAL 500 // milliseconds + + extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */ typedef struct back_buffer { @@ -65,6 +72,8 @@ typedef struct mswin_nethack_status_window { char window_text[NHSW_LINES][MAXWINDOWTEXT + 1]; mswin_status_lines * status_lines; back_buffer_t back_buffer; + boolean blink_state; /* true = invert blink text */ + boolean has_blink_fields; /* true if one or more has blink attriubte */ } NHStatusWindow, *PNHStatusWindow; @@ -135,6 +144,9 @@ mswin_init_status_window() status_fg_brush = CreateSolidBrush(status_fg_color); } + /* set cursor blink timer */ + SetTimer(ret, 0, STATUS_BLINK_INTERVAL, NULL); + return ret; } @@ -183,28 +195,23 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case MSNH_MSG_GETTEXT: { PMSNHMsgGetText msg_data = (PMSNHMsgGetText) lParam; -#ifdef STATUS_HILITES msg_data->buffer[0] = '\0'; + size_t space_remaining = msg_data->max_size; for (int line = 0; line < NHSW_LINES; line++) { mswin_status_line *status_line = data->status_lines[line].lines; for (int i = 0; i < status_line->status_strings.count; i++) { mswin_status_string * status_string = status_line->status_strings.status_strings[i]; - strncat(msg_data->buffer, status_string->str, - msg_data->max_size - strlen(msg_data->buffer)); + if (status_string->space_in_front) { + strncat(msg_data->buffer, " ", space_remaining); + space_remaining = msg_data->max_size - strlen(msg_data->buffer); + } + strncat(msg_data->buffer, status_string->str, space_remaining); + space_remaining = msg_data->max_size - strlen(msg_data->buffer); } - strncat(msg_data->buffer, "\r\n", - msg_data->max_size - strlen(msg_data->buffer)); + strncat(msg_data->buffer, "\r\n", space_remaining); + space_remaining = msg_data->max_size - strlen(msg_data->buffer); } - -#else - strncpy(msg_data->buffer, data->window_text[0], - msg_data->max_size); - strncat(msg_data->buffer, "\r\n", - msg_data->max_size - strlen(msg_data->buffer)); - strncat(msg_data->buffer, data->window_text[1], - msg_data->max_size - strlen(msg_data->buffer)); -#endif } break; case MSNH_MSG_UPDATE_STATUS: { @@ -245,22 +252,25 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetFocus(GetNHApp()->hMainWnd); break; + case WM_TIMER: + data->blink_state = !data->blink_state; + if (data->has_blink_fields) + InvalidateRect(hWnd, NULL, TRUE); + break; + default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } -#ifdef STATUS_HILITES static LRESULT onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) { SIZE sz; - HGDIOBJ normalFont, boldFont; WCHAR wbuf[BUFSZ]; RECT rt; PAINTSTRUCT ps; - HDC hdc; PNHStatusWindow data; int width, height; RECT clear_rect; @@ -276,12 +286,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) 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); - - SelectObject(hdc, normalFont); + HDC hdc = data->back_buffer.hdc; SetBkColor(hdc, status_bg_color); SetTextColor(hdc, status_fg_color); @@ -293,149 +298,166 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) FillRect(hdc, &clear_rect, status_bg_brush); - // TODO: Put it around for loop instead -- temporary to get a better diff - if (data->status_lines == NULL) { - BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY); + if (data->status_lines != NULL) { + + data->has_blink_fields = FALSE; - EndPaint(hWnd, &ps); - return 0; - } + for (int line = 0; line < NHSW_LINES; line++) { + LONG left = rt.left; + LONG cy = 0; + int vlen; - for (int line = 0; line < NHSW_LINES; line++) { - LONG left = rt.left; - LONG cy = 0; - int vlen; + mswin_status_line * status_line = &data->status_lines->lines[line]; - mswin_status_line * status_line = &data->status_lines->lines[line]; + for (int i = 0; i < status_line->status_strings.count; i++) { + mswin_status_string * status_string = status_line->status_strings.status_strings[i]; + int clr, atr; + int fntatr = ATR_NONE; + COLORREF nFg, nBg; - for (int i = 0; i < status_line->status_strings.count; i++) { - mswin_status_string * status_string = status_line->status_strings.status_strings[i]; - int clr, atr; - int fntatr = ATR_NONE; - HGDIOBJ fnt; - COLORREF nFg, nBg; + if (status_string->str == NULL || status_string->str[0] == '\0') + continue; - if (status_string->str == NULL || status_string->str[0] == '\0') - continue; + clr = status_string->color; + atr = status_string->attribute; + const char *str = status_string->str; - clr = status_string->color & 0x00ff; - atr = (status_string->color & 0xff00) >> 8; + vlen = strlen(str); - const char *str = status_string->str; + if (atr & HL_BOLD) + fntatr = ATR_BOLD; + else if (atr & HL_INVERSE) + fntatr = ATR_INVERSE; + else if (atr & HL_ULINE) + fntatr = ATR_ULINE; + else if (atr & HL_BLINK) { + data->has_blink_fields = TRUE; + if (data->blink_state) { + fntatr = ATR_INVERSE; + atr |= HL_INVERSE; + } + } + else if (atr & HL_DIM) + fntatr = ATR_DIM; - vlen = strlen(str); + cached_font * fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE); - if (atr & HL_BOLD) - fntatr = ATR_BOLD; - else if (atr & HL_INVERSE) - fntatr = ATR_INVERSE; - else if (atr & HL_ULINE) - fntatr = ATR_ULINE; - else if (atr & HL_BLINK) - fntatr = ATR_BLINK; - else if (atr & HL_DIM) - fntatr = ATR_DIM; + BOOL useUnicode = fnt->supportsUnicode; - fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE); + winos_ascii_to_wide_str(str, wbuf, SIZE(wbuf)); - BOOL useUnicode = mswin_font_supports_unicode(fnt); + nFg = (clr == NO_COLOR ? status_fg_color + : ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr) + : status_fg_color)); - winos_ascii_to_wide_str(str, wbuf, SIZE(wbuf)); + if (atr & HL_DIM) { + /* make a dim representation - this can produce color shift */ + float redReduction = 0.5f; + float greenReduction = 0.5f; + float blueReduction = 0.25f; + uchar red = (uchar)(GetRValue(nFg) * (1.0f - redReduction)); + uchar green = (uchar)(GetGValue(nFg) * (1.0f - greenReduction)); + uchar blue = (uchar)(GetBValue(nFg) * (1.0f - blueReduction)); + nFg = RGB(red, green, blue); + } - nFg = (clr == NO_COLOR ? status_fg_color - : ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr) - : status_fg_color)); - nBg = status_bg_color; + nBg = status_bg_color; - sz.cy = -1; + if (status_string->space_in_front) + rt.left += fnt->width; - if (status_string->draw_bar && iflags.wc2_hitpointbar) { + sz.cy = -1; - /* when we are drawing bar we need to look at the hp status - * field to get the correct percentage and color */ - COLORREF bar_color = nhcolor_to_RGB(status_string->bar_color); - HBRUSH back_brush = CreateSolidBrush(bar_color); - RECT barrect; + if (status_string->draw_bar && iflags.wc2_hitpointbar) { + /* NOTE: we current don't support bar attributes */ - /* prepare for drawing */ - SelectObject(hdc, fnt); - SetBkMode(hdc, OPAQUE); - SetBkColor(hdc, status_bg_color); - /* SetTextColor(hdc, nhcolor_to_RGB(hpbar_color)); */ - SetTextColor(hdc, status_fg_color); + /* when we are drawing bar we need to look at the hp status + * field to get the correct percentage and color */ + COLORREF bar_color = nhcolor_to_RGB(status_string->bar_color); + HBRUSH back_brush = CreateSolidBrush(bar_color); + RECT barrect; - if (useUnicode) { - /* get bounding rectangle */ - GetTextExtentPoint32W(hdc, wbuf, vlen, &sz); + /* prepare for drawing */ + SelectObject(hdc, fnt->hFont); + SetBkMode(hdc, OPAQUE); + SetBkColor(hdc, status_bg_color); + SetTextColor(hdc, status_fg_color); - /* first draw title normally */ - DrawTextW(hdc, wbuf, vlen, &rt, DT_LEFT); + if (useUnicode) { + /* get bounding rectangle */ + GetTextExtentPoint32W(hdc, wbuf, vlen, &sz); + + /* first draw title normally */ + DrawTextW(hdc, wbuf, vlen, &rt, DT_LEFT); + } + else { + /* get bounding rectangle */ + GetTextExtentPoint32A(hdc, str, vlen, &sz); + + /* first draw title normally */ + DrawTextA(hdc, str, vlen, &rt, DT_LEFT); + } + int bar_percent = status_string->bar_percent; + if (bar_percent > 0) { + /* calc bar length */ + barrect.left = rt.left; + barrect.top = rt.top; + barrect.bottom = sz.cy; + if (bar_percent > 0) + barrect.right = (int)((bar_percent * sz.cx) / 100); + /* else + barrect.right = sz.cx; */ + + /* then draw hpbar on top of title */ + FillRect(hdc, &barrect, back_brush); + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, nBg); + + if (useUnicode) + DrawTextW(hdc, wbuf, vlen, &barrect, DT_LEFT); + else + DrawTextA(hdc, str, vlen, &barrect, DT_LEFT); + } + DeleteObject(back_brush); } else { - /* get bounding rectangle */ - GetTextExtentPoint32A(hdc, str, vlen, &sz); + if (atr & HL_INVERSE) { + COLORREF tmp = nFg; + nFg = nBg; + nBg = tmp; + } - /* first draw title normally */ - DrawTextA(hdc, str, vlen, &rt, DT_LEFT); + /* prepare for drawing */ + SelectObject(hdc, fnt->hFont); + SetBkMode(hdc, OPAQUE); + SetBkColor(hdc, nBg); + SetTextColor(hdc, nFg); + + if (useUnicode) { + /* get bounding rectangle */ + GetTextExtentPoint32W(hdc, wbuf, vlen, &sz); + + /* draw */ + DrawTextW(hdc, wbuf, vlen, &rt, DT_LEFT); + } + else { + /* get bounding rectangle */ + GetTextExtentPoint32A(hdc, str, vlen, &sz); + + /* draw */ + DrawTextA(hdc, str, vlen, &rt, DT_LEFT); + } } - int bar_percent = status_string->bar_percent; - if (bar_percent > 0) { - /* calc bar length */ - barrect.left = rt.left; - barrect.top = rt.top; - barrect.bottom = sz.cy; - if (bar_percent > 0) - barrect.right = (int)((bar_percent * sz.cx) / 100); - /* else - barrect.right = sz.cx; */ + assert(sz.cy >= 0); - /* then draw hpbar on top of title */ - FillRect(hdc, &barrect, back_brush); - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, nBg); - - if (useUnicode) - DrawTextW(hdc, wbuf, vlen, &barrect, DT_LEFT); - else - DrawTextA(hdc, str, vlen, &barrect, DT_LEFT); - } - DeleteObject(back_brush); - } else { - if (atr & HL_INVERSE) { - COLORREF tmp = nFg; - nFg = nBg; - nBg = tmp; - } - - /* prepare for drawing */ - SelectObject(hdc, fnt); - SetBkMode(hdc, OPAQUE); - SetBkColor(hdc, nBg); - SetTextColor(hdc, nFg); - - if (useUnicode) { - /* get bounding rectangle */ - GetTextExtentPoint32W(hdc, wbuf, vlen, &sz); - - /* draw */ - DrawTextW(hdc, wbuf, vlen, &rt, DT_LEFT); - } else { - /* get bounding rectangle */ - GetTextExtentPoint32A(hdc, str, vlen, &sz); - - /* draw */ - DrawTextA(hdc, str, vlen, &rt, DT_LEFT); - } + rt.left += sz.cx; + cy = max(cy, sz.cy); } - assert(sz.cy >= 0); - rt.left += sz.cx; - cy = max(cy, sz.cy); + rt.left = left; + rt.top += cy; } - - rt.left = left; - rt.top += cy; } BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY); @@ -444,70 +466,24 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) return 0; } -#else -static LRESULT -onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - int i; - SIZE sz; - HGDIOBJ oldFont; - TCHAR wbuf[BUFSZ]; - COLORREF OldBg, OldFg; - RECT rt; - PAINTSTRUCT ps; - HDC hdc; - PNHStatusWindow data; - - data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); - - hdc = BeginPaint(hWnd, &ps); - GetClientRect(hWnd, &rt); - - oldFont = - SelectObject(hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE)); - - OldBg = SetBkColor(hdc, status_bg_brush ? status_bg_color - : (COLORREF) GetSysColor( - DEFAULT_COLOR_BG_STATUS)); - OldFg = SetTextColor(hdc, status_fg_brush ? status_fg_color - : (COLORREF) GetSysColor( - DEFAULT_COLOR_FG_STATUS)); - - for (i = 0; i < NHSW_LINES; i++) { - int wlen = strlen(data->window_text[i]); - NH_A2W(data->window_text[i], wbuf, SIZE(wbuf)); - GetTextExtentPoint32(hdc, wbuf, wlen, &sz); - DrawText(hdc, wbuf, wlen, &rt, DT_LEFT | DT_END_ELLIPSIS); - rt.top += sz.cy; - } - - SelectObject(hdc, oldFont); - SetTextColor(hdc, OldFg); - SetBkColor(hdc, OldBg); - EndPaint(hWnd, &ps); - - return 0; -} -#endif /* !STATUS_HILITES */ void mswin_status_window_size(HWND hWnd, LPSIZE sz) { - TEXTMETRIC tm; - HGDIOBJ saveFont; - HDC hdc; - PNHStatusWindow data; RECT rt; - SIZE text_sz; GetClientRect(hWnd, &rt); - data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); + PNHStatusWindow data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); if (data) { - hdc = GetDC(hWnd); - saveFont = SelectObject( - hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE)); + HDC hdc = GetDC(hWnd); + cached_font * font = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE); + HGDIOBJ saveFont = SelectObject(hdc, font->hFont); + + SIZE text_sz; GetTextExtentPoint32(hdc, _T("W"), 1, &text_sz); + + TEXTMETRIC tm; GetTextMetrics(hdc, &tm); rt.bottom = rt.top + text_sz.cy * NHSW_LINES; diff --git a/win/win32/mhstatus.h b/win/win32/mhstatus.h index 1f0d75d26..4d5d93753 100644 --- a/win/win32/mhstatus.h +++ b/win/win32/mhstatus.h @@ -34,10 +34,13 @@ static const int fieldcounts[NHSW_LINES] = { SIZE(fieldorder1) - 1, SIZE(fieldor * to represent what needs to be rendered. */ typedef struct mswin_status_string { const char * str; /* ascii string to be displayed */ - int color; /* string text color */ - boolean draw_bar; - int bar_percent; /* a percentage to indicate; 100 will draw no percentage bar */ + boolean space_in_front; /* render with a space in front of string */ + int color; /* string text color index */ + int attribute; /* string text attributes */ + boolean draw_bar; /* draw a percentage bar */ + int bar_percent; /* a percentage to indicate */ int bar_color; /* color index of percentage bar */ + int bar_attribute; /* attributes of percentage bar */ } mswin_status_string; typedef struct mswin_status_strings @@ -51,9 +54,11 @@ typedef struct mswin_status_field { boolean enabled; // whether the field is enabled const char * name; // name of status field const char * format; // format of field + boolean space_in_front; // add a space in front of the field int percent; int color; + int attribute; char string[BUFSZ]; } mswin_status_field; diff --git a/win/win32/mhtext.c b/win/win32/mhtext.c index 626e46e2b..8c1c2b32f 100644 --- a/win/win32/mhtext.c +++ b/win/win32/mhtext.c @@ -84,38 +84,35 @@ mswin_display_text_window(HWND hWnd) INT_PTR CALLBACK NHTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - HWND control; - HDC hdc; - PNHTextWindow data; - TCHAR title[MAX_LOADSTRING]; + PNHTextWindow data = (PNHTextWindow)GetWindowLongPtr(hWnd, GWLP_USERDATA); - data = (PNHTextWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); switch (message) { - case WM_INITDIALOG: + case WM_INITDIALOG: { + HWND control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + HDC hdc = GetDC(control); + cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE); /* set text control font */ - control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + if (!control) { panic("cannot get text view window"); } - hdc = GetDC(control); - SendMessage(control, WM_SETFONT, - (WPARAM) mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE), - 0); + SendMessage(control, WM_SETFONT, (WPARAM) font->hFont, 0); ReleaseDC(control, hdc); /* subclass edit control */ editControlWndProc = - (WNDPROC) GetWindowLongPtr(control, GWLP_WNDPROC); - SetWindowLongPtr(control, GWLP_WNDPROC, (LONG_PTR) NHEditHookWndProc); + (WNDPROC)GetWindowLongPtr(control, GWLP_WNDPROC); + SetWindowLongPtr(control, GWLP_WNDPROC, (LONG_PTR)NHEditHookWndProc); SetFocus(control); /* Even though the dialog has no caption, you can still set the title which shows on Alt-Tab */ + TCHAR title[MAX_LOADSTRING]; LoadString(GetNHApp()->hApp, IDS_APP_TITLE, title, MAX_LOADSTRING); SetWindowText(hWnd, title); - return FALSE; + } break; case WM_MSNH_COMMAND: onMSNHCommand(hWnd, wParam, lParam); diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 74a4cd3c6..3cfcc95bf 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -1913,16 +1913,13 @@ mswin_outrip(winid wid, int how, time_t when) void mswin_preference_update(const char *pref) { - HDC hdc; - int i; - if (stricmp(pref, "font_menu") == 0 || stricmp(pref, "font_size_menu") == 0) { if (iflags.wc_fontsiz_menu < NHFONT_SIZE_MIN || iflags.wc_fontsiz_menu > NHFONT_SIZE_MAX) iflags.wc_fontsiz_menu = NHFONT_DEFAULT_SIZE; - hdc = GetDC(GetNHApp()->hMainWnd); + HDC hdc = GetDC(GetNHApp()->hMainWnd); mswin_get_font(NHW_MENU, ATR_NONE, hdc, TRUE); mswin_get_font(NHW_MENU, ATR_BOLD, hdc, TRUE); mswin_get_font(NHW_MENU, ATR_DIM, hdc, TRUE); @@ -1941,7 +1938,7 @@ mswin_preference_update(const char *pref) || iflags.wc_fontsiz_status > NHFONT_SIZE_MAX) iflags.wc_fontsiz_status = NHFONT_DEFAULT_SIZE; - hdc = GetDC(GetNHApp()->hMainWnd); + HDC hdc = GetDC(GetNHApp()->hMainWnd); mswin_get_font(NHW_STATUS, ATR_NONE, hdc, TRUE); mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, TRUE); mswin_get_font(NHW_STATUS, ATR_DIM, hdc, TRUE); @@ -1950,7 +1947,7 @@ mswin_preference_update(const char *pref) mswin_get_font(NHW_STATUS, ATR_INVERSE, hdc, TRUE); ReleaseDC(GetNHApp()->hMainWnd, hdc); - for (i = 1; i < MAXWINDOWS; i++) { + for (int i = 1; i < MAXWINDOWS; i++) { if (GetNHApp()->windowlist[i].type == NHW_STATUS && GetNHApp()->windowlist[i].win != NULL) { InvalidateRect(GetNHApp()->windowlist[i].win, NULL, TRUE); @@ -1966,7 +1963,7 @@ mswin_preference_update(const char *pref) || iflags.wc_fontsiz_message > NHFONT_SIZE_MAX) iflags.wc_fontsiz_message = NHFONT_DEFAULT_SIZE; - hdc = GetDC(GetNHApp()->hMainWnd); + HDC hdc = GetDC(GetNHApp()->hMainWnd); mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, TRUE); mswin_get_font(NHW_MESSAGE, ATR_BOLD, hdc, TRUE); mswin_get_font(NHW_MESSAGE, ATR_DIM, hdc, TRUE); @@ -1986,7 +1983,7 @@ mswin_preference_update(const char *pref) || iflags.wc_fontsiz_text > NHFONT_SIZE_MAX) iflags.wc_fontsiz_text = NHFONT_DEFAULT_SIZE; - hdc = GetDC(GetNHApp()->hMainWnd); + HDC hdc = GetDC(GetNHApp()->hMainWnd); mswin_get_font(NHW_TEXT, ATR_NONE, hdc, TRUE); mswin_get_font(NHW_TEXT, ATR_BOLD, hdc, TRUE); mswin_get_font(NHW_TEXT, ATR_DIM, hdc, TRUE); @@ -2772,19 +2769,19 @@ static mswin_status_string _condition_strings[BL_MASK_BITS]; static mswin_status_field _status_fields[MAXBLSTATS]; static mswin_condition_field _condition_fields[BL_MASK_BITS] = { - { BL_MASK_STONE, " Stone" }, - { BL_MASK_SLIME, " Slime" }, - { BL_MASK_STRNGL, " Strngl" }, - { BL_MASK_FOODPOIS, " FoodPois" }, - { BL_MASK_TERMILL, " TermIll" }, - { BL_MASK_BLIND, " Blind" }, - { BL_MASK_DEAF, " Deaf" }, - { BL_MASK_STUN, " Stun" }, - { BL_MASK_CONF, " Conf" }, - { BL_MASK_HALLU, " Hallu" }, - { BL_MASK_LEV, " Lev" }, - { BL_MASK_FLY, " Fly" }, - { BL_MASK_RIDE, " Ride" } + { BL_MASK_STONE, "Stone" }, + { BL_MASK_SLIME, "Slime" }, + { BL_MASK_STRNGL, "Strngl" }, + { BL_MASK_FOODPOIS, "FoodPois" }, + { BL_MASK_TERMILL, "TermIll" }, + { BL_MASK_BLIND, "Blind" }, + { BL_MASK_DEAF, "Deaf" }, + { BL_MASK_STUN, "Stun" }, + { BL_MASK_CONF, "Conf" }, + { BL_MASK_HALLU, "Hallu" }, + { BL_MASK_LEV, "Lev" }, + { BL_MASK_FLY, "Fly" }, + { BL_MASK_RIDE, "Ride" } }; @@ -2915,10 +2912,13 @@ mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt, if (field != NULL) { field->format = fmt; + field->space_in_front = (fmt[0] == ' '); + if (field->space_in_front) field->format++; field->name = nm; field->enabled = enable; string->str = (field->enabled ? field->string : NULL); + string->space_in_front = field->space_in_front; if (field->field_index == BL_CONDITION) string->str = NULL; @@ -2943,6 +2943,22 @@ unsigned long *bmarray; return NO_COLOR; } +static int +mswin_condattr(bm, bmarray) +long bm; +unsigned long *bmarray; +{ + if (bm && bmarray) { + if (bm & bmarray[HL_ATTCLR_DIM]) return HL_DIM; + if (bm & bmarray[HL_ATTCLR_BLINK]) return HL_BLINK; + if (bm & bmarray[HL_ATTCLR_ULINE]) return HL_ULINE; + if (bm & bmarray[HL_ATTCLR_INVERSE]) return HL_INVERSE; + if (bm & bmarray[HL_ATTCLR_BOLD]) return HL_BOLD; + } + + return HL_NONE; +} + /* status_update(int fldindex, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks) @@ -2984,11 +3000,12 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percent, int color, u have to skip past ':' in passed "ptr" for the BL_GOLD case. -- color is the color that the NetHack core is telling you to use to display the text. - -- colormasks is a pointer to a set of CLR_MAX unsigned longs - telling you which fields should be displayed in each color. + -- condmasks is a pointer to a set of BL_ATTCLR_MAX unsigned + longs telling which conditions should be displayed in each + color and attriubte. */ void -mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks) +mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *condmasks) { long cond, *condptr = (long *) ptr; char *text = (char *) ptr; @@ -2996,19 +3013,7 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, int ocolor, ochar; unsigned ospecial; - logDebug("mswin_status_update(%d, %p, %d, %d, %x, %p)\n", idx, ptr, chg, percent, color, colormasks); - -#if 0 // TODO: this code was dead ... do we need to respond to these updates? - switch (idx) { - case BL_RESET: - reset_state = TRUE; - /* FALLTHRU */ - case BL_FLUSH: - /* FALLTHRU */ - default: - break; - } -#endif + logDebug("mswin_status_update(%d, %p, %d, %d, %x, %p)\n", idx, ptr, chg, percent, color, condmasks); if (idx >= 0) { @@ -3024,9 +3029,8 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, return; } - // TODO: is color actualy color and attribute OR not? - status_field->color = color & 0xff; - status_string->color = color & 0xff; + status_field->color = status_string->color = color & 0xff; + status_field->attribute = status_string->attribute = (color >> 8) & 0xff; switch (idx) { case BL_CONDITION: { @@ -3041,7 +3045,9 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, if (condition_field->mask & cond) { status_string->str = condition_field->name; - status_string->color = mswin_condcolor(condition_field->mask, colormasks); + status_string->space_in_front = TRUE; + status_string->color = mswin_condcolor(condition_field->mask, condmasks); + status_string->attribute = mswin_condattr(condition_field->mask, condmasks); } else status_string->str = NULL; @@ -3077,16 +3083,20 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, if (idx == BL_HP) { mswin_status_string * title_string = &_status_strings[BL_TITLE]; - title_string->bar_color = color; + title_string->bar_color = color & 0xff; + title_string->bar_attribute = (color >> 8) & 0xff; title_string->bar_percent = percent; } - /* send command to status window */ + } + + if (idx == BL_FLUSH || idx == BL_RESET) { + /* send command to status window to update */ ZeroMemory(&update_cmd_data, sizeof(update_cmd_data)); update_cmd_data.status_lines = &_status_lines; SendMessage(mswin_hwnd_from_winid(WIN_STATUS), WM_MSNH_COMMAND, - (WPARAM) MSNH_MSG_UPDATE_STATUS, (LPARAM) &update_cmd_data); + (WPARAM)MSNH_MSG_UPDATE_STATUS, (LPARAM)&update_cmd_data); } } diff --git a/win/win32/vs2017/NetHackW.vcxproj b/win/win32/vs2017/NetHackW.vcxproj index e8e104558..af28761da 100644 --- a/win/win32/vs2017/NetHackW.vcxproj +++ b/win/win32/vs2017/NetHackW.vcxproj @@ -174,6 +174,22 @@ + + + + + + + + + + + + + + + + @@ -184,4 +200,4 @@ - + \ No newline at end of file