//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; }
/* ================== 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) { //FIXME utf8 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'; TTY_con.xbuffer[TTY_con.cursor].codePoint = '\0'; TTY_con.xbuffer[TTY_con.cursor].numUtf8Bytes = 1; TTY_con.xbuffer[TTY_con.cursor].utf8Bytes[0] = '\0'; CON_Back(); } return NULL; } // check if this is a control char if ((key) && (key) < ' ') { if (key == '\n') { const char *fieldString; // push it in history Hist_Add(&TTY_con); //Q_strncpyz(text, TTY_con.buffer, sizeof(text)); fieldString = Field_AsStr(&TTY_con, 0, 0); Q_strncpyz(text, fieldString, sizeof(text)); Field_Clear(&TTY_con); key = '\n'; size = write(STDOUT_FILENO, &key, 1); size = write(STDOUT_FILENO, "]", 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; //FIXME utf8 // push regular character //TTY_con.buffer[TTY_con.cursor] = key; TTY_con.xbuffer[TTY_con.cursor].codePoint = key; TTY_con.xbuffer[TTY_con.cursor].utf8Bytes[0] = key; TTY_con.xbuffer[TTY_con.cursor].numUtf8Bytes = 0; 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; }