mirror of
https://github.com/ioquake/ioq3.git
synced 2025-05-31 09:01:54 +00:00
* Overhaul of console autocompletion
- No longer does weird stuff like move the cursor inappropriately - Autocomplete works with compound commands - Special autocomplete on some commands e.g. \map, \demo - Removed various hacks used to counter the original autocomplete code
This commit is contained in:
parent
893629fb0f
commit
c3f7915a8b
8 changed files with 340 additions and 103 deletions
|
@ -483,7 +483,7 @@ void Console_Key (int key) {
|
||||||
|
|
||||||
// enter finishes the line
|
// enter finishes the line
|
||||||
if ( key == K_ENTER || key == K_KP_ENTER ) {
|
if ( key == K_ENTER || key == K_KP_ENTER ) {
|
||||||
// if not in the game explicitly prepent a slash if needed
|
// if not in the game explicitly prepend a slash if needed
|
||||||
if ( cls.state != CA_ACTIVE && g_consoleField.buffer[0] != '\\'
|
if ( cls.state != CA_ACTIVE && g_consoleField.buffer[0] != '\\'
|
||||||
&& g_consoleField.buffer[0] != '/' ) {
|
&& g_consoleField.buffer[0] != '/' ) {
|
||||||
char temp[MAX_STRING_CHARS];
|
char temp[MAX_STRING_CHARS];
|
||||||
|
@ -528,7 +528,7 @@ void Console_Key (int key) {
|
||||||
// command completion
|
// command completion
|
||||||
|
|
||||||
if (key == K_TAB) {
|
if (key == K_TAB) {
|
||||||
Field_CompleteCommand(&g_consoleField);
|
Field_AutoComplete(&g_consoleField);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,7 +439,7 @@ will point into this temporary buffer.
|
||||||
*/
|
*/
|
||||||
// NOTE TTimo define that to track tokenization issues
|
// NOTE TTimo define that to track tokenization issues
|
||||||
//#define TKN_DBG
|
//#define TKN_DBG
|
||||||
void Cmd_TokenizeString( const char *text_in ) {
|
static void Cmd_TokenizeString2( const char *text_in, qboolean ignoreQuotes ) {
|
||||||
const char *text;
|
const char *text;
|
||||||
char *textOut;
|
char *textOut;
|
||||||
|
|
||||||
|
@ -495,7 +495,7 @@ void Cmd_TokenizeString( const char *text_in ) {
|
||||||
|
|
||||||
// handle quoted strings
|
// handle quoted strings
|
||||||
// NOTE TTimo this doesn't handle \" escaping
|
// NOTE TTimo this doesn't handle \" escaping
|
||||||
if ( *text == '"' ) {
|
if ( !ignoreQuotes && *text == '"' ) {
|
||||||
cmd_argv[cmd_argc] = textOut;
|
cmd_argv[cmd_argc] = textOut;
|
||||||
cmd_argc++;
|
cmd_argc++;
|
||||||
text++;
|
text++;
|
||||||
|
@ -516,7 +516,7 @@ void Cmd_TokenizeString( const char *text_in ) {
|
||||||
|
|
||||||
// skip until whitespace, quote, or command
|
// skip until whitespace, quote, or command
|
||||||
while ( *text > ' ' ) {
|
while ( *text > ' ' ) {
|
||||||
if ( text[0] == '"' ) {
|
if ( !ignoreQuotes && text[0] == '"' ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +541,23 @@ void Cmd_TokenizeString( const char *text_in ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
Cmd_TokenizeString
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
void Cmd_TokenizeString( const char *text_in ) {
|
||||||
|
Cmd_TokenizeString2( text_in, qfalse );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
Cmd_TokenizeStringIgnoreQuotes
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
void Cmd_TokenizeStringIgnoreQuotes( const char *text_in ) {
|
||||||
|
Cmd_TokenizeString2( text_in, qtrue );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
|
|
|
@ -2912,7 +2912,7 @@ void Field_Clear( field_t *edit ) {
|
||||||
static const char *completionString;
|
static const char *completionString;
|
||||||
static char shortestMatch[MAX_TOKEN_CHARS];
|
static char shortestMatch[MAX_TOKEN_CHARS];
|
||||||
static int matchCount;
|
static int matchCount;
|
||||||
// field we are working on, passed to Field_CompleteCommand (&g_consoleCommand for instance)
|
// field we are working on, passed to Field_AutoComplete(&g_consoleCommand for instance)
|
||||||
static field_t *completionField;
|
static field_t *completionField;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2948,11 +2948,11 @@ static void FindMatches( const char *s ) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
PrintCmdMatches
|
PrintMatches
|
||||||
|
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
static void PrintCmdMatches( const char *s ) {
|
static void PrintMatches( const char *s ) {
|
||||||
if ( !Q_stricmpn( s, shortestMatch, strlen( shortestMatch ) ) ) {
|
if ( !Q_stricmpn( s, shortestMatch, strlen( shortestMatch ) ) ) {
|
||||||
Com_Printf( " %s\n", s );
|
Com_Printf( " %s\n", s );
|
||||||
}
|
}
|
||||||
|
@ -2970,96 +2970,231 @@ static void PrintCvarMatches( const char *s ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyConcatArgs( void ) {
|
/*
|
||||||
int i;
|
===============
|
||||||
char *arg;
|
Field_FindFirstSeparator
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static char *Field_FindFirstSeparator( char *s )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
for ( i = 1 ; i < Cmd_Argc() ; i++ ) {
|
for( i = 0; i < strlen( s ); i++ )
|
||||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
{
|
||||||
arg = Cmd_Argv( i );
|
if( s[ i ] == ';' )
|
||||||
while (*arg) {
|
return &s[ i ];
|
||||||
if (*arg == ' ') {
|
|
||||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), "\"");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), Cmd_Argv( i ) );
|
|
||||||
if (*arg == ' ') {
|
|
||||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), "\"");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConcatRemaining( const char *src, const char *start ) {
|
/*
|
||||||
char *str;
|
===============
|
||||||
|
Field_CompleteFilename
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void Field_CompleteFilename( const char *dir,
|
||||||
|
const char *ext, qboolean stripExt )
|
||||||
|
{
|
||||||
|
matchCount = 0;
|
||||||
|
shortestMatch[ 0 ] = 0;
|
||||||
|
|
||||||
str = strstr(src, start);
|
FS_FilenameCompletion( dir, ext, stripExt, FindMatches );
|
||||||
if (!str) {
|
|
||||||
keyConcatArgs();
|
if( matchCount == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Q_strcat( completionField->buffer, sizeof( completionField->buffer ),
|
||||||
|
shortestMatch + strlen( completionString ) );
|
||||||
|
completionField->cursor = strlen( completionField->buffer );
|
||||||
|
|
||||||
|
if( matchCount == 1 )
|
||||||
|
{
|
||||||
|
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
||||||
|
completionField->cursor++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
str += strlen(start);
|
Com_Printf( "]%s\n", completionField->buffer );
|
||||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), str);
|
|
||||||
|
FS_FilenameCompletion( dir, ext, stripExt, PrintMatches );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
Field_CompleteCommand
|
Field_CompleteCommand
|
||||||
|
|
||||||
perform Tab expansion
|
|
||||||
NOTE TTimo this was originally client code only
|
|
||||||
moved to common code when writing tty console for *nix dedicated server
|
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
void Field_CompleteCommand( field_t *field ) {
|
static void Field_CompleteCommand( char *cmd,
|
||||||
field_t temp;
|
qboolean doCommands, qboolean doCvars )
|
||||||
|
{
|
||||||
|
int completionArgument = 0;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
// Skip leading whitespace and quotes
|
||||||
|
cmd = Com_SkipCharset( cmd, " \"" );
|
||||||
|
|
||||||
|
Cmd_TokenizeStringIgnoreQuotes( cmd );
|
||||||
|
completionArgument = Cmd_Argc( );
|
||||||
|
|
||||||
|
// If there is trailing whitespace on the cmd
|
||||||
|
if( *( cmd + strlen( cmd ) - 1 ) == ' ' )
|
||||||
|
{
|
||||||
|
completionString = "";
|
||||||
|
completionArgument++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
completionString = Cmd_Argv( completionArgument - 1 );
|
||||||
|
|
||||||
|
if( completionArgument > 1 )
|
||||||
|
{
|
||||||
|
const char *baseCmd = Cmd_Argv( 0 );
|
||||||
|
|
||||||
|
#ifndef DEDICATED
|
||||||
|
// If the very first token does not have a leading \ or /,
|
||||||
|
// refuse to autocomplete
|
||||||
|
if( cmd == completionField->buffer )
|
||||||
|
{
|
||||||
|
if( baseCmd[ 0 ] != '\\' && baseCmd[ 0 ] != '/' )
|
||||||
|
return;
|
||||||
|
|
||||||
|
baseCmd++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( ( p = Field_FindFirstSeparator( cmd ) ) )
|
||||||
|
{
|
||||||
|
// Compound command
|
||||||
|
Field_CompleteCommand( p + 1, qtrue, qtrue );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: all this junk should really be associated with the respective
|
||||||
|
// commands, instead of being hard coded here
|
||||||
|
if( ( !Q_stricmp( baseCmd, "map" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "devmap" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "spmap" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "spdevmap" ) ) &&
|
||||||
|
completionArgument == 2 )
|
||||||
|
{
|
||||||
|
Field_CompleteFilename( "maps", "bsp", qtrue );
|
||||||
|
}
|
||||||
|
else if( ( !Q_stricmp( baseCmd, "exec" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "writeconfig" ) ) &&
|
||||||
|
completionArgument == 2 )
|
||||||
|
{
|
||||||
|
Field_CompleteFilename( "", "cfg", qfalse );
|
||||||
|
}
|
||||||
|
else if( !Q_stricmp( baseCmd, "condump" ) &&
|
||||||
|
completionArgument == 2 )
|
||||||
|
{
|
||||||
|
Field_CompleteFilename( "", "txt", qfalse );
|
||||||
|
}
|
||||||
|
else if( !Q_stricmp( baseCmd, "demo" ) && completionArgument == 2 )
|
||||||
|
{
|
||||||
|
char demoExt[ 16 ];
|
||||||
|
|
||||||
|
Com_sprintf( demoExt, sizeof( demoExt ), ".dm_%d", PROTOCOL_VERSION );
|
||||||
|
Field_CompleteFilename( "demos", demoExt, qtrue );
|
||||||
|
}
|
||||||
|
else if( ( !Q_stricmp( baseCmd, "toggle" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "vstr" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "set" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "seta" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "setu" ) ||
|
||||||
|
!Q_stricmp( baseCmd, "sets" ) ) &&
|
||||||
|
completionArgument == 2 )
|
||||||
|
{
|
||||||
|
// Skip "<cmd> "
|
||||||
|
p = Com_SkipTokens( cmd, 1, " " );
|
||||||
|
|
||||||
|
if( p > cmd )
|
||||||
|
Field_CompleteCommand( p, qfalse, qtrue );
|
||||||
|
}
|
||||||
|
else if( !Q_stricmp( baseCmd, "rcon" ) && completionArgument == 2 )
|
||||||
|
{
|
||||||
|
// Skip "rcon "
|
||||||
|
p = Com_SkipTokens( cmd, 1, " " );
|
||||||
|
|
||||||
|
if( p > cmd )
|
||||||
|
Field_CompleteCommand( p, qtrue, qtrue );
|
||||||
|
}
|
||||||
|
else if( !Q_stricmp( baseCmd, "bind" ) && completionArgument >= 3 )
|
||||||
|
{
|
||||||
|
// Skip "bind <key> "
|
||||||
|
p = Com_SkipTokens( cmd, 2, " " );
|
||||||
|
|
||||||
|
if( p > cmd )
|
||||||
|
Field_CompleteCommand( p, qtrue, qtrue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( completionString[0] == '\\' || completionString[0] == '/' )
|
||||||
|
completionString++;
|
||||||
|
|
||||||
|
matchCount = 0;
|
||||||
|
shortestMatch[ 0 ] = 0;
|
||||||
|
|
||||||
|
if( strlen( completionString ) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( doCommands )
|
||||||
|
Cmd_CommandCompletion( FindMatches );
|
||||||
|
|
||||||
|
if( doCvars )
|
||||||
|
Cvar_CommandCompletion( FindMatches );
|
||||||
|
|
||||||
|
if( matchCount == 0 )
|
||||||
|
return; // no matches
|
||||||
|
|
||||||
|
if( cmd == completionField->buffer )
|
||||||
|
{
|
||||||
|
#ifndef DEDICATED
|
||||||
|
Com_sprintf( completionField->buffer,
|
||||||
|
sizeof( completionField->buffer ), "\\%s", shortestMatch );
|
||||||
|
#else
|
||||||
|
Com_sprintf( completionField->buffer,
|
||||||
|
sizeof( completionField->buffer ), "%s", shortestMatch );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_strcat( completionField->buffer, sizeof( completionField->buffer ),
|
||||||
|
shortestMatch + strlen( completionString ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
completionField->cursor = strlen( completionField->buffer );
|
||||||
|
|
||||||
|
if( matchCount == 1 )
|
||||||
|
{
|
||||||
|
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
||||||
|
completionField->cursor++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Printf( "]%s\n", completionField->buffer );
|
||||||
|
|
||||||
|
// run through again, printing matches
|
||||||
|
if( doCommands )
|
||||||
|
Cmd_CommandCompletion( PrintMatches );
|
||||||
|
|
||||||
|
if( doCvars )
|
||||||
|
Cvar_CommandCompletion( PrintCvarMatches );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
Field_AutoComplete
|
||||||
|
|
||||||
|
Perform Tab expansion
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void Field_AutoComplete( field_t *field )
|
||||||
|
{
|
||||||
completionField = field;
|
completionField = field;
|
||||||
|
|
||||||
// only look at the first token for completion purposes
|
Field_CompleteCommand( completionField->buffer, qtrue, qtrue );
|
||||||
Cmd_TokenizeString( completionField->buffer );
|
|
||||||
|
|
||||||
completionString = Cmd_Argv(0);
|
|
||||||
if ( completionString[0] == '\\' || completionString[0] == '/' ) {
|
|
||||||
completionString++;
|
|
||||||
}
|
|
||||||
matchCount = 0;
|
|
||||||
shortestMatch[0] = 0;
|
|
||||||
|
|
||||||
if ( strlen( completionString ) == 0 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cmd_CommandCompletion( FindMatches );
|
|
||||||
Cvar_CommandCompletion( FindMatches );
|
|
||||||
|
|
||||||
if ( matchCount == 0 ) {
|
|
||||||
return; // no matches
|
|
||||||
}
|
|
||||||
|
|
||||||
Com_Memcpy(&temp, completionField, sizeof(field_t));
|
|
||||||
|
|
||||||
if ( matchCount == 1 ) {
|
|
||||||
Com_sprintf( completionField->buffer, sizeof( completionField->buffer ), "\\%s", shortestMatch );
|
|
||||||
if ( Cmd_Argc() == 1 ) {
|
|
||||||
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
|
||||||
} else {
|
|
||||||
ConcatRemaining( temp.buffer, completionString );
|
|
||||||
}
|
|
||||||
completionField->cursor = strlen( completionField->buffer );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// multiple matches, complete to shortest
|
|
||||||
Com_sprintf( completionField->buffer, sizeof( completionField->buffer ), "\\%s", shortestMatch );
|
|
||||||
completionField->cursor = strlen( completionField->buffer );
|
|
||||||
ConcatRemaining( temp.buffer, completionString );
|
|
||||||
|
|
||||||
Com_Printf( "]%s\n", completionField->buffer );
|
|
||||||
|
|
||||||
// run through again, printing matches
|
|
||||||
Cmd_CommandCompletion( PrintCmdMatches );
|
|
||||||
Cvar_CommandCompletion( PrintCvarMatches );
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3426,3 +3426,26 @@ void FS_Flush( fileHandle_t f ) {
|
||||||
fflush(fsh[f].handleFiles.file.o);
|
fflush(fsh[f].handleFiles.file.o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FS_FilenameCompletion( const char *dir, const char *ext,
|
||||||
|
qboolean stripExt, void(*callback)(const char *s) ) {
|
||||||
|
char **filenames;
|
||||||
|
int nfiles;
|
||||||
|
int i;
|
||||||
|
char filename[ MAX_STRING_CHARS ];
|
||||||
|
|
||||||
|
filenames = FS_ListFilteredFiles( dir, ext, NULL, &nfiles );
|
||||||
|
|
||||||
|
FS_SortFileList( filenames, nfiles );
|
||||||
|
|
||||||
|
for( i = 0; i < nfiles; i++ ) {
|
||||||
|
FS_ConvertPath( filenames[ i ] );
|
||||||
|
Q_strncpyz( filename, filenames[ i ], MAX_STRING_CHARS );
|
||||||
|
|
||||||
|
if( stripExt ) {
|
||||||
|
COM_StripExtension( filename, filename );
|
||||||
|
}
|
||||||
|
|
||||||
|
callback( filename );
|
||||||
|
}
|
||||||
|
FS_FreeFileList( filenames );
|
||||||
|
}
|
||||||
|
|
|
@ -59,10 +59,19 @@ COM_StripExtension
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void COM_StripExtension( const char *in, char *out ) {
|
void COM_StripExtension( const char *in, char *out ) {
|
||||||
while ( *in && *in != '.' ) {
|
int length;
|
||||||
*out++ = *in++;
|
|
||||||
|
strcpy( out, in );
|
||||||
|
|
||||||
|
length = strlen(out)-1;
|
||||||
|
while (length > 0 && out[length] != '.')
|
||||||
|
{
|
||||||
|
length--;
|
||||||
|
if (out[length] == '/')
|
||||||
|
return; // no extension
|
||||||
}
|
}
|
||||||
*out = 0;
|
if (length)
|
||||||
|
out[length] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1249,4 +1258,68 @@ void Info_SetValueForKey_Big( char *s, const char *key, const char *value ) {
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
Com_CharIsOneOfCharset
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static qboolean Com_CharIsOneOfCharset( char c, char *set )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < strlen( set ); i++ )
|
||||||
|
{
|
||||||
|
if( set[ i ] == c )
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
Com_SkipCharset
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
char *Com_SkipCharset( char *s, char *sep )
|
||||||
|
{
|
||||||
|
char *p = s;
|
||||||
|
|
||||||
|
while( p )
|
||||||
|
{
|
||||||
|
if( Com_CharIsOneOfCharset( *p, sep ) )
|
||||||
|
p++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
Com_SkipTokens
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
char *Com_SkipTokens( char *s, int numTokens, char *sep )
|
||||||
|
{
|
||||||
|
int sepCount = 0;
|
||||||
|
char *p = s;
|
||||||
|
|
||||||
|
while( sepCount < numTokens )
|
||||||
|
{
|
||||||
|
if( Com_CharIsOneOfCharset( *p++, sep ) )
|
||||||
|
{
|
||||||
|
sepCount++;
|
||||||
|
while( Com_CharIsOneOfCharset( *p, sep ) )
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if( *p == '\0' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sepCount == numTokens )
|
||||||
|
return p;
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
|
@ -610,6 +610,8 @@ void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m);
|
||||||
|
|
||||||
void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
|
void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
|
||||||
|
|
||||||
|
char *Com_SkipTokens( char *s, int numTokens, char *sep );
|
||||||
|
char *Com_SkipCharset( char *s, char *sep );
|
||||||
|
|
||||||
// mode parm for FS_FOpenFile
|
// mode parm for FS_FOpenFile
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -415,6 +415,7 @@ char *Cmd_Cmd (void);
|
||||||
// if arg > argc, so string operations are allways safe.
|
// if arg > argc, so string operations are allways safe.
|
||||||
|
|
||||||
void Cmd_TokenizeString( const char *text );
|
void Cmd_TokenizeString( const char *text );
|
||||||
|
void Cmd_TokenizeStringIgnoreQuotes( const char *text_in );
|
||||||
// Takes a null terminated string. Does not need to be /n terminated.
|
// Takes a null terminated string. Does not need to be /n terminated.
|
||||||
// breaks the string up into arg tokens.
|
// breaks the string up into arg tokens.
|
||||||
|
|
||||||
|
@ -657,6 +658,8 @@ void FS_Rename( const char *from, const char *to );
|
||||||
void FS_Remove( const char *osPath );
|
void FS_Remove( const char *osPath );
|
||||||
void FS_HomeRemove( const char *homePath );
|
void FS_HomeRemove( const char *homePath );
|
||||||
|
|
||||||
|
void FS_FilenameCompletion( const char *dir, const char *ext,
|
||||||
|
qboolean stripExt, void(*callback)(const char *s) );
|
||||||
/*
|
/*
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
|
@ -674,7 +677,7 @@ typedef struct {
|
||||||
} field_t;
|
} field_t;
|
||||||
|
|
||||||
void Field_Clear( field_t *edit );
|
void Field_Clear( field_t *edit );
|
||||||
void Field_CompleteCommand( field_t *edit );
|
void Field_AutoComplete( field_t *edit );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
|
@ -549,7 +549,6 @@ char *Sys_ConsoleInput(void)
|
||||||
{
|
{
|
||||||
// we use this when sending back commands
|
// we use this when sending back commands
|
||||||
static char text[256];
|
static char text[256];
|
||||||
int i;
|
|
||||||
int avail;
|
int avail;
|
||||||
char key;
|
char key;
|
||||||
field_t *history;
|
field_t *history;
|
||||||
|
@ -588,22 +587,7 @@ char *Sys_ConsoleInput(void)
|
||||||
if (key == '\t')
|
if (key == '\t')
|
||||||
{
|
{
|
||||||
tty_Hide();
|
tty_Hide();
|
||||||
Field_CompleteCommand( &tty_con );
|
Field_AutoComplete( &tty_con );
|
||||||
// Field_CompleteCommand does weird things to the string, do a cleanup
|
|
||||||
// it adds a '\' at the beginning of the string
|
|
||||||
// cursor doesn't reflect actual length of the string that's sent back
|
|
||||||
tty_con.cursor = strlen(tty_con.buffer);
|
|
||||||
if (tty_con.cursor>0)
|
|
||||||
{
|
|
||||||
if (tty_con.buffer[0] == '\\')
|
|
||||||
{
|
|
||||||
for (i=0; i<=tty_con.cursor; i++)
|
|
||||||
{
|
|
||||||
tty_con.buffer[i] = tty_con.buffer[i+1];
|
|
||||||
}
|
|
||||||
tty_con.cursor--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tty_Show();
|
tty_Show();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue