/* ================== CON_ConsoleInput ================== */ char *CON_ConsoleInput (void) { INPUT_RECORD buff[MAXCMDLINE]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if (!GetNumberOfConsoleInputEvents(qconsole_hin, &events)) return NULL; if (events < 1) return NULL; // if we have overflowed, start dropping oldest input events if (events >= MAXCMDLINE) { ReadConsoleInput(qconsole_hin, buff, 1, &events); return NULL; } if (!ReadConsoleInput(qconsole_hin, buff, events, &count)) return NULL; FlushConsoleInputBuffer(qconsole_hin); for (i = 0; i < count; i++) { if (buff[i].EventType != KEY_EVENT) continue; if (!buff[i].Event.KeyEvent.bKeyDown) continue; key = buff[i].Event.KeyEvent.wVirtualKeyCode; if (key == VK_RETURN) { newlinepos = i; break; } else if (key == VK_UP) { CON_HistPrev(); break; } else if (key == VK_DOWN) { CON_HistNext(); break; } else if (key == VK_TAB) { // command completion field_t f; Field_Clear(&f); Q_strlcpy(f.buffer, qconsole_line, sizeof(f.buffer)); Field_AutoComplete(&f); Q_strlcpy(qconsole_line, f.buffer, sizeof(qconsole_line)); qconsole_linelen = strlen(qconsole_line); break; } if (qconsole_linelen < sizeof(qconsole_line) - 1) { char c = buff[i].Event.KeyEvent.uChar.AsciiChar; if (key == VK_BACK) { int pos = (qconsole_linelen > 0) ? qconsole_linelen - 1 : 0; qconsole_line[pos] = '\0'; qconsole_linelen = pos; } else if (c) { qconsole_line[qconsole_linelen++] = c; qconsole_line[qconsole_linelen] = '\0'; } } } if (newlinepos < 0) { CON_Show(); return NULL; } if (!qconsole_linelen) { CON_Show(); Com_Printf("\n"); return NULL; } qconsole_linelen = 0; CON_Show(); CON_HistAdd(); Com_Printf("%s\n", qconsole_line); return qconsole_line; }
/* ================== CON_Input ================== */ char *CON_Input( void ) { INPUT_RECORD buff[ MAX_EDIT_LINE ]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if ( !GetNumberOfConsoleInputEvents( qconsole_hin, &events ) ) { return NULL; } if ( events < 1 ) { return NULL; } // if we have overflowed, start dropping oldest input events if ( events >= MAX_EDIT_LINE ) { ReadConsoleInput( qconsole_hin, buff, 1, &events ); return NULL; } if ( !ReadConsoleInput( qconsole_hin, buff, events, &count ) ) { return NULL; } FlushConsoleInputBuffer( qconsole_hin ); for ( i = 0; i < count; i++ ) { if ( buff[ i ].EventType != KEY_EVENT ) { continue; } if ( !buff[ i ].Event.KeyEvent.bKeyDown ) { continue; } key = buff[ i ].Event.KeyEvent.wVirtualKeyCode; if ( key == VK_RETURN ) { newlinepos = i; break; } else if ( key == VK_UP ) { Q_strncpyz( qconsole_line, Hist_Prev(), sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); break; } else if ( key == VK_DOWN ) { const char *history = Hist_Next(); if ( history ) { Q_strncpyz( qconsole_line, history, sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); } else if ( qconsole_linelen ) { Hist_Add( qconsole_line ); qconsole_line[ 0 ] = '\0'; qconsole_linelen = 0; } break; } else if ( key == VK_TAB ) { field_t f; Q_strncpyz( f.buffer, qconsole_line, sizeof( f.buffer ) ); Field_AutoComplete( &f, "]" ); Q_strncpyz( qconsole_line, f.buffer, sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); break; } if ( qconsole_linelen < sizeof( qconsole_line ) - 1 ) { char c = buff[ i ].Event.KeyEvent.uChar.AsciiChar; if ( key == VK_BACK ) { int pos = ( qconsole_linelen > 0 ) ? qconsole_linelen - 1 : 0; qconsole_line[ pos ] = '\0'; qconsole_linelen = pos; } else if ( c ) { qconsole_line[ qconsole_linelen++ ] = c; qconsole_line[ qconsole_linelen ] = '\0'; } } } CON_Show(); if ( newlinepos < 0 ) { return NULL; } if ( !qconsole_linelen ) { Com_Printf( "\n" ); return NULL; } Hist_Add( qconsole_line ); Com_Printf( "]%s\n", qconsole_line ); qconsole_linelen = 0; return qconsole_line; }
/* ================== CON_Input ================== */ char *CON_Input( void ) { // we use this when sending back commands static char text[MAX_EDIT_LINE]; int avail; char key; field_t *history; size_t size; if(ttycon_on) { avail = read(STDIN_FILENO, &key, 1); if (avail != -1) { // we have something // backspace? // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere if ((key == TTY_erase) || (key == 127) || (key == 8)) { if (TTY_con.cursor > 0) { TTY_con.cursor--; TTY_con.buffer[TTY_con.cursor] = '\0'; CON_Back(); } return NULL; } // check if this is a control char if ((key) && (key) < ' ') { if (key == '\n') { // push it in history Hist_Add(&TTY_con); Q_strncpyz(text, TTY_con.buffer, sizeof(text)); Field_Clear(&TTY_con); key = '\n'; size = write(1, &key, 1); size = write( 1, "]", 1 ); return text; } if (key == '\t') { CON_Hide(); Field_AutoComplete( &TTY_con ); CON_Show(); return NULL; } avail = read(STDIN_FILENO, &key, 1); if (avail != -1) { // VT 100 keys if (key == '[' || key == 'O') { avail = read(STDIN_FILENO, &key, 1); if (avail != -1) { switch (key) { case 'A': history = Hist_Prev(); if (history) { CON_Hide(); TTY_con = *history; CON_Show(); } CON_FlushIn(); return NULL; break; case 'B': history = Hist_Next(); CON_Hide(); if (history) { TTY_con = *history; } else { Field_Clear(&TTY_con); } CON_Show(); CON_FlushIn(); return NULL; break; case 'C': return NULL; case 'D': return NULL; } } } } Com_DPrintf("droping ISCTL sequence: %d, TTY_erase: %d\n", key, TTY_erase); CON_FlushIn(); return NULL; } if (TTY_con.cursor >= sizeof(text) - 1) return NULL; // push regular character TTY_con.buffer[TTY_con.cursor] = key; TTY_con.cursor++; // print the current line (this is differential) size = write(STDOUT_FILENO, &key, 1); } return NULL; } else if (stdin_active) { int len; fd_set fdset; struct timeval timeout; FD_ZERO(&fdset); FD_SET(STDIN_FILENO, &fdset); // stdin timeout.tv_sec = 0; timeout.tv_usec = 0; if(select (STDIN_FILENO + 1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(STDIN_FILENO, &fdset)) return NULL; len = read(STDIN_FILENO, text, sizeof(text)); if (len == 0) { // eof! stdin_active = qfalse; return NULL; } if (len < 1) return NULL; text[len-1] = 0; // rip off the /n and terminate return text; } return NULL; }
/* ================== CON_Input ================== */ char *CON_Input(void) { // we use this when sending back commands static char text[MAX_EDIT_LINE]; int avail; char key; field_t *history; size_t UNUSED_VAR size; if(ttycon_on) { avail = read(STDIN_FILENO, &key, 1); if(avail != -1) { // we have something // backspace? // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere if((key == TTY_erase) || (key == 127) || (key == 8)) { if(TTY_con.cursor > 0) { TTY_con.cursor--; TTY_con.buffer[TTY_con.cursor] = '\0'; CON_Back(); } return NULL; } // check if this is a control char if((key) && (key) < ' ') { if(key == '\n') { #ifndef DEDICATED // if not in the game explicitly prepend a slash if needed if (clc.state != CA_ACTIVE && TTY_con.cursor && TTY_con.buffer[0] != '/' && TTY_con.buffer[0] != '\\') { memmove(TTY_con.buffer + 1, TTY_con.buffer, sizeof(TTY_con.buffer) - 1); TTY_con.buffer[0] = '\\'; TTY_con.cursor++; } if (TTY_con.buffer[0] == '/' || TTY_con.buffer[0] == '\\') { Q_strncpyz(text, TTY_con.buffer + 1, sizeof(text)); } else if (TTY_con.cursor) { Com_sprintf(text, sizeof(text), "cmd say %s", TTY_con.buffer); } else { text[0] = '\0'; } // push it in history Hist_Add(&TTY_con); CON_Hide(); Com_Printf("%s%s\n", TTY_CONSOLE_PROMPT, TTY_con.buffer); Field_Clear(&TTY_con); CON_Show(); #else // push it in history Hist_Add(&TTY_con); Q_strncpyz(text, TTY_con.buffer, sizeof(text)); Field_Clear(&TTY_con); key = '\n'; size = write(STDOUT_FILENO, &key, 1); size = write(STDOUT_FILENO, TTY_CONSOLE_PROMPT, strlen(TTY_CONSOLE_PROMPT)); #endif return text; } if(key == '\t') { CON_Hide(); Field_AutoComplete(&TTY_con); CON_Show(); return NULL; } avail = read(STDIN_FILENO, &key, 1); if(avail != -1) { // VT 100 keys if(key == '[' || key == 'O') { avail = read(STDIN_FILENO, &key, 1); if(avail != -1) { switch (key) { case 'A': history = Hist_Prev(); if(history) { CON_Hide(); TTY_con = *history; CON_Show(); } CON_FlushIn(); return NULL; break; case 'B': history = Hist_Next(); CON_Hide(); if(history) { TTY_con = *history; } else { Field_Clear(&TTY_con); } CON_Show(); CON_FlushIn(); return NULL; break; case 'C': return NULL; case 'D': return NULL; } } } } Com_DPrintf("droping ISCTL sequence: %d, TTY_erase: %d\n", key, TTY_erase); CON_FlushIn(); return NULL; } if(TTY_con.cursor >= sizeof(text) - 1) return NULL; // push regular character TTY_con.buffer[TTY_con.cursor] = key; TTY_con.cursor++; // next char will always be '\0' // print the current line (this is differential) size = write(STDOUT_FILENO, &key, 1); } return NULL; } else if(stdin_active) { int len; fd_set fdset; struct timeval timeout; FD_ZERO(&fdset); FD_SET(STDIN_FILENO, &fdset); // stdin timeout.tv_sec = 0; timeout.tv_usec = 0; if(select(STDIN_FILENO + 1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(STDIN_FILENO, &fdset)) return NULL; len = read(STDIN_FILENO, text, sizeof(text)); if(len == 0) { // eof! stdin_active = qfalse; return NULL; } if(len < 1) return NULL; text[len - 1] = 0; // rip off the /n and terminate return text; } return NULL; }
static LRESULT CALLBACK InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ) { case WM_KILLFOCUS: if ( ( HWND ) wParam == s_wcd.hWnd || ( HWND ) wParam == s_wcd.hwndErrorBox ) { SetFocus( hWnd ); return 0; } break; case WM_CHAR: GetWindowText( s_wcd.hwndInputLine, s_wcd.g_consoleField.buffer, sizeof( s_wcd.g_consoleField.buffer ) ); SendMessage( s_wcd.hwndInputLine, EM_GETSEL, (WPARAM) NULL, (LPARAM) &s_wcd.g_consoleField.cursor ); if ( wParam == VK_RETURN ) { strncat( s_wcd.consoleText, s_wcd.g_consoleField.buffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 ); strcat( s_wcd.consoleText, "\n" ); SetWindowText( s_wcd.hwndInputLine, "" ); Sys_Print( va( "%c%s\n", CONSOLE_PROMPT_CHAR, s_wcd.g_consoleField.buffer ) ); // empty lines just scroll the console without adding to history if ( !s_wcd.g_consoleField.buffer[0] ) return 0; // copy line to history buffer s_wcd.historyEditLines[s_wcd.nextHistoryLine % COMMAND_HISTORY] = s_wcd.g_consoleField; s_wcd.nextHistoryLine++; s_wcd.historyLine = s_wcd.nextHistoryLine; Field_Clear( &s_wcd.g_consoleField ); s_wcd.g_consoleField.widthInChars = g_console_field_width; return 0; } if ( wParam == VK_TAB ) { Field_AutoComplete( &s_wcd.g_consoleField ); SetWindowText( s_wcd.hwndInputLine, s_wcd.g_consoleField.buffer ); SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.g_consoleField.cursor, s_wcd.g_consoleField.cursor ); return 0; } break; case WM_KEYDOWN: // history scrolling if ( wParam == VK_UP ) {// scroll up: arrow-up if ( s_wcd.nextHistoryLine - s_wcd.historyLine < COMMAND_HISTORY && s_wcd.historyLine > 0 ) s_wcd.historyLine--; s_wcd.g_consoleField = s_wcd.historyEditLines[s_wcd.historyLine % COMMAND_HISTORY]; SetWindowText( s_wcd.hwndInputLine, s_wcd.g_consoleField.buffer ); SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.g_consoleField.cursor, s_wcd.g_consoleField.cursor ); return 0; } if ( wParam == VK_DOWN ) {// scroll down: arrow-down s_wcd.historyLine++; if (s_wcd.historyLine >= s_wcd.nextHistoryLine) { s_wcd.historyLine = s_wcd.nextHistoryLine; Field_Clear( &s_wcd.g_consoleField ); s_wcd.g_consoleField.widthInChars = g_console_field_width; SetWindowText( s_wcd.hwndInputLine, s_wcd.g_consoleField.buffer ); SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.g_consoleField.cursor, s_wcd.g_consoleField.cursor ); return 0; } s_wcd.g_consoleField = s_wcd.historyEditLines[s_wcd.historyLine % COMMAND_HISTORY]; SetWindowText( s_wcd.hwndInputLine, s_wcd.g_consoleField.buffer ); SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.g_consoleField.cursor, s_wcd.g_consoleField.cursor ); return 0; } break; } return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam ); }
//FIXME utf8 input char *CON_Input( void ) { INPUT_RECORD buff[ MAX_EDIT_LINE ]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if( !GetNumberOfConsoleInputEvents( qconsole_hin, &events ) ) return NULL; if( events < 1 ) return NULL; // if we have overflowed, start dropping oldest input events if( events >= MAX_EDIT_LINE ) { ReadConsoleInput( qconsole_hin, buff, 1, &events ); return NULL; } if( !ReadConsoleInput( qconsole_hin, buff, events, &count ) ) return NULL; FlushConsoleInputBuffer( qconsole_hin ); for( i = 0; i < count; i++ ) { if( buff[ i ].EventType != KEY_EVENT ) continue; if( !buff[ i ].Event.KeyEvent.bKeyDown ) continue; key = buff[ i ].Event.KeyEvent.wVirtualKeyCode; if( key == VK_RETURN ) { newlinepos = i; qconsole_cursor = 0; break; } else if( key == VK_UP ) { CON_HistPrev(); break; } else if( key == VK_DOWN ) { CON_HistNext(); break; } else if( key == VK_LEFT ) { qconsole_cursor--; if ( qconsole_cursor < 0 ) { qconsole_cursor = 0; } break; } else if( key == VK_RIGHT ) { qconsole_cursor++; if ( qconsole_cursor > qconsole_linelen ) { qconsole_cursor = qconsole_linelen; } break; } else if( key == VK_HOME ) { qconsole_cursor = 0; break; } else if( key == VK_END ) { qconsole_cursor = qconsole_linelen; break; } else if( key == VK_TAB ) { field_t f; const char *fieldString; //Q_strncpyz( f.buffer, qconsole_line, sizeof( f.buffer ) ); Field_SetBuffer(&f, qconsole_line, sizeof(qconsole_line), 0); Field_AutoComplete( &f ); //Q_strncpyz( qconsole_line, f.buffer, sizeof( qconsole_line ) ); fieldString = Field_AsStr(&f, 0, 0); Q_strncpyz(qconsole_line, fieldString, sizeof(qconsole_line)); qconsole_linelen = strlen( qconsole_line ); qconsole_cursor = qconsole_linelen; break; } if( qconsole_linelen < sizeof( qconsole_line ) - 1 ) { char c = buff[ i ].Event.KeyEvent.uChar.AsciiChar; if( key == VK_BACK ) { if ( qconsole_cursor > 0 ) { int newlen = ( qconsole_linelen > 0 ) ? qconsole_linelen - 1 : 0; if ( qconsole_cursor < qconsole_linelen ) { memmove( qconsole_line + qconsole_cursor - 1, qconsole_line + qconsole_cursor, qconsole_linelen - qconsole_cursor ); } qconsole_line[ newlen ] = '\0'; qconsole_linelen = newlen; qconsole_cursor--; } } else if( c ) { if ( qconsole_linelen > qconsole_cursor ) { memmove( qconsole_line + qconsole_cursor + 1, qconsole_line + qconsole_cursor, qconsole_linelen - qconsole_cursor ); } qconsole_line[ qconsole_cursor++ ] = c; qconsole_linelen++; qconsole_line[ qconsole_linelen ] = '\0'; } } } if( newlinepos < 0) { CON_Show(); return NULL; } if( !qconsole_linelen ) { CON_Show(); Com_Printf( "\n" ); return NULL; } qconsole_linelen = 0; CON_Show(); CON_HistAdd(); Com_Printf( "%s\n", qconsole_line ); return qconsole_line; }
/* ==================== Console_Key Handles history and console scrollback ==================== */ void Console_Key (int key) { // ctrl-L clears screen if ( key == 'l' && keys[K_CTRL].down ) { Cbuf_AddText ("clear\n"); return; } // enter finishes the line if ( key == K_ENTER || key == K_KP_ENTER ) { // if not in the game explicitly prepend a slash if needed if ( cls.state != CA_ACTIVE && g_consoleField.buffer[0] != '\0' && g_consoleField.buffer[0] != '\\' && g_consoleField.buffer[0] != '/' ) { char temp[MAX_EDIT_LINE-1]; Q_strncpyz( temp, g_consoleField.buffer, sizeof( temp ) ); Com_sprintf( g_consoleField.buffer, sizeof( g_consoleField.buffer ), "\\%s", temp ); g_consoleField.cursor++; } Com_Printf ( "]%s\n", g_consoleField.buffer ); // leading slash is an explicit command if ( g_consoleField.buffer[0] == '\\' || g_consoleField.buffer[0] == '/' ) { Cbuf_AddText( g_consoleField.buffer+1 ); // valid command Cbuf_AddText ("\n"); } else { // other text will be chat messages if ( !g_consoleField.buffer[0] ) { return; // empty lines just scroll the console without adding to history } else { Cbuf_AddText ("cmd say "); Cbuf_AddText( g_consoleField.buffer ); Cbuf_AddText ("\n"); } } // copy line to history buffer Con_SaveField( &g_consoleField ); Field_Clear( &g_consoleField ); g_consoleField.widthInChars = g_console_field_width; if ( cls.state == CA_DISCONNECTED ) { SCR_UpdateScreen (); // force an update, because the command } // may take some time return; } // command completion if (key == K_TAB) { Field_AutoComplete(&g_consoleField); return; } // command history (ctrl-p ctrl-n for unix style) if ( (key == K_MWHEELUP && keys[K_SHIFT].down) || ( key == K_UPARROW ) || ( key == K_KP_UPARROW ) || ( ( tolower(key) == 'p' ) && keys[K_CTRL].down ) ) { Con_HistoryGetPrev( &g_consoleField ); g_consoleField.widthInChars = g_console_field_width; return; } if ( (key == K_MWHEELDOWN && keys[K_SHIFT].down) || ( key == K_DOWNARROW ) || ( key == K_KP_DOWNARROW ) || ( ( tolower(key) == 'n' ) && keys[K_CTRL].down ) ) { Con_HistoryGetNext( &g_consoleField ); g_consoleField.widthInChars = g_console_field_width; return; } // console scrolling if ( key == K_PGUP ) { if ( keys[K_CTRL].down ) { // hold <ctrl> to accelerate scrolling Con_PageUp( 0 ); // by one visible page } else { Con_PageUp( 1 ); } return; } if ( key == K_PGDN ) { if ( keys[K_CTRL].down ) { // hold <ctrl> to accelerate scrolling Con_PageDown( 0 ); // by one visible page } else { Con_PageDown( 1 ); } return; } if ( key == K_MWHEELUP ) { //----(SA) added some mousewheel functionality to the console if ( keys[K_CTRL].down ) { // hold <ctrl> to accelerate scrolling Con_PageUp( 4 ); } else { Con_PageUp( 1 ); } return; } if ( key == K_MWHEELDOWN ) { //----(SA) added some mousewheel functionality to the console if ( keys[K_CTRL].down ) { // hold <ctrl> to accelerate scrolling Con_PageDown( 4 ); } else { Con_PageDown( 1 ); } return; } // ctrl-home = top of console if ( key == K_HOME && keys[K_CTRL].down ) { Con_Top(); return; } // ctrl-end = bottom of console if ( key == K_END && keys[K_CTRL].down ) { Con_Bottom(); return; } // pass to the normal editline routine Field_KeyDownEvent( &g_consoleField, key ); }
LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { char inputBuffer[1024]; switch ( uMsg ) { case WM_KILLFOCUS: if ( ( HWND ) wParam == s_wcd.hWnd || ( HWND ) wParam == s_wcd.hwndErrorBox ) { SetFocus( hWnd ); return 0; } break; case WM_CHAR: if ( wParam == 13 ) { GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) ); strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 ); strcat( s_wcd.consoleText, "\n" ); SetWindowText( s_wcd.hwndInputLine, "" ); Sys_Print( va( "]%s\n", inputBuffer ) ); strcpy(g_consoleField.buffer, inputBuffer); historyEditLines[nextHistoryLine % COMMAND_HISTORY] = g_consoleField; nextHistoryLine++; historyLine = nextHistoryLine; return 0; } else if (wParam == 9 ) { GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) ); strcpy(g_consoleField.buffer, inputBuffer); Field_AutoComplete( &g_consoleField ); SetWindowText( s_wcd.hwndInputLine, g_consoleField.buffer); SendMessage(s_wcd.hwndInputLine, EM_SETSEL, strlen(g_consoleField.buffer) , MAKELONG(0xffff, 0xffff) ); } break; case WM_KEYDOWN: if (wParam == VK_UP) { if ( nextHistoryLine - historyLine < COMMAND_HISTORY && historyLine > 0 ) { historyLine--; } g_consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ]; SetWindowText( s_wcd.hwndInputLine, g_consoleField.buffer); SendMessage(s_wcd.hwndInputLine, EM_SETSEL, strlen(g_consoleField.buffer) , MAKELONG(0xffff, 0xffff) ); return 0; } else if (wParam == VK_DOWN) { if (historyLine == nextHistoryLine) { return 0; } historyLine++; g_consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ]; SetWindowText( s_wcd.hwndInputLine, g_consoleField.buffer); SendMessage(s_wcd.hwndInputLine, EM_SETSEL, strlen(g_consoleField.buffer) , MAKELONG(0xffff, 0xffff) ); return 0; } break; } return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam ); }
/* ================== CON_Input ================== */ char *CON_Input(void) { int chr, num_chars = 0; static char text[MAX_EDIT_LINE]; static int lasttime = -1; if (!curses_on) return CON_Input_tty(); if (com_ansiColor->modified) { CON_Resize(); com_ansiColor->modified = qfalse; } if (Com_RealTime(NULL) != lasttime) { lasttime = Com_RealTime(NULL); CON_UpdateClock(); num_chars++; } while (1) { chr = getch(); num_chars++; // Special characters switch (chr) { case ERR: if (num_chars > 1) { werase(inputwin); if (input_field.cursor < input_field.scroll) { input_field.scroll = input_field.cursor - INPUT_SCROLL; if (input_field.scroll < 0) input_field.scroll = 0; } else if (input_field.cursor >= input_field.scroll + input_field.widthInChars) input_field.scroll = input_field.cursor - input_field.widthInChars + INPUT_SCROLL; CON_ColorPrint(inputwin, input_field.buffer + input_field.scroll, qfalse); #ifdef _WIN32 wrefresh(inputwin); // If this is not done the cursor moves strangely #else wnoutrefresh(inputwin); #endif CON_UpdateCursor(); doupdate(); } return NULL; case '\n': case '\r': case KEY_ENTER: if (!input_field.buffer[0]) continue; Hist_Add(input_field.buffer); strcpy(text, input_field.buffer); Field_Clear(&input_field); werase(inputwin); wnoutrefresh(inputwin); CON_UpdateCursor(); //doupdate(); Com_Printf(PROMPT "^7%s\n", text); return text; case '\t': case KEY_STAB: Field_AutoComplete(&input_field, PROMPT); input_field.cursor = strlen(input_field.buffer); continue; case '\f': CON_Resize(); continue; case KEY_LEFT: if (input_field.cursor > 0) input_field.cursor--; continue; case KEY_RIGHT: if (input_field.cursor < strlen(input_field.buffer)) input_field.cursor++; continue; case KEY_UP: Q_strncpyz(input_field.buffer, Hist_Prev(), sizeof(input_field.buffer)); input_field.cursor = strlen(input_field.buffer); continue; case KEY_DOWN: Q_strncpyz(input_field.buffer, Hist_Next(input_field.buffer), sizeof(input_field.buffer)); input_field.cursor = strlen(input_field.buffer); continue; case KEY_HOME: input_field.cursor = 0; continue; case KEY_END: input_field.cursor = strlen(input_field.buffer); continue; case KEY_NPAGE: if (lastline > scrollline + LOG_LINES) { scrollline += LOG_SCROLL; if (scrollline + LOG_LINES > lastline) scrollline = lastline - LOG_LINES; pnoutrefresh(logwin, scrollline, 0, 2, 1, LOG_LINES + 1, LOG_COLS + 1); CON_DrawScrollBar(); } continue; case KEY_PPAGE: if (scrollline > 0) { scrollline -= LOG_SCROLL; if (scrollline < 0) scrollline = 0; pnoutrefresh(logwin, scrollline, 0, 2, 1, LOG_LINES + 1, LOG_COLS + 1); CON_DrawScrollBar(); } continue; case '\b': case 127: case KEY_BACKSPACE: if (input_field.cursor <= 0) continue; input_field.cursor--; // Fall through case KEY_DC: if (input_field.cursor < strlen(input_field.buffer)) { memmove(input_field.buffer + input_field.cursor, input_field.buffer + input_field.cursor + 1, strlen(input_field.buffer) - input_field.cursor); } continue; } // Normal characters if (chr >= ' ' && chr < 256 && strlen(input_field.buffer) + 1 < sizeof(input_field.buffer)) { memmove(input_field.buffer + input_field.cursor + 1, input_field.buffer + input_field.cursor, strlen(input_field.buffer) - input_field.cursor); input_field.buffer[input_field.cursor] = chr; input_field.cursor++; } } }
/* ================== CON_Input ================== */ char *CON_Input( void ) { // we use this when sending back commands static char text[MAX_EDIT_LINE]; int avail; char key; if(ttycon_on) { CON_CheckRep(); avail = read(STDIN_FILENO, &key, 1); if (avail != -1) { // we have something // disable hibernation for ten seconds to workaround console input lagg svs.hibernation.disableUntil = svs.time + 10000; // backspace? // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere if ((key == TTY_erase) || (key == 127) || (key == 8)) { if (TTY_con.cursor > 0) { TTY_con.cursor--; TTY_con.buffer[TTY_con.cursor] = '\0'; CON_Back(); } return NULL; } // check if this is a control char if ((key) && (key) < ' ') { if (key == '\n') { #ifndef DEDICATED if (TTY_con.buffer[0] == '/' || TTY_con.buffer[0] == '\\') { Q_strncpyz(text, TTY_con.buffer + 1, sizeof(text)); } else if (TTY_con.cursor) { Q_strncpyz(text, TTY_con.buffer, sizeof(text)); } else { text[0] = '\0'; } // push it in history Hist_Add(); CON_Hide(); Com_Printf("%s%s\n", TTY_CONSOLE_PROMPT, TTY_con.buffer); Field_Clear(&TTY_con); CON_Show(); #else // push it in history Hist_Add(); Q_strncpyz(text, TTY_con.buffer, sizeof(text)); Field_Clear(&TTY_con); key = '\n'; write(STDOUT_FILENO, &key, 1); write(STDOUT_FILENO, TTY_CONSOLE_PROMPT, strlen(TTY_CONSOLE_PROMPT)); #endif return text; } if (key == '\t') { CON_Hide(); Field_AutoComplete( &TTY_con ); CON_Show(); return NULL; } avail = read(STDIN_FILENO, &key, 1); if (avail != -1) { // VT 100 keys if (key == '[' || key == 'O') { avail = read(STDIN_FILENO, &key, 1); if (avail != -1) { switch (key) { case 'A': Hist_Prev(); CON_FlushIn(); return NULL; break; case 'B': Hist_Next(); CON_FlushIn(); return NULL; break; case 'C': return NULL; case 'D': return NULL; } } } } Com_DPrintf("droping ISCTL sequence: %d, TTY_erase: %d\n", key, TTY_erase); CON_FlushIn(); return NULL; } if (TTY_con.cursor >= (int)sizeof(text) - 1) return NULL; // push regular character TTY_con.buffer[TTY_con.cursor] = key; TTY_con.cursor++; // next char will always be '\0' // print the current line (this is differential) write(STDOUT_FILENO, &key, 1); } return NULL; } else if (stdin_active) { int len; fd_set fdset; struct timeval timeout; FD_ZERO(&fdset); FD_SET(STDIN_FILENO, &fdset); // stdin timeout.tv_sec = 0; timeout.tv_usec = 0; if(select (STDIN_FILENO + 1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(STDIN_FILENO, &fdset)) return NULL; len = read(STDIN_FILENO, text, sizeof(text)); if (len == 0) { // eof! stdin_active = qfalse; return NULL; } if (len < 1) return NULL; text[len-1] = 0; // rip off the /n and terminate return text; } return NULL; }