aboutsummaryrefslogtreecommitdiffstats
path: root/code
diff options
context:
space:
mode:
Diffstat (limited to 'code')
-rw-r--r--code/client/cl_keys.c12
-rw-r--r--code/qcommon/common.c128
-rw-r--r--code/qcommon/qcommon.h3
3 files changed, 105 insertions, 38 deletions
diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c
index 0f481a3..38f41d0 100644
--- a/code/client/cl_keys.c
+++ b/code/client/cl_keys.c
@@ -1063,6 +1063,18 @@ void Key_Bindlist_f( void ) {
}
/*
+============
+Key_KeynameCompletion
+============
+*/
+void Key_KeynameCompletion( void(*callback)(const char *s) ) {
+ int i;
+
+ for( i = 0; keynames[ i ].name != NULL; i++ )
+ callback( keynames[ i ].name );
+}
+
+/*
===================
CL_InitKeyCommands
===================
diff --git a/code/qcommon/common.c b/code/qcommon/common.c
index c8aaaeb..fd99449 100644
--- a/code/qcommon/common.c
+++ b/code/qcommon/common.c
@@ -3085,6 +3085,40 @@ static char *Field_FindFirstSeparator( char *s )
return NULL;
}
+#ifndef DEDICATED
+/*
+===============
+Field_CompleteKeyname
+===============
+*/
+static void Field_CompleteKeyname( void )
+{
+ matchCount = 0;
+ shortestMatch[ 0 ] = 0;
+
+ Key_KeynameCompletion( FindMatches );
+
+ if( matchCount == 0 )
+ return;
+
+ Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
+ strlen( completionString ) ], shortestMatch,
+ sizeof( completionField->buffer ) );
+ completionField->cursor = strlen( completionField->buffer );
+
+ if( matchCount == 1 )
+ {
+ Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
+ completionField->cursor++;
+ return;
+ }
+
+ Com_Printf( "]%s\n", completionField->buffer );
+
+ Key_KeynameCompletion( PrintMatches );
+}
+#endif
+
/*
===============
Field_CompleteFilename
@@ -3101,8 +3135,9 @@ static void Field_CompleteFilename( const char *dir,
if( matchCount == 0 )
return;
- Q_strcat( completionField->buffer, sizeof( completionField->buffer ),
- shortestMatch + strlen( completionString ) );
+ Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
+ strlen( completionString ) ], shortestMatch,
+ sizeof( completionField->buffer ) );
completionField->cursor = strlen( completionField->buffer );
if( matchCount == 1 )
@@ -3143,20 +3178,36 @@ static void Field_CompleteCommand( char *cmd,
else
completionString = Cmd_Argv( completionArgument - 1 );
+#ifndef DEDICATED
+ // Unconditionally add a '\' to the start of the buffer
+ if( completionField->buffer[ 0 ] &&
+ completionField->buffer[ 0 ] != '\\' )
+ {
+ if( completionField->buffer[ 0 ] != '/' )
+ {
+ // Buffer is full, refuse to complete
+ if( strlen( completionField->buffer ) + 1 >=
+ sizeof( completionField->buffer ) )
+ return;
+
+ memmove( &completionField->buffer[ 1 ],
+ &completionField->buffer[ 0 ],
+ strlen( completionField->buffer ) + 1 );
+ completionField->cursor++;
+ }
+
+ completionField->buffer[ 0 ] = '\\';
+ }
+#endif
+
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;
-
+ // This should always be true
+ if( baseCmd[ 0 ] == '\\' || baseCmd[ 0 ] == '/' )
baseCmd++;
- }
#endif
if( ( p = Field_FindFirstSeparator( cmd ) ) )
@@ -3187,13 +3238,6 @@ static void Field_CompleteCommand( char *cmd,
{
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" ) ||
@@ -3208,6 +3252,14 @@ static void Field_CompleteCommand( char *cmd,
if( p > cmd )
Field_CompleteCommand( p, qfalse, qtrue );
}
+#ifndef DEDICATED
+ 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, "rcon" ) && completionArgument == 2 )
{
// Skip "rcon "
@@ -3216,14 +3268,26 @@ static void Field_CompleteCommand( char *cmd,
if( p > cmd )
Field_CompleteCommand( p, qtrue, qtrue );
}
- else if( !Q_stricmp( baseCmd, "bind" ) && completionArgument >= 3 )
+ else if( !Q_stricmp( baseCmd, "bind" ) )
{
- // Skip "bind <key> "
- p = Com_SkipTokens( cmd, 2, " " );
+ if( completionArgument == 2 )
+ {
+ // Skip "bind "
+ p = Com_SkipTokens( cmd, 1, " " );
- if( p > cmd )
- Field_CompleteCommand( p, qtrue, qtrue );
+ if( p > cmd )
+ Field_CompleteKeyname( );
+ }
+ else if( completionArgument >= 3 )
+ {
+ // Skip "bind <key> "
+ p = Com_SkipTokens( cmd, 2, " " );
+
+ if( p > cmd )
+ Field_CompleteCommand( p, qtrue, qtrue );
+ }
}
+#endif
}
}
else
@@ -3244,23 +3308,11 @@ static void Field_CompleteCommand( char *cmd,
Cvar_CommandCompletion( FindMatches );
if( matchCount == 0 )
- return; // no matches
+ 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 ) );
- }
+ Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
+ strlen( completionString ) ], shortestMatch,
+ sizeof( completionField->buffer ) );
completionField->cursor = strlen( completionField->buffer );
diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h
index 7d977ac..916e6e5 100644
--- a/code/qcommon/qcommon.h
+++ b/code/qcommon/qcommon.h
@@ -926,6 +926,9 @@ void CL_FlushMemory( void );
void CL_StartHunkUsers( qboolean rendererOnly );
// start all the client stuff using the hunk
+void Key_KeynameCompletion( void(*callback)(const char *s) );
+// for keyname autocompletion
+
void Key_WriteBindings( fileHandle_t f );
// for writing the config files