OSDN Git Service

upgrade to 3.6.6
[jnethack/source.git] / sys / winnt / nttty.c
1 /* NetHack 3.6  nttty.c $NHDT-Date: 1554215932 2019/04/02 14:38:52 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.99 $ */
2 /* Copyright (c) NetHack PC Development Team 1993    */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* tty.c - (Windows NT) version */
6
7 /*
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
12  * Use of back buffer to improve performance    B. House    2018/05/06
13  *
14  */
15
16 #ifdef WIN32
17 #define NEED_VARARGS /* Uses ... */
18 #include "win32api.h"
19 #include "winos.h"
20 #include "hack.h"
21 #include "wintty.h"
22 #include <sys\types.h>
23 #include <sys\stat.h>
24
25 extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
26 extern int redirect_stdout;
27
28 #ifdef TTY_GRAPHICS
29 /*
30  * Console Buffer Flipping Support
31  *
32  * To minimize the number of calls into the WriteConsoleOutputXXX methods,
33  * we implement a notion of a console back buffer which keeps the next frame
34  * of console output as it is being composed.  When ready to show the new
35  * frame, we compare this next frame to what is currently being output and
36  * only call WriteConsoleOutputXXX for those console values that need to
37  * change.
38  *
39  */
40
41 #define CONSOLE_CLEAR_ATTRIBUTE (FOREGROUND_RED | FOREGROUND_GREEN \
42                                                 | FOREGROUND_BLUE)
43 #define CONSOLE_CLEAR_CHARACTER (' ')
44
45 #define CONSOLE_UNDEFINED_ATTRIBUTE (0)
46 #define CONSOLE_UNDEFINED_CHARACTER ('\0')
47
48 typedef struct {
49     WCHAR   character;
50     WORD    attribute;
51 #if 1 /*JP*/
52     int     iskanji;
53 #endif
54 } cell_t;
55
56 #if 0 /*JP*/
57 cell_t clear_cell = { CONSOLE_CLEAR_CHARACTER, CONSOLE_CLEAR_ATTRIBUTE };
58 cell_t undefined_cell = { CONSOLE_UNDEFINED_CHARACTER,
59                           CONSOLE_UNDEFINED_ATTRIBUTE };
60 #else
61 cell_t clear_cell = { CONSOLE_CLEAR_CHARACTER, CONSOLE_CLEAR_ATTRIBUTE, 0 };
62 cell_t undefined_cell = { CONSOLE_UNDEFINED_CHARACTER,
63                           CONSOLE_UNDEFINED_ATTRIBUTE, 0 };
64 #endif
65
66 /*
67  * The following WIN32 Console API routines are used in this file.
68  *
69  * CreateFile
70  * GetConsoleScreenBufferInfo
71  * GetStdHandle
72  * SetConsoleCursorPosition
73  * SetConsoleTextAttribute
74  * SetConsoleCtrlHandler
75  * PeekConsoleInput
76  * ReadConsoleInput
77  * WriteConsoleOutputCharacter
78  * FillConsoleOutputAttribute
79  * GetConsoleOutputCP
80  */
81
82 static BOOL FDECL(CtrlHandler, (DWORD));
83 static void FDECL(xputc_core, (char));
84 #if 1 /*JP*/
85 static void FDECL(xputc2_core, (unsigned int, unsigned int));
86 #endif
87 void FDECL(cmov, (int, int));
88 void FDECL(nocmov, (int, int));
89 int FDECL(process_keystroke,
90           (INPUT_RECORD *, boolean *, BOOLEAN_P numberpad, int portdebug));
91 static void NDECL(init_ttycolor);
92 static void NDECL(really_move_cursor);
93 static void NDECL(check_and_set_font);
94 #if 0 /*JP*/
95 static boolean NDECL(check_font_widths);
96 #endif
97 static void NDECL(set_known_good_console_font);
98 static void NDECL(restore_original_console_font);
99 extern void NDECL(safe_routines);
100
101 /* Win32 Screen buffer,coordinate,console I/O information */
102 COORD ntcoord;
103 INPUT_RECORD ir;
104 static boolean orig_QuickEdit;
105
106 /* Support for changing console font if existing glyph widths are too wide */
107
108 /* Flag for whether NetHack was launched via the GUI, not the command line.
109  * The reason we care at all, is so that we can get
110  * a final RETURN at the end of the game when launched from the GUI
111  * to prevent the scoreboard (or panic message :-|) from vanishing
112  * immediately after it is displayed, yet not bother when started
113  * from the command line.
114  */
115 int GUILaunched = FALSE;
116 /* Flag for whether unicode is supported */
117 static boolean init_ttycolor_completed;
118 #ifdef PORT_DEBUG
119 static boolean display_cursor_info = FALSE;
120 #endif
121 #ifdef CHANGE_COLOR
122 static void NDECL(adjust_palette);
123 static int FDECL(match_color_name, (const char *));
124 typedef HWND(WINAPI *GETCONSOLEWINDOW)();
125 static HWND GetConsoleHandle(void);
126 static HWND GetConsoleHwnd(void);
127 static boolean altered_palette;
128 static COLORREF UserDefinedColors[CLR_MAX];
129 static COLORREF NetHackColors[CLR_MAX] = {
130     0x00000000, 0x00c80000, 0x0000c850, 0x00b4b432, 0x000000d2, 0x00800080,
131     0x000064b4, 0x00c0c0c0, 0x00646464, 0x00f06464, 0x0000ff00, 0x00ffff00,
132     0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
133 };
134 static COLORREF DefaultColors[CLR_MAX] = {
135     0x00000000, 0x00800000, 0x00008000, 0x00808000, 0x00000080, 0x00800080,
136     0x00008080, 0x00c0c0c0, 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
137     0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
138 };
139 #endif
140 struct console_t {
141     WORD background;
142     WORD foreground;
143     WORD attr;
144     int current_nhcolor;
145     int current_nhattr[ATR_INVERSE+1];
146     COORD cursor;
147     HANDLE hConOut;
148     HANDLE hConIn;
149     CONSOLE_SCREEN_BUFFER_INFO origcsbi;
150     int width;
151     int height;
152     boolean has_unicode;
153     int buffer_size;
154     cell_t * front_buffer;
155     cell_t * back_buffer;
156     WCHAR cpMap[256];
157     boolean font_changed;
158     CONSOLE_FONT_INFOEX original_font_info;
159     UINT original_code_page;
160 } console = {
161     0,
162     (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
163     (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
164     NO_COLOR,
165     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE},
166     {0, 0},
167     NULL,
168     NULL,
169     { 0 },
170     0,
171     0,
172     FALSE,
173     0,
174     NULL,
175     NULL,
176     { 0 },
177     FALSE,
178     { 0 },
179     0
180 };
181
182 static DWORD ccount, acount;
183 #ifndef CLR_MAX
184 #define CLR_MAX 16
185 #endif
186
187 int ttycolors[CLR_MAX];
188 int ttycolors_inv[CLR_MAX];
189
190 #define MAX_OVERRIDES 256
191 unsigned char key_overrides[MAX_OVERRIDES];
192 static char nullstr[] = "";
193 char erase_char, kill_char;
194 #define DEFTEXTCOLOR ttycolors[7]
195
196 /* dynamic keystroke handling .DLL support */
197 typedef int(__stdcall *PROCESS_KEYSTROKE)(HANDLE, INPUT_RECORD *, boolean *,
198                                           BOOLEAN_P, int);
199
200 typedef int(__stdcall *NHKBHIT)(HANDLE, INPUT_RECORD *);
201
202 typedef int(__stdcall *CHECKINPUT)(HANDLE, INPUT_RECORD *, DWORD *, BOOLEAN_P,
203                                    int, int *, coord *);
204
205 typedef int(__stdcall *SOURCEWHERE)(char **);
206
207 typedef int(__stdcall *SOURCEAUTHOR)(char **);
208
209 typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
210
211 typedef struct {
212     char *              name;       // name without DLL extension
213     HANDLE              hLibrary;
214     PROCESS_KEYSTROKE   pProcessKeystroke;
215     NHKBHIT             pNHkbhit;
216     CHECKINPUT          pCheckInput;
217     SOURCEWHERE         pSourceWhere;
218     SOURCEAUTHOR        pSourceAuthor;
219     KEYHANDLERNAME      pKeyHandlerName;
220 } keyboard_handler_t;
221
222 keyboard_handler_t keyboard_handler;
223
224
225 /* Console buffer flipping support */
226
227 static void back_buffer_flip()
228 {
229     cell_t * back = console.back_buffer;
230     cell_t * front = console.front_buffer;
231     COORD pos;
232     DWORD unused;
233
234     for (pos.Y = 0; pos.Y < console.height; pos.Y++) {
235         for (pos.X = 0; pos.X < console.width; pos.X++) {
236 #if 1 /*JP*/
237             if (back->iskanji == 1) {
238                 cell_t * back2 = back + 1;
239                 cell_t * front2 = front + 1;
240                 if (back->attribute != front->attribute ||
241                     back2->attribute != front2->attribute) {
242                     WORD attrs[2];
243                     attrs[0] = attrs[1] = back->attribute;
244                     WriteConsoleOutputAttribute(console.hConOut, attrs,
245                                                 2, pos, &unused);
246                     front->attribute = back->attribute;
247                     front2->attribute = back2->attribute;
248                 }
249                 if (back->character != front->character ||
250                     back2->character != front2->character) {
251                     unsigned char buf[2];
252                     buf[0] = (unsigned char)(back->character);
253                     buf[1] = (unsigned char)(back2->character);
254                     WriteConsoleOutputCharacter(console.hConOut, buf, 2, pos,
255                                                     &unused);
256                     front->character = back->character;
257                     front2->character = back2->character;
258                 }
259                 pos.X++;
260                 back += 2;
261                 front += 2;
262                 continue;
263             }
264 #endif
265             if (back->attribute != front->attribute) {
266                 WriteConsoleOutputAttribute(console.hConOut, &back->attribute,
267                                             1, pos, &unused);
268                 front->attribute = back->attribute;
269             }
270             if (back->character != front->character) {
271                 if (console.has_unicode) {
272                     WriteConsoleOutputCharacterW(console.hConOut,
273                         &back->character, 1, pos, &unused);
274                 } else {
275                     char ch = (char)back->character;
276                     WriteConsoleOutputCharacterA(console.hConOut, &ch, 1, pos,
277                                                     &unused);
278                 }
279                 *front = *back;
280             }
281             back++;
282             front++;
283         }
284     }
285 }
286
287 void buffer_fill_to_end(cell_t * buffer, cell_t * fill, int x, int y)
288 {
289     nhassert(x >= 0 && x < console.width);
290     nhassert(y >= 0 && ((y < console.height) || (y == console.height && 
291                                                  x == 0)));
292
293     cell_t * dst = buffer + console.width * y + x;
294     cell_t * sentinel = buffer + console.buffer_size;
295     while (dst != sentinel)
296         *dst++ = *fill;
297
298     if (iflags.debug.immediateflips && buffer == console.back_buffer)
299         back_buffer_flip();
300 }
301
302 static void buffer_clear_to_end_of_line(cell_t * buffer, int x, int y)
303 {
304     nhassert(x >= 0 && x < console.width);
305     nhassert(y >= 0 && ((y < console.height) || (y == console.height && 
306                                                  x == 0)));
307     cell_t * dst = buffer + console.width * y + x;
308     cell_t *sentinel = buffer + console.width * (y + 1);
309
310     while (dst != sentinel)
311         *dst++ = clear_cell;
312
313     if (iflags.debug.immediateflips)
314         back_buffer_flip();
315 }
316
317 void buffer_write(cell_t * buffer, cell_t * cell, COORD pos)
318 {
319     nhassert(pos.X >= 0 && pos.X < console.width);
320     nhassert(pos.Y >= 0 && pos.Y < console.height);
321
322     cell_t * dst = buffer + (console.width * pos.Y) + pos.X;
323     *dst = *cell;
324
325     if (iflags.debug.immediateflips && buffer == console.back_buffer)
326         back_buffer_flip();
327 }
328
329 /*
330  * Called after returning from ! or ^Z
331  */
332 void
333 gettty()
334 {
335 #ifndef TEXTCOLOR
336     int k;
337 #endif
338     erase_char = '\b';
339     kill_char = 21; /* cntl-U */
340     iflags.cbreak = TRUE;
341 #ifdef TEXTCOLOR
342     init_ttycolor();
343 #else
344     for (k = 0; k < CLR_MAX; ++k)
345         ttycolors[k] = NO_COLOR;
346 #endif
347 }
348
349 /* reset terminal to original state */
350 void
351 settty(s)
352 const char *s;
353 {
354     cmov(ttyDisplay->curx, ttyDisplay->cury);
355     end_screen();
356     if (s)
357         raw_print(s);
358     restore_original_console_font();
359     if (orig_QuickEdit) {
360         DWORD cmode;
361
362         GetConsoleMode(console.hConIn, &cmode);
363         cmode |= (ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS);
364         SetConsoleMode(console.hConIn, cmode);
365     }
366 }
367
368 /* called by init_nhwindows() and resume_nhwindows() */
369 void
370 setftty()
371 {
372 #ifdef CHANGE_COLOR
373     if (altered_palette)
374         adjust_palette();
375 #endif
376     start_screen();
377 }
378
379 void
380 tty_startup(wid, hgt)
381 int *wid, *hgt;
382 {
383     *wid = console.width;
384     *hgt = console.height;
385     set_option_mod_status("mouse_support", SET_IN_GAME);
386 }
387
388 void
389 tty_number_pad(state)
390 int state;
391 {
392     // do nothing
393 }
394
395 void
396 tty_start_screen()
397 {
398     if (iflags.num_pad)
399         tty_number_pad(1); /* make keypad send digits */
400 }
401
402 void
403 tty_end_screen()
404 {
405     clear_screen();
406     really_move_cursor();
407     buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
408     back_buffer_flip();
409     FlushConsoleInputBuffer(console.hConIn);
410 }
411
412 static BOOL
413 CtrlHandler(ctrltype)
414 DWORD ctrltype;
415 {
416     switch (ctrltype) {
417     /*  case CTRL_C_EVENT: */
418     case CTRL_BREAK_EVENT:
419         clear_screen();
420     case CTRL_CLOSE_EVENT:
421     case CTRL_LOGOFF_EVENT:
422     case CTRL_SHUTDOWN_EVENT:
423         getreturn_enabled = FALSE;
424 #ifndef NOSAVEONHANGUP
425         hangup(0);
426 #endif
427 #if defined(SAFERHANGUP)
428         CloseHandle(console.hConIn); /* trigger WAIT_FAILED */
429         return TRUE;
430 #endif
431     default:
432         return FALSE;
433     }
434 }
435
436 /* called by pcmain() and process_options() */
437 void
438 nttty_open(mode)
439 int mode; // unused
440 {
441     DWORD cmode;
442
443     /* Initialize the function pointer that points to
444      * the kbhit() equivalent, in this TTY case nttty_kbhit()
445      */
446     nt_kbhit = nttty_kbhit;
447
448     if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
449         /* Unable to set control handler */
450         cmode = 0; /* just to have a statement to break on for debugger */
451     }
452
453     LI = console.height;
454     CO = console.width;
455
456     really_move_cursor();
457 }
458
459 void
460 nttty_exit()
461 {
462     /* go back to using the safe routines */
463     safe_routines();
464 }
465
466 int
467 process_keystroke(ir, valid, numberpad, portdebug)
468 INPUT_RECORD *ir;
469 boolean *valid;
470 boolean numberpad;
471 int portdebug;
472 {
473     int ch;
474
475 #ifdef QWERTZ_SUPPORT
476     if (Cmd.swap_yz)
477         numberpad |= 0x10;
478 #endif
479     ch = keyboard_handler.pProcessKeystroke(
480                     console.hConIn, ir, valid, numberpad, portdebug);
481 #ifdef QWERTZ_SUPPORT
482     numberpad &= ~0x10;
483 #endif
484     /* check for override */
485     if (ch && ch < MAX_OVERRIDES && key_overrides[ch])
486         ch = key_overrides[ch];
487     return ch;
488 }
489
490 int
491 nttty_kbhit()
492 {
493     return keyboard_handler.pNHkbhit(console.hConIn, &ir);
494 }
495
496 int
497 tgetch()
498 {
499     int mod;
500     coord cc;
501     DWORD count;
502     boolean numpad = iflags.num_pad;
503
504     really_move_cursor();
505     if (iflags.debug_fuzzer)
506         return randomkey();
507 #ifdef QWERTZ_SUPPORT
508     if (Cmd.swap_yz)
509         numpad |= 0x10;
510 #endif
511
512     return (program_state.done_hup)
513                ? '\033'
514                : keyboard_handler.pCheckInput(
515                    console.hConIn, &ir, &count, numpad, 0, &mod, &cc);
516 }
517
518 int
519 ntposkey(x, y, mod)
520 int *x, *y, *mod;
521 {
522     int ch;
523     coord cc;
524     DWORD count;
525     boolean numpad = iflags.num_pad;
526
527     really_move_cursor();
528     if (iflags.debug_fuzzer)
529         return randomkey();
530 #ifdef QWERTZ_SUPPORT
531     if (Cmd.swap_yz)
532         numpad |= 0x10;
533 #endif
534     ch = (program_state.done_hup)
535              ? '\033'
536              : keyboard_handler.pCheckInput(
537                    console.hConIn, &ir, &count, numpad, 1, mod, &cc);
538 #ifdef QWERTZ_SUPPORT
539     numpad &= ~0x10;
540 #endif
541     if (!ch) {
542         *x = cc.x;
543         *y = cc.y;
544     }
545     return ch;
546 }
547
548 static void set_console_cursor(int x, int y)
549 {
550     nhassert(x >= 0 && x < console.width);
551     nhassert(y >= 0 && y < console.height);
552
553     console.cursor.X = max(0, min(console.width - 1, x));
554     console.cursor.Y = max(0, min(console.height - 1, y));
555 }
556
557 static void
558 really_move_cursor()
559 {
560 #ifdef PORT_DEBUG
561     char oldtitle[BUFSZ], newtitle[BUFSZ];
562     if (display_cursor_info && wizard) {
563         oldtitle[0] = '\0';
564         if (GetConsoleTitle(oldtitle, BUFSZ)) {
565             oldtitle[39] = '\0';
566         }
567         Sprintf(newtitle, "%-55s tty=(%02d,%02d) nttty=(%02d,%02d)", oldtitle,
568                 ttyDisplay->curx, ttyDisplay->cury,
569                 console.cursor.X, console.cursor.Y);
570         (void) SetConsoleTitle(newtitle);
571     }
572 #endif
573     if (ttyDisplay)
574         set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
575
576     back_buffer_flip();
577     SetConsoleCursorPosition(console.hConOut, console.cursor);
578 }
579
580 void
581 cmov(x, y)
582 register int x, y;
583 {
584     ttyDisplay->cury = y;
585     ttyDisplay->curx = x;
586
587     set_console_cursor(x, y);
588 }
589
590 void
591 nocmov(x, y)
592 int x, y;
593 {
594     ttyDisplay->curx = x;
595     ttyDisplay->cury = y;
596
597     set_console_cursor(x, y);
598 }
599
600 /* same signature as 'putchar()' with potential failure result ignored */
601 int
602 xputc(ch)
603 int ch;
604 {
605     set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
606     xputc_core((char) ch);
607     return 0;
608 }
609
610 #if 1 /*JP*/
611 void
612 xputc2_core(ch1, ch2)
613 unsigned int ch1;
614 unsigned int ch2;
615 {
616     nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
617     nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
618
619     boolean inverse = FALSE;
620     cell_t cell;
621
622     /* xputc_core()\82©\82ç\82Ì\83R\83s\81[ */
623     inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
624     console.attr = (inverse) ?
625         ttycolors_inv[console.current_nhcolor] :
626     ttycolors[console.current_nhcolor];
627     if (console.current_nhattr[ATR_BOLD])
628         console.attr |= (inverse) ?
629           BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
630
631     cell.attribute = console.attr;
632
633     /* \89E\92[\82É1\83o\83C\83g\95ª\82µ\82©\8bó\82«\82ª\82È\82¢\8fê\8d\87 */
634     if (console.cursor.X == console.width - 2) {
635         /* \8bó\94\92\95\\8e¦ */
636         cell.character = ' ';
637         cell.iskanji = 0;
638         buffer_write(console.back_buffer, &cell, console.cursor);
639         console.cursor.X++;
640         if (console.cursor.Y < console.height - 1) {
641             /* \8e\9f\82Ì\8ds\82É */
642             console.cursor.X = 1;
643             console.cursor.Y++;
644         } else {
645             /* \8aù\82É\89º\92[\82Ì\8fê\8d\87\82Í\82È\82É\82à\82µ\82È\82¢ */
646             return;
647         }
648     }
649
650     cell.character = ch1;
651     cell.iskanji = 1;
652     buffer_write(console.back_buffer, &cell, console.cursor);
653     console.cursor.X++;
654
655     cell.character = ch2;
656     cell.iskanji = 2;
657     buffer_write(console.back_buffer, &cell, console.cursor);
658
659     if (console.cursor.X == console.width - 1) {
660         if (console.cursor.Y < console.height - 1) {
661             console.cursor.X = 1;
662             console.cursor.Y++;
663         }
664     } else {
665         console.cursor.X++;
666     }
667
668     nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
669     nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
670 }
671
672 void
673 xputc2(ch1, ch2)
674 int ch1;
675 int ch2;
676 {
677     /* wintty.c \82Å\82Í 1 \83o\83C\83g\96\88\82É curx \82ð\89Á\8eZ\82·\82é\82ª\81A\82±\82±\82Í
678        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Å
679       \82µ\82Ü\82Á\82Ä\82¢\82é\81B\8f]\82Á\82Ä 1 \82ð\88ø\82­\81B */
680     console.cursor.X = ttyDisplay->curx - 1;
681     console.cursor.Y = ttyDisplay->cury;
682
683     xputc2_core(ch1, ch2);
684 }
685 #endif
686
687 void
688 xputs(s)
689 const char *s;
690 {
691     int k;
692     int slen = (int) strlen(s);
693
694     if (ttyDisplay)
695         set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
696
697     if (s) {
698         for (k = 0; k < slen && s[k]; ++k)
699             xputc_core(s[k]);
700     }
701 }
702
703 /* xputc_core() and g_putch() are the only
704  * two routines that actually place output
705  * on the display.
706  */
707 void
708 xputc_core(ch)
709 char ch;
710 {
711     nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
712     nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
713
714     boolean inverse = FALSE;
715     cell_t cell;
716
717     switch (ch) {
718     case '\n':
719         if (console.cursor.Y < console.height - 1)
720             console.cursor.Y++;
721     /* fall through */
722     case '\r':
723         console.cursor.X = 1;
724         break;
725     case '\b':
726         if (console.cursor.X > 1) {
727             console.cursor.X--;
728         } else if(console.cursor.Y > 0) {
729             console.cursor.X = console.width - 1;
730             console.cursor.Y--;
731         }
732         break;
733     default:
734
735         inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
736         console.attr = (inverse) ?
737                         ttycolors_inv[console.current_nhcolor] :
738                         ttycolors[console.current_nhcolor];
739         if (console.current_nhattr[ATR_BOLD])
740                 console.attr |= (inverse) ?
741                                 BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
742
743         cell.attribute = console.attr;
744 #if 0 /*JP*/
745         cell.character = (console.has_unicode ? console.cpMap[ch] : ch);
746 #else
747         cell.character = ch;
748 #endif
749 #if 1 /*JP*//*\8fí\82É1\83o\83C\83g\95\8e\9a*/
750         cell.iskanji = 0;
751 #endif
752
753         buffer_write(console.back_buffer, &cell, console.cursor);
754
755         if (console.cursor.X == console.width - 1) {
756             if (console.cursor.Y < console.height - 1) {
757                 console.cursor.X = 1;
758                 console.cursor.Y++;
759             }
760         } else {
761             console.cursor.X++;
762         }
763     }
764
765     nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
766     nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
767 }
768
769 /*
770  * Overrides wintty.c function of the same name
771  * for win32. It is used for glyphs only, not text.
772  */
773
774 void
775 g_putch(in_ch)
776 int in_ch;
777 {
778     boolean inverse = FALSE;
779     unsigned char ch = (unsigned char) in_ch;
780
781     set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
782
783     inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
784     console.attr = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse) ?
785                     ttycolors_inv[console.current_nhcolor] :
786                     ttycolors[console.current_nhcolor];
787     if (console.current_nhattr[ATR_BOLD])
788         console.attr |= (inverse) ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
789
790     cell_t cell;
791
792     cell.attribute = console.attr;
793 #if 0 /*JP*/
794     cell.character = (console.has_unicode ? cp437[ch] : ch);
795 #else
796     cell.character = ch;
797 #endif
798 #if 1 /*JP*//*\8fí\82É1\83o\83C\83g\95\8e\9a*/
799     cell.iskanji = 0;
800 #endif
801
802     buffer_write(console.back_buffer, &cell, console.cursor);
803 }
804
805 void
806 cl_end()
807 {
808     set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
809     buffer_clear_to_end_of_line(console.back_buffer, console.cursor.X,
810                                 console.cursor.Y);
811     tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
812 }
813
814 void
815 raw_clear_screen()
816 {
817     if (WINDOWPORT("tty")) {
818         cell_t * back = console.back_buffer;
819         cell_t * front = console.front_buffer;
820         COORD pos;
821         DWORD unused;
822
823         for (pos.Y = 0; pos.Y < console.height; pos.Y++) {
824             for (pos.X = 0; pos.X < console.width; pos.X++) {
825                  WriteConsoleOutputAttribute(console.hConOut, &back->attribute,
826                                              1, pos, &unused);
827                  front->attribute = back->attribute;
828                  if (console.has_unicode) {
829                      WriteConsoleOutputCharacterW(console.hConOut,
830                              &back->character, 1, pos, &unused);
831                  } else {
832                      char ch = (char)back->character;
833                      WriteConsoleOutputCharacterA(console.hConOut, &ch, 1, pos,
834                                                          &unused);
835                  }
836                  *front = *back;
837                  back++;
838                  front++;
839             }
840         }
841     }
842 }
843
844 void
845 clear_screen()
846 {
847     buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);    
848     home();
849 }
850
851 void
852 home()
853 {
854     ttyDisplay->curx = ttyDisplay->cury = 0;
855     set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
856 }
857
858 void
859 backsp()
860 {
861     set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
862     xputc_core('\b');
863 }
864
865 void
866 cl_eos()
867 {
868     buffer_fill_to_end(console.back_buffer, &clear_cell, ttyDisplay->curx,
869                         ttyDisplay->cury);
870     tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
871 }
872
873 void
874 tty_nhbell()
875 {
876     if (flags.silent || iflags.debug_fuzzer)
877         return;
878     Beep(8000, 500);
879 }
880
881 volatile int junk; /* prevent optimizer from eliminating loop below */
882
883 void
884 tty_delay_output()
885 {
886     /* delay 50 ms - uses ANSI C clock() function now */
887     clock_t goal;
888     int k;
889
890     goal = 50 + clock();
891     back_buffer_flip();
892     if (iflags.debug_fuzzer)
893         return;
894
895     while (goal > clock()) {
896         k = junk; /* Do nothing */
897     }
898 }
899
900 /*
901  * CLR_BLACK            0
902  * CLR_RED              1
903  * CLR_GREEN            2
904  * CLR_BROWN            3       low-intensity yellow
905  * CLR_BLUE             4
906  * CLR_MAGENTA          5
907  * CLR_CYAN             6
908  * CLR_GRAY             7       low-intensity white
909  * NO_COLOR             8
910  * CLR_ORANGE           9
911  * CLR_BRIGHT_GREEN     10
912  * CLR_YELLOW           11
913  * CLR_BRIGHT_BLUE      12
914  * CLR_BRIGHT_MAGENTA   13
915  * CLR_BRIGHT_CYAN      14
916  * CLR_WHITE            15
917  * CLR_MAX              16
918  * BRIGHT               8
919  */
920
921 static void
922 init_ttycolor()
923 {
924 #ifdef TEXTCOLOR
925     ttycolors[CLR_BLACK]        = FOREGROUND_INTENSITY; /* fix by Quietust */
926     ttycolors[CLR_RED]          = FOREGROUND_RED;
927     ttycolors[CLR_GREEN]        = FOREGROUND_GREEN;
928     ttycolors[CLR_BROWN]        = FOREGROUND_GREEN | FOREGROUND_RED;
929     ttycolors[CLR_BLUE]         = FOREGROUND_BLUE;
930     ttycolors[CLR_MAGENTA]      = FOREGROUND_BLUE | FOREGROUND_RED;
931     ttycolors[CLR_CYAN]         = FOREGROUND_GREEN | FOREGROUND_BLUE;
932     ttycolors[CLR_GRAY]         = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
933     ttycolors[NO_COLOR]         = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
934     ttycolors[CLR_ORANGE]       = FOREGROUND_RED | FOREGROUND_INTENSITY;
935     ttycolors[CLR_BRIGHT_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
936     ttycolors[CLR_YELLOW]       = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
937     ttycolors[CLR_BRIGHT_BLUE]  = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
938     ttycolors[CLR_BRIGHT_MAGENTA]=FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
939     ttycolors[CLR_BRIGHT_CYAN]  = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
940     ttycolors[CLR_WHITE]        = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED
941                                     | FOREGROUND_INTENSITY;
942
943     ttycolors_inv[CLR_BLACK]       = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
944                                         | BACKGROUND_INTENSITY;
945     ttycolors_inv[CLR_RED]         = BACKGROUND_RED | BACKGROUND_INTENSITY;
946     ttycolors_inv[CLR_GREEN]       = BACKGROUND_GREEN;
947     ttycolors_inv[CLR_BROWN]       = BACKGROUND_GREEN | BACKGROUND_RED;
948     ttycolors_inv[CLR_BLUE]        = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
949     ttycolors_inv[CLR_MAGENTA]     = BACKGROUND_BLUE | BACKGROUND_RED;
950     ttycolors_inv[CLR_CYAN]        = BACKGROUND_GREEN | BACKGROUND_BLUE;
951     ttycolors_inv[CLR_GRAY]        = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE;
952     ttycolors_inv[NO_COLOR]        = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
953     ttycolors_inv[CLR_ORANGE]      = BACKGROUND_RED | BACKGROUND_INTENSITY;
954     ttycolors_inv[CLR_BRIGHT_GREEN]= BACKGROUND_GREEN | BACKGROUND_INTENSITY;
955     ttycolors_inv[CLR_YELLOW]      = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
956     ttycolors_inv[CLR_BRIGHT_BLUE] = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
957     ttycolors_inv[CLR_BRIGHT_MAGENTA] =BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY;
958     ttycolors_inv[CLR_BRIGHT_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
959     ttycolors_inv[CLR_WHITE]       = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
960                                        | BACKGROUND_INTENSITY;
961 #else
962     int k;
963     ttycolors[0] = FOREGROUND_INTENSITY;
964     ttycolors_inv[0] = BACKGROUND_INTENSITY;
965     for (k = 1; k < SIZE(ttycolors); ++k) {
966         ttycolors[k] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
967         ttycolors_inv[k] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
968     }
969 #endif
970     init_ttycolor_completed = TRUE;
971 }
972
973 #if 0
974 int
975 has_color(int color)        /* this function is commented out */
976 {
977 #ifdef TEXTCOLOR
978     if ((color >= 0) && (color < CLR_MAX))
979         return 1;
980 #else
981     if ((color == CLR_BLACK) || (color == CLR_WHITE) || (color == NO_COLOR))
982         return 1;
983 #endif
984     else
985         return 0;
986 }
987 #endif
988
989 int
990 term_attr_fixup(int attrmask)
991 {
992     return attrmask;
993 }
994
995 void
996 term_start_attr(int attrib)
997 {
998     console.current_nhattr[attrib] = TRUE;
999     if (attrib) console.current_nhattr[ATR_NONE] = FALSE;
1000 }
1001
1002 void
1003 term_end_attr(int attrib)
1004 {
1005     int k;
1006
1007     switch (attrib) {
1008     case ATR_INVERSE:
1009     case ATR_ULINE:
1010     case ATR_BLINK:
1011     case ATR_BOLD:
1012         break;
1013     }
1014     console.current_nhattr[attrib] = FALSE;
1015     console.current_nhattr[ATR_NONE] = TRUE;
1016     /* re-evaluate all attr now for performance at output time */
1017     for (k=ATR_NONE; k <= ATR_INVERSE; ++k) {
1018         if (console.current_nhattr[k])
1019             console.current_nhattr[ATR_NONE] = FALSE;
1020     }
1021 }
1022
1023 void
1024 term_end_raw_bold(void)
1025 {
1026     term_end_attr(ATR_BOLD);
1027 }
1028
1029 void
1030 term_start_raw_bold(void)
1031 {
1032     term_start_attr(ATR_BOLD);
1033 }
1034
1035 void
1036 term_start_color(int color)
1037 {
1038 #ifdef TEXTCOLOR
1039     if (color >= 0 && color < CLR_MAX) {
1040         console.current_nhcolor = color;
1041     } else
1042 #endif
1043     console.current_nhcolor = NO_COLOR;
1044 }
1045
1046 void
1047 term_end_color(void)
1048 {
1049 #ifdef TEXTCOLOR
1050     console.foreground = DEFTEXTCOLOR;
1051 #endif
1052     console.attr = (console.foreground | console.background);
1053     console.current_nhcolor = NO_COLOR;
1054 }
1055
1056 void
1057 standoutbeg()
1058 {
1059     term_start_attr(ATR_BOLD);
1060 }
1061
1062 void
1063 standoutend()
1064 {
1065     term_end_attr(ATR_BOLD);
1066 }
1067
1068 #ifndef NO_MOUSE_ALLOWED
1069 void
1070 toggle_mouse_support()
1071 {
1072     static int qeinit = 0;
1073     DWORD cmode;
1074
1075     GetConsoleMode(console.hConIn, &cmode);
1076     if (!qeinit) {
1077         qeinit = 1;
1078         orig_QuickEdit = ((cmode & ENABLE_QUICK_EDIT_MODE) != 0);
1079     }
1080     switch(iflags.wc_mouse_support) {
1081         case 2:
1082                 cmode |= ENABLE_MOUSE_INPUT;
1083                 break;
1084         case 1:
1085                 cmode |= ENABLE_MOUSE_INPUT;
1086                 cmode &= ~ENABLE_QUICK_EDIT_MODE;
1087                 cmode |= ENABLE_EXTENDED_FLAGS;
1088                 break;
1089         case 0:
1090                 /*FALLTHRU*/
1091         default:
1092                 cmode &= ~ENABLE_MOUSE_INPUT;
1093                 if (orig_QuickEdit)
1094                     cmode |= (ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS);
1095     }
1096     SetConsoleMode(console.hConIn, cmode);
1097 }
1098 #endif
1099
1100 /* handle tty options updates here */
1101 void
1102 nttty_preference_update(pref)
1103 const char *pref;
1104 {
1105     if (stricmp(pref, "mouse_support") == 0) {
1106 #ifndef NO_MOUSE_ALLOWED
1107         toggle_mouse_support();
1108 #endif
1109     }
1110     if (stricmp(pref, "symset") == 0)
1111         check_and_set_font();
1112     return;
1113 }
1114
1115 #ifdef PORT_DEBUG
1116 void
1117 win32con_debug_keystrokes()
1118 {
1119     DWORD count;
1120     boolean valid = 0;
1121     int ch;
1122     xputs("\n");
1123     while (!valid || ch != 27) {
1124         nocmov(ttyDisplay->curx, ttyDisplay->cury);
1125         ReadConsoleInput(console.hConIn, &ir, 1, &count);
1126         if ((ir.EventType == KEY_EVENT) && ir.Event.KeyEvent.bKeyDown)
1127             ch = process_keystroke(&ir, &valid, iflags.num_pad, 1);
1128     }
1129     (void) doredraw();
1130 }
1131 void
1132 win32con_handler_info()
1133 {
1134     char *buf;
1135     int ci;
1136     if (!keyboard_handler.pSourceAuthor && !keyboard_handler.pSourceWhere)
1137         pline("Keyboard handler source info and author unavailable.");
1138     else {
1139         if (keyboard_handler.pKeyHandlerName &&
1140             keyboard_handler.pKeyHandlerName(&buf, 1)) {
1141             xputs("\n");
1142             xputs("Keystroke handler loaded: \n    ");
1143             xputs(buf);
1144         }
1145         if (keyboard_handler.pSourceAuthor &&
1146             keyboard_handler.pSourceAuthor(&buf)) {
1147             xputs("\n");
1148             xputs("Keystroke handler Author: \n    ");
1149             xputs(buf);
1150         }
1151         if (keyboard_handler.pSourceWhere &&
1152             keyboard_handler.pSourceWhere(&buf)) {
1153             xputs("\n");
1154             xputs("Keystroke handler source code available at:\n    ");
1155             xputs(buf);
1156         }
1157         xputs("\nPress any key to resume.");
1158         ci = nhgetch();
1159         (void) doredraw();
1160     }
1161 }
1162
1163 void
1164 win32con_toggle_cursor_info()
1165 {
1166     display_cursor_info = !display_cursor_info;
1167 }
1168 #endif
1169
1170 void
1171 map_subkeyvalue(op)
1172 register char *op;
1173 {
1174     char digits[] = "0123456789";
1175     int length, i, idx, val;
1176     char *kp;
1177
1178     idx = -1;
1179     val = -1;
1180     kp = index(op, '/');
1181     if (kp) {
1182         *kp = '\0';
1183         kp++;
1184         length = strlen(kp);
1185         if (length < 1 || length > 3)
1186             return;
1187         for (i = 0; i < length; i++)
1188             if (!index(digits, kp[i]))
1189                 return;
1190         val = atoi(kp);
1191         length = strlen(op);
1192         if (length < 1 || length > 3)
1193             return;
1194         for (i = 0; i < length; i++)
1195             if (!index(digits, op[i]))
1196                 return;
1197         idx = atoi(op);
1198     }
1199     if (idx >= MAX_OVERRIDES || idx < 0 || val >= MAX_OVERRIDES || val < 1)
1200         return;
1201     key_overrides[idx] = val;
1202 }
1203
1204 void unload_keyboard_handler()
1205 {
1206     nhassert(keyboard_handler.hLibrary != NULL);
1207
1208     FreeLibrary(keyboard_handler.hLibrary);
1209     memset(&keyboard_handler, 0, sizeof(keyboard_handler_t));
1210 }
1211
1212 boolean
1213 load_keyboard_handler(const char * inName)
1214 {
1215     char path[MAX_ALTKEYHANDLER + 4];
1216     strcpy(path, inName);
1217     strcat(path, ".dll");
1218
1219     HANDLE hLibrary = LoadLibrary(path);
1220
1221     if (hLibrary == NULL)
1222         return FALSE;
1223
1224     PROCESS_KEYSTROKE pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
1225         hLibrary, TEXT("ProcessKeystroke"));
1226     NHKBHIT pNHkbhit = (NHKBHIT) GetProcAddress(
1227         hLibrary, TEXT("NHkbhit"));
1228     CHECKINPUT pCheckInput =
1229         (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
1230
1231     if (!pProcessKeystroke || !pNHkbhit || !pCheckInput)
1232     {
1233         return FALSE;
1234     } else {
1235         if (keyboard_handler.hLibrary != NULL)
1236             unload_keyboard_handler();
1237
1238         keyboard_handler.hLibrary = hLibrary;
1239
1240         keyboard_handler.pProcessKeystroke = pProcessKeystroke;
1241         keyboard_handler.pNHkbhit = pNHkbhit;
1242         keyboard_handler.pCheckInput = pCheckInput;
1243
1244         keyboard_handler.pSourceWhere =
1245             (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
1246         keyboard_handler.pSourceAuthor =
1247             (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
1248         keyboard_handler.pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
1249             hLibrary, TEXT("KeyHandlerName"));
1250     }
1251
1252     return TRUE;
1253 }
1254
1255 void set_altkeyhandler(const char * inName)
1256 {
1257     if (strlen(inName) >= MAX_ALTKEYHANDLER) {
1258         config_error_add("altkeyhandler name '%s' is too long", inName);
1259         return;
1260     }
1261
1262     char name[MAX_ALTKEYHANDLER];
1263     strcpy(name, inName);
1264
1265     /* We support caller mistakenly giving name with '.dll' extension */
1266     char * ext = strchr(name, '.');
1267     if (ext != NULL) *ext = '\0';
1268
1269     if (load_keyboard_handler(name))
1270         strcpy(iflags.altkeyhandler, name);
1271     else {
1272         config_error_add("unable to load altkeyhandler '%s'", name);
1273         return;
1274     }
1275
1276     return;
1277 }
1278
1279
1280 /* fatal error */
1281 /*VARARGS1*/
1282 void nttty_error
1283 VA_DECL(const char *, s)
1284 {
1285     char buf[BUFSZ];
1286     VA_START(s);
1287     VA_INIT(s, const char *);
1288     /* error() may get called before tty is initialized */
1289     if (iflags.window_inited)
1290         end_screen();
1291     buf[0] = '\n';
1292     (void) vsnprintf(&buf[1], sizeof buf - 1, s, VA_ARGS);
1293     msmsg(buf);
1294     really_move_cursor();
1295     VA_END();
1296     exit(EXIT_FAILURE);
1297 }
1298
1299 void
1300 synch_cursor()
1301 {
1302     really_move_cursor();
1303 }
1304
1305 #ifdef CHANGE_COLOR
1306 void
1307 tty_change_color(color_number, rgb, reverse)
1308 int color_number, reverse;
1309 long rgb;
1310 {
1311     /* Map NetHack color index to NT Console palette index */
1312     int idx, win32_color_number[] = {
1313         0,  /* CLR_BLACK           0 */
1314         4,  /* CLR_RED             1 */
1315         2,  /* CLR_GREEN           2 */
1316         6,  /* CLR_BROWN           3 */
1317         1,  /* CLR_BLUE            4 */
1318         5,  /* CLR_MAGENTA         5 */
1319         3,  /* CLR_CYAN            6 */
1320         7,  /* CLR_GRAY            7 */
1321         8,  /* NO_COLOR            8 */
1322         12, /* CLR_ORANGE          9 */
1323         10, /* CLR_BRIGHT_GREEN   10 */
1324         14, /* CLR_YELLOW         11 */
1325         9,  /* CLR_BRIGHT_BLUE    12 */
1326         13, /* CLR_BRIGHT_MAGENTA 13 */
1327         11, /* CLR_BRIGHT_CYAN    14 */
1328         15  /* CLR_WHITE          15 */
1329     };
1330     int k;
1331     if (color_number < 0) { /* indicates OPTIONS=palette with no value */
1332         /* copy the NetHack palette into UserDefinedColors */
1333         for (k = 0; k < CLR_MAX; k++)
1334             UserDefinedColors[k] = NetHackColors[k];
1335     } else if (color_number >= 0 && color_number < CLR_MAX) {
1336         if (!altered_palette) {
1337             /* make sure a full suite is available */
1338             for (k = 0; k < CLR_MAX; k++)
1339                 UserDefinedColors[k] = DefaultColors[k];
1340         }
1341         idx = win32_color_number[color_number];
1342         UserDefinedColors[idx] = rgb;
1343     }
1344     altered_palette = TRUE;
1345 }
1346
1347 char *
1348 tty_get_color_string()
1349 {
1350     return "";
1351 }
1352
1353 int
1354 match_color_name(c)
1355 const char *c;
1356 {
1357     const struct others {
1358         int idx;
1359         const char *colorname;
1360     } othernames[] = {
1361         { CLR_MAGENTA, "purple" },
1362         { CLR_BRIGHT_MAGENTA, "bright purple" },
1363         { NO_COLOR, "dark gray" },
1364         { NO_COLOR, "dark grey" },
1365         { CLR_GRAY, "grey" },
1366     };
1367
1368     int cnt;
1369     for (cnt = 0; cnt < CLR_MAX; ++cnt) {
1370         if (!strcmpi(c, c_obj_colors[cnt]))
1371             return cnt;
1372     }
1373     for (cnt = 0; cnt < SIZE(othernames); ++cnt) {
1374         if (!strcmpi(c, othernames[cnt].colorname))
1375             return othernames[cnt].idx;
1376     }
1377     return -1;
1378 }
1379
1380 /*
1381  * Returns 0 if badoption syntax
1382  */
1383 int
1384 alternative_palette(op)
1385 char *op;
1386 {
1387     /*
1388      *  palette:color-R-G-B
1389      *  OPTIONS=palette:green-4-3-1, palette:0-0-0-0
1390      */
1391     int fieldcnt, color_number, rgb, red, green, blue;
1392     char *fields[4], *cp;
1393
1394     if (!op) {
1395         change_color(-1, 0, 0); /* indicates palette option with
1396                                    no value meaning "load an entire
1397                                    hard-coded NetHack palette." */
1398         return 1;
1399     }
1400
1401     cp = fields[0] = op;
1402     for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
1403         cp = index(cp, '-');
1404         if (!cp)
1405             return 0;
1406         fields[fieldcnt] = cp;
1407         cp++;
1408     }
1409     for (fieldcnt = 1; fieldcnt < 4; ++fieldcnt) {
1410         *(fields[fieldcnt]) = '\0';
1411         ++fields[fieldcnt];
1412     }
1413     rgb = 0;
1414     for (fieldcnt = 0; fieldcnt < 4; ++fieldcnt) {
1415         if (fieldcnt == 0 && isalpha(*(fields[0]))) {
1416             color_number = match_color_name(fields[0]);
1417             if (color_number == -1)
1418                 return 0;
1419         } else {
1420             int dcount = 0, cval = 0;
1421             cp = fields[fieldcnt];
1422             if (*cp == '\\' && index("0123456789xXoO", cp[1])) {
1423                 const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
1424
1425                 cp++;
1426                 if (*cp == 'x' || *cp == 'X')
1427                     for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
1428                         cval = (int) ((cval * 16) + (dp - hex) / 2);
1429                 else if (*cp == 'o' || *cp == 'O')
1430                     for (++cp; (index("01234567", *cp)) && (dcount++ < 3);
1431                          cp++)
1432                         cval = (cval * 8) + (*cp - '0');
1433                 else
1434                     return 0;
1435             } else {
1436                 for (; *cp && (index("0123456789", *cp)) && (dcount++ < 3);
1437                      cp++)
1438                     cval = (cval * 10) + (*cp - '0');
1439             }
1440             switch (fieldcnt) {
1441             case 0:
1442                 color_number = cval;
1443                 break;
1444             case 1:
1445                 red = cval;
1446                 break;
1447             case 2:
1448                 green = cval;
1449                 break;
1450             case 3:
1451                 blue = cval;
1452                 break;
1453             }
1454         }
1455     }
1456     rgb = RGB(red, green, blue);
1457     if (color_number >= 0 && color_number < CLR_MAX)
1458         change_color(color_number, rgb, 0);
1459     return 1;
1460 }
1461
1462 /*
1463  *  This uses an undocumented method to set console attributes
1464  *  at runtime including console palette
1465  *
1466  *      VOID WINAPI SetConsolePalette(COLORREF palette[16])
1467  *
1468  *  Author: James Brown at www.catch22.net
1469  *
1470  *  Set palette of current console.
1471  *  Palette should be of the form:
1472  *
1473  *      COLORREF DefaultColors[CLR_MAX] =
1474  *      {
1475  *              0x00000000, 0x00800000, 0x00008000, 0x00808000,
1476  *              0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0,
1477  *              0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00,
1478  *              0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
1479  *       };
1480  */
1481
1482 #pragma pack(push, 1)
1483
1484 /*
1485  *      Structure to send console via WM_SETCONSOLEINFO
1486  */
1487 typedef struct _CONSOLE_INFO {
1488     ULONG Length;
1489     COORD ScreenBufferSize;
1490     COORD WindowSize;
1491     ULONG WindowPosX;
1492     ULONG WindowPosY;
1493
1494     COORD FontSize;
1495     ULONG FontFamily;
1496     ULONG FontWeight;
1497     WCHAR FaceName[32];
1498
1499     ULONG CursorSize;
1500     ULONG FullScreen;
1501     ULONG QuickEdit;
1502     ULONG AutoPosition;
1503     ULONG InsertMode;
1504
1505     USHORT ScreenColors;
1506     USHORT PopupColors;
1507     ULONG HistoryNoDup;
1508     ULONG HistoryBufferSize;
1509     ULONG NumberOfHistoryBuffers;
1510
1511     COLORREF ColorTable[16];
1512
1513     ULONG CodePage;
1514     HWND Hwnd;
1515
1516     WCHAR ConsoleTitle[0x100];
1517 } CONSOLE_INFO;
1518
1519 #pragma pack(pop)
1520
1521 BOOL SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci);
1522 static void GetConsoleSizeInfo(CONSOLE_INFO *pci);
1523 VOID WINAPI SetConsolePalette(COLORREF crPalette[16]);
1524
1525 void
1526 adjust_palette(VOID_ARGS)
1527 {
1528     SetConsolePalette(UserDefinedColors);
1529     altered_palette = 0;
1530 }
1531
1532 /*
1533 /* only in Win2k+  (use FindWindow for NT4) */
1534 /* HWND WINAPI GetConsoleWindow(); */
1535
1536 /*  Undocumented console message */
1537 #define WM_SETCONSOLEINFO (WM_USER + 201)
1538
1539 VOID WINAPI
1540 SetConsolePalette(COLORREF palette[16])
1541 {
1542     CONSOLE_INFO ci = { sizeof(ci) };
1543     int i;
1544     HWND hwndConsole = GetConsoleHandle();
1545
1546     /* get current size/position settings rather than using defaults.. */
1547     GetConsoleSizeInfo(&ci);
1548
1549     /* set these to zero to keep current settings */
1550     ci.FontSize.X = 0; /* def = 8  */
1551     ci.FontSize.Y = 0; /* def = 12 */
1552     ci.FontFamily = 0; /* def = 0x30 = FF_MODERN|FIXED_PITCH */
1553     ci.FontWeight = 0; /* 0x400;   */
1554     /* lstrcpyW(ci.FaceName, L"Terminal"); */
1555     ci.FaceName[0] = L'\0';
1556
1557     ci.CursorSize = 25;
1558     ci.FullScreen = FALSE;
1559     ci.QuickEdit = TRUE;
1560     ci.AutoPosition = 0x10000;
1561     ci.InsertMode = TRUE;
1562     ci.ScreenColors = MAKEWORD(0x7, 0x0);
1563     ci.PopupColors = MAKEWORD(0x5, 0xf);
1564
1565     ci.HistoryNoDup = FALSE;
1566     ci.HistoryBufferSize = 50;
1567     ci.NumberOfHistoryBuffers = 4;
1568
1569     // colour table
1570     for (i = 0; i < 16; i++)
1571         ci.ColorTable[i] = palette[i];
1572
1573     ci.CodePage = GetConsoleOutputCP();
1574     ci.Hwnd = hwndConsole;
1575
1576     lstrcpyW(ci.ConsoleTitle, L"");
1577
1578     SetConsoleInfo(hwndConsole, &ci);
1579 }
1580
1581 /*
1582  *  Wrapper around WM_SETCONSOLEINFO. We need to create the
1583  *  necessary section (file-mapping) object in the context of the
1584  *  process which owns the console, before posting the message
1585  */
1586 BOOL
1587 SetConsoleInfo(HWND hwndConsole, CONSOLE_INFO *pci)
1588 {
1589     DWORD dwConsoleOwnerPid;
1590     HANDLE hProcess;
1591     HANDLE hSection, hDupSection;
1592     PVOID ptrView = 0;
1593     HANDLE hThread;
1594
1595     /*
1596      *  Open the process which "owns" the console
1597      */
1598     GetWindowThreadProcessId(hwndConsole, &dwConsoleOwnerPid);
1599     hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
1600
1601     /*
1602      * Create a SECTION object backed by page-file, then map a view of
1603      * this section into the owner process so we can write the contents
1604      * of the CONSOLE_INFO buffer into it
1605      */
1606     hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
1607                                  pci->Length, 0);
1608
1609     /*
1610      *  Copy our console structure into the section-object
1611      */
1612     ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0,
1613                             pci->Length);
1614     memcpy(ptrView, pci, pci->Length);
1615     UnmapViewOfFile(ptrView);
1616
1617     /*
1618      *  Map the memory into owner process
1619      */
1620     DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection, 0,
1621                     FALSE, DUPLICATE_SAME_ACCESS);
1622
1623     /*  Send console window the "update" message */
1624     SendMessage(hwndConsole, WM_SETCONSOLEINFO, (WPARAM) hDupSection, 0);
1625
1626     /*
1627      * clean up
1628      */
1629     hThread = CreateRemoteThread(hProcess, 0, 0,
1630                                  (LPTHREAD_START_ROUTINE) CloseHandle,
1631                                  hDupSection, 0, 0);
1632
1633     CloseHandle(hThread);
1634     CloseHandle(hSection);
1635     CloseHandle(hProcess);
1636
1637     return TRUE;
1638 }
1639
1640 /*
1641  *  Fill the CONSOLE_INFO structure with information
1642  *  about the current console window
1643  */
1644 static void
1645 GetConsoleSizeInfo(CONSOLE_INFO *pci)
1646 {
1647     CONSOLE_SCREEN_BUFFER_INFO csbi;
1648
1649     HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
1650
1651     GetConsoleScreenBufferInfo(hConsoleOut, &csbi);
1652
1653     pci->ScreenBufferSize = csbi.dwSize;
1654     pci->WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
1655     pci->WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
1656     pci->WindowPosX = csbi.srWindow.Left;
1657     pci->WindowPosY = csbi.srWindow.Top;
1658 }
1659
1660 static HWND
1661 GetConsoleHandle(void)
1662 {
1663     HMODULE hMod = GetModuleHandle("kernel32.dll");
1664     GETCONSOLEWINDOW pfnGetConsoleWindow =
1665         (GETCONSOLEWINDOW) GetProcAddress(hMod, "GetConsoleWindow");
1666     if (pfnGetConsoleWindow)
1667         return pfnGetConsoleWindow();
1668     else
1669         return GetConsoleHwnd();
1670 }
1671
1672 static HWND
1673 GetConsoleHwnd(void)
1674 {
1675     int iterations = 0;
1676     HWND hwndFound = 0;
1677     char OldTitle[1024], NewTitle[1024], TestTitle[1024];
1678
1679     /* Get current window title */
1680     GetConsoleTitle(OldTitle, sizeof OldTitle);
1681
1682     (void) sprintf(NewTitle, "NETHACK%d/%d", GetTickCount(),
1683                    GetCurrentProcessId());
1684     SetConsoleTitle(NewTitle);
1685
1686     GetConsoleTitle(TestTitle, sizeof TestTitle);
1687     while (strcmp(TestTitle, NewTitle) != 0) {
1688         iterations++;
1689         /* sleep(0); */
1690         GetConsoleTitle(TestTitle, sizeof TestTitle);
1691     }
1692     hwndFound = FindWindow(NULL, NewTitle);
1693     SetConsoleTitle(OldTitle);
1694     /*       printf("%d iterations\n", iterations); */
1695     return hwndFound;
1696 }
1697 #endif /*CHANGE_COLOR*/
1698
1699 static int CALLBACK EnumFontCallback(
1700     const LOGFONTW * lf, const TEXTMETRICW * tm, DWORD fontType, LPARAM lParam)
1701 {
1702     LOGFONTW * lf_ptr = (LOGFONTW *) lParam;
1703     *lf_ptr = *lf;
1704     return 0;
1705 }
1706
1707 /* check_and_set_font ensures that the current font will render the symbols
1708  * that are currently being used correctly.  If they will not be rendered
1709  * correctly, then it will change the font to a known good font.
1710  */
1711 void
1712 check_and_set_font()
1713 {
1714 #if 0 /*JP*//* \83R\81[\83h\83y\81[\83W\82Í\95Ï\8dX\82µ\82È\82¢\81B932\82ð\89¼\92è\82·\82é\81B*/
1715     if (!check_font_widths()) {
1716         raw_print("WARNING: glyphs too wide in console font."
1717                   "  Changing code page to 437 and font to Consolas\n");
1718         set_known_good_console_font();
1719     }
1720 #endif
1721 }
1722
1723 #if 0 /*JP*/
1724 /* check_font_widths returns TRUE if all glyphs in current console font
1725  * fit within the width of a single console cell.
1726  */
1727 boolean
1728 check_font_widths()
1729 {
1730     CONSOLE_FONT_INFOEX console_font_info;
1731     console_font_info.cbSize = sizeof(console_font_info);
1732     BOOL success = GetCurrentConsoleFontEx(console.hConOut, FALSE,
1733                                             &console_font_info);
1734
1735     /* get console window and DC
1736      * NOTE: the DC from the console window does not have the correct
1737      *       font selected at this point.
1738      */
1739     HWND hWnd = GetConsoleWindow();
1740     HDC hDC = GetDC(hWnd);
1741
1742     LOGFONTW logical_font;
1743     logical_font.lfCharSet = DEFAULT_CHARSET;
1744     wcscpy(logical_font.lfFaceName, console_font_info.FaceName);
1745     logical_font.lfPitchAndFamily = 0;
1746
1747     /* getting matching console font */
1748     LOGFONTW matching_log_font = { 0 };
1749     EnumFontFamiliesExW(hDC, &logical_font, EnumFontCallback,
1750                                         (LPARAM) &matching_log_font, 0);
1751
1752     if (matching_log_font.lfHeight == 0) {
1753         raw_print("Unable to enumerate system fonts\n");
1754         return FALSE;
1755     }
1756
1757     /* create font matching console font */
1758     LOGFONTW console_font_log_font = matching_log_font;
1759     console_font_log_font.lfWeight = console_font_info.FontWeight;
1760     console_font_log_font.lfHeight = console_font_info.dwFontSize.Y;
1761     console_font_log_font.lfWidth = console_font_info.dwFontSize.X;
1762     HFONT console_font = CreateFontIndirectW(&console_font_log_font);
1763
1764     if (console_font == NULL) {
1765         raw_print("Unable to create console font\n");
1766         return FALSE;
1767     }
1768
1769     /* select font */
1770     HGDIOBJ saved_font = SelectObject(hDC, console_font);
1771
1772     /* determine whether it is a true type font */
1773     TEXTMETRICA tm;
1774     success = GetTextMetricsA(hDC, &tm);
1775
1776     if (!success) {
1777         raw_print("Unable to get console font text metrics\n");
1778         goto clean_up;
1779     }
1780
1781     boolean isTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
1782
1783     /* determine which glyphs are used */
1784     boolean used[256];
1785     memset(used, 0, sizeof(used));
1786     for (int i = 0; i < SYM_MAX; i++) {
1787         used[primary_syms[i]] = TRUE;
1788         used[rogue_syms[i]] = TRUE;
1789     }
1790
1791     int wcUsedCount = 0;
1792     wchar_t wcUsed[256];
1793     for (int i = 0; i < sizeof(used); i++)
1794         if (used[i])
1795             wcUsed[wcUsedCount++] = cp437[i];
1796
1797     /* measure the set of used glyphs to ensure they fit */
1798     boolean all_glyphs_fit = TRUE;
1799
1800     for (int i = 0; i < wcUsedCount; i++) {
1801         int width;
1802         if (isTrueType) {
1803             ABC abc;
1804             success = GetCharABCWidthsW(hDC, wcUsed[i], wcUsed[i], &abc);
1805             width = abc.abcA + abc.abcB + abc.abcC;
1806         } else {
1807             success = GetCharWidthW(hDC, wcUsed[i], wcUsed[i], &width);
1808         }
1809
1810         if (success && width > console_font_info.dwFontSize.X) {
1811             all_glyphs_fit = FALSE;
1812             break;
1813         }
1814     }
1815
1816 clean_up:
1817
1818     SelectObject(hDC, saved_font);
1819     DeleteObject(console_font);
1820
1821     return all_glyphs_fit;
1822 }
1823 #endif
1824
1825 /* set_known_good_console_font sets the code page and font used by the console
1826  * to settings know to work well with NetHack.  It also saves the original
1827  * settings so that they can be restored prior to NetHack exit.
1828  */
1829 void
1830 set_known_good_console_font()
1831 {
1832     CONSOLE_FONT_INFOEX console_font_info;
1833     console_font_info.cbSize = sizeof(console_font_info);
1834     BOOL success = GetCurrentConsoleFontEx(console.hConOut, FALSE,
1835                                             &console_font_info);
1836
1837     console.font_changed = TRUE;
1838     console.original_font_info = console_font_info;
1839     console.original_code_page = GetConsoleOutputCP();
1840
1841     wcscpy_s(console_font_info.FaceName,
1842         sizeof(console_font_info.FaceName)
1843             / sizeof(console_font_info.FaceName[0]),
1844         L"Consolas");
1845
1846     success = SetConsoleOutputCP(437);
1847     nhassert(success);
1848
1849     success = SetCurrentConsoleFontEx(console.hConOut, FALSE, &console_font_info);
1850     nhassert(success);
1851 }
1852
1853 /* restore_original_console_font will restore the console font and code page
1854  * settings to what they were when NetHack was launched.
1855  */
1856 void
1857 restore_original_console_font()
1858 {
1859     if (console.font_changed) {
1860         BOOL success;
1861         raw_print("Restoring original font and code page\n");
1862         success = SetConsoleOutputCP(console.original_code_page);
1863         if (!success)
1864             raw_print("Unable to restore original code page\n");
1865
1866         success = SetCurrentConsoleFontEx(console.hConOut, FALSE,
1867                                             &console.original_font_info);
1868         if (!success)
1869             raw_print("Unable to restore original font\n");
1870
1871         console.font_changed = FALSE;
1872     }
1873 }
1874
1875 #if 0 /*JP*/
1876 /* set_cp_map() creates a mapping of every possible character of a code
1877  * page to its corresponding WCHAR.  This is necessary due to the high
1878  * cost of making calls to MultiByteToWideChar() for every character we
1879  * wish to print to the console.
1880  */
1881
1882 void set_cp_map()
1883 {
1884     if (console.has_unicode) {
1885         UINT codePage = GetConsoleOutputCP();
1886
1887         if (codePage == 437) {
1888             memcpy(console.cpMap, cp437, sizeof(console.cpMap));
1889         } else {
1890             for (int i = 0; i < 256; i++) {
1891                 char c = (char)i;
1892                 int count = MultiByteToWideChar(codePage, 0, &c, 1,
1893                                                 &console.cpMap[i], 1);
1894                 nhassert(count == 1);
1895
1896                 // If a character was mapped to unicode control codes,
1897                 // remap to the appropriate unicode character per our
1898                 // code page 437 mappings.
1899                 if (console.cpMap[i] < 32)
1900                     console.cpMap[i] = cp437[console.cpMap[i]];
1901             }        
1902         }
1903
1904     }
1905 }
1906 #endif
1907
1908 #if 0
1909 /* early_raw_print() is used during early game intialization prior to the
1910  * setting up of the windowing system.  This allows early errors and panics
1911  * to have there messages displayed.
1912  *
1913  * early_raw_print() eventually gets replaced by tty_raw_print().
1914  *
1915  */
1916
1917 void early_raw_print(const char *s)
1918 {
1919     if (console.hConOut == NULL)
1920         return;
1921
1922     nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
1923     nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
1924
1925     WORD attribute = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
1926     DWORD unused;
1927
1928     while (*s != '\0') {
1929         switch (*s) {
1930         case '\n':
1931             if (console.cursor.Y < console.height - 1)
1932                 console.cursor.Y++;
1933         /* fall through */
1934         case '\r':
1935             console.cursor.X = 1;
1936             break;
1937         case '\b':
1938             if (console.cursor.X > 1) {
1939                 console.cursor.X--;
1940             } else if(console.cursor.Y > 0) {
1941                 console.cursor.X = console.width - 1;
1942                 console.cursor.Y--;
1943             }
1944             break;
1945         default:
1946             WriteConsoleOutputAttribute(console.hConOut, &attribute,
1947                                             1, console.cursor, &unused);
1948             WriteConsoleOutputCharacterA(console.hConOut, s,
1949                                             1, console.cursor, &unused);
1950             if (console.cursor.X == console.width - 1) {
1951                 if (console.cursor.Y < console.height - 1) {
1952                     console.cursor.X = 1;
1953                     console.cursor.Y++;
1954                 }
1955             } else {
1956                 console.cursor.X++;
1957             }
1958         }
1959         s++;
1960     }
1961
1962     nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
1963     nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
1964
1965     SetConsoleCursorPosition(console.hConOut, console.cursor);
1966
1967 }
1968 #endif
1969
1970 /* nethack_enter_nttty() is the first thing that is called from main
1971  * once the tty port is confirmed.
1972  *
1973  * We initialize all console state to support rendering to the console
1974  * through out flipping support at this time.  This allows us to support
1975  * raw_print prior to our returning.
1976  *
1977  * During this early initialization, we also determine the width and
1978  * height of the console that will be used.  This width and height will
1979  * not later change.
1980  *
1981  * We also check and set the console font to a font that we know will work
1982  * well with nethack.
1983  *
1984  * The intent of this early initialization is to get all state that is
1985  * not dependent upon game options initialized allowing us to simplify
1986  * any additional initialization that might be needed when we are actually
1987  * asked to open.
1988  *
1989  * Other then the call below which clears the entire console buffer, no
1990  * other code outputs directly to the console other then the code that
1991  * handles flipping the back buffer.
1992  *
1993  */
1994
1995 void nethack_enter_nttty()
1996 {
1997 #if 0
1998     /* set up state needed by early_raw_print() */
1999     windowprocs.win_raw_print = early_raw_print;
2000 #endif
2001     console.hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
2002     nhassert(console.hConOut != NULL); // NOTE: this assert will not print
2003
2004     GetConsoleScreenBufferInfo(console.hConOut, &console.origcsbi);
2005
2006     /* Testing of widths != COLNO has not turned up any problems.  Need
2007      * to do a bit more testing and then we are likely to enable having
2008      * console width match window width.
2009      */
2010 #if 0
2011     console.width = console.origcsbi.srWindow.Right -
2012                      console.origcsbi.srWindow.Left + 1;
2013     console.Width = max(console.Width, COLNO);
2014 #else
2015     console.width = COLNO;
2016 #endif
2017
2018     console.height = console.origcsbi.srWindow.Bottom -
2019                      console.origcsbi.srWindow.Top + 1;
2020     console.height = max(console.height, ROWNO + 3);
2021
2022     console.buffer_size = console.width * console.height;
2023
2024
2025     /* clear the entire console buffer */
2026     int size = console.origcsbi.dwSize.X * console.origcsbi.dwSize.Y;
2027     DWORD unused;
2028     set_console_cursor(0, 0);
2029     FillConsoleOutputAttribute(
2030         console.hConOut, CONSOLE_CLEAR_ATTRIBUTE,
2031         size, console.cursor, &unused);
2032
2033     FillConsoleOutputCharacter(
2034         console.hConOut, CONSOLE_CLEAR_CHARACTER,
2035         size, console.cursor, &unused);
2036
2037     set_console_cursor(1, 0);
2038     SetConsoleCursorPosition(console.hConOut, console.cursor);
2039
2040     /* At this point early_raw_print will work */
2041
2042     console.hConIn = GetStdHandle(STD_INPUT_HANDLE);
2043     nhassert(console.hConIn  != NULL);
2044
2045     /* grow the size of the console buffer if it is not wide enough */
2046     if (console.origcsbi.dwSize.X < console.width) {
2047         COORD size = {
2048             size.Y = console.origcsbi.dwSize.Y,
2049             size.X = console.width
2050         };
2051
2052         SetConsoleScreenBufferSize(console.hConOut, size);
2053     }
2054
2055     /* setup front and back buffers */
2056     int buffer_size_bytes = sizeof(cell_t) * console.buffer_size;
2057
2058     console.front_buffer = (cell_t *)malloc(buffer_size_bytes);
2059     buffer_fill_to_end(console.front_buffer, &undefined_cell, 0, 0);
2060
2061     console.back_buffer = (cell_t *)malloc(buffer_size_bytes);
2062     buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
2063
2064     /* determine whether OS version has unicode support */
2065     console.has_unicode = ((GetVersion() & 0x80000000) == 0);
2066
2067     /* check the font before we capture the code page map */
2068     check_and_set_font();
2069 #if 0 /*JP*/
2070     set_cp_map();
2071 #endif
2072
2073     /* Set console mode */
2074     DWORD cmode, mask;
2075     GetConsoleMode(console.hConIn, &cmode);
2076 #ifdef NO_MOUSE_ALLOWED
2077     mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT
2078            | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT;
2079 #else
2080     mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
2081            | ENABLE_WINDOW_INPUT;
2082 #endif
2083     /* Turn OFF the settings specified in the mask */
2084     cmode &= ~mask;
2085 #ifndef NO_MOUSE_ALLOWED
2086     cmode |= ENABLE_MOUSE_INPUT;
2087 #endif
2088     SetConsoleMode(console.hConIn, cmode);
2089
2090     /* load default keyboard handler */
2091     HKL keyboard_layout = GetKeyboardLayout(0);
2092     DWORD primary_language = (UINT_PTR) keyboard_layout & 0x3f;
2093
2094     /* This was overriding the handler that had already
2095        been loaded during options parsing. Needs to
2096        check first */
2097 #if 0 /*JP*//* \93ú\96{\8cê\82Å\82Ínhdefkey\82µ\82©\8eg\82í\82È\82¢ */
2098     if (!iflags.altkeyhandler[0]) {
2099         if (primary_language == LANG_ENGLISH) {
2100             if (!load_keyboard_handler("nhdefkey"))
2101                 error("Unable to load nhdefkey.dll");
2102         } else {
2103             if (!load_keyboard_handler("nhraykey"))
2104                 error("Unable to load nhraykey.dll");
2105         }
2106     }
2107 #else
2108     if (!load_keyboard_handler("nhdefkey"))
2109         error("nhdefkey.dll\82ð\93Ç\82Ý\8d\9e\82ß\82Ü\82¹\82ñ");
2110 #endif
2111 }
2112 #endif /* TTY_GRAPHICS */
2113
2114 /* this is used as a printf() replacement when the window
2115  * system isn't initialized yet
2116  */
2117 void msmsg
2118 VA_DECL(const char *, fmt)
2119 {
2120     char buf[ROWNO * COLNO]; /* worst case scenario */
2121     VA_START(fmt);
2122     VA_INIT(fmt, const char *);
2123     (void) vsnprintf(buf, sizeof buf, fmt, VA_ARGS);
2124     if (redirect_stdout)
2125         fprintf(stdout, "%s", buf);
2126     else {
2127 #ifdef TTY_GRAPHICS
2128         if(!init_ttycolor_completed)
2129             init_ttycolor();
2130         /* if we have generated too many messages ... ask the user to
2131          * confirm and then clear.
2132          */
2133         if (console.cursor.Y > console.height - 4) {
2134             xputs("Hit <Enter> to continue.");
2135             while (pgetchar() != '\n')
2136                 ;
2137             raw_clear_screen();
2138             set_console_cursor(1, 0);
2139         }
2140 #if 0 /*JP*/
2141         xputs(buf);
2142 #else
2143         if(ttyDisplay){
2144             console.cursor.X = ttyDisplay->curx;
2145             console.cursor.Y = ttyDisplay->cury;
2146         }
2147         {
2148             char *str = buf;
2149             while(*str){
2150                 jbuffer(*(str++), NULL, (void (__cdecl *)(unsigned int))xputc_core, xputc2_core);
2151             }
2152         }
2153 #endif
2154         if (ttyDisplay)
2155             curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
2156 #else
2157         fprintf(stdout, "%s", buf);
2158 #endif
2159     }
2160     VA_END();
2161     return;
2162 }
2163
2164 #endif /* WIN32 */