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));
42 static void FDECL(xputc2_core, (unsigned int, unsigned int));
44 void FDECL(cmov, (int, int));
45 void FDECL(nocmov, (int, int));
46 int FDECL(process_keystroke,
47 (INPUT_RECORD *, boolean *, BOOLEAN_P numberpad, int portdebug));
48 static void NDECL(init_ttycolor);
49 static void NDECL(really_move_cursor);
50 static void NDECL(check_and_set_font);
51 static boolean NDECL(check_font_widths);
52 static void NDECL(set_known_good_console_font);
53 static void NDECL(restore_original_console_font);
55 /* Win32 Console handles for input and output */
59 /* Win32 Screen buffer,coordinate,console I/O information */
60 CONSOLE_SCREEN_BUFFER_INFO csbi, origcsbi;
64 /* Support for changing console font if existing glyph widths are too wide */
65 boolean console_font_changed;
66 CONSOLE_FONT_INFOEX original_console_font_info;
67 UINT original_console_code_page;
69 extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
70 extern int redirect_stdout;
72 /* Flag for whether NetHack was launched via the GUI, not the command line.
73 * The reason we care at all, is so that we can get
74 * a final RETURN at the end of the game when launched from the GUI
75 * to prevent the scoreboard (or panic message :-|) from vanishing
76 * immediately after it is displayed, yet not bother when started
77 * from the command line.
80 /* Flag for whether unicode is supported */
81 static boolean has_unicode;
82 static boolean init_ttycolor_completed;
84 static boolean display_cursor_info = FALSE;
87 static void NDECL(adjust_palette);
88 static int FDECL(match_color_name, (const char *));
89 typedef HWND(WINAPI *GETCONSOLEWINDOW)();
90 static HWND GetConsoleHandle(void);
91 static HWND GetConsoleHwnd(void);
92 static boolean altered_palette;
93 static COLORREF UserDefinedColors[CLR_MAX];
94 static COLORREF NetHackColors[CLR_MAX] = {
95 0x00000000, 0x00c80000, 0x0000c850, 0x00b4b432, 0x000000d2, 0x00800080,
96 0x000064b4, 0x00c0c0c0, 0x00646464, 0x00f06464, 0x0000ff00, 0x00ffff00,
97 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
99 static COLORREF DefaultColors[CLR_MAX] = {
100 0x00000000, 0x00800000, 0x00008000, 0x00808000, 0x00000080, 0x00800080,
101 0x00008080, 0x00c0c0c0, 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
102 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
110 int current_nhattr[ATR_INVERSE+1];
114 (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
115 (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
117 {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE},
120 static DWORD ccount, acount;
125 int ttycolors[CLR_MAX];
126 int ttycolors_inv[CLR_MAX];
128 #define MAX_OVERRIDES 256
129 unsigned char key_overrides[MAX_OVERRIDES];
130 static char nullstr[] = "";
131 char erase_char, kill_char;
132 #define DEFTEXTCOLOR ttycolors[7]
134 /* dynamic keystroke handling .DLL support */
135 typedef int(__stdcall *PROCESS_KEYSTROKE)(HANDLE, INPUT_RECORD *, boolean *,
138 typedef int(__stdcall *NHKBHIT)(HANDLE, INPUT_RECORD *);
140 typedef int(__stdcall *CHECKINPUT)(HANDLE, INPUT_RECORD *, DWORD *, BOOLEAN_P,
141 int, int *, coord *);
143 typedef int(__stdcall *SOURCEWHERE)(char **);
145 typedef int(__stdcall *SOURCEAUTHOR)(char **);
147 typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
150 PROCESS_KEYSTROKE pProcessKeystroke;
152 CHECKINPUT pCheckInput;
153 SOURCEWHERE pSourceWhere;
154 SOURCEAUTHOR pSourceAuthor;
155 KEYHANDLERNAME pKeyHandlerName;
158 * Called after returning from ! or ^Z
163 console_font_changed = FALSE;
165 check_and_set_font();
171 kill_char = 21; /* cntl-U */
172 iflags.cbreak = TRUE;
176 for (k = 0; k < CLR_MAX; ++k)
177 ttycolors[k] = NO_COLOR;
181 /* reset terminal to original state */
186 cmov(ttyDisplay->curx, ttyDisplay->cury);
191 restore_original_console_font();
194 /* called by init_nhwindows() and resume_nhwindows() */
203 has_unicode = ((GetVersion() & 0x80000000) == 0);
207 tty_startup(wid, hgt)
210 int twid = origcsbi.srWindow.Right - origcsbi.srWindow.Left + 1;
215 *hgt = origcsbi.srWindow.Bottom - origcsbi.srWindow.Top + 1;
216 set_option_mod_status("mouse_support", SET_IN_GAME);
220 tty_number_pad(state)
229 tty_number_pad(1); /* make keypad send digits */
236 really_move_cursor();
237 if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
243 FillConsoleOutputAttribute(
244 hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
245 csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
246 FillConsoleOutputCharacter(
247 hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
249 FlushConsoleInputBuffer(hConIn);
253 CtrlHandler(ctrltype)
257 /* case CTRL_C_EVENT: */
258 case CTRL_BREAK_EVENT:
260 case CTRL_CLOSE_EVENT:
261 case CTRL_LOGOFF_EVENT:
262 case CTRL_SHUTDOWN_EVENT:
263 getreturn_enabled = FALSE;
264 #ifndef NOSAVEONHANGUP
267 #if defined(SAFERHANGUP)
268 CloseHandle(hConIn); /* trigger WAIT_FAILED */
276 /* called by init_tty in wintty.c for WIN32 port only */
288 /* The following lines of code were suggested by
289 * Bob Landau of Microsoft WIN32 Developer support,
290 * as the only current means of determining whether
291 * we were launched from the command prompt, or from
292 * the NT program manager. M. Allison
294 hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
297 GetConsoleScreenBufferInfo(hStdOut, &origcsbi);
299 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
300 HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
302 if (!hStdOut && !hStdIn) {
305 AttachConsole(GetCurrentProcessId());
306 /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
307 freopen("CON", "w", stdout);
308 freopen("CON", "r", stdin);
316 /* Obtain handles for the standard Console I/O devices */
317 hConIn = GetStdHandle(STD_INPUT_HANDLE);
318 hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
320 load_keyboard_handler();
321 /* Initialize the function pointer that points to
322 * the kbhit() equivalent, in this TTY case nttty_kbhit()
324 nt_kbhit = nttty_kbhit;
326 GetConsoleMode(hConIn, &cmode);
327 #ifdef NO_MOUSE_ALLOWED
328 mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT
329 | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT;
331 mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
332 | ENABLE_WINDOW_INPUT;
334 /* Turn OFF the settings specified in the mask */
336 #ifndef NO_MOUSE_ALLOWED
337 cmode |= ENABLE_MOUSE_INPUT;
339 SetConsoleMode(hConIn, cmode);
340 if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
341 /* Unable to set control handler */
342 cmode = 0; /* just to have a statement to break on for debugger */
345 console.cursor.X = console.cursor.Y = 0;
346 really_move_cursor();
350 process_keystroke(ir, valid, numberpad, portdebug)
356 int ch = pProcessKeystroke(hConIn, ir, valid, numberpad, portdebug);
357 /* check for override */
358 if (ch && ch < MAX_OVERRIDES && key_overrides[ch])
359 ch = key_overrides[ch];
366 return pNHkbhit(hConIn, &ir);
374 GetConsoleScreenBufferInfo(hConOut, &csbi);
376 lines = csbi.srWindow.Bottom - (csbi.srWindow.Top + 1);
377 cols = csbi.srWindow.Right - (csbi.srWindow.Left + 1);
382 if ((LI < 25) || (CO < 80)) {
391 SetConsoleScreenBufferSize(hConOut, newcoord);
401 really_move_cursor();
402 return (program_state.done_hup)
404 : pCheckInput(hConIn, &ir, &count, iflags.num_pad, 0, &mod,
415 really_move_cursor();
416 ch = (program_state.done_hup)
418 : pCheckInput(hConIn, &ir, &count, iflags.num_pad, 1, mod, &cc);
430 char oldtitle[BUFSZ], newtitle[BUFSZ];
431 if (display_cursor_info && wizard) {
433 if (GetConsoleTitle(oldtitle, BUFSZ)) {
436 Sprintf(newtitle, "%-55s tty=(%02d,%02d) nttty=(%02d,%02d)", oldtitle,
437 ttyDisplay->curx, ttyDisplay->cury, console.cursor.X, console.cursor.Y);
438 (void) SetConsoleTitle(newtitle);
442 console.cursor.X = ttyDisplay->curx;
443 console.cursor.Y = ttyDisplay->cury;
445 SetConsoleCursorPosition(hConOut, console.cursor);
452 ttyDisplay->cury = y;
453 ttyDisplay->curx = x;
454 console.cursor.X = x;
455 console.cursor.Y = y;
462 console.cursor.X = x;
463 console.cursor.Y = y;
464 ttyDisplay->curx = x;
465 ttyDisplay->cury = y;
472 console.cursor.X = ttyDisplay->curx;
473 console.cursor.Y = ttyDisplay->cury;
479 xputc2_core(ch1, ch2)
483 unsigned char buf[2];
485 boolean inverse = FALSE;
490 /* xputc_core()
\82©
\82ç
\82Ì
\83R
\83s
\81[ */
491 inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
492 console.attr = (inverse) ?
493 ttycolors_inv[console.current_nhcolor] :
494 ttycolors[console.current_nhcolor];
495 if (console.current_nhattr[ATR_BOLD])
496 console.attr |= (inverse) ?
497 BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
499 attrs[0] = attrs[1] = console.attr;
501 WriteConsoleOutputAttribute(hConOut, attrs, 2,
502 console.cursor, &acount);
503 WriteConsoleOutputCharacter(hConOut, buf, 2,
504 console.cursor, &ccount);
505 console.cursor.X += 2;
513 /* wintty.c
\82Å
\82Í 1
\83o
\83C
\83g
\96\88\82É curx
\82ð
\89Á
\8eZ
\82·
\82é
\82ª
\81A
\82±
\82±
\82Í
514 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Å
515 \82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81B
\8f]
\82Á
\82Ä 1
\82ð
\88ø
\82
\81B */
516 console.cursor.X = ttyDisplay->curx - 1;
517 console.cursor.Y = ttyDisplay->cury;
519 xputc2_core(ch1, ch2);
528 int slen = strlen(s);
531 console.cursor.X = ttyDisplay->curx;
532 console.cursor.Y = ttyDisplay->cury;
536 for (k = 0; k < slen && s[k]; ++k)
541 /* xputc_core() and g_putch() are the only
542 * two routines that actually place output
549 boolean inverse = FALSE;
555 console.cursor.X = 1;
561 inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
562 console.attr = (inverse) ?
563 ttycolors_inv[console.current_nhcolor] :
564 ttycolors[console.current_nhcolor];
565 if (console.current_nhattr[ATR_BOLD])
566 console.attr |= (inverse) ?
567 BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
568 WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
570 /* Avoid bug in ANSI API on WinNT */
573 rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, &ch, 1, c2, 2);
574 WriteConsoleOutputCharacterW(hConOut, c2, rc, console.cursor, &ccount);
576 WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
583 * Overrides wintty.c function of the same name
584 * for win32. It is used for glyphs only, not text.
587 /* CP437 to Unicode mapping according to the Unicode Consortium */
588 static const WCHAR cp437[] = {
589 0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
590 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
591 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
592 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
593 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
594 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
595 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
596 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
597 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
598 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
599 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
600 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
601 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
602 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
603 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
604 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
605 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
606 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
607 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
608 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
609 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
610 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
611 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
612 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
613 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
614 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
615 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
616 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
617 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
618 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
619 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
620 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
627 boolean inverse = FALSE;
628 unsigned char ch = (unsigned char) in_ch;
630 console.cursor.X = ttyDisplay->curx;
631 console.cursor.Y = ttyDisplay->cury;
633 inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
634 console.attr = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse) ?
635 ttycolors_inv[console.current_nhcolor] :
636 ttycolors[console.current_nhcolor];
637 if (console.current_nhattr[ATR_BOLD])
638 console.attr |= (inverse) ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
639 WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
642 WriteConsoleOutputCharacterW(hConOut, &cp437[ch], 1, console.cursor, &ccount);
644 WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
651 console.cursor.X = ttyDisplay->curx;
652 console.cursor.Y = ttyDisplay->cury;
653 cx = CO - console.cursor.X;
654 FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, cx, console.cursor, &acount);
655 FillConsoleOutputCharacter(hConOut, ' ', cx, console.cursor, &ccount);
656 tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
662 if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
668 FillConsoleOutputAttribute(
669 hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
670 csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
671 FillConsoleOutputCharacter(
672 hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
686 console.cursor.X = console.cursor.Y = 0;
687 ttyDisplay->curx = ttyDisplay->cury = 0;
693 console.cursor.X = ttyDisplay->curx;
694 console.cursor.Y = ttyDisplay->cury;
701 int cy = ttyDisplay->cury + 1;
702 if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
706 newcoord.X = ttyDisplay->curx;
707 newcoord.Y = ttyDisplay->cury;
708 FillConsoleOutputAttribute(
709 hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
710 csbi.dwSize.X * csbi.dwSize.Y - cy, newcoord, &ccnt);
711 FillConsoleOutputCharacter(hConOut, ' ',
712 csbi.dwSize.X * csbi.dwSize.Y - cy,
715 tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
726 volatile int junk; /* prevent optimizer from eliminating loop below */
731 /* delay 50 ms - uses ANSI C clock() function now */
736 while (goal > clock()) {
737 k = junk; /* Do nothing */
746 * CLR_BROWN 3 low-intensity yellow
750 * CLR_GRAY 7 low-intensity white
753 * CLR_BRIGHT_GREEN 10
756 * CLR_BRIGHT_MAGENTA 13
767 ttycolors[CLR_BLACK] = FOREGROUND_INTENSITY; /* fix by Quietust */
768 ttycolors[CLR_RED] = FOREGROUND_RED;
769 ttycolors[CLR_GREEN] = FOREGROUND_GREEN;
770 ttycolors[CLR_BROWN] = FOREGROUND_GREEN | FOREGROUND_RED;
771 ttycolors[CLR_BLUE] = FOREGROUND_BLUE;
772 ttycolors[CLR_MAGENTA] = FOREGROUND_BLUE | FOREGROUND_RED;
773 ttycolors[CLR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE;
774 ttycolors[CLR_GRAY] = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
775 ttycolors[NO_COLOR] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
776 ttycolors[CLR_ORANGE] = FOREGROUND_RED | FOREGROUND_INTENSITY;
777 ttycolors[CLR_BRIGHT_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
778 ttycolors[CLR_YELLOW] = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
779 ttycolors[CLR_BRIGHT_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
780 ttycolors[CLR_BRIGHT_MAGENTA]=FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
781 ttycolors[CLR_BRIGHT_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
782 ttycolors[CLR_WHITE] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED
783 | FOREGROUND_INTENSITY;
785 ttycolors_inv[CLR_BLACK] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
786 | BACKGROUND_INTENSITY;
787 ttycolors_inv[CLR_RED] = BACKGROUND_RED | BACKGROUND_INTENSITY;
788 ttycolors_inv[CLR_GREEN] = BACKGROUND_GREEN;
789 ttycolors_inv[CLR_BROWN] = BACKGROUND_GREEN | BACKGROUND_RED;
790 ttycolors_inv[CLR_BLUE] = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
791 ttycolors_inv[CLR_MAGENTA] = BACKGROUND_BLUE | BACKGROUND_RED;
792 ttycolors_inv[CLR_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE;
793 ttycolors_inv[CLR_GRAY] = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE;
794 ttycolors_inv[NO_COLOR] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
795 ttycolors_inv[CLR_ORANGE] = BACKGROUND_RED | BACKGROUND_INTENSITY;
796 ttycolors_inv[CLR_BRIGHT_GREEN]= BACKGROUND_GREEN | BACKGROUND_INTENSITY;
797 ttycolors_inv[CLR_YELLOW] = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
798 ttycolors_inv[CLR_BRIGHT_BLUE] = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
799 ttycolors_inv[CLR_BRIGHT_MAGENTA] =BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY;
800 ttycolors_inv[CLR_BRIGHT_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
801 ttycolors_inv[CLR_WHITE] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
802 | BACKGROUND_INTENSITY;
805 ttycolors[0] = FOREGROUND_INTENSITY;
806 ttycolors_inv[0] = BACKGROUND_INTENSITY;
807 for (k = 1; k < SIZE(ttycolors); ++k) {
808 ttycolors[k] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
809 ttycolors_inv[k] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
812 init_ttycolor_completed = TRUE;
814 #endif /* TEXTCOLOR */
820 if ((color >= 0) && (color < CLR_MAX))
823 if ((color == CLR_BLACK) || (color == CLR_WHITE) || (color == NO_COLOR))
831 term_start_attr(int attrib)
833 console.current_nhattr[attrib] = TRUE;
834 if (attrib) console.current_nhattr[ATR_NONE] = FALSE;
838 term_end_attr(int attrib)
849 console.current_nhattr[attrib] = FALSE;
850 console.current_nhattr[ATR_NONE] = TRUE;
851 /* re-evaluate all attr now for performance at output time */
852 for (k=ATR_NONE; k <= ATR_INVERSE; ++k) {
853 if (console.current_nhattr[k])
854 console.current_nhattr[ATR_NONE] = FALSE;
859 term_end_raw_bold(void)
861 term_end_attr(ATR_BOLD);
865 term_start_raw_bold(void)
867 term_start_attr(ATR_BOLD);
871 term_start_color(int color)
874 if (color >= 0 && color < CLR_MAX) {
875 console.current_nhcolor = color;
878 console.current_nhcolor = NO_COLOR;
885 console.foreground = DEFTEXTCOLOR;
887 console.attr = (console.foreground | console.background);
888 console.current_nhcolor = NO_COLOR;
894 term_start_attr(ATR_BOLD);
900 term_end_attr(ATR_BOLD);
903 #ifndef NO_MOUSE_ALLOWED
905 toggle_mouse_support()
908 GetConsoleMode(hConIn, &cmode);
909 if (iflags.wc_mouse_support)
910 cmode |= ENABLE_MOUSE_INPUT;
912 cmode &= ~ENABLE_MOUSE_INPUT;
913 SetConsoleMode(hConIn, cmode);
917 /* handle tty options updates here */
919 nttty_preference_update(pref)
922 if (stricmp(pref, "mouse_support") == 0) {
923 #ifndef NO_MOUSE_ALLOWED
924 toggle_mouse_support();
927 if (stricmp(pref, "symset") == 0)
928 check_and_set_font();
934 win32con_debug_keystrokes()
940 while (!valid || ch != 27) {
941 nocmov(ttyDisplay->curx, ttyDisplay->cury);
942 ReadConsoleInput(hConIn, &ir, 1, &count);
943 if ((ir.EventType == KEY_EVENT) && ir.Event.KeyEvent.bKeyDown)
944 ch = process_keystroke(&ir, &valid, iflags.num_pad, 1);
949 win32con_handler_info()
953 if (!pSourceAuthor && !pSourceWhere)
954 pline("Keyboard handler source info and author unavailable.");
956 if (pKeyHandlerName && pKeyHandlerName(&buf, 1)) {
958 xputs("Keystroke handler loaded: \n ");
961 if (pSourceAuthor && pSourceAuthor(&buf)) {
963 xputs("Keystroke handler Author: \n ");
966 if (pSourceWhere && pSourceWhere(&buf)) {
968 xputs("Keystroke handler source code available at:\n ");
971 xputs("\nPress any key to resume.");
978 win32con_toggle_cursor_info()
980 display_cursor_info = !display_cursor_info;
988 char digits[] = "0123456789";
989 int length, i, idx, val;
999 if (length < 1 || length > 3)
1001 for (i = 0; i < length; i++)
1002 if (!index(digits, kp[i]))
1005 length = strlen(op);
1006 if (length < 1 || length > 3)
1008 for (i = 0; i < length; i++)
1009 if (!index(digits, op[i]))
1013 if (idx >= MAX_OVERRIDES || idx < 0 || val >= MAX_OVERRIDES || val < 1)
1015 key_overrides[idx] = val;
1019 load_keyboard_handler()
1021 char suffx[] = ".dll";
1023 #define MAX_DLLNAME 25
1024 char kh[MAX_ALTKEYHANDLER];
1025 if (iflags.altkeyhandler[0]) {
1026 if (hLibrary) { /* already one loaded apparently */
1027 FreeLibrary(hLibrary);
1028 hLibrary = (HANDLE) 0;
1029 pNHkbhit = (NHKBHIT) 0;
1030 pCheckInput = (CHECKINPUT) 0;
1031 pSourceWhere = (SOURCEWHERE) 0;
1032 pSourceAuthor = (SOURCEAUTHOR) 0;
1033 pKeyHandlerName = (KEYHANDLERNAME) 0;
1034 pProcessKeystroke = (PROCESS_KEYSTROKE) 0;
1036 if ((truncspot = strstri(iflags.altkeyhandler, suffx)) != 0)
1038 (void) strncpy(kh, iflags.altkeyhandler,
1039 (MAX_ALTKEYHANDLER - sizeof suffx) - 1);
1040 kh[(MAX_ALTKEYHANDLER - sizeof suffx) - 1] = '\0';
1042 Strcpy(iflags.altkeyhandler, kh);
1043 hLibrary = LoadLibrary(kh);
1045 pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
1046 hLibrary, TEXT("ProcessKeystroke"));
1047 pNHkbhit = (NHKBHIT) GetProcAddress(hLibrary, TEXT("NHkbhit"));
1049 (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
1051 (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
1053 (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
1054 pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
1055 hLibrary, TEXT("KeyHandlerName"));
1058 if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) {
1060 FreeLibrary(hLibrary);
1061 hLibrary = (HANDLE) 0;
1062 pNHkbhit = (NHKBHIT) 0;
1063 pCheckInput = (CHECKINPUT) 0;
1064 pSourceWhere = (SOURCEWHERE) 0;
1065 pSourceAuthor = (SOURCEAUTHOR) 0;
1066 pKeyHandlerName = (KEYHANDLERNAME) 0;
1067 pProcessKeystroke = (PROCESS_KEYSTROKE) 0;
1069 (void) strncpy(kh, "nhdefkey.dll",
1070 (MAX_ALTKEYHANDLER - sizeof suffx) - 1);
1071 kh[(MAX_ALTKEYHANDLER - sizeof suffx) - 1] = '\0';
1072 Strcpy(iflags.altkeyhandler, kh);
1073 hLibrary = LoadLibrary(kh);
1075 pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
1076 hLibrary, TEXT("ProcessKeystroke"));
1078 (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
1079 pNHkbhit = (NHKBHIT) GetProcAddress(hLibrary, TEXT("NHkbhit"));
1081 (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
1083 (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
1084 pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
1085 hLibrary, TEXT("KeyHandlerName"));
1088 if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) {
1090 raw_printf("\nNetHack was unable to load keystroke handler.\n");
1092 FreeLibrary(hLibrary);
1093 hLibrary = (HANDLE) 0;
1094 raw_printf("\nNetHack keystroke handler is invalid.\n");
1100 /* this is used as a printf() replacement when the window
1101 * system isn't initialized yet
1104 VA_DECL(const char *, fmt)
1106 char buf[ROWNO * COLNO]; /* worst case scenario */
1108 VA_INIT(fmt, const char *);
1109 Vsprintf(buf, fmt, VA_ARGS);
1110 if (redirect_stdout)
1111 fprintf(stdout, "%s", buf);
1113 if(!init_ttycolor_completed)
1120 console.cursor.X = ttyDisplay->curx;
1121 console.cursor.Y = ttyDisplay->cury;
1126 jbuffer(*(str++), NULL, (void (__cdecl *)(unsigned int))xputc_core, xputc2_core);
1131 curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
1140 VA_DECL(const char *, s)
1144 VA_INIT(s, const char *);
1145 /* error() may get called before tty is initialized */
1146 if (iflags.window_inited)
1149 (void) vsprintf(&buf[1], s, VA_ARGS);
1151 really_move_cursor();
1159 really_move_cursor();
1164 tty_change_color(color_number, rgb, reverse)
1165 int color_number, reverse;
1168 /* Map NetHack color index to NT Console palette index */
1169 int idx, win32_color_number[] = {
1170 0, /* CLR_BLACK 0 */
1172 2, /* CLR_GREEN 2 */
1173 6, /* CLR_BROWN 3 */
1175 5, /* CLR_MAGENTA 5 */
1179 12, /* CLR_ORANGE 9 */
1180 10, /* CLR_BRIGHT_GREEN 10 */
1181 14, /* CLR_YELLOW 11 */
1182 9, /* CLR_BRIGHT_BLUE 12 */
1183 13, /* CLR_BRIGHT_MAGENTA 13 */
1184 11, /* CLR_BRIGHT_CYAN 14 */
1185 15 /* CLR_WHITE 15 */
1188 if (color_number < 0) { /* indicates OPTIONS=palette with no value */
1189 /* copy the NetHack palette into UserDefinedColors */
1190 for (k = 0; k < CLR_MAX; k++)
1191 UserDefinedColors[k] = NetHackColors[k];
1192 } else if (color_number >= 0 && color_number < CLR_MAX) {
1193 if (!altered_palette) {
1194 /* make sure a full suite is available */
1195 for (k = 0; k < CLR_MAX; k++)
1196 UserDefinedColors[k] = DefaultColors[k];
1198 idx = win32_color_number[color_number];
1199 UserDefinedColors[idx] = rgb;
1201 altered_palette = TRUE;
1205 tty_get_color_string()
1214 const struct others {
1216 const char *colorname;
1218 { CLR_MAGENTA, "purple" },
1219 { CLR_BRIGHT_MAGENTA, "bright purple" },
1220 { NO_COLOR, "dark gray" },
1221 { NO_COLOR, "dark grey" },
1222 { CLR_GRAY, "grey" },
1226 for (cnt = 0; cnt < CLR_MAX; ++cnt) {
1227 if (!strcmpi(c, c_obj_colors[cnt]))
1230 for (cnt = 0; cnt < SIZE(othernames); ++cnt) {
1231 if (!strcmpi(c, othernames[cnt].colorname))
1232 return othernames[cnt].idx;
1238 * Returns 0 if badoption syntax
1241 alternative_palette(op)
1245 * palette:color-R-G-B
1246 * OPTIONS=palette:green-4-3-1, palette:0-0-0-0
1248 int fieldcnt, color_number, rgb, red, green, blue;
1249 char *fields[4], *cp;
1252 change_color(-1, 0, 0); /* indicates palette option with
1253 no value meaning "load an entire
1254 hard-coded NetHack palette." */
1258 cp = fields[0] = op;
1259 for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
1260 cp = index(cp, '-');
1263 fields[fieldcnt] = cp;
1266 for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
1267 *(fields[fieldcnt]) = '\0';
1271 for (fieldcnt = 0; fieldcnt < 4; ++fieldcnt) {
1272 if (fieldcnt == 0 && isalpha(*(fields[0]))) {
1273 color_number = match_color_name(fields[0]);
1274 if (color_number == -1)
1277 int dcount = 0, cval = 0;
1278 cp = fields[fieldcnt];
1279 if (*cp == '\\' && index("0123456789xXoO", cp[1])) {
1280 const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
1283 if (*cp == 'x' || *cp == 'X')
1284 for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
1285 cval = (int) ((cval * 16) + (dp - hex) / 2);
1286 else if (*cp == 'o' || *cp == 'O')
1287 for (++cp; (index("01234567", *cp)) && (dcount++ < 3);
1289 cval = (cval * 8) + (*cp - '0');
1293 for (; *cp && (index("0123456789", *cp)) && (dcount++ < 3);
1295 cval = (cval * 10) + (*cp - '0');
1299 color_number = cval;
1313 rgb = RGB(red, green, blue);
1314 if (color_number >= 0 && color_number < CLR_MAX)
1315 change_color(color_number, rgb, 0);
1320 * This uses an undocumented method to set console attributes
1321 * at runtime including console palette
1323 * VOID WINAPI SetConsolePalette(COLORREF palette[16])
1325 * Author: James Brown at www.catch22.net
1327 * Set palette of current console.
1328 * Palette should be of the form:
1330 * COLORREF DefaultColors[CLR_MAX] =
1332 * 0x00000000, 0x00800000, 0x00008000, 0x00808000,
1333 * 0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0,
1334 * 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
1335 * 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
1339 #pragma pack(push, 1)
1342 * Structure to send console via WM_SETCONSOLEINFO
1344 typedef struct _CONSOLE_INFO {
1346 COORD ScreenBufferSize;
1362 USHORT ScreenColors;
1365 ULONG HistoryBufferSize;
1366 ULONG NumberOfHistoryBuffers;
1368 COLORREF ColorTable[16];
1373 WCHAR ConsoleTitle[0x100];
1378 BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci);
1379 static void GetConsoleSizeInfo(CONSOLE_INFO *pci);
1380 VOID WINAPI SetConsolePalette(COLORREF crPalette[16]);
1383 adjust_palette(VOID_ARGS)
1385 SetConsolePalette(UserDefinedColors);
1386 altered_palette = 0;
1390 /* only in Win2k+ (use FindWindow for NT4) */
1391 /* HWND WINAPI GetConsoleWindow(); */
1393 /* Undocumented console message */
1394 #define WM_SETCONSOLEINFO (WM_USER + 201)
1397 SetConsolePalette(COLORREF palette[16])
1399 CONSOLE_INFO ci = { sizeof(ci) };
1401 HWND hwndConsole = GetConsoleHandle();
1403 /* get current size/position settings rather than using defaults.. */
1404 GetConsoleSizeInfo(&ci);
1406 /* set these to zero to keep current settings */
1407 ci.FontSize.X = 0; /* def = 8 */
1408 ci.FontSize.Y = 0; /* def = 12 */
1409 ci.FontFamily = 0; /* def = 0x30 = FF_MODERN|FIXED_PITCH */
1410 ci.FontWeight = 0; /* 0x400; */
1411 /* lstrcpyW(ci.FaceName, L"Terminal"); */
1412 ci.FaceName[0] = L'\0';
1415 ci.FullScreen = FALSE;
1416 ci.QuickEdit = TRUE;
1417 ci.AutoPosition = 0x10000;
1418 ci.InsertMode = TRUE;
1419 ci.ScreenColors = MAKEWORD(0x7, 0x0);
1420 ci.PopupColors = MAKEWORD(0x5, 0xf);
1422 ci.HistoryNoDup = FALSE;
1423 ci.HistoryBufferSize = 50;
1424 ci.NumberOfHistoryBuffers = 4;
1427 for (i = 0; i < 16; i++)
1428 ci.ColorTable[i] = palette[i];
1430 ci.CodePage = GetConsoleOutputCP();
1431 ci.Hwnd = hwndConsole;
1433 lstrcpyW(ci.ConsoleTitle, L"");
1435 SetConsoleInfo(hwndConsole, &ci);
1439 * Wrapper around WM_SETCONSOLEINFO. We need to create the
1440 * necessary section (file-mapping) object in the context of the
1441 * process which owns the console, before posting the message
1444 SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci)
1446 DWORD dwConsoleOwnerPid;
1448 HANDLE hSection, hDupSection;
1453 * Open the process which "owns" the console
1455 GetWindowThreadProcessId(hwndConsole, &dwConsoleOwnerPid);
1456 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
1459 * Create a SECTION object backed by page-file, then map a view of
1460 * this section into the owner process so we can write the contents
1461 * of the CONSOLE_INFO buffer into it
1463 hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
1467 * Copy our console structure into the section-object
1469 ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0,
1471 memcpy(ptrView, pci, pci->Length);
1472 UnmapViewOfFile(ptrView);
1475 * Map the memory into owner process
1477 DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection, 0,
1478 FALSE, DUPLICATE_SAME_ACCESS);
1480 /* Send console window the "update" message */
1481 SendMessage(hwndConsole, WM_SETCONSOLEINFO, (WPARAM) hDupSection, 0);
1486 hThread = CreateRemoteThread(hProcess, 0, 0,
1487 (LPTHREAD_START_ROUTINE) CloseHandle,
1490 CloseHandle(hThread);
1491 CloseHandle(hSection);
1492 CloseHandle(hProcess);
1498 * Fill the CONSOLE_INFO structure with information
1499 * about the current console window
1502 GetConsoleSizeInfo(CONSOLE_INFO *pci)
1504 CONSOLE_SCREEN_BUFFER_INFO csbi;
1506 HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
1508 GetConsoleScreenBufferInfo(hConsoleOut, &csbi);
1510 pci->ScreenBufferSize = csbi.dwSize;
1511 pci->WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
1512 pci->WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
1513 pci->WindowPosX = csbi.srWindow.Left;
1514 pci->WindowPosY = csbi.srWindow.Top;
1518 GetConsoleHandle(void)
1520 HMODULE hMod = GetModuleHandle("kernel32.dll");
1521 GETCONSOLEWINDOW pfnGetConsoleWindow =
1522 (GETCONSOLEWINDOW) GetProcAddress(hMod, "GetConsoleWindow");
1523 if (pfnGetConsoleWindow)
1524 return pfnGetConsoleWindow();
1526 return GetConsoleHwnd();
1530 GetConsoleHwnd(void)
1534 char OldTitle[1024], NewTitle[1024], TestTitle[1024];
1536 /* Get current window title */
1537 GetConsoleTitle(OldTitle, sizeof OldTitle);
1539 (void) sprintf(NewTitle, "NETHACK%d/%d", GetTickCount(),
1540 GetCurrentProcessId());
1541 SetConsoleTitle(NewTitle);
1543 GetConsoleTitle(TestTitle, sizeof TestTitle);
1544 while (strcmp(TestTitle, NewTitle) != 0) {
1547 GetConsoleTitle(TestTitle, sizeof TestTitle);
1549 hwndFound = FindWindow(NULL, NewTitle);
1550 SetConsoleTitle(OldTitle);
1551 /* printf("%d iterations\n", iterations); */
1554 #endif /*CHANGE_COLOR*/
1556 static int CALLBACK EnumFontCallback(
1557 const LOGFONTW * lf, const TEXTMETRICW * tm, DWORD fontType, LPARAM lParam)
1559 LOGFONTW * lf_ptr = (LOGFONTW *) lParam;
1564 /* check_and_set_font ensures that the current font will render the symbols
1565 * that are currently being used correctly. If they will not be rendered
1566 * correctly, then it will change the font to a known good font.
1569 check_and_set_font()
1571 #if 0 /*JP*//*
\83R
\81[
\83h
\83y
\81[
\83W
\82Í
\95Ï
\8dX
\82µ
\82È
\82¢
\81B932
\82ð
\89¼
\92è
\82·
\82é
\81B*/
1572 if (!check_font_widths()) {
1573 raw_print("WARNING: glyphs too wide in console font."
1574 " Changing code page to 437 and font to Consolas\n");
1575 set_known_good_console_font();
1580 /* check_font_widths returns TRUE if all glyphs in current console font
1581 * fit within the width of a single console cell.
1586 CONSOLE_FONT_INFOEX console_font_info;
1587 console_font_info.cbSize = sizeof(console_font_info);
1588 BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
1589 &console_font_info);
1591 /* get console window and DC
1592 * NOTE: the DC from the console window does not have the correct
1593 * font selected at this point.
1595 HWND hWnd = GetConsoleWindow();
1596 HDC hDC = GetDC(hWnd);
1598 LOGFONTW logical_font;
1599 logical_font.lfCharSet = DEFAULT_CHARSET;
1600 wcscpy(logical_font.lfFaceName, console_font_info.FaceName);
1601 logical_font.lfPitchAndFamily = 0;
1603 /* getting matching console font */
1604 LOGFONTW matching_log_font = { 0 };
1605 EnumFontFamiliesExW(hDC, &logical_font, EnumFontCallback,
1606 (LPARAM) &matching_log_font, 0);
1608 if (matching_log_font.lfHeight == 0) {
1609 raw_print("Unable to enumerate system fonts\n");
1613 /* create font matching console font */
1614 LOGFONTW console_font_log_font = matching_log_font;
1615 console_font_log_font.lfWeight = console_font_info.FontWeight;
1616 console_font_log_font.lfHeight = console_font_info.dwFontSize.Y;
1617 console_font_log_font.lfWidth = 0;
1618 HFONT console_font = CreateFontIndirectW(&console_font_log_font);
1620 if (console_font == NULL) {
1621 raw_print("Unable to create console font\n");
1626 HGDIOBJ saved_font = SelectObject(hDC, console_font);
1628 /* determine whether it is a true type font */
1630 success = GetTextMetricsA(hDC, &tm);
1633 raw_print("Unable to get console font text metrics\n");
1637 boolean isTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
1639 /* determine which glyphs are used */
1641 memset(used, 0, sizeof(used));
1642 for (int i = 0; i < SYM_MAX; i++) {
1643 used[l_syms[i]] = TRUE;
1644 used[r_syms[i]] = TRUE;
1647 int wcUsedCount = 0;
1648 wchar_t wcUsed[256];
1649 for (int i = 0; i < sizeof(used); i++)
1651 wcUsed[wcUsedCount++] = cp437[i];
1653 /* measure the set of used glyphs to ensure they fit */
1654 boolean all_glyphs_fit = TRUE;
1656 for (int i = 0; i < wcUsedCount; i++) {
1660 success = GetCharABCWidthsW(hDC, wcUsed[i], wcUsed[i], &abc);
1661 width = abc.abcA + abc.abcB + abc.abcC;
1663 success = GetCharWidthW(hDC, wcUsed[i], wcUsed[i], &width);
1666 if (success && width > console_font_info.dwFontSize.X) {
1667 all_glyphs_fit = FALSE;
1674 SelectObject(hDC, saved_font);
1675 DeleteObject(console_font);
1677 return all_glyphs_fit;
1680 /* set_known_good_console_font sets the code page and font used by the console
1681 * to settings know to work well with NetHack. It also saves the original
1682 * settings so that they can be restored prior to NetHack exit.
1685 set_known_good_console_font()
1687 CONSOLE_FONT_INFOEX console_font_info;
1688 console_font_info.cbSize = sizeof(console_font_info);
1689 BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
1690 &console_font_info);
1692 console_font_changed = TRUE;
1693 original_console_font_info = console_font_info;
1694 original_console_code_page = GetConsoleOutputCP();
1696 wcscpy_s(console_font_info.FaceName,
1697 sizeof(console_font_info.FaceName)
1698 / sizeof(console_font_info.FaceName[0]),
1701 success = SetConsoleOutputCP(437);
1703 raw_print("Unable to set console code page to 437\n");
1705 success = SetCurrentConsoleFontEx(hConOut, FALSE, &console_font_info);
1707 raw_print("Unable to set console font to Consolas\n");
1710 /* restore_original_console_font will restore the console font and code page
1711 * settings to what they were when NetHack was launched.
1714 restore_original_console_font()
1716 if (console_font_changed) {
1718 raw_print("Restoring original font and code page\n");
1719 success = SetConsoleOutputCP(original_console_code_page);
1721 raw_print("Unable to restore original code page\n");
1723 success = SetCurrentConsoleFontEx(hConOut, FALSE,
1724 &original_console_font_info);
1726 raw_print("Unable to restore original font\n");
1728 console_font_changed = FALSE;