diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 15d5b2d6d..53ba866ea 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -275,6 +275,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/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/src/cmd.c b/src/cmd.c index 20327366c..92b2fc0d2 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: 1543797825 2018/12/03 00:43:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.312 $ */ /* 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,15 +5675,22 @@ 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; @@ -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/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