static inline BOOL w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize, DWORD *waiting) { return (w32_console_unicode_input ? ReadConsoleInputW (h, rec, recsize, waiting) : ReadConsoleInputA (h, rec, recsize, waiting)); }
char Consola::getch(void) { INPUT_RECORD irInputRecord; DWORD dwEventsRead; CHAR cChar; while(ReadConsoleInputA(hStdin, &irInputRecord, 1, &dwEventsRead)) /* Read key press */ if (irInputRecord.EventType == KEY_EVENT && irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_SHIFT && irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_MENU && irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_CONTROL) { cChar = irInputRecord.Event.KeyEvent.uChar.AsciiChar; ReadConsoleInputA (hStdin, &irInputRecord , 1, &dwEventsRead); /* Read key release */ if (irInputRecord.Event.KeyEvent.wVirtualKeyCode == VK_LEFT) return ESQUERDA; if (irInputRecord.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT) return DIREITA; if (irInputRecord.Event.KeyEvent.wVirtualKeyCode == VK_UP) return CIMA; if (irInputRecord.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) return BAIXO; return cChar; } return EOF; }
static void DOSVM_ProcessConsole(void) { INPUT_RECORD msg; DWORD res; BYTE scan, ascii; if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res)) { switch (msg.EventType) { case KEY_EVENT: scan = msg.Event.KeyEvent.wVirtualScanCode; ascii = msg.Event.KeyEvent.uChar.AsciiChar; TRACE("scan %02x, ascii %02x\n", scan, ascii); /* set the "break" (release) flag if key released */ if (!msg.Event.KeyEvent.bKeyDown) scan |= 0x80; /* check whether extended bit is set, * and if so, queue the extension prefix */ if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) { DOSVM_Int09SendScan(0xE0,0); } DOSVM_Int09SendScan(scan, ascii); break; case MOUSE_EVENT: DOSVM_Int33Console(&msg.Event.MouseEvent); break; case WINDOW_BUFFER_SIZE_EVENT: FIXME("unhandled WINDOW_BUFFER_SIZE_EVENT.\n"); break; case MENU_EVENT: FIXME("unhandled MENU_EVENT.\n"); break; case FOCUS_EVENT: FIXME("unhandled FOCUS_EVENT.\n"); break; default: FIXME("unknown console event: %d\n", msg.EventType); } } }
void Console::readInput() // Check for input and stuff. { DWORD num_events, num_events_read; GetNumberOfConsoleInputEvents(in, &num_events); if (num_events) { INPUT_RECORD *events = new INPUT_RECORD[num_events]; ReadConsoleInputA(in, events, num_events, &num_events_read); for (DWORD i = 0; i < num_events_read; ++i) { INPUT_RECORD &i_event = events[i]; switch (i_event.EventType) { case KEY_EVENT: keys[i_event.Event.KeyEvent.wVirtualKeyCode] = i_event.Event.KeyEvent.bKeyDown; break; default: continue; break; } } delete[] events; } }
/* Note that this should parse some special keys into their emacs ctrl-key combos * Return of -1 signifies unrecognized code */ static char linenoiseReadChar(int fd){ #ifdef _WIN32 INPUT_RECORD rec; DWORD count; do { ReadConsoleInputA(console_in, &rec, 1, &count); } while (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown); if (rec.Event.KeyEvent.uChar.AsciiChar == 0) { /* handle keys that aren't converted to ASCII */ switch (rec.Event.KeyEvent.wVirtualKeyCode) { case VK_LEFT: return 2; /* ctrl-b */ case VK_RIGHT: return 6; /* ctrl-f */ case VK_UP: return 16; /* ctrl-p */ case VK_DOWN: return 14; /* ctrl-n */ case VK_DELETE: return 127; /* ascii DEL byte */ case VK_HOME: return 1; /* ctrl-a */ case VK_END: return 5; /* ctrl-e */ default: return -1; } } return rec.Event.KeyEvent.uChar.AsciiChar; #else char c; int nread; char seq[2], seq2[2]; nread = read(fd,&c,1); if (nread <= 0) return 0; #if defined(_DEBUG) if (c == 28) { /* ctrl-\ */ /* special debug mode. prints all keys hit. ctrl-c to get out */ printf("\x1b[1G\n"); /* go to first column of new line */ while (true) { char keys[10]; int ret = read(fd, keys, 10); int i; if (ret <= 0) { printf("\nret: %d\n", ret); } for (i=0; i < ret; i++) printf("%d ", (int)keys[i]); printf("\x1b[1G\n"); /* go to first column of new line */ if (keys[0] == 3) /* ctrl-c. may cause signal instead */ return -1; } } #endif if (c == 27) { /* escape */ if (read(fd,seq,2) == -1) return 0; if (seq[0] == 91){ if (seq[1] == 68) { /* left arrow */ return 2; /* ctrl-b */ } else if (seq[1] == 67) { /* right arrow */ return 6; /* ctrl-f */ } else if (seq[1] == 65) { /* up arrow */ return 16; /* ctrl-p */ } else if (seq[1] == 66) { /* down arrow */ return 14; /* ctrl-n */ } else if (seq[1] > 48 && seq[1] < 57) { /* extended escape */ if (read(fd,seq2,2) == -1) return 0; if (seq2[0] == 126) { if (seq[1] == 49 || seq[1] == 55) { /* home (linux console and rxvt based) */ return 1; /* ctrl-a */ } else if (seq[1] == 52 || seq[1] == 56 ) { /* end (linux console and rxvt based) */ return 5; /* ctrl-e */ } else if (seq[1] == 51) { /* delete */ return 127; /* ascii DEL byte */ } else { return -1; } } else { return -1; } if (seq[1] == 51 && seq2[0] == 126) { /* delete */ return 127; /* ascii DEL byte */ } else { return -1; } } else { return -1; } } else if (seq[0] == 79){ if (seq[1] == 72) { /* home (xterm based) */ return 1; /* ctrl-a */ } else if (seq[1] == 70) { /* end (xterm based) */ return 5; /* ctrl-e */ } else { return -1; } } else { return -1; } } else if (c == 127) { /* some consoles use 127 for backspace rather than delete. * we only use it for delete */ return 8; } return c; /* normalish character */ #endif }
int ProcessInput(LPCTSTR asName) { HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); TCHAR szName[MAX_PATH] = _T("\\\\.\\pipe\\"); _tcscat(szName, asName); DWORD nRead, nWrite; INPUT_RECORD r; BOOL b; char sInfo[300] = ""; wsprintfA(sInfo, "Client started, PID=%u\nConnecting to server '", GetCurrentProcessId()); #ifdef _UNICODE WideCharToMultiByte(CP_OEMCP, 0, asName, -1, sInfo+lstrlenA(sInfo), 200, 0, 0); #else lstrcat(sInfo, asName); #endif lstrcatA(sInfo, "'"); PrintOut(sInfo); DWORD nStart = GetTickCount(); while ((GetTickCount() - nStart) < 30000) { if (WaitNamedPipe(szName, 500)) break; printf("."); Sleep(2000); } HANDLE hPipe = CreateFile(szName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (!hPipe || hPipe == INVALID_HANDLE_VALUE) { nRead = GetLastError(); printf("\n!!! OpenPipe failed, code=%u !!!\n", nRead); return nRead; } printf("\nConnected! Alt+X - exit, Alt+L - clear, Alt+F - fill\n"); SetConsoleCtrlHandler((PHANDLER_ROUTINE)HandlerRoutine, true); while (!gbExit) { if (ReadConsoleInputA(hIn, &r, 1, &nRead) && nRead) { if (r.EventType == KEY_EVENT && r.Event.KeyEvent.bKeyDown) { switch (r.Event.KeyEvent.wVirtualKeyCode) { case VK_UP: SendAnsi(hPipe, hOut, "\x1B[A"); continue; case VK_DOWN: SendAnsi(hPipe, hOut, "\x1B[B"); continue; case VK_RIGHT: SendAnsi(hPipe, hOut, "\x1B[C"); continue; case VK_LEFT: SendAnsi(hPipe, hOut, "\x1B[D"); continue; case VK_HOME: if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[1;1H"); else SendAnsi(hPipe, hOut, "\x1B[1G"); continue; case VK_END: if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[9999;1H"); else { CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { char chEsc[32]; wsprintfA(chEsc, "\x1B[%uG", csbi.dwSize.X); SendAnsi(hPipe, hOut, chEsc); } } continue; case VK_PRIOR: // PgUp if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[9999S"); else SendAnsi(hPipe, hOut, "\x1B[S"); continue; case VK_NEXT: // PgDn if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[9999T"); else SendAnsi(hPipe, hOut, "\x1B[T"); continue; case VK_DELETE: if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[M"); else if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[P"); else if (r.Event.KeyEvent.dwControlKeyState & (SHIFT_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[X"); else PrintOut("\nCtrl+Del - delete line, Alt+Del - delete char, Shift+Del - clear char\n"); continue; case VK_INSERT: if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[L"); else if (r.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED)) SendAnsi(hPipe, hOut, "\x1B[@"); else PrintOut("\nCtrl+Ins - insert line, Alt+Ins - insert char\n"); continue; } if (r.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) { switch (r.Event.KeyEvent.wVirtualKeyCode) { case '1': SendFile(hPipe, hOut, _T("AnsiColors16.ans")); continue; case '2': SendFile(hPipe, hOut, _T("AnsiColors16t.ans")); continue; case '3': SendFile(hPipe, hOut, _T("AnsiColors256.ans")); continue; } } if (r.Event.KeyEvent.uChar.AsciiChar) { if (r.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) { char szText[100]; switch (r.Event.KeyEvent.uChar.AsciiChar) { case 'x': case 'X': printf("\nExit session\n"); gbExit = true; break; case 'l': case 'L': SendAnsi(hPipe, hOut, "\x1B[2J"); SendAnsi(hPipe, hOut, "\x1B[1;1H"); break; case 'f': case 'F': SendAnsi(NULL, hOut, "\r\nFilling server console width text...\r\n"); SendAnsi(hPipe, NULL, "\x02"); break; case '1': SendAnsi(NULL, hOut, "{Alt+1}"); SendAnsi(hPipe, NULL, "\r\nRequest terminal primary DA: "); SendAnsi(hPipe, hOut, "\x1B[c"); SendAnsi(hPipe, NULL, "\x01"); break; case '2': SendAnsi(NULL, hOut, "{Alt+2}"); SendAnsi(hPipe, NULL, "\r\nRequest terminal secondary DA: "); SendAnsi(hPipe, hOut, "\x1B[>c"); SendAnsi(hPipe, NULL, "\x01"); break; case '3': SendAnsi(NULL, hOut, "{Alt+3}"); SendAnsi(hPipe, NULL, "\r\nRequest terminal status: "); SendAnsi(hPipe, hOut, "\x1B[5n"); SendAnsi(hPipe, NULL, "\x01"); break; case '4': SendAnsi(NULL, hOut, "{Alt+4}"); SendAnsi(hPipe, NULL, "\r\nRequest cursor pos [row;col]: "); SendAnsi(hPipe, hOut, "\x1B[6n"); SendAnsi(hPipe, NULL, "\x01"); break; case '5': SendAnsi(NULL, hOut, "{Alt+5}"); SendAnsi(hPipe, NULL, "\r\nRequest text area size [height;width]: "); SendAnsi(hPipe, hOut, "\x1B[18t"); SendAnsi(hPipe, NULL, "\x01"); break; case '6': SendAnsi(NULL, hOut, "{Alt+6}"); SendAnsi(hPipe, NULL, "\r\nRequest screen area size [height;width]: "); SendAnsi(hPipe, hOut, "\x1B[19t"); SendAnsi(hPipe, NULL, "\x01"); break; case '7': SendAnsi(NULL, hOut, "{Alt+7}"); SendAnsi(hPipe, NULL, "\r\nRequest terminal title: "); SendAnsi(hPipe, hOut, "\x1B[21t"); SendAnsi(hPipe, NULL, "\x01"); break; } continue; } if (r.Event.KeyEvent.uChar.AsciiChar == 27) WriteConsoleW(hOut, gszAnalogues+27, 1, &nWrite, NULL); else WriteConsoleA(hOut, &r.Event.KeyEvent.uChar.AsciiChar, 1, &nWrite, NULL); b = WriteFile(hPipe, &r.Event.KeyEvent.uChar.AsciiChar, 1, &nWrite, NULL); if (b && r.Event.KeyEvent.uChar.AsciiChar == '\r') { WriteConsoleA(hOut, "\n", 1, &nWrite, NULL); b = WriteFile(hPipe, "\n", 1, &nWrite, NULL); } if (!b) { nRead = GetLastError(); printf("\n!!! WritePipe failed, code=%u !!!\n", nRead); return nRead; } } } } } return 0; }
int getkbm(void) { HANDLE con; DWORD nevents = 0; INPUT_RECORD buf; init_ti(); if (nkeybuf) { return keybuf[--nkeybuf]; } if (keystate) keystate = 0; con = GetStdHandle(STD_INPUT_HANDLE); while (1) { ReadConsoleInputA(con, &buf, 1, &nevents); if (buf.EventType == KEY_EVENT && buf.Event.KeyEvent.bKeyDown) { _controlkeystate = buf.Event.KeyEvent.dwControlKeyState; if (buf.Event.KeyEvent.uChar.AsciiChar == 0) return KEY_SPECIAL + buf.Event.KeyEvent.wVirtualScanCode; return buf.Event.KeyEvent.uChar.AsciiChar & 0xFF; } else if (buf.EventType == WINDOW_BUFFER_SIZE_EVENT) { ti.screenwidth = buf.Event.WindowBufferSizeEvent.dwSize.X; ti.screenheight = buf.Event.WindowBufferSizeEvent.dwSize.Y; if (ti.winright>ti.screenwidth) ti.winright = ti.screenwidth; if (ti.winbottom>ti.screenheight) ti.winbottom = ti.screenheight; if (ti.winleft>ti.winright) ti.winleft = ti.winright; if (ti.wintop>ti.winbottom) ti.wintop = ti.winbottom; if (!in_window(ti.winleft + ti.curx - 1, ti.wintop + ti.cury - 1)) gotoxy(1, 1); return WINDOW_RESIZE; } else if (buf.EventType == MOUSE_EVENT) { switch (buf.Event.MouseEvent.dwEventFlags) { case 0: if (buf.Event.MouseEvent.dwButtonState != 0) { _mousebuttons = buf.Event.MouseEvent.dwButtonState; _mousex = buf.Event.MouseEvent.dwMousePosition.X + 1; _mousey = buf.Event.MouseEvent.dwMousePosition.Y + 1; return MOUSE_CLICK; } break; case DOUBLE_CLICK: _mousebuttons = buf.Event.MouseEvent.dwButtonState; _mousex = buf.Event.MouseEvent.dwMousePosition.X + 1; _mousey = buf.Event.MouseEvent.dwMousePosition.Y + 1; return MOUSE_DBLCLICK; case MOUSE_WHEELED: _mousex = buf.Event.MouseEvent.dwMousePosition.X + 1; _mousey = buf.Event.MouseEvent.dwMousePosition.Y + 1; if ((int)buf.Event.MouseEvent.dwButtonState>0) return MOUSE_WHEELUP; return MOUSE_WHEELDOWN; default: break; } } } }
static size_t console_read(struct file *f, char *buf, size_t count) { struct console_file *console_file = (struct console_file *)f; console_lock(); console_retrieve_state(); size_t bytes_read = 0; while (console->input_buffer_head != console->input_buffer_tail && count > 0) { count--; buf[bytes_read++] = console->input_buffer[console->input_buffer_tail]; console->input_buffer_tail = (console->input_buffer_tail + 1) % MAX_INPUT; } if (console->termios.c_lflag & ICANON) { char line[MAX_CANON + 1]; /* One more for storing CR or LF */ size_t len = 0; while (count > 0) { INPUT_RECORD ir; DWORD read; ReadConsoleInputA(console->in, &ir, 1, &read); if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { switch (ir.Event.KeyEvent.wVirtualKeyCode) { case VK_RETURN: { if (!(console->termios.c_iflag & IGNCR)) line[len++] = console->termios.c_iflag & ICRNL ? '\n' : '\r'; size_t r = min(count, len); memcpy(buf + bytes_read, line, r); bytes_read += r; count -= r; if (r < len) { /* Some bytes not fit, add to input buffer */ console_add_input(line + r, len - r); } if (console->termios.c_lflag & ECHO) crnl(); goto read_done; } case VK_BACK: { if (len > 0) { len--; if (console->termios.c_lflag & ECHO) backspace(TRUE); } } default: { char ch = ir.Event.KeyEvent.uChar.AsciiChar; if (ch >= 0x20) { if (len < MAX_CANON) { line[len++] = ch; if (console->termios.c_lflag & ECHO) write_normal(&ch, 1); } } } } } } } else /* Non canonical mode */ { int vtime = console->termios.c_cc[VTIME]; int vmin = console->termios.c_cc[VMIN]; while (count > 0) { if (bytes_read > 0 && bytes_read >= vmin) break; /* If vmin > 0 and vtime == 0, it is a blocking read, otherwise we need to poll first */ if (vtime > 0 || (vmin == 0 && vtime == 0)) { if (WaitForSingleObject(console->in, vtime * 100) == WAIT_TIMEOUT) break; } INPUT_RECORD ir; DWORD read; ReadConsoleInputA(console->in, &ir, 1, &read); if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { switch (ir.Event.KeyEvent.wVirtualKeyCode) { case VK_UP: console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOA" : "\x1B[A", 3); break; case VK_DOWN: console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOB" : "\x1B[B", 3); break; case VK_RIGHT: console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOC" : "\x1B[C", 3); break; case VK_LEFT: console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOD" : "\x1B[D", 3); break; case VK_HOME: console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOH" : "\x1B[H", 3); break; case VK_END: console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOF" : "\x1B[F", 3); break; case VK_INSERT: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[2~", 4); break; case VK_DELETE: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[3~", 4); break; case VK_PRIOR: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[5~", 4); break; case VK_NEXT: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[6~", 4); break; case VK_F1: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOP", 3); break; case VK_F2: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOQ", 3); break; case VK_F3: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOR", 3); break; case VK_F4: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOS", 3); break; case VK_F5: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[15~", 5); break; case VK_F6: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[17~", 5); break; case VK_F7: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[18~", 5); break; case VK_F8: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[19~", 5); break; case VK_F9: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[20~", 5); break; case VK_F10: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[21~", 5); break; case VK_F11: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[23~", 5); break; case VK_F12: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[24~", 5); break; case VK_F13: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[25~", 5); break; case VK_F14: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[26~", 5); break; case VK_F15: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[28~", 5); break; case VK_F16: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[29~", 5); break; case VK_F17: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[31~", 5); break; case VK_F18: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[32~", 5); break; case VK_F19: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[33~", 5); break; case VK_F20: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[34~", 5); break; default: { char ch = ir.Event.KeyEvent.uChar.AsciiChar; if (ch == '\r' && console->termios.c_iflag & IGNCR) break; if (ch == '\r' && console->termios.c_iflag & ICRNL) ch = '\n'; else if (ch == '\n' && console->termios.c_iflag & ICRNL) ch = '\r'; if (ch > 0) { count--; buf[bytes_read++] = ch; if (console->termios.c_lflag & ECHO) write_normal(&ch, 1); } } } } else { /* TODO: Other types of input */ } } } read_done: /* This will make the caret immediately visible */ set_pos(console->x, console->y); console_unlock(); return bytes_read; }
/********************************************************************* * _getch (MSVCRT.@) */ int CDECL _getch(void) { int retval = MSVCRT_EOF; LOCK_CONSOLE; if (__MSVCRT_console_buffer != MSVCRT_EOF) { retval = __MSVCRT_console_buffer; __MSVCRT_console_buffer = MSVCRT_EOF; } else { INPUT_RECORD ir; DWORD count; DWORD mode = 0; GetConsoleMode(MSVCRT_console_in, &mode); if(mode) SetConsoleMode(MSVCRT_console_in, 0); do { if (ReadConsoleInputA(MSVCRT_console_in, &ir, 1, &count)) { unsigned int i; /* Only interested in ASCII chars */ if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { if (ir.Event.KeyEvent.uChar.AsciiChar) { retval = ir.Event.KeyEvent.uChar.AsciiChar; break; } for (i = 0; i < sizeof(enh_map) / sizeof(enh_map[0]); i++) { if (ir.Event.KeyEvent.wVirtualScanCode == enh_map[i].vk) break; } if (i < sizeof(enh_map) / sizeof(enh_map[0])) { unsigned idx; if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) idx = ALT_CHAR; else if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) ) idx = CTRL_CHAR; else if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) idx = SHIFT_CHAR; else idx = NORMAL_CHAR; retval = enh_map[i].ch[idx][0]; __MSVCRT_console_buffer = enh_map[i].ch[idx][1]; break; } WARN("Unmapped char keyState=%x vk=%x\n", ir.Event.KeyEvent.dwControlKeyState, ir.Event.KeyEvent.wVirtualScanCode); } } else break; } while(1); if (mode) SetConsoleMode(MSVCRT_console_in, mode); } UNLOCK_CONSOLE; return retval; }
// replacement get_s which is EL_BIND aware static char * el_get_s (char *buffer, int chars) { // char *head = buffer; // for ( ;; Sleep( 10 ) ) { // INPUT_RECORD _record; // DWORD _read = 0; if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE ) break; // if we didnt read a key if ( _read == 0 ) continue; // only interested in key events if ( _record.EventType != KEY_EVENT ) continue; // is the key down if (! _record.Event.KeyEvent.bKeyDown ) continue; // read the ascii key character char _key = _record.Event.KeyEvent.uChar.AsciiChar; // non ascii conformant key press if ( _key == 0 ) { // check the scan code // if VK_UP scroll back through history // if VK_DOWN scroll forward through history continue; } // try to execute any bind this key may have if ( runBind( _key ) ) continue; // if we read a return key if ( _key == '\n' || _key == '\r' ) { con_return( ); break; } // key is backspace if ( _key == 0x8 ) { // avoid deleting past beginning if ( head > buffer ) { con_backspace( ); head--; } continue; } // add this key to the input buffer if ( (head-buffer) < (chars-1) ) { con_output( _key ); *(head++) = _key; } } // insert end of line character *head = '\0'; return buffer; }
static int linenoisePrompt(char* buf, size_t buflen, const char* prompt) { size_t plen = strlen(prompt); size_t pos = 0; size_t len = 0; int history_index = 0; #ifdef ALT_KEYS unsigned char last_down = 0; #endif buf[0] = '\0'; buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; GetConsoleScreenBufferInfo(console_out, &inf); size_t cols = inf.dwSize.X; output(prompt, plen, 0, inf.dwCursorPosition.Y); inf.dwCursorPosition.X = (SHORT)plen; SetConsoleCursorPosition(console_out, inf.dwCursorPosition); for ( ; ; ) { INPUT_RECORD rec; DWORD count; ReadConsoleInputA(console_in, &rec, 1, &count); if (rec.EventType != KEY_EVENT) continue; #ifdef ALT_KEYS if (rec.Event.KeyEvent.bKeyDown) { last_down = rec.Event.KeyEvent.uChar.AsciiChar; continue; } #else if (!rec.Event.KeyEvent.bKeyDown) { continue; } #endif switch (rec.Event.KeyEvent.wVirtualKeyCode) { case VK_RETURN: /* enter */ history_len--; free(history[history_len]); return (int)len; case VK_BACK: /* backspace */ #ifdef ALT_KEYS backspace: #endif if (pos > 0 && len > 0) { memmove(buf + pos - 1, buf + pos, len - pos); pos--; len--; buf[len] = '\0'; refreshLine(prompt, buf, len, pos, cols); } break; case VK_LEFT: #ifdef ALT_KEYS left_arrow: #endif /* left arrow */ if (pos > 0) { pos--; refreshLine(prompt, buf, len, pos, cols); } break; case VK_RIGHT: #ifdef ALT_KEYS right_arrow: #endif /* right arrow */ if (pos != len) { pos++; refreshLine(prompt, buf, len, pos, cols); } break; case VK_UP: case VK_DOWN: #ifdef ALT_KEYS up_down_arrow: #endif /* up and down arrow: history */ if (history_len > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ free(history[history_len - 1 - history_index]); history[history_len - 1 - history_index] = _strdup(buf); /* Show the new entry */ history_index += (rec.Event.KeyEvent.wVirtualKeyCode == VK_UP) ? 1 : -1; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_len) { history_index = history_len - 1; break; } strncpy(buf, history[history_len - 1 - history_index], buflen); buf[buflen] = '\0'; len = pos = strlen(buf); refreshLine(prompt, buf, len, pos, cols); } break; case VK_DELETE: /* delete */ if (len > 0 && pos < len) { memmove(buf + pos, buf + pos + 1, len - pos - 1); len--; buf[len] = '\0'; refreshLine(prompt, buf, len, pos, cols); } break; case VK_HOME: /* Ctrl+a, go to the start of the line */ #ifdef ALT_KEYS home: #endif pos = 0; refreshLine(prompt, buf, len, pos, cols); break; case VK_END: /* ctrl+e, go to the end of the line */ #ifdef ALT_KEYS end: #endif pos = len; refreshLine(prompt, buf, len, pos, cols); break; default: #ifdef ALT_KEYS /* Use alt instead of CTRL since windows eats CTRL+char combos */ if (rec.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { switch (last_down) { case 'a': /* ctrl-t */ goto home; case 'e': /* ctrl-t */ goto end; case 't': /* ctrl-t */ if (pos > 0 && pos < len) { int aux = buf[pos - 1]; buf[pos - 1] = buf[pos]; buf[pos] = aux; if (pos != len - 1) pos++; refreshLine(prompt, buf, len, pos, cols); } break; case 'h': /* ctrl-h */ goto backspace; case 'b': /* ctrl-b */ goto left_arrow; case 'f': /* ctrl-f */ goto right_arrow; case 'p': /* ctrl-p */ rec.Event.KeyEvent.wVirtualKeyCode = VK_UP; goto up_down_arrow; case 'n': /* ctrl-n */ rec.Event.KeyEvent.wVirtualKeyCode = VK_DOWN; goto up_down_arrow; case 'u': /* Ctrl+u, delete the whole line. */ buf[0] = '\0'; pos = len = 0; refreshLine(prompt, buf, len, pos, cols); break; case 'k': /* Ctrl+k, delete from current to end of line. */ buf[pos] = '\0'; len = pos; refreshLine(prompt, buf, len, pos, cols); break; } continue; } #endif /* ALT_KEYS */ if (rec.Event.KeyEvent.uChar.AsciiChar < ' ' || rec.Event.KeyEvent.uChar.AsciiChar > '~') continue; if (len < buflen) { if (len != pos) memmove(buf + pos + 1, buf + pos, len - pos); buf[pos] = rec.Event.KeyEvent.uChar.AsciiChar; len++; pos++; buf[len] = '\0'; refreshLine(prompt, buf, len, pos, cols); } break; } } }