stupid ideas of when the terminal is actually resized).
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1604 c06c8d41-db1a-0410-9941-cceddc491573
NEECVIIAOBP72T6O44DWAA6HFSDY3KSWYCFMKAEMDMVOI7XASD7QC YCXLDUFP5QPEX7YHXWAOETMZ2FWUMFI2GYFFS3NJAJYMEYUD5CUQC UB73UGG2GEG6AL4T76UILFLTELH4Z5WN54UROLJD6RDR3JG77CXAC W6IY6LF3MREPXC23AAKA2BJNUCJYCSOWY55DIWJWFLUEE2Y3LGNQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC UXBKTJSK6DEFSCQ4HB36YM6KVFGWYVCEORXIMOKQ3JZL4NNEOKGQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC TOKBONNNPTP2CIEHMMR4QAJZTXYETS55OGGDA6FY6NIMNDYMWJDAC CTTZKXEF5P64ZO2UNJZIAKKZH7ZWZ54C5E27ATXKGZJFRJJC6FJAC EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC RCU52DRCPWJVQ6HME4QR6V6EVQWTBKZTPWDI47UGUDAUBPOO5YNAC PL6I2CMSTHY5ZHWVMIQE5YTM5S5VPKBNZM6QJVHZSSKOJGIJ5W4AC GCIZIUXO5TYROKDUYB3HAY7H7MRDTJNM7HR7DGSH7KXDIZC2LCDAC YRY2TC3VHOYE47M23UJGUWDGF7H7WGU7WLWI4SUNM4EDNTGUPHGAC CVC5FFFLGVRR3KPYDNB6RF4FNACV3LI3HPSR4MCUNZ4C3FSQYBDAC // TIMING infostatic int ncalls[6] = { 0,0,0,0,0,0 };static double runavg[6] = { 0.0,0.0,0.0,0.0,0.0,0.0 };static int oob[6] = { 0,0,0,0,0,0 };static int dlen[6] = { 0,0,0,0,0,0 };static LARGE_INTEGER t1, t2;static void addcall(int i, LARGE_INTEGER &tm1, LARGE_INTEGER &tm2)
void writeChar(char c)
if (d > 1.4*runavg[i])oob[i] ++;}}#define CLOCKIN {QueryPerformanceCounter(&t1);}#define CLOCKOUT(x) {QueryPerformanceCounter(&t2); \addcall((x), t1, t2);}static char *descrip[] ={"bflush:WriteConsoleOutput","_setCursorType:SetConsoleCursorInfo","gotoxy:SetConsoleCursorPosition","textcolor:SetConsoleTextAttribute","cprintf:WriteConsole","getch:ReadConsoleInput"};void print_timings(void){int i;char s[100];
// must flush current bufferbFlush();
sprintf(s, "Avg (#/oob), CpS = %.1lf", cps.QuadPart);mpr(s);for(i=0; i<3; i++){int dl = 0;if (ncalls[i] > 0)dl = dlen[i] / ncalls[i];sprintf(s, "%-40s %.1f us (%d/%d), avg dlen = %d", descrip[i],(1000000.0 * runavg[i]) / cps.QuadPart, ncalls[i], oob[i], dl);mpr(s);
return;
void writeChar(char c){bool noop = true;PCHAR_INFO pci;// check for CR: noopif (c == 0x0D)return;// check for newlineif (c == 0x0A){// must flush current bufferbFlush();// repositiongotoxy(1, cy+2);return;}int tc = WIN32COLOR(current_color);pci = &screen[SCREENINDEX(cx,cy)];// is this a no-op?if (pci->Char.AsciiChar != c)noop = false;else if (pci->Attributes != tc)noop = false;if (!noop){// write the info and update the dirty areapci->Char.AsciiChar = c;pci->Attributes = tc;
if (!noop){// write the info and update the dirty areapci->Char.AsciiChar = c;pci->Attributes = tc;
// if cursor is not NOCURSOR, update screenif (cursor_is_enabled){COORD xy;xy.X = cx;xy.Y = cy;CLOCKINSetConsoleCursorPosition(outbuf, xy);CLOCKOUT(2)}
// if cursor is not NOCURSOR, update screenif (cursor_is_enabled){COORD xy;xy.X = cx;xy.Y = cy;SetConsoleCursorPosition(outbuf, xy);}
DWORD inmodes, outmodes;if (value == TRUE){inmodes = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT;outmodes = ENABLE_PROCESSED_OUTPUT;}else{inmodes = 0;outmodes = 0;}
DWORD inmodes, outmodes;if (value == TRUE){inmodes = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT| ENABLE_PROCESSED_INPUT| ENABLE_MOUSE_INPUT| ENABLE_WINDOW_INPUT;outmodes = ENABLE_PROCESSED_OUTPUT;}else{inmodes = ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT;outmodes = 0;}
if ( SetConsoleMode( inbuf, inmodes ) == 0){fputs("Error initialising console input mode.", stderr);exit(0);}
if ( SetConsoleMode( inbuf, inmodes ) == 0){fputs("Error initialising console input mode.", stderr);exit(0);}
if ( SetConsoleMode( outbuf, outmodes ) == 0){fputs("Error initialising console output mode.", stderr);exit(0);}
if ( SetConsoleMode( outbuf, outmodes ) == 0){fputs("Error initialising console output mode.", stderr);exit(0);}
static void set_w32_screen_size(){CONSOLE_SCREEN_BUFFER_INFO cinf;if (::GetConsoleScreenBufferInfo(outbuf, &cinf)){screensize.X = cinf.srWindow.Right - cinf.srWindow.Left + 1;screensize.Y = cinf.srWindow.Bottom - cinf.srWindow.Top + 1;}else{screensize.X = 80;screensize.Y = 25;}if (screen){delete [] screen;screen = NULL;}screen = new CHAR_INFO[screensize.X * screensize.Y];COORD topleft;SMALL_RECT used;topleft.X = topleft.Y = 0;::ReadConsoleOutput(outbuf, screen, screensize, topleft, &used);}static void w32_handle_resize_event(){if (crawl_state.waiting_for_command)handle_terminal_resize(true);elsecrawl_state.terminal_resized = true;}static void w32_check_screen_resize(){CONSOLE_SCREEN_BUFFER_INFO cinf;if (::GetConsoleScreenBufferInfo(outbuf, &cinf)){if (screensize.X != cinf.srWindow.Right - cinf.srWindow.Left + 1|| screensize.Y != cinf.srWindow.Bottom - cinf.srWindow.Top + 1){w32_handle_resize_event();}}}
if (inbuf == INVALID_HANDLE_VALUE || outbuf == INVALID_HANDLE_VALUE){fputs("Could not initialise libw32c console support.", stderr);exit(0);}
if (inbuf == INVALID_HANDLE_VALUE || outbuf == INVALID_HANDLE_VALUE){fputs("Could not initialise libw32c console support.", stderr);exit(0);}
init_colors(oldTitle);// by default, set string input to false: use char-input onlysetStringInput( false );if (SetConsoleMode( outbuf, 0 ) == 0){fputs("Error initialising console output mode.", stderr);exit(0);}
CONSOLE_SCREEN_BUFFER_INFO cinf;if (::GetConsoleScreenBufferInfo(outbuf, &cinf)){screensize.X = cinf.srWindow.Right - cinf.srWindow.Left + 1;screensize.Y = cinf.srWindow.Bottom - cinf.srWindow.Top + 1;}else{screensize.X = 80;screensize.Y = 25;}
// by default, set string input to false: use char-input onlysetStringInput( false );
//DEBUG//foo = fopen("debug.txt", "w");
crawl_state.terminal_resize_handler = w32_term_resizer;crawl_state.terminal_resize_check = w32_check_screen_resize;// JWM, 06/12/2004: Code page setting, as XP does not use ANSI 437 by// default.InputCP = GetConsoleCP();OutputCP = GetConsoleOutputCP();
// JWM, 06/12/2004: Code page setting, as XP does not use ANSI 437 by// default.InputCP = GetConsoleCP();OutputCP = GetConsoleOutputCP();// DS: Don't kill Crawl if we can't set the codepage. Windows 95/98/ME don't// have support for setting the input and output codepage. I'm also not// convinced we need to set the input codepage at all.if (InputCP != PREFERRED_CODEPAGE)SetConsoleCP(PREFERRED_CODEPAGE);
// Don't kill Crawl if we can't set the codepage. Windows 95/98/ME// don't have support for setting the input and output codepage.// I'm also not convinced we need to set the input codepage at all.if (InputCP != PREFERRED_CODEPAGE)SetConsoleCP(PREFERRED_CODEPAGE);
// JWM, 06/12/2004: Code page stuff. If it was the preferred code page, it// doesn't need restoring. Shouldn't be an error and too bad if there is.if (InputCP && InputCP != PREFERRED_CODEPAGE)SetConsoleCP(InputCP);
// JWM, 06/12/2004: Code page stuff. If it was the preferred code page, it// doesn't need restoring. Shouldn't be an error and too bad if there is.if (InputCP && InputCP != PREFERRED_CODEPAGE)SetConsoleCP(InputCP);
if (OutputCP && OutputCP != PREFERRED_CODEPAGE)SetConsoleOutputCP(OutputCP);// restore console attributes for normal functionsetStringInput(true);
if (OutputCP && OutputCP != PREFERRED_CODEPAGE)SetConsoleOutputCP(OutputCP);// restore console attributes for normal functionsetStringInput(true);
// set cursor and normal textcolor_setcursortype_internal(true);textcolor(DARKGREY);
// set cursor and normal textcolor_setcursortype_internal(true);textcolor(DARKGREY);
cci.dwSize = 5;cci.bVisible = curstype? TRUE : FALSE;cursor_is_enabled = curstype;CLOCKINSetConsoleCursorInfo( outbuf, &cci );CLOCKOUT(1)
cci.dwSize = 5;cci.bVisible = curstype? TRUE : FALSE;cursor_is_enabled = curstype;SetConsoleCursorInfo( outbuf, &cci );
// now, if we just changed from NOCURSOR to CURSOR,// actually move screen cursorif (cursor_is_enabled)gotoxy(cx+1, cy+1);
// now, if we just changed from NOCURSOR to CURSOR,// actually move screen cursorif (cursor_is_enabled)gotoxy(cx+1, cy+1);
for(x = 0; x < screensize.X; x++){for(y = 0; y < screensize.Y; y++){pci->Char.AsciiChar = ' ';pci->Attributes = 0;pci++;}}
for(x = 0; x < screensize.X; x++){for(y = 0; y < screensize.Y; y++){pci->Char.AsciiChar = ' ';pci->Attributes = 0;pci++;}}
source.X = 0;source.Y = 0;target.Left = 0;target.Top = 0;target.Right = screensize.X - 1;target.Bottom = screensize.Y - 1;
source.X = 0;source.Y = 0;target.Left = 0;target.Top = 0;target.Right = screensize.X - 1;target.Bottom = screensize.Y - 1;
// bounds checkif (x < 1)x = 1;if (x > screensize.X)x = screensize.X;if (y < 1)y = 1;if (y > screensize.Y)y = screensize.Y;
// bounds checkif (x < 1)x = 1;if (x > screensize.X)x = screensize.X;if (y < 1)y = 1;if (y > screensize.Y)y = screensize.Y;
// if cursor is not NOCURSOR, update screenif (cursor_is_enabled){COORD xy;xy.X = cx;xy.Y = cy;CLOCKINif (SetConsoleCursorPosition(outbuf, xy) == 0)fputs("SetConsoleCursorPosition() failed!", stderr);CLOCKOUT(2)}
// if cursor is not NOCURSOR, update screenif (cursor_is_enabled){COORD xy;xy.X = cx;xy.Y = cy;if (SetConsoleCursorPosition(outbuf, xy) == 0)fputs("SetConsoleCursorPosition() failed!", stderr);}
PCHAR_INFO pci = screen + SCREENINDEX(crawl_view.msgp.x - 1,crawl_view.msgp.y - 1);for (int x = 0; x < screensize.X; x++){for (int y = 0; y < crawl_view.msgsz.y; y++){pci->Char.AsciiChar = ' ';pci->Attributes = 0;pci++;}}
PCHAR_INFO pci = screen + SCREENINDEX(crawl_view.msgp.x - 1,crawl_view.msgp.y - 1);for (int x = 0; x < screensize.X; x++){for (int y = 0; y < crawl_view.msgsz.y; y++){pci->Char.AsciiChar = ' ';pci->Attributes = 0;pci++;}}
source.X = crawl_view.msgp.x - 1;source.Y = crawl_view.msgp.y - 1;target.Left = crawl_view.msgp.x - 1;target.Top = crawl_view.msgp.y - 1;target.Right = screensize.X - 1;target.Bottom = screensize.Y - 1;
source.X = crawl_view.msgp.x - 1;source.Y = crawl_view.msgp.y - 1;target.Left = crawl_view.msgp.x - 1;target.Top = crawl_view.msgp.y - 1;target.Right = screensize.X - 1;target.Bottom = screensize.Y - 1;
// loop through stringchar *p = (char *)s;while(*p){writeChar(*p++);}
// loop through stringchar *p = (char *)s;while(*p){writeChar(*p++);}
bool shftDown = false;bool ctrlDown = false;bool altDown = !!(cKeys & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED));// DEBUG//fprintf(foo, "Received code %d (%c) with modifiers: %d\n", VirtCode, c, cKeys);
bool shftDown = false;bool ctrlDown = false;bool altDown = !!(cKeys & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED));
// step 1 - we don't care about shift or controlif (VirtCode == VK_SHIFT || VirtCode == VK_CONTROL ||VirtCode == VK_MENU || VirtCode == VK_CAPITAL ||VirtCode == VK_NUMLOCK)return 0;
// step 1 - we don't care about shift or controlif (VirtCode == VK_SHIFT || VirtCode == VK_CONTROL ||VirtCode == VK_MENU || VirtCode == VK_CAPITAL ||VirtCode == VK_NUMLOCK)return 0;
// step 3 - translate shifted or controlled numeric keypad keysif (cKeys & SHIFT_PRESSED)shftDown = true;if (cKeys & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))ctrlDown = true; // control takes precedence over shift
// step 3 - translate shifted or controlled numeric keypad keysif (cKeys & SHIFT_PRESSED)shftDown = true;if (cKeys & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))ctrlDown = true; // control takes precedence over shift
// hack - translate ^P and ^Q since 16 and 17 are taken by CTRL and SHIFTif ((VirtCode == 80 || VirtCode == 81) && ctrlDown)return VirtCode & 0x003f; // shift back down
// hack - translate ^P and ^Q since 16 and 17 are taken by CTRL and SHIFTif ((VirtCode == 80 || VirtCode == 81) && ctrlDown)return VirtCode & 0x003f; // shift back down
// see if we're a vkeyint mkey;for(mkey = 0; mkey<VKEY_MAPPINGS; mkey++)if (VirtCode == vk_tr[0][mkey]) break;
// see if we're a vkeyint mkey;for(mkey = 0; mkey<VKEY_MAPPINGS; mkey++)if (VirtCode == vk_tr[0][mkey]) break;
// step 4 - just return the damn key.if (mkey == VKEY_MAPPINGS){if (c)return c;
// step 4 - just return the damn key.if (mkey == VKEY_MAPPINGS){if (c)return c;
// ds -- Icky hacks to allow keymaps with funky keys.if (ctrlDown)VirtCode |= 512;if (shftDown)VirtCode |= 1024;if (altDown)VirtCode |= 2048;
// ds -- Icky hacks to allow keymaps with funky keys.if (ctrlDown)VirtCode |= 512;if (shftDown)VirtCode |= 1024;if (altDown)VirtCode |= 2048;
// ds -- Cheat and returns 256 + VK if the char is zero. This allows us// to use the VK for macros and is on par for evil with the rest of// this function anyway.return VirtCode | 256;}
// ds -- Cheat and returns 256 + VK if the char is zero. This allows us// to use the VK for macros and is on par for evil with the rest of// this function anyway.return VirtCode | 256;}
CLOCKINif (ReadConsoleInput( inbuf, &ir, 1, &nread) == 0)fputs("Error in ReadConsoleInput()!", stderr);CLOCKOUT(5)if (nread > 0){// ignore if it isn't a keyboard event.if (ir.EventType == KEY_EVENT){kr = &(ir.Event.KeyEvent);// ignore if it is a 'key up' - we only want 'key down'if (kr->bKeyDown == true){key = vk_translate( kr->wVirtualKeyCode, kr->uChar.AsciiChar, kr->dwControlKeyState );if (key > 0)
if (ReadConsoleInput( inbuf, &ir, 1, &nread) == 0)fputs("Error in ReadConsoleInput()!", stderr);if (nread > 0){// ignore if it isn't a keyboard event.switch (ir.EventType){case KEY_EVENT:kr = &(ir.Event.KeyEvent);// ignore if it is a 'key up' - we only want 'key down'if (kr->bKeyDown == true)
repeat_count = kr->wRepeatCount - 1;repeat_key = key;break;
key = vk_translate( kr->wVirtualKeyCode,kr->uChar.AsciiChar,kr->dwControlKeyState );if (key > 0){repeat_count = kr->wRepeatCount - 1;repeat_key = key;waiting_for_event = false;break;}
// turn buffering off temporarilyconst bool oldValue = buffering;setBuffering(false);
// turn buffering off temporarilyconst bool oldValue = buffering;setBuffering(false);
// terminate string, then strip CRLF, replace with \0buf[maxlen-1] = 0;for (unsigned i=(nread<3 ? 0 : nread-3); i<nread; i++){if (buf[i] == 0x0A || buf[i] == 0x0D){buf[i] = '\0';break;}
// terminate string, then strip CRLF, replace with \0buf[maxlen-1] = 0;for (unsigned i=(nread<3 ? 0 : nread-3); i<nread; i++){if (buf[i] == 0x0A || buf[i] == 0x0D){buf[i] = '\0';break;}
// reset console mode - also flushes if player has typed in// too long of a name so we don't get silly garbage on return.setStringInput( false );
// reset console mode - also flushes if player has typed in// too long of a name so we don't get silly garbage on return.setStringInput( false );