-/* NetHack 3.6 nttty.c $NHDT-Date: 1520825872 2018/03/12 03:37:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
+/* 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 $ */
/* Copyright (c) NetHack PC Development Team 1993 */
/* NetHack may be freely redistributed. See license for details. */
* Initial Creation M. Allison 1993/01/31
* Switch to low level console output routines M. Allison 2003/10/01
* Restrict cursor movement until input pending M. Lehotay 2003/10/02
- * Call Unicode version of output API on NT R. Chason 2005/10/28
+ * Call Unicode version of output API on NT R. Chason 2005/10/28
+ * Use of back buffer to improve performance B. House 2018/05/06
*
*/
#ifdef WIN32
#define NEED_VARARGS /* Uses ... */
+#include "win32api.h"
+#include "winos.h"
#include "hack.h"
#include "wintty.h"
#include <sys\types.h>
#include <sys\stat.h>
-#include "win32api.h"
+
+extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
+extern int redirect_stdout;
+
+#ifdef TTY_GRAPHICS
+/*
+ * Console Buffer Flipping Support
+ *
+ * To minimize the number of calls into the WriteConsoleOutputXXX methods,
+ * we implement a notion of a console back buffer which keeps the next frame
+ * of console output as it is being composed. When ready to show the new
+ * frame, we compare this next frame to what is currently being output and
+ * only call WriteConsoleOutputXXX for those console values that need to
+ * change.
+ *
+ */
+
+#define CONSOLE_CLEAR_ATTRIBUTE (FOREGROUND_RED | FOREGROUND_GREEN \
+ | FOREGROUND_BLUE)
+#define CONSOLE_CLEAR_CHARACTER (' ')
+
+#define CONSOLE_UNDEFINED_ATTRIBUTE (0)
+#define CONSOLE_UNDEFINED_CHARACTER ('\0')
+
+typedef struct {
+ WCHAR character;
+ WORD attribute;
+#if 1 /*JP*/
+ int iskanji;
+#endif
+} cell_t;
+
+#if 0 /*JP*/
+cell_t clear_cell = { CONSOLE_CLEAR_CHARACTER, CONSOLE_CLEAR_ATTRIBUTE };
+cell_t undefined_cell = { CONSOLE_UNDEFINED_CHARACTER,
+ CONSOLE_UNDEFINED_ATTRIBUTE };
+#else
+cell_t clear_cell = { CONSOLE_CLEAR_CHARACTER, CONSOLE_CLEAR_ATTRIBUTE, 0 };
+cell_t undefined_cell = { CONSOLE_UNDEFINED_CHARACTER,
+ CONSOLE_UNDEFINED_ATTRIBUTE, 0 };
+#endif
/*
* The following WIN32 Console API routines are used in this file.
static BOOL FDECL(CtrlHandler, (DWORD));
static void FDECL(xputc_core, (char));
+#if 1 /*JP*/
+static void FDECL(xputc2_core, (unsigned char *));
+#endif
void FDECL(cmov, (int, int));
void FDECL(nocmov, (int, int));
int FDECL(process_keystroke,
static void NDECL(init_ttycolor);
static void NDECL(really_move_cursor);
static void NDECL(check_and_set_font);
+#if 0 /*JP*/
static boolean NDECL(check_font_widths);
+#endif
static void NDECL(set_known_good_console_font);
static void NDECL(restore_original_console_font);
-
-/* Win32 Console handles for input and output */
-HANDLE hConIn;
-HANDLE hConOut;
+extern void NDECL(safe_routines);
/* Win32 Screen buffer,coordinate,console I/O information */
-CONSOLE_SCREEN_BUFFER_INFO csbi, origcsbi;
COORD ntcoord;
INPUT_RECORD ir;
+static boolean orig_QuickEdit;
/* Support for changing console font if existing glyph widths are too wide */
-boolean console_font_changed;
-CONSOLE_FONT_INFOEX original_console_font_info;
-UINT original_console_code_page;
-
-extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
-extern int redirect_stdout;
/* Flag for whether NetHack was launched via the GUI, not the command line.
* The reason we care at all, is so that we can get
* immediately after it is displayed, yet not bother when started
* from the command line.
*/
-int GUILaunched;
+int GUILaunched = FALSE;
/* Flag for whether unicode is supported */
-static boolean has_unicode;
static boolean init_ttycolor_completed;
#ifdef PORT_DEBUG
static boolean display_cursor_info = FALSE;
int current_nhcolor;
int current_nhattr[ATR_INVERSE+1];
COORD cursor;
+ HANDLE hConOut;
+ HANDLE hConIn;
+ CONSOLE_SCREEN_BUFFER_INFO origcsbi;
+ int width;
+ int height;
+ boolean has_unicode;
+ int buffer_size;
+ cell_t * front_buffer;
+ cell_t * back_buffer;
+ WCHAR cpMap[256];
+ boolean font_changed;
+ CONSOLE_FONT_INFOEX original_font_info;
+ UINT original_code_page;
} console = {
0,
(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
NO_COLOR,
{FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE},
- {0, 0}
+ {0, 0},
+ NULL,
+ NULL,
+ { 0 },
+ 0,
+ 0,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ { 0 },
+ FALSE,
+ { 0 },
+ 0
};
+
static DWORD ccount, acount;
#ifndef CLR_MAX
#define CLR_MAX 16
typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
-HANDLE hLibrary;
-PROCESS_KEYSTROKE pProcessKeystroke;
-NHKBHIT pNHkbhit;
-CHECKINPUT pCheckInput;
-SOURCEWHERE pSourceWhere;
-SOURCEAUTHOR pSourceAuthor;
-KEYHANDLERNAME pKeyHandlerName;
+typedef struct {
+ char * name; // name without DLL extension
+ HANDLE hLibrary;
+ PROCESS_KEYSTROKE pProcessKeystroke;
+ NHKBHIT pNHkbhit;
+ CHECKINPUT pCheckInput;
+ SOURCEWHERE pSourceWhere;
+ SOURCEAUTHOR pSourceAuthor;
+ KEYHANDLERNAME pKeyHandlerName;
+} keyboard_handler_t;
+
+keyboard_handler_t keyboard_handler;
+
+
+/* Console buffer flipping support */
+
+static void back_buffer_flip()
+{
+ cell_t * back = console.back_buffer;
+ cell_t * front = console.front_buffer;
+ COORD pos;
+ DWORD unused;
+
+ for (pos.Y = 0; pos.Y < console.height; pos.Y++) {
+ for (pos.X = 0; pos.X < console.width; pos.X++) {
+#if 1 /*JP*/
+ if (back->iskanji == 1) {
+ cell_t * back2 = back + 1;
+ cell_t * front2 = front + 1;
+ /* pos.x == 0 \82Ì\8fð\8c\8f\82Í\95s\97v\82Ì\82Í\82¸\82¾\82ª #42072 \91Î\8dô\82Å\92Ç\89Á\81B */
+ if (back->attribute != front->attribute ||
+ back2->attribute != front2->attribute || pos.X == 0) {
+ WORD attrs[2];
+ attrs[0] = attrs[1] = back->attribute;
+ WriteConsoleOutputAttribute(console.hConOut, attrs,
+ 2, pos, &unused);
+ front->attribute = back->attribute;
+ front2->attribute = back2->attribute;
+ }
+ /* pos.x == 0 \82Ì\8fð\8c\8f\82Í\95s\97v\82Ì\82Í\82¸\82¾\82ª #42072 \91Î\8dô\82Å\92Ç\89Á\81B */
+ if (back->character != front->character ||
+ back2->character != front2->character || pos.X == 0) {
+ wchar_t wbuf[1];
+ wbuf[0] = back->character;
+ WriteConsoleOutputCharacterW(console.hConOut, wbuf, 1, pos,
+ &unused);
+ *front = *back;
+ *front2 = *back2;
+ }
+ pos.X++;
+ back += 2;
+ front += 2;
+ continue;
+ }
+#endif
+ if (back->attribute != front->attribute) {
+ WriteConsoleOutputAttribute(console.hConOut, &back->attribute,
+ 1, pos, &unused);
+ front->attribute = back->attribute;
+ }
+ if (back->character != front->character) {
+ if (console.has_unicode) {
+ WriteConsoleOutputCharacterW(console.hConOut,
+ &back->character, 1, pos, &unused);
+ } else {
+ char ch = (char)back->character;
+ WriteConsoleOutputCharacterA(console.hConOut, &ch, 1, pos,
+ &unused);
+ }
+#if 1 /*JP*/
+ /* \8a¿\8e\9a\82Ì1\83o\83C\83g\96Ú\82¾\82Á\82½\8fê\8d\87\81A
+ 2\83o\83C\83g\96Ú\82ð\83N\83\8a\83A\82µ\82Ä\8am\8eÀ\82É\8dX\90V\82·\82é */
+ if (front->iskanji == 1) {
+ (front + 1)->character = '\0';
+ }
+#endif
+ *front = *back;
+ }
+ back++;
+ front++;
+ }
+ }
+}
+
+void buffer_fill_to_end(cell_t * buffer, cell_t * fill, int x, int y)
+{
+ nhassert(x >= 0 && x < console.width);
+ nhassert(y >= 0 && ((y < console.height) || (y == console.height &&
+ x == 0)));
+
+ cell_t * dst = buffer + console.width * y + x;
+ cell_t * sentinel = buffer + console.buffer_size;
+ while (dst != sentinel)
+ *dst++ = *fill;
+
+ if (iflags.debug.immediateflips && buffer == console.back_buffer)
+ back_buffer_flip();
+}
+
+static void buffer_clear_to_end_of_line(cell_t * buffer, int x, int y)
+{
+ nhassert(x >= 0 && x < console.width);
+ nhassert(y >= 0 && ((y < console.height) || (y == console.height &&
+ x == 0)));
+ cell_t * dst = buffer + console.width * y + x;
+ cell_t *sentinel = buffer + console.width * (y + 1);
+
+ while (dst != sentinel)
+ *dst++ = clear_cell;
+
+ if (iflags.debug.immediateflips)
+ back_buffer_flip();
+}
+
+void buffer_write(cell_t * buffer, cell_t * cell, COORD pos)
+{
+ nhassert(pos.X >= 0 && pos.X < console.width);
+ nhassert(pos.Y >= 0 && pos.Y < console.height);
+
+ cell_t * dst = buffer + (console.width * pos.Y) + pos.X;
+ *dst = *cell;
+
+ if (iflags.debug.immediateflips && buffer == console.back_buffer)
+ back_buffer_flip();
+}
/*
* Called after returning from ! or ^Z
void
gettty()
{
- console_font_changed = FALSE;
-
- check_and_set_font();
-
#ifndef TEXTCOLOR
int k;
#endif
end_screen();
if (s)
raw_print(s);
-
restore_original_console_font();
+ if (orig_QuickEdit) {
+ DWORD cmode;
+
+ GetConsoleMode(console.hConIn, &cmode);
+ cmode |= (ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS);
+ SetConsoleMode(console.hConIn, cmode);
+ }
}
/* called by init_nhwindows() and resume_nhwindows() */
adjust_palette();
#endif
start_screen();
- has_unicode = ((GetVersion() & 0x80000000) == 0);
}
void
tty_startup(wid, hgt)
int *wid, *hgt;
{
- int twid = origcsbi.srWindow.Right - origcsbi.srWindow.Left + 1;
-
- if (twid > 80)
- twid = 80;
- *wid = twid;
- *hgt = origcsbi.srWindow.Bottom - origcsbi.srWindow.Top + 1;
+ *wid = console.width;
+ *hgt = console.height;
set_option_mod_status("mouse_support", SET_IN_GAME);
}
tty_number_pad(state)
int state;
{
+ // do nothing
}
void
{
clear_screen();
really_move_cursor();
- if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
- DWORD ccnt;
- COORD newcoord;
-
- newcoord.X = 0;
- newcoord.Y = 0;
- FillConsoleOutputAttribute(
- hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
- csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
- FillConsoleOutputCharacter(
- hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
- }
- FlushConsoleInputBuffer(hConIn);
+ buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
+ back_buffer_flip();
+ FlushConsoleInputBuffer(console.hConIn);
}
static BOOL
hangup(0);
#endif
#if defined(SAFERHANGUP)
- CloseHandle(hConIn); /* trigger WAIT_FAILED */
+ CloseHandle(console.hConIn); /* trigger WAIT_FAILED */
return TRUE;
#endif
default:
}
}
-/* called by init_tty in wintty.c for WIN32 port only */
+/* called by pcmain() and process_options() */
void
nttty_open(mode)
-int mode;
+int mode; // unused
{
- HANDLE hStdOut;
DWORD cmode;
- long mask;
-
- GUILaunched = 0;
-
- try :
- /* The following lines of code were suggested by
- * Bob Landau of Microsoft WIN32 Developer support,
- * as the only current means of determining whether
- * we were launched from the command prompt, or from
- * the NT program manager. M. Allison
- */
- hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (hStdOut) {
- GetConsoleScreenBufferInfo(hStdOut, &origcsbi);
- } else if (mode) {
- HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
- HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
-
- if (!hStdOut && !hStdIn) {
- /* Bool rval; */
- AllocConsole();
- AttachConsole(GetCurrentProcessId());
- /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
- freopen("CON", "w", stdout);
- freopen("CON", "r", stdin);
- }
- mode = 0;
- goto try;
- } else {
- return;
- }
-
- /* Obtain handles for the standard Console I/O devices */
- hConIn = GetStdHandle(STD_INPUT_HANDLE);
- hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
- load_keyboard_handler();
/* Initialize the function pointer that points to
- * the kbhit() equivalent, in this TTY case nttty_kbhit()
- */
+ * the kbhit() equivalent, in this TTY case nttty_kbhit()
+ */
nt_kbhit = nttty_kbhit;
- GetConsoleMode(hConIn, &cmode);
-#ifdef NO_MOUSE_ALLOWED
- mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT
- | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT;
-#else
- mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
- | ENABLE_WINDOW_INPUT;
-#endif
- /* Turn OFF the settings specified in the mask */
- cmode &= ~mask;
-#ifndef NO_MOUSE_ALLOWED
- cmode |= ENABLE_MOUSE_INPUT;
-#endif
- SetConsoleMode(hConIn, cmode);
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
/* Unable to set control handler */
cmode = 0; /* just to have a statement to break on for debugger */
}
- get_scr_size();
- console.cursor.X = console.cursor.Y = 0;
+
+ LI = console.height;
+ CO = console.width;
+
really_move_cursor();
}
+void
+nttty_exit()
+{
+ /* go back to using the safe routines */
+ safe_routines();
+}
+
int
process_keystroke(ir, valid, numberpad, portdebug)
INPUT_RECORD *ir;
boolean numberpad;
int portdebug;
{
- int ch = pProcessKeystroke(hConIn, ir, valid, numberpad, portdebug);
+ int ch;
+
+#ifdef QWERTZ_SUPPORT
+ if (Cmd.swap_yz)
+ numberpad |= 0x10;
+#endif
+ ch = keyboard_handler.pProcessKeystroke(
+ console.hConIn, ir, valid, numberpad, portdebug);
+#ifdef QWERTZ_SUPPORT
+ numberpad &= ~0x10;
+#endif
/* check for override */
if (ch && ch < MAX_OVERRIDES && key_overrides[ch])
ch = key_overrides[ch];
int
nttty_kbhit()
{
- return pNHkbhit(hConIn, &ir);
-}
-
-void
-get_scr_size()
-{
- int lines, cols;
-
- GetConsoleScreenBufferInfo(hConOut, &csbi);
-
- lines = csbi.srWindow.Bottom - (csbi.srWindow.Top + 1);
- cols = csbi.srWindow.Right - (csbi.srWindow.Left + 1);
-
- LI = lines;
- CO = min(cols, 80);
-
- if ((LI < 25) || (CO < 80)) {
- COORD newcoord;
-
- LI = 25;
- CO = 80;
-
- newcoord.Y = LI;
- newcoord.X = CO;
-
- SetConsoleScreenBufferSize(hConOut, newcoord);
- }
+ return keyboard_handler.pNHkbhit(console.hConIn, &ir);
}
int
int mod;
coord cc;
DWORD count;
+ boolean numpad = iflags.num_pad;
+
really_move_cursor();
+ if (iflags.debug_fuzzer)
+ return randomkey();
+#ifdef QWERTZ_SUPPORT
+ if (Cmd.swap_yz)
+ numpad |= 0x10;
+#endif
+
return (program_state.done_hup)
? '\033'
- : pCheckInput(hConIn, &ir, &count, iflags.num_pad, 0, &mod,
- &cc);
+ : keyboard_handler.pCheckInput(
+ console.hConIn, &ir, &count, numpad, 0, &mod, &cc);
}
int
int ch;
coord cc;
DWORD count;
+ boolean numpad = iflags.num_pad;
+
really_move_cursor();
+ if (iflags.debug_fuzzer)
+ return randomkey();
+#ifdef QWERTZ_SUPPORT
+ if (Cmd.swap_yz)
+ numpad |= 0x10;
+#endif
ch = (program_state.done_hup)
? '\033'
- : pCheckInput(hConIn, &ir, &count, iflags.num_pad, 1, mod, &cc);
+ : keyboard_handler.pCheckInput(
+ console.hConIn, &ir, &count, numpad, 1, mod, &cc);
+#ifdef QWERTZ_SUPPORT
+ numpad &= ~0x10;
+#endif
if (!ch) {
*x = cc.x;
*y = cc.y;
return ch;
}
+static void set_console_cursor(int x, int y)
+{
+ nhassert(x >= 0 && x < console.width);
+ nhassert(y >= 0 && y < console.height);
+
+ console.cursor.X = max(0, min(console.width - 1, x));
+ console.cursor.Y = max(0, min(console.height - 1, y));
+}
+
static void
really_move_cursor()
{
oldtitle[39] = '\0';
}
Sprintf(newtitle, "%-55s tty=(%02d,%02d) nttty=(%02d,%02d)", oldtitle,
- ttyDisplay->curx, ttyDisplay->cury, console.cursor.X, console.cursor.Y);
+ ttyDisplay->curx, ttyDisplay->cury,
+ console.cursor.X, console.cursor.Y);
(void) SetConsoleTitle(newtitle);
}
#endif
- if (ttyDisplay) {
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
- }
- SetConsoleCursorPosition(hConOut, console.cursor);
+ if (ttyDisplay)
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
+
+ back_buffer_flip();
+ SetConsoleCursorPosition(console.hConOut, console.cursor);
}
void
{
ttyDisplay->cury = y;
ttyDisplay->curx = x;
- console.cursor.X = x;
- console.cursor.Y = y;
+
+ set_console_cursor(x, y);
}
void
nocmov(x, y)
int x, y;
{
- console.cursor.X = x;
- console.cursor.Y = y;
ttyDisplay->curx = x;
ttyDisplay->cury = y;
+
+ set_console_cursor(x, y);
}
-void
+/* same signature as 'putchar()' with potential failure result ignored */
+int
xputc(ch)
-char ch;
+int ch;
{
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
- xputc_core(ch);
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
+ xputc_core((char) ch);
+ return 0;
}
#if 1 /*JP*/
void
-xputc2_core(ch1, ch2)
-int ch1;
-int ch2;
+xputc2_core(str)
+unsigned char *str;
{
- unsigned char buf[2];
- WORD attrs[2];
+ nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
+ nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
+
+ boolean inverse = FALSE;
+ cell_t cell;
+ wchar_t wbuf[1];
+
+ /* xputc_core()\82©\82ç\82Ì\83R\83s\81[ */
+ inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
+ console.attr = (inverse) ?
+ ttycolors_inv[console.current_nhcolor] :
+ ttycolors[console.current_nhcolor];
+ if (console.current_nhattr[ATR_BOLD])
+ console.attr |= (inverse) ?
+ BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
+
+ cell.attribute = console.attr;
- buf[0] = ch1;
- buf[1] = ch2;
+ /* \89E\92[\82É1\83o\83C\83g\95ª\82µ\82©\8bó\82«\82ª\82È\82¢\8fê\8d\87 */
+ if (console.cursor.X == console.width - 2) {
+ /* \8bó\94\92\95\\8e¦ */
+ cell.character = ' ';
+ cell.iskanji = 0;
+ buffer_write(console.back_buffer, &cell, console.cursor);
+ console.cursor.X++;
+ if (console.cursor.Y < console.height - 1) {
+ /* \8e\9f\82Ì\8ds\82É */
+ console.cursor.X = 1;
+ console.cursor.Y++;
+ } else {
+ /* \8aù\82É\89º\92[\82Ì\8fê\8d\87\82Í\82È\82É\82à\82µ\82È\82¢ */
+ return;
+ }
+ }
- attrs[0] = attrs[1] = console.attr;
+ int ret = MultiByteToWideChar(
+ CP_ACP,
+ MB_PRECOMPOSED,
+ str,
+ strlen(str),
+ wbuf,
+ 1);
+
+ /* \8d¶\91¤\82É\83\8f\83C\83h\95¶\8e\9a\8fî\95ñ\82ð\8bl\82ß\82é */
+ cell.character = wbuf[0];
+ cell.iskanji = 1;
+ buffer_write(console.back_buffer, &cell, console.cursor);
+ console.cursor.X++;
+
+ /* \89E\91¤\82Í\83_\83~\81[ */
+ cell.character = 255;
+ cell.iskanji = 2;
+ buffer_write(console.back_buffer, &cell, console.cursor);
+
+ if (console.cursor.X == console.width - 1) {
+ if (console.cursor.Y < console.height - 1) {
+ console.cursor.X = 1;
+ console.cursor.Y++;
+ }
+ } else {
+ console.cursor.X++;
+ }
- WriteConsoleOutputAttribute(hConOut, (WORD *)(&attrs), 2,
- console.cursor, &acount);
- WriteConsoleOutputCharacter(hConOut, buf, 2,
- console.cursor, &ccount);
- console.cursor.X += 2;
+ nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
+ nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
}
void
-xputc2(ch1, ch2)
-int ch1;
-int ch2;
+xputc2(str)
+unsigned char *str;
{
/* wintty.c \82Å\82Í 1 \83o\83C\83g\96\88\82É curx \82ð\89Á\8eZ\82·\82é\82ª\81A\82±\82±\82Í
- 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Å
- \82µ\82Ü\82Á\82Ä\82¢\82é\81B\8f]\82Á\82Ä 1 \82ð\88ø\82\81B */
- console.cursor.X = ttyDisplay->curx - 1;
+ n \83o\83C\83g\82½\82Ü\82Á\82Ä\82©\82ç\8cÄ\82Ñ\8fo\82³\82ê\82é\82Ì\82Å\81An-1 \95¶\8e\9a\95ª\90æ\82É\90i\82ñ\82Å
+ \82µ\82Ü\82Á\82Ä\82¢\82é\81B\8f]\82Á\82Ä n-1 \82ð\88ø\82\81B */
+ console.cursor.X = ttyDisplay->curx - (strlen(str) - 1);
console.cursor.Y = ttyDisplay->cury;
- xputc2_core(ch1, ch2);
+ xputc2_core(str);
}
#endif
const char *s;
{
int k;
- int slen = strlen(s);
+ int slen = (int) strlen(s);
- if (ttyDisplay) {
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
- }
+ if (ttyDisplay)
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
if (s) {
for (k = 0; k < slen && s[k]; ++k)
xputc_core(ch)
char ch;
{
+ nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
+ nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
+
boolean inverse = FALSE;
+ cell_t cell;
+
switch (ch) {
case '\n':
- console.cursor.Y++;
+ if (console.cursor.Y < console.height - 1)
+ console.cursor.Y++;
/* fall through */
case '\r':
console.cursor.X = 1;
break;
case '\b':
- console.cursor.X--;
+ if (console.cursor.X > 1) {
+ console.cursor.X--;
+ } else if(console.cursor.Y > 0) {
+ console.cursor.X = console.width - 1;
+ console.cursor.Y--;
+ }
break;
default:
+
inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
console.attr = (inverse) ?
ttycolors_inv[console.current_nhcolor] :
if (console.current_nhattr[ATR_BOLD])
console.attr |= (inverse) ?
BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
- WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
- if (has_unicode) {
- /* Avoid bug in ANSI API on WinNT */
- WCHAR c2[2];
- int rc;
- rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, &ch, 1, c2, 2);
- WriteConsoleOutputCharacterW(hConOut, c2, rc, console.cursor, &ccount);
+
+ cell.attribute = console.attr;
+#if 0 /*JP*/
+ cell.character = (console.has_unicode ? console.cpMap[ch] : ch);
+#else
+ cell.character = ch;
+#endif
+#if 1 /*JP*//*\8fí\82É1\83o\83C\83g\95¶\8e\9a*/
+ cell.iskanji = 0;
+#endif
+
+ buffer_write(console.back_buffer, &cell, console.cursor);
+
+ if (console.cursor.X == console.width - 1) {
+ if (console.cursor.Y < console.height - 1) {
+ console.cursor.X = 1;
+ console.cursor.Y++;
+ }
} else {
- WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
+ console.cursor.X++;
}
- console.cursor.X++;
}
+
+ nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
+ nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
}
/*
* for win32. It is used for glyphs only, not text.
*/
-/* CP437 to Unicode mapping according to the Unicode Consortium */
-static const WCHAR cp437[] = {
- 0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
- 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
- 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
- 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
- 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
- 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
- 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
- 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
- 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
- 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
- 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
- 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
- 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
- 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
- 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
- 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
- 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
- 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
- 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
- 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
-};
-
void
g_putch(in_ch)
int in_ch;
boolean inverse = FALSE;
unsigned char ch = (unsigned char) in_ch;
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
console.attr = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse) ?
ttycolors[console.current_nhcolor];
if (console.current_nhattr[ATR_BOLD])
console.attr |= (inverse) ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
- WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
- if (has_unicode)
- WriteConsoleOutputCharacterW(hConOut, &cp437[ch], 1, console.cursor, &ccount);
- else
- WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
+ cell_t cell;
+
+ cell.attribute = console.attr;
+#if 0 /*JP*/
+ cell.character = (console.has_unicode ? cp437[ch] : ch);
+#else
+ cell.character = ch;
+#endif
+#if 1 /*JP*//*\8fí\82É1\83o\83C\83g\95¶\8e\9a*/
+ cell.iskanji = 0;
+#endif
+
+ buffer_write(console.back_buffer, &cell, console.cursor);
}
void
cl_end()
{
- int cx;
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
- cx = CO - console.cursor.X;
- FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, cx, console.cursor, &acount);
- FillConsoleOutputCharacter(hConOut, ' ', cx, console.cursor, &ccount);
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
+ buffer_clear_to_end_of_line(console.back_buffer, console.cursor.X,
+ console.cursor.Y);
tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
}
void
raw_clear_screen()
{
- if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
- DWORD ccnt;
- COORD newcoord;
-
- newcoord.X = 0;
- newcoord.Y = 0;
- FillConsoleOutputAttribute(
- hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
- csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
- FillConsoleOutputCharacter(
- hConOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, newcoord, &ccnt);
+ if (WINDOWPORT("tty")) {
+ cell_t * back = console.back_buffer;
+ cell_t * front = console.front_buffer;
+ COORD pos;
+ DWORD unused;
+
+ for (pos.Y = 0; pos.Y < console.height; pos.Y++) {
+ for (pos.X = 0; pos.X < console.width; pos.X++) {
+ WriteConsoleOutputAttribute(console.hConOut, &back->attribute,
+ 1, pos, &unused);
+ front->attribute = back->attribute;
+ if (console.has_unicode) {
+ WriteConsoleOutputCharacterW(console.hConOut,
+ &back->character, 1, pos, &unused);
+ } else {
+ char ch = (char)back->character;
+ WriteConsoleOutputCharacterA(console.hConOut, &ch, 1, pos,
+ &unused);
+ }
+ *front = *back;
+ back++;
+ front++;
+ }
+ }
}
}
void
clear_screen()
{
- raw_clear_screen();
+ buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
home();
}
void
home()
{
- console.cursor.X = console.cursor.Y = 0;
ttyDisplay->curx = ttyDisplay->cury = 0;
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
}
void
backsp()
{
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
+ set_console_cursor(ttyDisplay->curx, ttyDisplay->cury);
xputc_core('\b');
}
void
cl_eos()
{
- int cy = ttyDisplay->cury + 1;
- if (GetConsoleScreenBufferInfo(hConOut, &csbi)) {
- DWORD ccnt;
- COORD newcoord;
-
- newcoord.X = ttyDisplay->curx;
- newcoord.Y = ttyDisplay->cury;
- FillConsoleOutputAttribute(
- hConOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
- csbi.dwSize.X * csbi.dwSize.Y - cy, newcoord, &ccnt);
- FillConsoleOutputCharacter(hConOut, ' ',
- csbi.dwSize.X * csbi.dwSize.Y - cy,
- newcoord, &ccnt);
- }
+ buffer_fill_to_end(console.back_buffer, &clear_cell, ttyDisplay->curx,
+ ttyDisplay->cury);
tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
}
void
tty_nhbell()
{
- if (flags.silent)
+ if (flags.silent || iflags.debug_fuzzer)
return;
Beep(8000, 500);
}
int k;
goal = 50 + clock();
+ back_buffer_flip();
+ if (iflags.debug_fuzzer)
+ return;
+
while (goal > clock()) {
k = junk; /* Do nothing */
}
}
-#ifdef TEXTCOLOR
/*
* CLR_BLACK 0
* CLR_RED 1
#endif
init_ttycolor_completed = TRUE;
}
-#endif /* TEXTCOLOR */
+#if 0
int
-has_color(int color)
+has_color(int color) /* this function is commented out */
{
#ifdef TEXTCOLOR
if ((color >= 0) && (color < CLR_MAX))
else
return 0;
}
+#endif
+
+int
+term_attr_fixup(int attrmask)
+{
+ return attrmask;
+}
void
term_start_attr(int attrib)
void
toggle_mouse_support()
{
+ static int qeinit = 0;
DWORD cmode;
- GetConsoleMode(hConIn, &cmode);
- if (iflags.wc_mouse_support)
- cmode |= ENABLE_MOUSE_INPUT;
- else
- cmode &= ~ENABLE_MOUSE_INPUT;
- SetConsoleMode(hConIn, cmode);
+
+ GetConsoleMode(console.hConIn, &cmode);
+ if (!qeinit) {
+ qeinit = 1;
+ orig_QuickEdit = ((cmode & ENABLE_QUICK_EDIT_MODE) != 0);
+ }
+ switch(iflags.wc_mouse_support) {
+ case 2:
+ cmode |= ENABLE_MOUSE_INPUT;
+ break;
+ case 1:
+ cmode |= ENABLE_MOUSE_INPUT;
+ cmode &= ~ENABLE_QUICK_EDIT_MODE;
+ cmode |= ENABLE_EXTENDED_FLAGS;
+ break;
+ case 0:
+ /*FALLTHRU*/
+ default:
+ cmode &= ~ENABLE_MOUSE_INPUT;
+ if (orig_QuickEdit)
+ cmode |= (ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS);
+ }
+ SetConsoleMode(console.hConIn, cmode);
}
#endif
xputs("\n");
while (!valid || ch != 27) {
nocmov(ttyDisplay->curx, ttyDisplay->cury);
- ReadConsoleInput(hConIn, &ir, 1, &count);
+ ReadConsoleInput(console.hConIn, &ir, 1, &count);
if ((ir.EventType == KEY_EVENT) && ir.Event.KeyEvent.bKeyDown)
ch = process_keystroke(&ir, &valid, iflags.num_pad, 1);
}
{
char *buf;
int ci;
- if (!pSourceAuthor && !pSourceWhere)
+ if (!keyboard_handler.pSourceAuthor && !keyboard_handler.pSourceWhere)
pline("Keyboard handler source info and author unavailable.");
else {
- if (pKeyHandlerName && pKeyHandlerName(&buf, 1)) {
+ if (keyboard_handler.pKeyHandlerName &&
+ keyboard_handler.pKeyHandlerName(&buf, 1)) {
xputs("\n");
xputs("Keystroke handler loaded: \n ");
xputs(buf);
}
- if (pSourceAuthor && pSourceAuthor(&buf)) {
+ if (keyboard_handler.pSourceAuthor &&
+ keyboard_handler.pSourceAuthor(&buf)) {
xputs("\n");
xputs("Keystroke handler Author: \n ");
xputs(buf);
}
- if (pSourceWhere && pSourceWhere(&buf)) {
+ if (keyboard_handler.pSourceWhere &&
+ keyboard_handler.pSourceWhere(&buf)) {
xputs("\n");
xputs("Keystroke handler source code available at:\n ");
xputs(buf);
key_overrides[idx] = val;
}
-void
-load_keyboard_handler()
-{
- char suffx[] = ".dll";
- char *truncspot;
-#define MAX_DLLNAME 25
- char kh[MAX_ALTKEYHANDLER];
- if (iflags.altkeyhandler[0]) {
- if (hLibrary) { /* already one loaded apparently */
- FreeLibrary(hLibrary);
- hLibrary = (HANDLE) 0;
- pNHkbhit = (NHKBHIT) 0;
- pCheckInput = (CHECKINPUT) 0;
- pSourceWhere = (SOURCEWHERE) 0;
- pSourceAuthor = (SOURCEAUTHOR) 0;
- pKeyHandlerName = (KEYHANDLERNAME) 0;
- pProcessKeystroke = (PROCESS_KEYSTROKE) 0;
- }
- if ((truncspot = strstri(iflags.altkeyhandler, suffx)) != 0)
- *truncspot = '\0';
- (void) strncpy(kh, iflags.altkeyhandler,
- (MAX_ALTKEYHANDLER - sizeof suffx) - 1);
- kh[(MAX_ALTKEYHANDLER - sizeof suffx) - 1] = '\0';
- Strcat(kh, suffx);
- Strcpy(iflags.altkeyhandler, kh);
- hLibrary = LoadLibrary(kh);
- if (hLibrary) {
- pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
- hLibrary, TEXT("ProcessKeystroke"));
- pNHkbhit = (NHKBHIT) GetProcAddress(hLibrary, TEXT("NHkbhit"));
- pCheckInput =
- (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
- pSourceWhere =
- (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
- pSourceAuthor =
- (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
- pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
- hLibrary, TEXT("KeyHandlerName"));
- }
- }
- if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) {
- if (hLibrary) {
- FreeLibrary(hLibrary);
- hLibrary = (HANDLE) 0;
- pNHkbhit = (NHKBHIT) 0;
- pCheckInput = (CHECKINPUT) 0;
- pSourceWhere = (SOURCEWHERE) 0;
- pSourceAuthor = (SOURCEAUTHOR) 0;
- pKeyHandlerName = (KEYHANDLERNAME) 0;
- pProcessKeystroke = (PROCESS_KEYSTROKE) 0;
- }
- (void) strncpy(kh, "nhdefkey.dll",
- (MAX_ALTKEYHANDLER - sizeof suffx) - 1);
- kh[(MAX_ALTKEYHANDLER - sizeof suffx) - 1] = '\0';
- Strcpy(iflags.altkeyhandler, kh);
- hLibrary = LoadLibrary(kh);
- if (hLibrary) {
- pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
- hLibrary, TEXT("ProcessKeystroke"));
- pCheckInput =
- (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
- pNHkbhit = (NHKBHIT) GetProcAddress(hLibrary, TEXT("NHkbhit"));
- pSourceWhere =
- (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
- pSourceAuthor =
- (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
- pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
- hLibrary, TEXT("KeyHandlerName"));
- }
- }
- if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) {
- if (!hLibrary)
- raw_printf("\nNetHack was unable to load keystroke handler.\n");
- else {
- FreeLibrary(hLibrary);
- hLibrary = (HANDLE) 0;
- raw_printf("\nNetHack keystroke handler is invalid.\n");
- }
- exit(EXIT_FAILURE);
+void unload_keyboard_handler()
+{
+ nhassert(keyboard_handler.hLibrary != NULL);
+
+ FreeLibrary(keyboard_handler.hLibrary);
+ memset(&keyboard_handler, 0, sizeof(keyboard_handler_t));
+}
+
+boolean
+load_keyboard_handler(const char * inName)
+{
+ char path[MAX_ALTKEYHANDLER + 4];
+ strcpy(path, inName);
+ strcat(path, ".dll");
+
+ HANDLE hLibrary = LoadLibrary(path);
+
+ if (hLibrary == NULL)
+ return FALSE;
+
+ PROCESS_KEYSTROKE pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
+ hLibrary, TEXT("ProcessKeystroke"));
+ NHKBHIT pNHkbhit = (NHKBHIT) GetProcAddress(
+ hLibrary, TEXT("NHkbhit"));
+ CHECKINPUT pCheckInput =
+ (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
+
+ if (!pProcessKeystroke || !pNHkbhit || !pCheckInput)
+ {
+ return FALSE;
+ } else {
+ if (keyboard_handler.hLibrary != NULL)
+ unload_keyboard_handler();
+
+ keyboard_handler.hLibrary = hLibrary;
+
+ keyboard_handler.pProcessKeystroke = pProcessKeystroke;
+ keyboard_handler.pNHkbhit = pNHkbhit;
+ keyboard_handler.pCheckInput = pCheckInput;
+
+ keyboard_handler.pSourceWhere =
+ (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
+ keyboard_handler.pSourceAuthor =
+ (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
+ keyboard_handler.pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
+ hLibrary, TEXT("KeyHandlerName"));
}
+
+ return TRUE;
}
-/* this is used as a printf() replacement when the window
- * system isn't initialized yet
- */
-void msmsg
-VA_DECL(const char *, fmt)
+void set_altkeyhandler(const char * inName)
{
- char buf[ROWNO * COLNO]; /* worst case scenario */
- VA_START(fmt);
- VA_INIT(fmt, const char *);
- Vsprintf(buf, fmt, VA_ARGS);
- if (redirect_stdout)
- fprintf(stdout, "%s", buf);
- else {
- if(!init_ttycolor_completed)
- init_ttycolor();
+ if (strlen(inName) >= MAX_ALTKEYHANDLER) {
+ config_error_add("altkeyhandler name '%s' is too long", inName);
+ return;
+ }
-#if 0 /*JP*/
- xputs(buf);
-#else
- if(ttyDisplay){
- console.cursor.X = ttyDisplay->curx;
- console.cursor.Y = ttyDisplay->cury;
- }
- {
- char *str = buf;
- while(*str){
- jbuffer(*(str++), NULL, xputc_core, xputc2_core);
- }
- }
-#endif
- if (ttyDisplay)
- curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
+ char name[MAX_ALTKEYHANDLER];
+ strcpy(name, inName);
+
+ /* We support caller mistakenly giving name with '.dll' extension */
+ char * ext = strchr(name, '.');
+ if (ext != NULL) *ext = '\0';
+
+ if (load_keyboard_handler(name))
+ strcpy(iflags.altkeyhandler, name);
+ else {
+ config_error_add("unable to load altkeyhandler '%s'", name);
+ return;
}
- VA_END();
+
return;
}
+
/* fatal error */
/*VARARGS1*/
void nttty_error
if (iflags.window_inited)
end_screen();
buf[0] = '\n';
- (void) vsprintf(&buf[1], s, VA_ARGS);
+ (void) vsnprintf(&buf[1], sizeof buf - 1, s, VA_ARGS);
msmsg(buf);
really_move_cursor();
VA_END();
void
check_and_set_font()
{
+#if 0 /*JP*//* \83R\81[\83h\83y\81[\83W\82Í\95Ï\8dX\82µ\82È\82¢\81B932\82ð\89¼\92è\82·\82é\81B*/
if (!check_font_widths()) {
raw_print("WARNING: glyphs too wide in console font."
" Changing code page to 437 and font to Consolas\n");
set_known_good_console_font();
}
+#endif
}
+#if 0 /*JP*/
/* check_font_widths returns TRUE if all glyphs in current console font
* fit within the width of a single console cell.
*/
{
CONSOLE_FONT_INFOEX console_font_info;
console_font_info.cbSize = sizeof(console_font_info);
- BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
+ BOOL success = GetCurrentConsoleFontEx(console.hConOut, FALSE,
&console_font_info);
/* get console window and DC
LOGFONTW console_font_log_font = matching_log_font;
console_font_log_font.lfWeight = console_font_info.FontWeight;
console_font_log_font.lfHeight = console_font_info.dwFontSize.Y;
- console_font_log_font.lfWidth = 0;
+ console_font_log_font.lfWidth = console_font_info.dwFontSize.X;
HFONT console_font = CreateFontIndirectW(&console_font_log_font);
if (console_font == NULL) {
boolean used[256];
memset(used, 0, sizeof(used));
for (int i = 0; i < SYM_MAX; i++) {
- used[l_syms[i]] = TRUE;
- used[r_syms[i]] = TRUE;
+ used[primary_syms[i]] = TRUE;
+ used[rogue_syms[i]] = TRUE;
}
int wcUsedCount = 0;
return all_glyphs_fit;
}
+#endif
/* set_known_good_console_font sets the code page and font used by the console
* to settings know to work well with NetHack. It also saves the original
{
CONSOLE_FONT_INFOEX console_font_info;
console_font_info.cbSize = sizeof(console_font_info);
- BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
+ BOOL success = GetCurrentConsoleFontEx(console.hConOut, FALSE,
&console_font_info);
- console_font_changed = TRUE;
- original_console_font_info = console_font_info;
- original_console_code_page = GetConsoleOutputCP();
+ console.font_changed = TRUE;
+ console.original_font_info = console_font_info;
+ console.original_code_page = GetConsoleOutputCP();
wcscpy_s(console_font_info.FaceName,
sizeof(console_font_info.FaceName)
L"Consolas");
success = SetConsoleOutputCP(437);
- if (!success)
- raw_print("Unable to set console code page to 437\n");
+ nhassert(success);
- success = SetCurrentConsoleFontEx(hConOut, FALSE, &console_font_info);
- if (!success)
- raw_print("Unable to set console font to Consolas\n");
+ success = SetCurrentConsoleFontEx(console.hConOut, FALSE, &console_font_info);
+ nhassert(success);
}
/* restore_original_console_font will restore the console font and code page
void
restore_original_console_font()
{
- if (console_font_changed) {
+ if (console.font_changed) {
BOOL success;
raw_print("Restoring original font and code page\n");
- success = SetConsoleOutputCP(original_console_code_page);
+ success = SetConsoleOutputCP(console.original_code_page);
if (!success)
raw_print("Unable to restore original code page\n");
- success = SetCurrentConsoleFontEx(hConOut, FALSE,
- &original_console_font_info);
+ success = SetCurrentConsoleFontEx(console.hConOut, FALSE,
+ &console.original_font_info);
if (!success)
raw_print("Unable to restore original font\n");
- console_font_changed = FALSE;
+ console.font_changed = FALSE;
+ }
+}
+
+#if 0 /*JP*/
+/* set_cp_map() creates a mapping of every possible character of a code
+ * page to its corresponding WCHAR. This is necessary due to the high
+ * cost of making calls to MultiByteToWideChar() for every character we
+ * wish to print to the console.
+ */
+
+void set_cp_map()
+{
+ if (console.has_unicode) {
+ UINT codePage = GetConsoleOutputCP();
+
+ if (codePage == 437) {
+ memcpy(console.cpMap, cp437, sizeof(console.cpMap));
+ } else {
+ for (int i = 0; i < 256; i++) {
+ char c = (char)i;
+ int count = MultiByteToWideChar(codePage, 0, &c, 1,
+ &console.cpMap[i], 1);
+ nhassert(count == 1);
+
+ // If a character was mapped to unicode control codes,
+ // remap to the appropriate unicode character per our
+ // code page 437 mappings.
+ if (console.cpMap[i] < 32)
+ console.cpMap[i] = cp437[console.cpMap[i]];
+ }
+ }
+
+ }
+}
+#endif
+
+#if 0
+/* early_raw_print() is used during early game intialization prior to the
+ * setting up of the windowing system. This allows early errors and panics
+ * to have there messages displayed.
+ *
+ * early_raw_print() eventually gets replaced by tty_raw_print().
+ *
+ */
+
+void early_raw_print(const char *s)
+{
+ if (console.hConOut == NULL)
+ return;
+
+ nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
+ nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
+
+ WORD attribute = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
+ DWORD unused;
+
+ while (*s != '\0') {
+ switch (*s) {
+ case '\n':
+ if (console.cursor.Y < console.height - 1)
+ console.cursor.Y++;
+ /* fall through */
+ case '\r':
+ console.cursor.X = 1;
+ break;
+ case '\b':
+ if (console.cursor.X > 1) {
+ console.cursor.X--;
+ } else if(console.cursor.Y > 0) {
+ console.cursor.X = console.width - 1;
+ console.cursor.Y--;
+ }
+ break;
+ default:
+ WriteConsoleOutputAttribute(console.hConOut, &attribute,
+ 1, console.cursor, &unused);
+ WriteConsoleOutputCharacterA(console.hConOut, s,
+ 1, console.cursor, &unused);
+ if (console.cursor.X == console.width - 1) {
+ if (console.cursor.Y < console.height - 1) {
+ console.cursor.X = 1;
+ console.cursor.Y++;
+ }
+ } else {
+ console.cursor.X++;
+ }
+ }
+ s++;
+ }
+
+ nhassert(console.cursor.X >= 0 && console.cursor.X < console.width);
+ nhassert(console.cursor.Y >= 0 && console.cursor.Y < console.height);
+
+ SetConsoleCursorPosition(console.hConOut, console.cursor);
+
+}
+#endif
+
+/* nethack_enter_nttty() is the first thing that is called from main
+ * once the tty port is confirmed.
+ *
+ * We initialize all console state to support rendering to the console
+ * through out flipping support at this time. This allows us to support
+ * raw_print prior to our returning.
+ *
+ * During this early initialization, we also determine the width and
+ * height of the console that will be used. This width and height will
+ * not later change.
+ *
+ * We also check and set the console font to a font that we know will work
+ * well with nethack.
+ *
+ * The intent of this early initialization is to get all state that is
+ * not dependent upon game options initialized allowing us to simplify
+ * any additional initialization that might be needed when we are actually
+ * asked to open.
+ *
+ * Other then the call below which clears the entire console buffer, no
+ * other code outputs directly to the console other then the code that
+ * handles flipping the back buffer.
+ *
+ */
+
+void nethack_enter_nttty()
+{
+#if 0
+ /* set up state needed by early_raw_print() */
+ windowprocs.win_raw_print = early_raw_print;
+#endif
+ console.hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ nhassert(console.hConOut != NULL); // NOTE: this assert will not print
+
+ GetConsoleScreenBufferInfo(console.hConOut, &console.origcsbi);
+
+ /* Testing of widths != COLNO has not turned up any problems. Need
+ * to do a bit more testing and then we are likely to enable having
+ * console width match window width.
+ */
+#if 0
+ console.width = console.origcsbi.srWindow.Right -
+ console.origcsbi.srWindow.Left + 1;
+ console.Width = max(console.Width, COLNO);
+#else
+ console.width = COLNO;
+#endif
+
+ console.height = console.origcsbi.srWindow.Bottom -
+ console.origcsbi.srWindow.Top + 1;
+ console.height = max(console.height, ROWNO + 3);
+
+ console.buffer_size = console.width * console.height;
+
+
+ /* clear the entire console buffer */
+ int size = console.origcsbi.dwSize.X * console.origcsbi.dwSize.Y;
+ DWORD unused;
+ set_console_cursor(0, 0);
+ FillConsoleOutputAttribute(
+ console.hConOut, CONSOLE_CLEAR_ATTRIBUTE,
+ size, console.cursor, &unused);
+
+ FillConsoleOutputCharacter(
+ console.hConOut, CONSOLE_CLEAR_CHARACTER,
+ size, console.cursor, &unused);
+
+ set_console_cursor(1, 0);
+ SetConsoleCursorPosition(console.hConOut, console.cursor);
+
+ /* At this point early_raw_print will work */
+
+ console.hConIn = GetStdHandle(STD_INPUT_HANDLE);
+ nhassert(console.hConIn != NULL);
+
+ /* grow the size of the console buffer if it is not wide enough */
+ if (console.origcsbi.dwSize.X < console.width) {
+ COORD size = {
+ size.Y = console.origcsbi.dwSize.Y,
+ size.X = console.width
+ };
+
+ SetConsoleScreenBufferSize(console.hConOut, size);
}
+
+ /* setup front and back buffers */
+ int buffer_size_bytes = sizeof(cell_t) * console.buffer_size;
+
+ console.front_buffer = (cell_t *)malloc(buffer_size_bytes);
+ buffer_fill_to_end(console.front_buffer, &undefined_cell, 0, 0);
+
+ console.back_buffer = (cell_t *)malloc(buffer_size_bytes);
+ buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
+
+ /* determine whether OS version has unicode support */
+ console.has_unicode = ((GetVersion() & 0x80000000) == 0);
+
+ /* check the font before we capture the code page map */
+ check_and_set_font();
+#if 0 /*JP*/
+ set_cp_map();
+#endif
+
+ /* Set console mode */
+ DWORD cmode, mask;
+ GetConsoleMode(console.hConIn, &cmode);
+#ifdef NO_MOUSE_ALLOWED
+ mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT
+ | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT;
+#else
+ mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT
+ | ENABLE_WINDOW_INPUT;
+#endif
+ /* Turn OFF the settings specified in the mask */
+ cmode &= ~mask;
+#ifndef NO_MOUSE_ALLOWED
+ cmode |= ENABLE_MOUSE_INPUT;
+#endif
+ SetConsoleMode(console.hConIn, cmode);
+
+ /* load default keyboard handler */
+ HKL keyboard_layout = GetKeyboardLayout(0);
+ DWORD primary_language = (UINT_PTR) keyboard_layout & 0x3f;
+
+ /* This was overriding the handler that had already
+ been loaded during options parsing. Needs to
+ check first */
+#if 0 /*JP*//* \93ú\96{\8cê\82Å\82Ínhdefkey\82µ\82©\8eg\82í\82È\82¢ */
+ if (!iflags.altkeyhandler[0]) {
+ if (primary_language == LANG_ENGLISH) {
+ if (!load_keyboard_handler("nhdefkey"))
+ error("Unable to load nhdefkey.dll");
+ } else {
+ if (!load_keyboard_handler("nhraykey"))
+ error("Unable to load nhraykey.dll");
+ }
+ }
+#else
+ if (!load_keyboard_handler("nhdefkey"))
+ error("nhdefkey.dll\82ð\93Ç\82Ý\8d\9e\82ß\82Ü\82¹\82ñ");
+#endif
+}
+#endif /* TTY_GRAPHICS */
+
+/* this is used as a printf() replacement when the window
+ * system isn't initialized yet
+ */
+void msmsg
+VA_DECL(const char *, fmt)
+{
+ char buf[ROWNO * COLNO]; /* worst case scenario */
+ VA_START(fmt);
+ VA_INIT(fmt, const char *);
+ (void) vsnprintf(buf, sizeof buf, fmt, VA_ARGS);
+ if (redirect_stdout)
+ fprintf(stdout, "%s", buf);
+ else {
+#ifdef TTY_GRAPHICS
+ if(!init_ttycolor_completed)
+ init_ttycolor();
+ /* if we have generated too many messages ... ask the user to
+ * confirm and then clear.
+ */
+ if (console.cursor.Y > console.height - 4) {
+ xputs("Hit <Enter> to continue.");
+ while (pgetchar() != '\n')
+ ;
+ raw_clear_screen();
+ set_console_cursor(1, 0);
+ }
+#if 0 /*JP*/
+ xputs(buf);
+#else
+ if(ttyDisplay){
+ console.cursor.X = ttyDisplay->curx;
+ console.cursor.Y = ttyDisplay->cury;
+ }
+ {
+ char *str = buf;
+ while(*str){
+ jbuffer(*(str++), NULL, (void (__cdecl *)(unsigned int))xputc_core, xputc2_core);
+ }
+ }
+#endif
+ if (ttyDisplay)
+ curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
+#else
+ fprintf(stdout, "%s", buf);
+#endif
+ }
+ VA_END();
+ return;
}
#endif /* WIN32 */