1 /* NetHack 3.6 nttty.c $NHDT-Date: 1520825872 2018/03/12 03:37:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
2 /* Copyright (c) NetHack PC Development Team 1993 */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* tty.c - (Windows NT) version */
8 * Initial Creation M. Allison 1993/01/31
9 * Switch to low level console output routines M. Allison 2003/10/01
10 * Restrict cursor movement until input pending M. Lehotay 2003/10/02
11 * Call Unicode version of output API on NT R. Chason 2005/10/28
16 #define NEED_VARARGS /* Uses ... */
19 #include <sys\types.h>
24 * The following WIN32 Console API routines are used in this file.
27 * GetConsoleScreenBufferInfo
29 * SetConsoleCursorPosition
30 * SetConsoleTextAttribute
31 * SetConsoleCtrlHandler
34 * WriteConsoleOutputCharacter
35 * FillConsoleOutputAttribute
39 static BOOL FDECL(CtrlHandler, (DWORD));
40 static void FDECL(xputc_core, (char));
41 void FDECL(cmov, (int, int));
42 void FDECL(nocmov, (int, int));
43 int FDECL(process_keystroke,
44 (INPUT_RECORD *, boolean *, BOOLEAN_P numberpad, int portdebug));
45 static void NDECL(init_ttycolor);
46 static void NDECL(really_move_cursor);
47 static void NDECL(check_and_set_font);
48 static boolean NDECL(check_font_widths);
49 static void NDECL(set_known_good_console_font);
50 static void NDECL(restore_original_console_font);
52 /* Win32 Console handles for input and output */
56 /* Win32 Screen buffer,coordinate,console I/O information */
57 CONSOLE_SCREEN_BUFFER_INFO csbi, origcsbi;
61 /* Support for changing console font if existing glyph widths are too wide */
62 boolean console_font_changed;
63 CONSOLE_FONT_INFOEX original_console_font_info;
64 UINT original_console_code_page;
66 extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
67 extern int redirect_stdout;
69 /* Flag for whether NetHack was launched via the GUI, not the command line.
70 * The reason we care at all, is so that we can get
71 * a final RETURN at the end of the game when launched from the GUI
72 * to prevent the scoreboard (or panic message :-|) from vanishing
73 * immediately after it is displayed, yet not bother when started
74 * from the command line.
77 /* Flag for whether unicode is supported */
78 static boolean has_unicode;
79 static boolean init_ttycolor_completed;
81 static boolean display_cursor_info = FALSE;
84 static void NDECL(adjust_palette);
85 static int FDECL(match_color_name, (const char *));
86 typedef HWND(WINAPI *GETCONSOLEWINDOW)();
87 static HWND GetConsoleHandle(void);
88 static HWND GetConsoleHwnd(void);
89 static boolean altered_palette;
90 static COLORREF UserDefinedColors[CLR_MAX];
91 static COLORREF NetHackColors[CLR_MAX] = {
92 0x00000000, 0x00c80000, 0x0000c850, 0x00b4b432, 0x000000d2, 0x00800080,
93 0x000064b4, 0x00c0c0c0, 0x00646464, 0x00f06464, 0x0000ff00, 0x00ffff00,
94 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
96 static COLORREF DefaultColors[CLR_MAX] = {
97 0x00000000, 0x00800000, 0x00008000, 0x00808000, 0x00000080, 0x00800080,
98 0x00008080, 0x00c0c0c0, 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
99 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
107 int current_nhattr[ATR_INVERSE+1];
111 (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
112 (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
114 {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE},
117 static DWORD ccount, acount;
122 int ttycolors[CLR_MAX];
123 int ttycolors_inv[CLR_MAX];
125 #define MAX_OVERRIDES 256
126 unsigned char key_overrides[MAX_OVERRIDES];
127 static char nullstr[] = "";
128 char erase_char, kill_char;
129 #define DEFTEXTCOLOR ttycolors[7]
131 /* dynamic keystroke handling .DLL support */
132 typedef int(__stdcall *PROCESS_KEYSTROKE)(HANDLE, INPUT_RECORD *, boolean *,
135 typedef int(__stdcall *NHKBHIT)(HANDLE, INPUT_RECORD *);
137 typedef int(__stdcall *CHECKINPUT)(HANDLE, INPUT_RECORD *, DWORD *, BOOLEAN_P,
138 int, int *, coord *);
140 typedef int(__stdcall *SOURCEWHERE)(char **);
142 typedef int(__stdcall *SOURCEAUTHOR)(char **);
144 typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
147 PROCESS_KEYSTROKE pProcessKeystroke;
149 CHECKINPUT pCheckInput;
150 SOURCEWHERE pSourceWhere;
151 SOURCEAUTHOR pSourceAuthor;
152 KEYHANDLERNAME pKeyHandlerName;
155 * Called after returning from ! or ^Z
160 console_font_changed = FALSE;
162 check_and_set_font();
168 kill_char = 21; /* cntl-U */
169 iflags.cbreak = TRUE;
173 for (k = 0; k < CLR_MAX; ++k)
174 ttycolors[k] = NO_COLOR;
178 /* reset terminal to original state */
183 cmov(ttyDisplay->curx, ttyDisplay->cury);
188 restore_original_console_font();
191 /* called by init_nhwindows() and resume_nhwindows() */
200 has_unicode = ((GetVersion() & 0x80000000) == 0);
204 tty_startup(wid, hgt)
207 int twid = origcsbi.srWindow.Right - origcsbi.srWindow.Left + 1;
212 *hgt = origcsbi.srWindow.Bottom - origcsbi.srWindow.Top + 1;
213 set_option_mod_status("mouse_support", SET_IN_GAME);
217 tty_number_pad(state)
226 tty_number_pad(1); /* make keypad send digits */
233 really_move_cursor();
234 if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
240 FillConsoleOutputAttribute(
241 hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
242 csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
243 FillConsoleOutputCharacter(
244 hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
246 FlushConsoleInputBuffer(hConIn);
250 CtrlHandler(ctrltype)
254 /* case CTRL_C_EVENT: */
255 case CTRL_BREAK_EVENT:
257 case CTRL_CLOSE_EVENT:
258 case CTRL_LOGOFF_EVENT:
259 case CTRL_SHUTDOWN_EVENT:
260 getreturn_enabled = FALSE;
261 #ifndef NOSAVEONHANGUP
264 #if defined(SAFERHANGUP)
265 CloseHandle(hConIn); /* trigger WAIT_FAILED */
273 /* called by init_tty in wintty.c for WIN32 port only */
285 /* The following lines of code were suggested by
286 * Bob Landau of Microsoft WIN32 Developer support,
287 * as the only current means of determining whether
288 * we were launched from the command prompt, or from
289 * the NT program manager. M. Allison
291 hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
294 GetConsoleScreenBufferInfo(hStdOut, &origcsbi);
296 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
297 HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
299 if (!hStdOut && !hStdIn) {
302 AttachConsole(GetCurrentProcessId());
303 /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
304 freopen("CON", "w", stdout);
305 freopen("CON", "r", stdin);
313 /* Obtain handles for the standard Console I/O devices */
314 hConIn = GetStdHandle(STD_INPUT_HANDLE);
315 hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
317 load_keyboard_handler();
318 /* Initialize the function pointer that points to
319 * the kbhit() equivalent, in this TTY case nttty_kbhit()
321 nt_kbhit = nttty_kbhit;
323 GetConsoleMode(hConIn, &cmode);
324 #ifdef NO_MOUSE_ALLOWED
325 mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT
326 | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT;
328 mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
329 | ENABLE_WINDOW_INPUT;
331 /* Turn OFF the settings specified in the mask */
333 #ifndef NO_MOUSE_ALLOWED
334 cmode |= ENABLE_MOUSE_INPUT;
336 SetConsoleMode(hConIn, cmode);
337 if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
338 /* Unable to set control handler */
339 cmode = 0; /* just to have a statement to break on for debugger */
342 console.cursor.X = console.cursor.Y = 0;
343 really_move_cursor();
347 process_keystroke(ir, valid, numberpad, portdebug)
353 int ch = pProcessKeystroke(hConIn, ir, valid, numberpad, portdebug);
354 /* check for override */
355 if (ch && ch < MAX_OVERRIDES && key_overrides[ch])
356 ch = key_overrides[ch];
363 return pNHkbhit(hConIn, &ir);
371 GetConsoleScreenBufferInfo(hConOut, &csbi);
373 lines = csbi.srWindow.Bottom - (csbi.srWindow.Top + 1);
374 cols = csbi.srWindow.Right - (csbi.srWindow.Left + 1);
379 if ((LI < 25) || (CO < 80)) {
388 SetConsoleScreenBufferSize(hConOut, newcoord);
398 really_move_cursor();
399 return (program_state.done_hup)
401 : pCheckInput(hConIn, &ir, &count, iflags.num_pad, 0, &mod,
412 really_move_cursor();
413 ch = (program_state.done_hup)
415 : pCheckInput(hConIn, &ir, &count, iflags.num_pad, 1, mod, &cc);
427 char oldtitle[BUFSZ], newtitle[BUFSZ];
428 if (display_cursor_info && wizard) {
430 if (GetConsoleTitle(oldtitle, BUFSZ)) {
433 Sprintf(newtitle, "%-55s tty=(%02d,%02d) nttty=(%02d,%02d)", oldtitle,
434 ttyDisplay->curx, ttyDisplay->cury, console.cursor.X, console.cursor.Y);
435 (void) SetConsoleTitle(newtitle);
439 console.cursor.X = ttyDisplay->curx;
440 console.cursor.Y = ttyDisplay->cury;
442 SetConsoleCursorPosition(hConOut, console.cursor);
449 ttyDisplay->cury = y;
450 ttyDisplay->curx = x;
451 console.cursor.X = x;
452 console.cursor.Y = y;
459 console.cursor.X = x;
460 console.cursor.Y = y;
461 ttyDisplay->curx = x;
462 ttyDisplay->cury = y;
469 console.cursor.X = ttyDisplay->curx;
470 console.cursor.Y = ttyDisplay->cury;
476 xputc2_core(ch1, ch2)
480 unsigned char buf[2];
486 attrs[0] = attrs[1] = console.attr;
488 WriteConsoleOutputAttribute(hConOut, (WORD *)(&attrs), 2,
489 console.cursor, &acount);
490 WriteConsoleOutputCharacter(hConOut, buf, 2,
491 console.cursor, &ccount);
492 console.cursor.X += 2;
500 /* wintty.c
\82Å
\82Í 1
\83o
\83C
\83g
\96\88\82É curx
\82ð
\89Á
\8eZ
\82·
\82é
\82ª
\81A
\82±
\82±
\82Í
501 2
\83o
\83C
\83g
\82½
\82Ü
\82Á
\82Ä
\82©
\82ç
\8cÄ
\82Ñ
\8fo
\82³
\82ê
\82é
\82Ì
\82Å
\81A1
\95¶
\8e\9a\95ª
\90æ
\82É
\90i
\82ñ
\82Å
502 \82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81B
\8f]
\82Á
\82Ä 1
\82ð
\88ø
\82
\81B */
503 console.cursor.X = ttyDisplay->curx - 1;
504 console.cursor.Y = ttyDisplay->cury;
506 xputc2_core(ch1, ch2);
515 int slen = strlen(s);
518 console.cursor.X = ttyDisplay->curx;
519 console.cursor.Y = ttyDisplay->cury;
523 for (k = 0; k < slen && s[k]; ++k)
528 /* xputc_core() and g_putch() are the only
529 * two routines that actually place output
536 boolean inverse = FALSE;
542 console.cursor.X = 1;
548 inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
549 console.attr = (inverse) ?
550 ttycolors_inv[console.current_nhcolor] :
551 ttycolors[console.current_nhcolor];
552 if (console.current_nhattr[ATR_BOLD])
553 console.attr |= (inverse) ?
554 BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
555 WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
557 /* Avoid bug in ANSI API on WinNT */
560 rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, &ch, 1, c2, 2);
561 WriteConsoleOutputCharacterW(hConOut, c2, rc, console.cursor, &ccount);
563 WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
570 * Overrides wintty.c function of the same name
571 * for win32. It is used for glyphs only, not text.
574 /* CP437 to Unicode mapping according to the Unicode Consortium */
575 static const WCHAR cp437[] = {
576 0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
577 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
578 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
579 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
580 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
581 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
582 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
583 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
584 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
585 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
586 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
587 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
588 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
589 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
590 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
591 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
592 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
593 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
594 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
595 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
596 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
597 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
598 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
599 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
600 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
601 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
602 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
603 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
604 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
605 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
606 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
607 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
614 boolean inverse = FALSE;
615 unsigned char ch = (unsigned char) in_ch;
617 console.cursor.X = ttyDisplay->curx;
618 console.cursor.Y = ttyDisplay->cury;
620 inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
621 console.attr = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse) ?
622 ttycolors_inv[console.current_nhcolor] :
623 ttycolors[console.current_nhcolor];
624 if (console.current_nhattr[ATR_BOLD])
625 console.attr |= (inverse) ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
626 WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
629 WriteConsoleOutputCharacterW(hConOut, &cp437[ch], 1, console.cursor, &ccount);
631 WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
638 console.cursor.X = ttyDisplay->curx;
639 console.cursor.Y = ttyDisplay->cury;
640 cx = CO - console.cursor.X;
641 FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, cx, console.cursor, &acount);
642 FillConsoleOutputCharacter(hConOut, ' ', cx, console.cursor, &ccount);
643 tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
649 if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
655 FillConsoleOutputAttribute(
656 hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
657 csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
658 FillConsoleOutputCharacter(
659 hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
673 console.cursor.X = console.cursor.Y = 0;
674 ttyDisplay->curx = ttyDisplay->cury = 0;
680 console.cursor.X = ttyDisplay->curx;
681 console.cursor.Y = ttyDisplay->cury;
688 int cy = ttyDisplay->cury + 1;
689 if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
693 newcoord.X = ttyDisplay->curx;
694 newcoord.Y = ttyDisplay->cury;
695 FillConsoleOutputAttribute(
696 hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
697 csbi.dwSize.X * csbi.dwSize.Y - cy, newcoord, &ccnt);
698 FillConsoleOutputCharacter(hConOut, ' ',
699 csbi.dwSize.X * csbi.dwSize.Y - cy,
702 tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
713 volatile int junk; /* prevent optimizer from eliminating loop below */
718 /* delay 50 ms - uses ANSI C clock() function now */
723 while (goal > clock()) {
724 k = junk; /* Do nothing */
733 * CLR_BROWN 3 low-intensity yellow
737 * CLR_GRAY 7 low-intensity white
740 * CLR_BRIGHT_GREEN 10
743 * CLR_BRIGHT_MAGENTA 13
754 ttycolors[CLR_BLACK] = FOREGROUND_INTENSITY; /* fix by Quietust */
755 ttycolors[CLR_RED] = FOREGROUND_RED;
756 ttycolors[CLR_GREEN] = FOREGROUND_GREEN;
757 ttycolors[CLR_BROWN] = FOREGROUND_GREEN | FOREGROUND_RED;
758 ttycolors[CLR_BLUE] = FOREGROUND_BLUE;
759 ttycolors[CLR_MAGENTA] = FOREGROUND_BLUE | FOREGROUND_RED;
760 ttycolors[CLR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE;
761 ttycolors[CLR_GRAY] = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
762 ttycolors[NO_COLOR] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
763 ttycolors[CLR_ORANGE] = FOREGROUND_RED | FOREGROUND_INTENSITY;
764 ttycolors[CLR_BRIGHT_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
765 ttycolors[CLR_YELLOW] = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
766 ttycolors[CLR_BRIGHT_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
767 ttycolors[CLR_BRIGHT_MAGENTA]=FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
768 ttycolors[CLR_BRIGHT_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
769 ttycolors[CLR_WHITE] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED
770 | FOREGROUND_INTENSITY;
772 ttycolors_inv[CLR_BLACK] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
773 | BACKGROUND_INTENSITY;
774 ttycolors_inv[CLR_RED] = BACKGROUND_RED | BACKGROUND_INTENSITY;
775 ttycolors_inv[CLR_GREEN] = BACKGROUND_GREEN;
776 ttycolors_inv[CLR_BROWN] = BACKGROUND_GREEN | BACKGROUND_RED;
777 ttycolors_inv[CLR_BLUE] = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
778 ttycolors_inv[CLR_MAGENTA] = BACKGROUND_BLUE | BACKGROUND_RED;
779 ttycolors_inv[CLR_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE;
780 ttycolors_inv[CLR_GRAY] = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE;
781 ttycolors_inv[NO_COLOR] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
782 ttycolors_inv[CLR_ORANGE] = BACKGROUND_RED | BACKGROUND_INTENSITY;
783 ttycolors_inv[CLR_BRIGHT_GREEN]= BACKGROUND_GREEN | BACKGROUND_INTENSITY;
784 ttycolors_inv[CLR_YELLOW] = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
785 ttycolors_inv[CLR_BRIGHT_BLUE] = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
786 ttycolors_inv[CLR_BRIGHT_MAGENTA] =BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY;
787 ttycolors_inv[CLR_BRIGHT_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
788 ttycolors_inv[CLR_WHITE] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
789 | BACKGROUND_INTENSITY;
792 ttycolors[0] = FOREGROUND_INTENSITY;
793 ttycolors_inv[0] = BACKGROUND_INTENSITY;
794 for (k = 1; k < SIZE(ttycolors); ++k) {
795 ttycolors[k] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
796 ttycolors_inv[k] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
799 init_ttycolor_completed = TRUE;
801 #endif /* TEXTCOLOR */
807 if ((color >= 0) && (color < CLR_MAX))
810 if ((color == CLR_BLACK) || (color == CLR_WHITE) || (color == NO_COLOR))
818 term_start_attr(int attrib)
820 console.current_nhattr[attrib] = TRUE;
821 if (attrib) console.current_nhattr[ATR_NONE] = FALSE;
825 term_end_attr(int attrib)
836 console.current_nhattr[attrib] = FALSE;
837 console.current_nhattr[ATR_NONE] = TRUE;
838 /* re-evaluate all attr now for performance at output time */
839 for (k=ATR_NONE; k <= ATR_INVERSE; ++k) {
840 if (console.current_nhattr[k])
841 console.current_nhattr[ATR_NONE] = FALSE;
846 term_end_raw_bold(void)
848 term_end_attr(ATR_BOLD);
852 term_start_raw_bold(void)
854 term_start_attr(ATR_BOLD);
858 term_start_color(int color)
861 if (color >= 0 && color < CLR_MAX) {
862 console.current_nhcolor = color;
865 console.current_nhcolor = NO_COLOR;
872 console.foreground = DEFTEXTCOLOR;
874 console.attr = (console.foreground | console.background);
875 console.current_nhcolor = NO_COLOR;
881 term_start_attr(ATR_BOLD);
887 term_end_attr(ATR_BOLD);
890 #ifndef NO_MOUSE_ALLOWED
892 toggle_mouse_support()
895 GetConsoleMode(hConIn, &cmode);
896 if (iflags.wc_mouse_support)
897 cmode |= ENABLE_MOUSE_INPUT;
899 cmode &= ~ENABLE_MOUSE_INPUT;
900 SetConsoleMode(hConIn, cmode);
904 /* handle tty options updates here */
906 nttty_preference_update(pref)
909 if (stricmp(pref, "mouse_support") == 0) {
910 #ifndef NO_MOUSE_ALLOWED
911 toggle_mouse_support();
914 if (stricmp(pref, "symset") == 0)
915 check_and_set_font();
921 win32con_debug_keystrokes()
927 while (!valid || ch != 27) {
928 nocmov(ttyDisplay->curx, ttyDisplay->cury);
929 ReadConsoleInput(hConIn, &ir, 1, &count);
930 if ((ir.EventType == KEY_EVENT) && ir.Event.KeyEvent.bKeyDown)
931 ch = process_keystroke(&ir, &valid, iflags.num_pad, 1);
936 win32con_handler_info()
940 if (!pSourceAuthor && !pSourceWhere)
941 pline("Keyboard handler source info and author unavailable.");
943 if (pKeyHandlerName && pKeyHandlerName(&buf, 1)) {
945 xputs("Keystroke handler loaded: \n ");
948 if (pSourceAuthor && pSourceAuthor(&buf)) {
950 xputs("Keystroke handler Author: \n ");
953 if (pSourceWhere && pSourceWhere(&buf)) {
955 xputs("Keystroke handler source code available at:\n ");
958 xputs("\nPress any key to resume.");
965 win32con_toggle_cursor_info()
967 display_cursor_info = !display_cursor_info;
975 char digits[] = "0123456789";
976 int length, i, idx, val;
986 if (length < 1 || length > 3)
988 for (i = 0; i < length; i++)
989 if (!index(digits, kp[i]))
993 if (length < 1 || length > 3)
995 for (i = 0; i < length; i++)
996 if (!index(digits, op[i]))
1000 if (idx >= MAX_OVERRIDES || idx < 0 || val >= MAX_OVERRIDES || val < 1)
1002 key_overrides[idx] = val;
1006 load_keyboard_handler()
1008 char suffx[] = ".dll";
1010 #define MAX_DLLNAME 25
1011 char kh[MAX_ALTKEYHANDLER];
1012 if (iflags.altkeyhandler[0]) {
1013 if (hLibrary) { /* already one loaded apparently */
1014 FreeLibrary(hLibrary);
1015 hLibrary = (HANDLE) 0;
1016 pNHkbhit = (NHKBHIT) 0;
1017 pCheckInput = (CHECKINPUT) 0;
1018 pSourceWhere = (SOURCEWHERE) 0;
1019 pSourceAuthor = (SOURCEAUTHOR) 0;
1020 pKeyHandlerName = (KEYHANDLERNAME) 0;
1021 pProcessKeystroke = (PROCESS_KEYSTROKE) 0;
1023 if ((truncspot = strstri(iflags.altkeyhandler, suffx)) != 0)
1025 (void) strncpy(kh, iflags.altkeyhandler,
1026 (MAX_ALTKEYHANDLER - sizeof suffx) - 1);
1027 kh[(MAX_ALTKEYHANDLER - sizeof suffx) - 1] = '\0';
1029 Strcpy(iflags.altkeyhandler, kh);
1030 hLibrary = LoadLibrary(kh);
1032 pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
1033 hLibrary, TEXT("ProcessKeystroke"));
1034 pNHkbhit = (NHKBHIT) GetProcAddress(hLibrary, TEXT("NHkbhit"));
1036 (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
1038 (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
1040 (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
1041 pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
1042 hLibrary, TEXT("KeyHandlerName"));
1045 if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) {
1047 FreeLibrary(hLibrary);
1048 hLibrary = (HANDLE) 0;
1049 pNHkbhit = (NHKBHIT) 0;
1050 pCheckInput = (CHECKINPUT) 0;
1051 pSourceWhere = (SOURCEWHERE) 0;
1052 pSourceAuthor = (SOURCEAUTHOR) 0;
1053 pKeyHandlerName = (KEYHANDLERNAME) 0;
1054 pProcessKeystroke = (PROCESS_KEYSTROKE) 0;
1056 (void) strncpy(kh, "nhdefkey.dll",
1057 (MAX_ALTKEYHANDLER - sizeof suffx) - 1);
1058 kh[(MAX_ALTKEYHANDLER - sizeof suffx) - 1] = '\0';
1059 Strcpy(iflags.altkeyhandler, kh);
1060 hLibrary = LoadLibrary(kh);
1062 pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
1063 hLibrary, TEXT("ProcessKeystroke"));
1065 (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
1066 pNHkbhit = (NHKBHIT) GetProcAddress(hLibrary, TEXT("NHkbhit"));
1068 (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
1070 (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
1071 pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
1072 hLibrary, TEXT("KeyHandlerName"));
1075 if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) {
1077 raw_printf("\nNetHack was unable to load keystroke handler.\n");
1079 FreeLibrary(hLibrary);
1080 hLibrary = (HANDLE) 0;
1081 raw_printf("\nNetHack keystroke handler is invalid.\n");
1087 /* this is used as a printf() replacement when the window
1088 * system isn't initialized yet
1091 VA_DECL(const char *, fmt)
1093 char buf[ROWNO * COLNO]; /* worst case scenario */
1095 VA_INIT(fmt, const char *);
1096 Vsprintf(buf, fmt, VA_ARGS);
1097 if (redirect_stdout)
1098 fprintf(stdout, "%s", buf);
1100 if(!init_ttycolor_completed)
1107 console.cursor.X = ttyDisplay->curx;
1108 console.cursor.Y = ttyDisplay->cury;
1113 jbuffer(*(str++), NULL, xputc_core, xputc2_core);
1118 curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
1127 VA_DECL(const char *, s)
1131 VA_INIT(s, const char *);
1132 /* error() may get called before tty is initialized */
1133 if (iflags.window_inited)
1136 (void) vsprintf(&buf[1], s, VA_ARGS);
1138 really_move_cursor();
1146 really_move_cursor();
1151 tty_change_color(color_number, rgb, reverse)
1152 int color_number, reverse;
1155 /* Map NetHack color index to NT Console palette index */
1156 int idx, win32_color_number[] = {
1157 0, /* CLR_BLACK 0 */
1159 2, /* CLR_GREEN 2 */
1160 6, /* CLR_BROWN 3 */
1162 5, /* CLR_MAGENTA 5 */
1166 12, /* CLR_ORANGE 9 */
1167 10, /* CLR_BRIGHT_GREEN 10 */
1168 14, /* CLR_YELLOW 11 */
1169 9, /* CLR_BRIGHT_BLUE 12 */
1170 13, /* CLR_BRIGHT_MAGENTA 13 */
1171 11, /* CLR_BRIGHT_CYAN 14 */
1172 15 /* CLR_WHITE 15 */
1175 if (color_number < 0) { /* indicates OPTIONS=palette with no value */
1176 /* copy the NetHack palette into UserDefinedColors */
1177 for (k = 0; k < CLR_MAX; k++)
1178 UserDefinedColors[k] = NetHackColors[k];
1179 } else if (color_number >= 0 && color_number < CLR_MAX) {
1180 if (!altered_palette) {
1181 /* make sure a full suite is available */
1182 for (k = 0; k < CLR_MAX; k++)
1183 UserDefinedColors[k] = DefaultColors[k];
1185 idx = win32_color_number[color_number];
1186 UserDefinedColors[idx] = rgb;
1188 altered_palette = TRUE;
1192 tty_get_color_string()
1201 const struct others {
1203 const char *colorname;
1205 { CLR_MAGENTA, "purple" },
1206 { CLR_BRIGHT_MAGENTA, "bright purple" },
1207 { NO_COLOR, "dark gray" },
1208 { NO_COLOR, "dark grey" },
1209 { CLR_GRAY, "grey" },
1213 for (cnt = 0; cnt < CLR_MAX; ++cnt) {
1214 if (!strcmpi(c, c_obj_colors[cnt]))
1217 for (cnt = 0; cnt < SIZE(othernames); ++cnt) {
1218 if (!strcmpi(c, othernames[cnt].colorname))
1219 return othernames[cnt].idx;
1225 * Returns 0 if badoption syntax
1228 alternative_palette(op)
1232 * palette:color-R-G-B
1233 * OPTIONS=palette:green-4-3-1, palette:0-0-0-0
1235 int fieldcnt, color_number, rgb, red, green, blue;
1236 char *fields[4], *cp;
1239 change_color(-1, 0, 0); /* indicates palette option with
1240 no value meaning "load an entire
1241 hard-coded NetHack palette." */
1245 cp = fields[0] = op;
1246 for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
1247 cp = index(cp, '-');
1250 fields[fieldcnt] = cp;
1253 for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
1254 *(fields[fieldcnt]) = '\0';
1258 for (fieldcnt = 0; fieldcnt < 4; ++fieldcnt) {
1259 if (fieldcnt == 0 && isalpha(*(fields[0]))) {
1260 color_number = match_color_name(fields[0]);
1261 if (color_number == -1)
1264 int dcount = 0, cval = 0;
1265 cp = fields[fieldcnt];
1266 if (*cp == '\\' && index("0123456789xXoO", cp[1])) {
1267 const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
1270 if (*cp == 'x' || *cp == 'X')
1271 for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
1272 cval = (int) ((cval * 16) + (dp - hex) / 2);
1273 else if (*cp == 'o' || *cp == 'O')
1274 for (++cp; (index("01234567", *cp)) && (dcount++ < 3);
1276 cval = (cval * 8) + (*cp - '0');
1280 for (; *cp && (index("0123456789", *cp)) && (dcount++ < 3);
1282 cval = (cval * 10) + (*cp - '0');
1286 color_number = cval;
1300 rgb = RGB(red, green, blue);
1301 if (color_number >= 0 && color_number < CLR_MAX)
1302 change_color(color_number, rgb, 0);
1307 * This uses an undocumented method to set console attributes
1308 * at runtime including console palette
1310 * VOID WINAPI SetConsolePalette(COLORREF palette[16])
1312 * Author: James Brown at www.catch22.net
1314 * Set palette of current console.
1315 * Palette should be of the form:
1317 * COLORREF DefaultColors[CLR_MAX] =
1319 * 0x00000000, 0x00800000, 0x00008000, 0x00808000,
1320 * 0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0,
1321 * 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
1322 * 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
1326 #pragma pack(push, 1)
1329 * Structure to send console via WM_SETCONSOLEINFO
1331 typedef struct _CONSOLE_INFO {
1333 COORD ScreenBufferSize;
1349 USHORT ScreenColors;
1352 ULONG HistoryBufferSize;
1353 ULONG NumberOfHistoryBuffers;
1355 COLORREF ColorTable[16];
1360 WCHAR ConsoleTitle[0x100];
1365 BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci);
1366 static void GetConsoleSizeInfo(CONSOLE_INFO *pci);
1367 VOID WINAPI SetConsolePalette(COLORREF crPalette[16]);
1370 adjust_palette(VOID_ARGS)
1372 SetConsolePalette(UserDefinedColors);
1373 altered_palette = 0;
1377 /* only in Win2k+ (use FindWindow for NT4) */
1378 /* HWND WINAPI GetConsoleWindow(); */
1380 /* Undocumented console message */
1381 #define WM_SETCONSOLEINFO (WM_USER + 201)
1384 SetConsolePalette(COLORREF palette[16])
1386 CONSOLE_INFO ci = { sizeof(ci) };
1388 HWND hwndConsole = GetConsoleHandle();
1390 /* get current size/position settings rather than using defaults.. */
1391 GetConsoleSizeInfo(&ci);
1393 /* set these to zero to keep current settings */
1394 ci.FontSize.X = 0; /* def = 8 */
1395 ci.FontSize.Y = 0; /* def = 12 */
1396 ci.FontFamily = 0; /* def = 0x30 = FF_MODERN|FIXED_PITCH */
1397 ci.FontWeight = 0; /* 0x400; */
1398 /* lstrcpyW(ci.FaceName, L"Terminal"); */
1399 ci.FaceName[0] = L'\0';
1402 ci.FullScreen = FALSE;
1403 ci.QuickEdit = TRUE;
1404 ci.AutoPosition = 0x10000;
1405 ci.InsertMode = TRUE;
1406 ci.ScreenColors = MAKEWORD(0x7, 0x0);
1407 ci.PopupColors = MAKEWORD(0x5, 0xf);
1409 ci.HistoryNoDup = FALSE;
1410 ci.HistoryBufferSize = 50;
1411 ci.NumberOfHistoryBuffers = 4;
1414 for (i = 0; i < 16; i++)
1415 ci.ColorTable[i] = palette[i];
1417 ci.CodePage = GetConsoleOutputCP();
1418 ci.Hwnd = hwndConsole;
1420 lstrcpyW(ci.ConsoleTitle, L"");
1422 SetConsoleInfo(hwndConsole, &ci);
1426 * Wrapper around WM_SETCONSOLEINFO. We need to create the
1427 * necessary section (file-mapping) object in the context of the
1428 * process which owns the console, before posting the message
1431 SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci)
1433 DWORD dwConsoleOwnerPid;
1435 HANDLE hSection, hDupSection;
1440 * Open the process which "owns" the console
1442 GetWindowThreadProcessId(hwndConsole, &dwConsoleOwnerPid);
1443 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
1446 * Create a SECTION object backed by page-file, then map a view of
1447 * this section into the owner process so we can write the contents
1448 * of the CONSOLE_INFO buffer into it
1450 hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
1454 * Copy our console structure into the section-object
1456 ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0,
1458 memcpy(ptrView, pci, pci->Length);
1459 UnmapViewOfFile(ptrView);
1462 * Map the memory into owner process
1464 DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection, 0,
1465 FALSE, DUPLICATE_SAME_ACCESS);
1467 /* Send console window the "update" message */
1468 SendMessage(hwndConsole, WM_SETCONSOLEINFO, (WPARAM) hDupSection, 0);
1473 hThread = CreateRemoteThread(hProcess, 0, 0,
1474 (LPTHREAD_START_ROUTINE) CloseHandle,
1477 CloseHandle(hThread);
1478 CloseHandle(hSection);
1479 CloseHandle(hProcess);
1485 * Fill the CONSOLE_INFO structure with information
1486 * about the current console window
1489 GetConsoleSizeInfo(CONSOLE_INFO *pci)
1491 CONSOLE_SCREEN_BUFFER_INFO csbi;
1493 HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
1495 GetConsoleScreenBufferInfo(hConsoleOut, &csbi);
1497 pci->ScreenBufferSize = csbi.dwSize;
1498 pci->WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
1499 pci->WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
1500 pci->WindowPosX = csbi.srWindow.Left;
1501 pci->WindowPosY = csbi.srWindow.Top;
1505 GetConsoleHandle(void)
1507 HMODULE hMod = GetModuleHandle("kernel32.dll");
1508 GETCONSOLEWINDOW pfnGetConsoleWindow =
1509 (GETCONSOLEWINDOW) GetProcAddress(hMod, "GetConsoleWindow");
1510 if (pfnGetConsoleWindow)
1511 return pfnGetConsoleWindow();
1513 return GetConsoleHwnd();
1517 GetConsoleHwnd(void)
1521 char OldTitle[1024], NewTitle[1024], TestTitle[1024];
1523 /* Get current window title */
1524 GetConsoleTitle(OldTitle, sizeof OldTitle);
1526 (void) sprintf(NewTitle, "NETHACK%d/%d", GetTickCount(),
1527 GetCurrentProcessId());
1528 SetConsoleTitle(NewTitle);
1530 GetConsoleTitle(TestTitle, sizeof TestTitle);
1531 while (strcmp(TestTitle, NewTitle) != 0) {
1534 GetConsoleTitle(TestTitle, sizeof TestTitle);
1536 hwndFound = FindWindow(NULL, NewTitle);
1537 SetConsoleTitle(OldTitle);
1538 /* printf("%d iterations\n", iterations); */
1541 #endif /*CHANGE_COLOR*/
1543 static int CALLBACK EnumFontCallback(
1544 const LOGFONTW * lf, const TEXTMETRICW * tm, DWORD fontType, LPARAM lParam)
1546 LOGFONTW * lf_ptr = (LOGFONTW *) lParam;
1551 /* check_and_set_font ensures that the current font will render the symbols
1552 * that are currently being used correctly. If they will not be rendered
1553 * correctly, then it will change the font to a known good font.
1556 check_and_set_font()
1558 if (!check_font_widths()) {
1559 raw_print("WARNING: glyphs too wide in console font."
1560 " Changing code page to 437 and font to Consolas\n");
1561 set_known_good_console_font();
1565 /* check_font_widths returns TRUE if all glyphs in current console font
1566 * fit within the width of a single console cell.
1571 CONSOLE_FONT_INFOEX console_font_info;
1572 console_font_info.cbSize = sizeof(console_font_info);
1573 BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
1574 &console_font_info);
1576 /* get console window and DC
1577 * NOTE: the DC from the console window does not have the correct
1578 * font selected at this point.
1580 HWND hWnd = GetConsoleWindow();
1581 HDC hDC = GetDC(hWnd);
1583 LOGFONTW logical_font;
1584 logical_font.lfCharSet = DEFAULT_CHARSET;
1585 wcscpy(logical_font.lfFaceName, console_font_info.FaceName);
1586 logical_font.lfPitchAndFamily = 0;
1588 /* getting matching console font */
1589 LOGFONTW matching_log_font = { 0 };
1590 EnumFontFamiliesExW(hDC, &logical_font, EnumFontCallback,
1591 (LPARAM) &matching_log_font, 0);
1593 if (matching_log_font.lfHeight == 0) {
1594 raw_print("Unable to enumerate system fonts\n");
1598 /* create font matching console font */
1599 LOGFONTW console_font_log_font = matching_log_font;
1600 console_font_log_font.lfWeight = console_font_info.FontWeight;
1601 console_font_log_font.lfHeight = console_font_info.dwFontSize.Y;
1602 console_font_log_font.lfWidth = 0;
1603 HFONT console_font = CreateFontIndirectW(&console_font_log_font);
1605 if (console_font == NULL) {
1606 raw_print("Unable to create console font\n");
1611 HGDIOBJ saved_font = SelectObject(hDC, console_font);
1613 /* determine whether it is a true type font */
1615 success = GetTextMetricsA(hDC, &tm);
1618 raw_print("Unable to get console font text metrics\n");
1622 boolean isTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
1624 /* determine which glyphs are used */
1626 memset(used, 0, sizeof(used));
1627 for (int i = 0; i < SYM_MAX; i++) {
1628 used[l_syms[i]] = TRUE;
1629 used[r_syms[i]] = TRUE;
1632 int wcUsedCount = 0;
1633 wchar_t wcUsed[256];
1634 for (int i = 0; i < sizeof(used); i++)
1636 wcUsed[wcUsedCount++] = cp437[i];
1638 /* measure the set of used glyphs to ensure they fit */
1639 boolean all_glyphs_fit = TRUE;
1641 for (int i = 0; i < wcUsedCount; i++) {
1645 success = GetCharABCWidthsW(hDC, wcUsed[i], wcUsed[i], &abc);
1646 width = abc.abcA + abc.abcB + abc.abcC;
1648 success = GetCharWidthW(hDC, wcUsed[i], wcUsed[i], &width);
1651 if (success && width > console_font_info.dwFontSize.X) {
1652 all_glyphs_fit = FALSE;
1659 SelectObject(hDC, saved_font);
1660 DeleteObject(console_font);
1662 return all_glyphs_fit;
1665 /* set_known_good_console_font sets the code page and font used by the console
1666 * to settings know to work well with NetHack. It also saves the original
1667 * settings so that they can be restored prior to NetHack exit.
1670 set_known_good_console_font()
1672 CONSOLE_FONT_INFOEX console_font_info;
1673 console_font_info.cbSize = sizeof(console_font_info);
1674 BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
1675 &console_font_info);
1677 console_font_changed = TRUE;
1678 original_console_font_info = console_font_info;
1679 original_console_code_page = GetConsoleOutputCP();
1681 wcscpy_s(console_font_info.FaceName,
1682 sizeof(console_font_info.FaceName)
1683 / sizeof(console_font_info.FaceName[0]),
1686 success = SetConsoleOutputCP(437);
1688 raw_print("Unable to set console code page to 437\n");
1690 success = SetCurrentConsoleFontEx(hConOut, FALSE, &console_font_info);
1692 raw_print("Unable to set console font to Consolas\n");
1695 /* restore_original_console_font will restore the console font and code page
1696 * settings to what they were when NetHack was launched.
1699 restore_original_console_font()
1701 if (console_font_changed) {
1703 raw_print("Restoring original font and code page\n");
1704 success = SetConsoleOutputCP(original_console_code_page);
1706 raw_print("Unable to restore original code page\n");
1708 success = SetCurrentConsoleFontEx(hConOut, FALSE,
1709 &original_console_font_info);
1711 raw_print("Unable to restore original font\n");
1713 console_font_changed = FALSE;