/* ==================== Console_Key Handles history and console scrollback ==================== */ void Console_Key ( int key, qboolean down ) { if ( !down ) { return; } if ( key & K_CHAR_FLAG ) { key &= ~K_CHAR_FLAG; MField_CharEvent( &g_consoleField, key ); return; } // ctrl-L clears screen if ( key == 'l' && trap_Key_IsDown( K_CTRL ) ) { trap_Cmd_ExecuteText( EXEC_APPEND, "clear\n" ); return; } // enter finishes the line if ( key == K_ENTER || key == K_KP_ENTER ) { uiClientState_t cls; trap_GetClientState( &cls ); // if not in the game explicitly prepend a slash if needed if ( cls.connState != CA_ACTIVE && con_autochat.integer && g_consoleField.buffer[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] == '/' ) { trap_Cmd_ExecuteText( EXEC_APPEND, g_consoleField.buffer+1 ); // valid command trap_Cmd_ExecuteText( EXEC_APPEND, "\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 { if ( con_autochat.integer ) { trap_Cmd_ExecuteText( EXEC_APPEND, "cmd say " ); } trap_Cmd_ExecuteText( EXEC_APPEND, g_consoleField.buffer ); trap_Cmd_ExecuteText( EXEC_APPEND, "\n" ); } } // copy line to history buffer historyEditLines[nextHistoryLine % COMMAND_HISTORY] = g_consoleField; nextHistoryLine++; historyLine = nextHistoryLine; MField_Clear( &g_consoleField ); g_consoleField.widthInChars = g_console_field_width; CG_SaveConsoleHistory( ); if ( cls.connState == CA_DISCONNECTED ) { trap_UpdateScreen(); // force an update, because the command } // may take some time return; } // command completion if (key == K_TAB) { char newbuf[MAX_EDIT_LINE]; trap_Cmd_AutoComplete( g_consoleField.buffer, newbuf, sizeof ( newbuf ) ); if ( strcmp( newbuf, g_consoleField.buffer ) != 0 ) { Q_strncpyz( g_consoleField.buffer, newbuf, sizeof ( g_consoleField.buffer ) ); g_consoleField.cursor = strlen( g_consoleField.buffer ); } return; } // command history (ctrl-p ctrl-n for unix style) if ( ( key == K_MWHEELUP && trap_Key_IsDown( K_SHIFT ) ) || ( key == K_UPARROW ) || ( key == K_KP_UPARROW ) || ( ( tolower(key) == 'p' ) && trap_Key_IsDown( K_CTRL ) ) ) { if ( nextHistoryLine - historyLine < COMMAND_HISTORY && historyLine > 0 ) { historyLine--; } g_consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ]; return; } if ( ( key == K_MWHEELDOWN && trap_Key_IsDown( K_SHIFT ) ) || ( key == K_DOWNARROW ) || ( key == K_KP_DOWNARROW ) || ( ( tolower(key) == 'n' ) && trap_Key_IsDown( K_CTRL ) ) ) { historyLine++; if (historyLine >= nextHistoryLine) { historyLine = nextHistoryLine; MField_Clear( &g_consoleField ); g_consoleField.widthInChars = g_console_field_width; return; } g_consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ]; return; } // console scrolling if ( key == K_PGUP || key == K_KP_PGUP ) { Con_PageUp(); return; } if ( key == K_PGDN || key == K_KP_PGDN ) { Con_PageDown(); return; } if ( key == K_MWHEELUP) { //----(SA) added some mousewheel functionality to the console Con_PageUp(); if ( trap_Key_IsDown( K_CTRL ) ) { // hold <ctrl> to accelerate scrolling Con_PageUp(); Con_PageUp(); } return; } if ( key == K_MWHEELDOWN) { //----(SA) added some mousewheel functionality to the console Con_PageDown(); if ( trap_Key_IsDown( K_CTRL ) ) { // hold <ctrl> to accelerate scrolling Con_PageDown(); Con_PageDown(); } return; } // ctrl-home = top of console if ( ( key == K_HOME || key == K_KP_HOME ) && trap_Key_IsDown( K_CTRL ) ) { Con_Top(); return; } // ctrl-end = bottom of console if ( ( key == K_END || key == K_KP_END ) && trap_Key_IsDown( K_CTRL ) ) { Con_Bottom(); return; } // pass to the normal editline routine MField_KeyDownEvent( &g_consoleField, key ); }
/* ================= MField_KeyDownEvent Performs the basic line editing functions for the console, in-game talk, and menu fields Key events are used for non-printable characters, others are gotten from char events. ================= */ void MField_KeyDownEvent( mfield_t *edit, int key ) { // shift-insert is paste if ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && trap_Key_IsDown( K_SHIFT ) ) { MField_Paste( edit ); return; } if ( key == K_DEL || key == K_KP_DEL ) { int i; if ( edit->cursor < edit->len ) { for ( i = edit->cursor; i < edit->len; i++ ) { edit->buffer[i] = edit->buffer[i+1]; } edit->len--; } return; } if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW ) { if ( edit->cursor < edit->len ) { edit->cursor++; } if ( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= edit->len ) { edit->scroll++; } return; } if ( key == K_LEFTARROW || key == K_KP_LEFTARROW ) { if ( edit->cursor > 0 ) { edit->cursor--; } if ( edit->cursor < edit->scroll ) { edit->scroll--; } return; } if ( key == K_HOME || key == K_KP_HOME || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) { edit->cursor = 0; edit->scroll = 0; return; } if ( key == K_END || key == K_KP_END || ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) { edit->cursor = edit->len; edit->scroll = edit->len - edit->widthInChars + 1; if (edit->scroll < 0) edit->scroll = 0; return; } if ( key == K_INS || key == K_KP_INS ) { trap_Key_SetOverstrikeMode( !trap_Key_GetOverstrikeMode() ); return; } }