|
|
@ -25,6 +25,7 @@ extern convar_t *con_gamemaps; |
|
|
|
typedef struct autocomplete_list_s |
|
|
|
typedef struct autocomplete_list_s |
|
|
|
{ |
|
|
|
{ |
|
|
|
const char *name; |
|
|
|
const char *name; |
|
|
|
|
|
|
|
int arg; // argument number to handle
|
|
|
|
qboolean (*func)( const char *s, char *name, int length ); |
|
|
|
qboolean (*func)( const char *s, char *name, int length ); |
|
|
|
} autocomplete_list_t; |
|
|
|
} autocomplete_list_t; |
|
|
|
|
|
|
|
|
|
|
@ -528,7 +529,137 @@ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length ) |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
===================================== |
|
|
|
|
|
|
|
Cmd_GetKeysList |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Autocomplete for bind command |
|
|
|
|
|
|
|
===================================== |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
qboolean Cmd_GetKeysList( const char *s, char *completedname, int length ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size_t i, numkeys; |
|
|
|
|
|
|
|
string keys[256]; |
|
|
|
|
|
|
|
string matchbuf; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// compare keys list with current keyword
|
|
|
|
|
|
|
|
for( i = 0, numkeys = 0; i < 255; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const char *keyname = Key_KeynumToString( i ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(( *s == '*' ) || !Q_strnicmp( keyname, s, Q_strlen( s ))) |
|
|
|
|
|
|
|
Q_strcpy( keys[numkeys++], keyname ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !numkeys ) return false; |
|
|
|
|
|
|
|
Q_strncpy( matchbuf, keys[0], sizeof( matchbuf )); |
|
|
|
|
|
|
|
if( completedname && length ) |
|
|
|
|
|
|
|
Q_strncpy( completedname, matchbuf, length ); |
|
|
|
|
|
|
|
if( numkeys == 1 ) return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < numkeys; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Q_strncpy( matchbuf, keys[i], sizeof( matchbuf )); |
|
|
|
|
|
|
|
Con_Printf( "%16s\n", matchbuf ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Con_Printf( "\n^3 %i keys found.\n", numkeys ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( completedname && length ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; matchbuf[i]; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) |
|
|
|
|
|
|
|
completedname[i] = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif // XASH_DEDICATED
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
=============== |
|
|
|
|
|
|
|
Con_AddCommandToList |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=============== |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( *s == '@' ) return; // never show system cvars or cmds
|
|
|
|
|
|
|
|
if( list->matchCount >= CON_MAXCMDS ) return; // list is full
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) ) |
|
|
|
|
|
|
|
return; // no match
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
list->cmds[list->matchCount++] = copystring( s ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
===================================== |
|
|
|
|
|
|
|
Cmd_GetCommandsList |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Autocomplete for bind command |
|
|
|
|
|
|
|
===================================== |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
string matchbuf; |
|
|
|
|
|
|
|
con_autocomplete_t list; // local autocomplete list
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset( &list, 0, sizeof( list )); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
list.completionString = s; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// skip backslash
|
|
|
|
|
|
|
|
while( *list.completionString && (*list.completionString == '\\' || *list.completionString == '/') ) |
|
|
|
|
|
|
|
list.completionString++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !Q_strlen( list.completionString ) ) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// find matching commands and variables
|
|
|
|
|
|
|
|
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList ); |
|
|
|
|
|
|
|
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !list.matchCount ) return false; |
|
|
|
|
|
|
|
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf )); |
|
|
|
|
|
|
|
if( completedname && length ) |
|
|
|
|
|
|
|
Q_strncpy( completedname, matchbuf, length ); |
|
|
|
|
|
|
|
if( list.matchCount == 1 ) return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < list.matchCount; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Q_strncpy( matchbuf, list.cmds[i], sizeof( matchbuf )); |
|
|
|
|
|
|
|
Con_Printf( "%16s\n", matchbuf ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Con_Printf( "\n^3 %i commands found.\n", list.matchCount ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( completedname && length ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; matchbuf[i]; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) |
|
|
|
|
|
|
|
completedname[i] = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < list.matchCount; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( list.cmds[i] != NULL ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Mem_Free( list.cmds[i] ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
===================================== |
|
|
|
===================================== |
|
|
@ -831,27 +962,30 @@ int Cmd_CheckMapsList( int fRefresh ) |
|
|
|
|
|
|
|
|
|
|
|
autocomplete_list_t cmd_list[] = |
|
|
|
autocomplete_list_t cmd_list[] = |
|
|
|
{ |
|
|
|
{ |
|
|
|
{ "map_background", Cmd_GetMapList }, |
|
|
|
{ "map_background", 1, Cmd_GetMapList }, |
|
|
|
{ "changelevel2", Cmd_GetMapList }, |
|
|
|
{ "changelevel2", 1, Cmd_GetMapList }, |
|
|
|
{ "changelevel", Cmd_GetMapList }, |
|
|
|
{ "changelevel", 1, Cmd_GetMapList }, |
|
|
|
{ "playdemo", Cmd_GetDemoList, }, |
|
|
|
{ "playdemo", 1, Cmd_GetDemoList, }, |
|
|
|
{ "timedemo", Cmd_GetDemoList, }, |
|
|
|
{ "timedemo", 1, Cmd_GetDemoList, }, |
|
|
|
{ "playvol", Cmd_GetSoundList }, |
|
|
|
{ "playvol", 1, Cmd_GetSoundList }, |
|
|
|
{ "hpkval", Cmd_GetCustomList }, |
|
|
|
{ "hpkval", 1, Cmd_GetCustomList }, |
|
|
|
{ "entpatch", Cmd_GetMapList }, |
|
|
|
{ "entpatch", 1, Cmd_GetMapList }, |
|
|
|
{ "music", Cmd_GetMusicList, }, |
|
|
|
{ "music", 1, Cmd_GetMusicList, }, |
|
|
|
{ "movie", Cmd_GetMovieList }, |
|
|
|
{ "movie", 1, Cmd_GetMovieList }, |
|
|
|
{ "exec", Cmd_GetConfigList }, |
|
|
|
{ "exec", 1, Cmd_GetConfigList }, |
|
|
|
#ifndef XASH_DEDICATED |
|
|
|
#ifndef XASH_DEDICATED |
|
|
|
{ "give", Cmd_GetItemsList }, |
|
|
|
{ "give", 1, Cmd_GetItemsList }, |
|
|
|
{ "drop", Cmd_GetItemsList }, |
|
|
|
{ "drop", 1, Cmd_GetItemsList }, |
|
|
|
|
|
|
|
{ "bind", 1, Cmd_GetKeysList }, |
|
|
|
|
|
|
|
{ "unbind", 1, Cmd_GetKeysList }, |
|
|
|
|
|
|
|
{ "bind", 2, Cmd_GetCommandsList }, |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
{ "game", Cmd_GetGamesList }, |
|
|
|
{ "game", 1, Cmd_GetGamesList }, |
|
|
|
{ "save", Cmd_GetSavesList }, |
|
|
|
{ "save", 1, Cmd_GetSavesList }, |
|
|
|
{ "load", Cmd_GetSavesList }, |
|
|
|
{ "load", 1, Cmd_GetSavesList }, |
|
|
|
{ "play", Cmd_GetSoundList }, |
|
|
|
{ "play", 1, Cmd_GetSoundList }, |
|
|
|
{ "map", Cmd_GetMapList }, |
|
|
|
{ "map", 1, Cmd_GetMapList }, |
|
|
|
{ "cd", Cmd_GetCDList }, |
|
|
|
{ "cd", 1, Cmd_GetCDList }, |
|
|
|
{ NULL }, // termiantor
|
|
|
|
{ NULL }, // termiantor
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -879,36 +1013,19 @@ Autocomplete filename |
|
|
|
for various cmds |
|
|
|
for various cmds |
|
|
|
============ |
|
|
|
============ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
qboolean Cmd_AutocompleteName( const char *source, char *buffer, size_t bufsize ) |
|
|
|
qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
autocomplete_list_t *list; |
|
|
|
autocomplete_list_t *list; |
|
|
|
|
|
|
|
|
|
|
|
for( list = cmd_list; list->name; list++ ) |
|
|
|
for( list = cmd_list; list->name; list++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if( Cmd_CheckName( list->name )) |
|
|
|
if( list->arg == arg && Cmd_CheckName( list->name )) |
|
|
|
return list->func( source, buffer, bufsize ); |
|
|
|
return list->func( source, buffer, bufsize ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
=============== |
|
|
|
|
|
|
|
Con_AddCommandToList |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=============== |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *unused3 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( *s == '@' ) return; // never show system cvars or cmds
|
|
|
|
|
|
|
|
if( con.matchCount >= CON_MAXCMDS ) return; // list is full
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( Q_strnicmp( s, con.completionString, Q_strlen( con.completionString ) ) ) |
|
|
|
|
|
|
|
return; // no match
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
con.cmds[con.matchCount++] = copystring( s ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
================= |
|
|
|
================= |
|
|
|
Con_SortCmds |
|
|
|
Con_SortCmds |
|
|
@ -1008,16 +1125,11 @@ void Con_CompleteCommand( field_t *field ) |
|
|
|
nextcmd = (con.completionField->buffer[Q_strlen( con.completionField->buffer ) - 1] == ' ') ? true : false; |
|
|
|
nextcmd = (con.completionField->buffer[Q_strlen( con.completionField->buffer ) - 1] == ' ') ? true : false; |
|
|
|
|
|
|
|
|
|
|
|
con.completionString = Cmd_Argv( 0 ); |
|
|
|
con.completionString = Cmd_Argv( 0 ); |
|
|
|
con.completionBuffer = Cmd_Argv( 1 ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// skip backslash
|
|
|
|
// skip backslash
|
|
|
|
while( *con.completionString && (*con.completionString == '\\' || *con.completionString == '/') ) |
|
|
|
while( *con.completionString && (*con.completionString == '\\' || *con.completionString == '/') ) |
|
|
|
con.completionString++; |
|
|
|
con.completionString++; |
|
|
|
|
|
|
|
|
|
|
|
// skip backslash
|
|
|
|
|
|
|
|
while( *con.completionBuffer && (*con.completionBuffer == '\\' || *con.completionBuffer == '/') ) |
|
|
|
|
|
|
|
con.completionBuffer++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !Q_strlen( con.completionString ) ) |
|
|
|
if( !Q_strlen( con.completionString ) ) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
@ -1035,33 +1147,41 @@ void Con_CompleteCommand( field_t *field ) |
|
|
|
con.shortestMatch[0] = 0; |
|
|
|
con.shortestMatch[0] = 0; |
|
|
|
|
|
|
|
|
|
|
|
// find matching commands and variables
|
|
|
|
// find matching commands and variables
|
|
|
|
Cmd_LookupCmds( NULL, NULL, (setpair_t)Con_AddCommandToList ); |
|
|
|
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList ); |
|
|
|
Cvar_LookupVars( 0, NULL, NULL, (setpair_t)Con_AddCommandToList ); |
|
|
|
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList ); |
|
|
|
|
|
|
|
|
|
|
|
if( !con.matchCount ) return; // no matches
|
|
|
|
if( !con.matchCount ) return; // no matches
|
|
|
|
|
|
|
|
|
|
|
|
memcpy( &temp, con.completionField, sizeof( field_t ) ); |
|
|
|
memcpy( &temp, con.completionField, sizeof( field_t ) ); |
|
|
|
|
|
|
|
|
|
|
|
// autocomplete second arg
|
|
|
|
// autocomplete second arg
|
|
|
|
if( (Cmd_Argc() == 2) || ((Cmd_Argc() == 1) && nextcmd) ) |
|
|
|
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
con.completionBuffer = Cmd_Argv( Cmd_Argc() - 1 ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// skip backslash
|
|
|
|
|
|
|
|
while( *con.completionBuffer && (*con.completionBuffer == '\\' || *con.completionBuffer == '/') ) |
|
|
|
|
|
|
|
con.completionBuffer++; |
|
|
|
|
|
|
|
|
|
|
|
if( !Q_strlen( con.completionBuffer ) ) |
|
|
|
if( !Q_strlen( con.completionBuffer ) ) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if( Cmd_AutocompleteName( con.completionBuffer, filename, sizeof( filename ) ) ) |
|
|
|
if( Cmd_AutocompleteName( con.completionBuffer, Cmd_Argc() - 1, filename, sizeof( filename ) ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
con.completionField->buffer[0] = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < Cmd_Argc() - 1; i++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Q_sprintf( con.completionField->buffer, "%s %s", Cmd_Argv( 0 ), filename ); |
|
|
|
Q_strncat( con.completionField->buffer, Cmd_Argv( i ), sizeof( con.completionField->buffer )); |
|
|
|
|
|
|
|
Q_strncat( con.completionField->buffer, " ", sizeof( con.completionField->buffer )); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Q_strncat( con.completionField->buffer, filename, sizeof( con.completionField->buffer )); |
|
|
|
con.completionField->cursor = Q_strlen( con.completionField->buffer ); |
|
|
|
con.completionField->cursor = Q_strlen( con.completionField->buffer ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// don't adjusting cursor pos if we nothing found
|
|
|
|
// don't adjusting cursor pos if we nothing found
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else if( Cmd_Argc() >= 3 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// disable autocomplete for all next args
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( con.matchCount == 1 ) |
|
|
|
if( con.matchCount == 1 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|