diff options
-rw-r--r-- | source/cl_console.c | 36 | ||||
-rw-r--r-- | source/cl_demo.c | 10 | ||||
-rw-r--r-- | source/cl_draw.c | 41 | ||||
-rw-r--r-- | source/cl_keys.c | 37 | ||||
-rw-r--r-- | source/cl_local.h | 5 | ||||
-rw-r--r-- | source/cl_main.c | 94 | ||||
-rw-r--r-- | source/cl_parse.c | 20 | ||||
-rw-r--r-- | source/cmd.c | 196 | ||||
-rw-r--r-- | source/com_local.h | 36 | ||||
-rw-r--r-- | source/com_public.h | 12 | ||||
-rw-r--r-- | source/common.c | 119 | ||||
-rw-r--r-- | source/cvar.c | 92 | ||||
-rw-r--r-- | source/files.c | 60 | ||||
-rw-r--r-- | source/mvd_client.c | 17 | ||||
-rw-r--r-- | source/mvd_local.h | 2 | ||||
-rw-r--r-- | source/prompt.c | 213 | ||||
-rw-r--r-- | source/q_shared.h | 3 | ||||
-rw-r--r-- | source/snd_local.h | 3 | ||||
-rw-r--r-- | source/snd_main.c | 51 | ||||
-rw-r--r-- | source/snd_public.h | 9 | ||||
-rw-r--r-- | source/sv_ccmds.c | 48 | ||||
-rw-r--r-- | source/sv_mvd.c | 8 |
22 files changed, 485 insertions, 627 deletions
diff --git a/source/cl_console.c b/source/cl_console.c index 3640a7f..1eca052 100644 --- a/source/cl_console.c +++ b/source/cl_console.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cl_local.h" #include "prompt.h" -#define CON_TIMES 4 +#define CON_TIMES 16 #define CON_TIMES_MASK ( CON_TIMES - 1 ) #define CON_TOTALLINES 1024 // total lines in console scrollback @@ -77,6 +77,7 @@ typedef struct console_s { static console_t con; static cvar_t *con_notifytime; +static cvar_t *con_notifylines; static cvar_t *con_clock; static cvar_t *con_height; static cvar_t *con_speed; @@ -182,13 +183,12 @@ static void Con_Clear_f( void ) { con.display = con.current; } -static const char *Con_Dump_g( const char *partial, int argnum, int state ) { +static void Con_Dump_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Com_FileNameGenerator( "", ".txt", partial, qtrue, state ); + FS_File_g( "condumps", ".txt", 0x80000000, ctx ); } - return NULL; } - + /* ================ Con_Dump_f @@ -311,6 +311,12 @@ static void Con_RemoteMode_f( void ) { con.remotePassword = Z_CopyString( s ); } +static void CL_RemoteMode_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + Com_Address_g( ctx ); + } +} + /* ================ Con_CheckResize @@ -365,10 +371,10 @@ static const cmdreg_t c_console[] = { { "togglechat2", Con_ToggleChat2_f }, { "messagemode", Con_MessageMode_f }, { "messagemode2", Con_MessageMode2_f }, - { "remotemode", Con_RemoteMode_f, CL_Server_g }, + { "remotemode", Con_RemoteMode_f, CL_RemoteMode_c }, { "clear", Con_Clear_f }, { "clearnotify", Con_ClearNotify_f }, - { "condump", Con_Dump_f, Con_Dump_g }, + { "condump", Con_Dump_f, Con_Dump_c }, { NULL } }; @@ -387,6 +393,7 @@ void Con_Init( void ) { Cmd_Register( c_console ); con_notifytime = Cvar_Get( "con_notifytime", "3", 0 ); + con_notifylines = Cvar_Get( "con_notifylines", "4", 0 ); con_clock = Cvar_Get( "con_clock", "0", CVAR_ARCHIVE ); con_height = Cvar_Get( "con_height", "0.5", CVAR_ARCHIVE ); con_speed = Cvar_Get( "scr_conspeed", "3", 0 ); @@ -606,12 +613,12 @@ Draws the last few lines of output transparently over the game top void Con_DrawNotify( void ) { int v; char *text; - int i; + int i, j; int time; int skip; float alpha; - /* only draw notify in game */ + // only draw notify in game if( cls.state != ca_active ) { return; } @@ -622,8 +629,13 @@ void Con_DrawNotify( void ) { return; } + j = con_notifylines->integer; + if( j > CON_TIMES ) { + j = CON_TIMES; + } + v = 0; - for( i = con.current - CON_TIMES + 1; i <= con.current; i++ ) { + for( i = con.current - j + 1; i <= con.current; i++ ) { if( i < 0 ) continue; time = con.times[i & CON_TIMES_MASK]; @@ -858,7 +870,7 @@ void Con_RunConsole( void ) { Cvar_ClampValue( con_height, 0.1f, con.maxHeight ); if( cls.state == ca_disconnected && !( cls.key_dest & KEY_MENU ) ) { - /* draw fullscreen console */ + // draw fullscreen console con.destHeight = con.maxHeight; con.currentHeight = con.destHeight; return; @@ -866,7 +878,7 @@ void Con_RunConsole( void ) { if( cls.state > ca_disconnected && cls.state < ca_active ) { if( !cls.ui_initialized ) { - /* draw half-screen console */ + // draw half-screen console con.destHeight = min( con.maxHeight, 0.5f ); con.currentHeight = con.destHeight; return; diff --git a/source/cl_demo.c b/source/cl_demo.c index a505058..51dca08 100644 --- a/source/cl_demo.c +++ b/source/cl_demo.c @@ -646,12 +646,10 @@ static void CL_PlayDemo_f( void ) { } } -static const char *CL_PlayDemo_g( const char *partial, int argnum, int state ) { +static void CL_Demo_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Com_FileNameGeneratorByFilter( "demos", "*.dm2;*.dm2.gz", - partial, qfalse, state ); + FS_File_g( "demos", "*.dm2;*.dm2.gz", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | 0x80000000, ctx ); } - return NULL; } static void CL_ParseInfoString( demoInfo_t *info, int clientNum, int index, const char *string ) { @@ -793,8 +791,8 @@ void CL_DemoFrame( void ) { } static const cmdreg_t c_demo[] = { - { "demo", CL_PlayDemo_f, CL_PlayDemo_g }, - { "record", CL_Record_f, CL_PlayDemo_g }, + { "demo", CL_PlayDemo_f, CL_Demo_c }, + { "record", CL_Record_f, CL_Demo_c }, { "stop", CL_Stop_f }, { "suspend", CL_Suspend_f }, diff --git a/source/cl_draw.c b/source/cl_draw.c index a5ec50e..1085d8d 100644 --- a/source/cl_draw.c +++ b/source/cl_draw.c @@ -468,19 +468,26 @@ typedef struct { //int type; //union { cvar_t *cvar; - xmacro_t macro; + cmd_macro_t *macro; // int stat; //}; } drawobj_t; static list_t scr_objects; +static void SCR_Draw_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + Cvar_Variable_g( ctx ); + Cmd_Macro_g( ctx ); + } +} + // draw cl_fps -1 80 static void SCR_Draw_f( void ) { int x, y; char *s; drawobj_t *obj; - xmacro_t macro; + cmd_macro_t *macro; // int stat; if( Cmd_Argc() != 4 ) { @@ -508,7 +515,7 @@ static void SCR_Draw_f( void ) { } else #endif { - macro = Cmd_FindMacroFunction( s ); + macro = Cmd_FindMacro( s ); if( macro ) { obj->cvar = NULL; obj->macro = macro; @@ -521,10 +528,28 @@ static void SCR_Draw_f( void ) { List_Append( &scr_objects, &obj->entry ); } +static void SCR_Draw_g( genctx_t *ctx ) { + drawobj_t *obj; + const char *s; + + LIST_FOR_EACH( drawobj_t, obj, &scr_objects, entry ) { + s = obj->macro ? obj->macro->name : obj->cvar->name; + if( !Prompt_AddMatch( ctx, s ) ) { + break; + } + } +} + +static void SCR_UnDraw_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + SCR_Draw_g( ctx ); + } +} + static void SCR_UnDraw_f( void ) { char *s; drawobj_t *obj, *next; - xmacro_t macro; + cmd_macro_t *macro; cvar_t *cvar; if( Cmd_Argc() != 2 ) { @@ -543,7 +568,7 @@ static void SCR_UnDraw_f( void ) { } cvar = NULL; - macro = Cmd_FindMacroFunction( s ); + macro = Cmd_FindMacro( s ); if( !macro ) { cvar = Cvar_Get( s, "", CVAR_USER_CREATED ); } @@ -573,7 +598,7 @@ static void draw_objects( void ) { y += scr_hudHeight - 8 + 1; } if( obj->macro ) { - obj->macro( buffer, sizeof( buffer ) ); + obj->macro->function( buffer, sizeof( buffer ) ); SCR_DrawString( x, y, flags, buffer ); } else { SCR_DrawString( x, y, flags, obj->cvar->string ); @@ -822,8 +847,8 @@ cmdreg_t scr_drawcmds[] = { #if USE_CHATHUD { "clearchat", SCR_ClearChatHUD_f }, #endif - { "draw", SCR_Draw_f, Cvar_Set_g }, - { "undraw", SCR_UnDraw_f/*, SCR_DrawStringGenerator*/ }, + { "draw", SCR_Draw_f, SCR_Draw_c }, + { "undraw", SCR_UnDraw_f, SCR_UnDraw_c }, { "scoreshot", SCR_ScoreShot_f }, { NULL } }; diff --git a/source/cl_keys.c b/source/cl_keys.c index 116c2f0..3274677 100644 --- a/source/cl_keys.c +++ b/source/cl_keys.c @@ -375,39 +375,28 @@ void Key_SetBinding( int keynum, const char *binding ) { keybindings[keynum] = Z_CopyString( binding ); } -static const char *Key_NameGenerator( const char *partial, int state ) { - static int length; - static keyname_t *k; - const char *name; - - if( !state ) { - length = strlen( partial ); - k = keynames; - } +static void Key_Name_g( genctx_t *ctx ) { + keyname_t *k; - while( k->name ) { - name = k->name; - k++; - if( !strncmp( partial, name, length ) ) { - return name; + for( k = keynames; k->name; k++ ) { + if( !Prompt_AddMatch( ctx, k->name ) ) { + break; } } - - return NULL; } -static const char *Key_Bind_g( const char *partial, int argnum, int state ) { +static void Key_Bind_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Key_NameGenerator( partial, state ); + Key_Name_g( ctx ); + } else { + Com_Generic_c( ctx, argnum - 2 ); } - return Prompt_Completer( partial, 2, argnum, state ); } -static const char *Key_Unbind_g( const char *partial, int argnum, int state ) { +static void Key_Unbind_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Key_NameGenerator( partial, state ); + Key_Name_g( ctx ); } - return NULL; } /* @@ -536,8 +525,8 @@ void Key_FillAPI( keyAPI_t *api ) { } static cmdreg_t c_keys[] = { - { "bind", Key_Bind_f, Key_Bind_g }, - { "unbind", Key_Unbind_f, Key_Unbind_g }, + { "bind", Key_Bind_f, Key_Bind_c }, + { "unbind", Key_Unbind_f, Key_Unbind_c }, { "unbindall", Key_Unbindall_f }, { "bindlist", Key_Bindlist_f }, diff --git a/source/cl_local.h b/source/cl_local.h index a03112f..6b58865 100644 --- a/source/cl_local.h +++ b/source/cl_local.h @@ -506,6 +506,11 @@ void CL_FillAPI( clientAPI_t *api ); void CL_SendRcon( const netadr_t *adr, const char *pass, const char *cmd ); const char *CL_Server_g( const char *partial, int argnum, int state ); +// the sound code makes callbacks to the client for entitiy position +// information, so entities can be dynamically re-spatialized +void CL_GetEntitySoundOrigin( int ent, vec3_t org ); + + // // cl_input // diff --git a/source/cl_main.c b/source/cl_main.c index c65989c..c6429b2 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -415,23 +415,16 @@ static void CL_CheckForResend( void ) { } } -static const char *CL_Connect_g( const char *partial, int argnum, int state ) { - static int protocol; - - if( !state ) { - protocol = 34; - } - +static void CL_Connect_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Com_AddressGenerator( partial, state ); + Com_Address_g( ctx ); } else if( argnum == 2 ) { - if( !partial[0] || ( partial[0] == '3' && !partial[1] ) ) { - while( protocol <= 36 ) { - return va( "%d", protocol++ ); - } + if( !ctx->partial[0] || ( ctx->partial[0] == '3' && !ctx->partial[1] ) ) { + Prompt_AddMatch( ctx, "34" ); + Prompt_AddMatch( ctx, "35" ); + Prompt_AddMatch( ctx, "36" ); } } - return NULL; } /* @@ -584,11 +577,10 @@ static void CL_Rcon_f( void ) { CL_SendRcon( &address, rcon_password->string, Cmd_RawArgs() ); } -const char *CL_Rcon_g( const char *partial, int argnum, int state ) { - return Prompt_Completer( partial, 1, argnum, state ); +static void CL_Rcon_c( genctx_t *ctx, int argnum ) { + Com_Generic_c( ctx, argnum - 1 ); } - /* ===================== CL_ClearState @@ -703,12 +695,10 @@ static void CL_Disconnect_f( void ) { } } - -const char *CL_Server_g( const char *partial, int argnum, int state ) { +static void CL_ServerStatus_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Com_AddressGenerator( partial, state ); + Com_Address_g( ctx ); } - return NULL; } /* @@ -1183,25 +1173,20 @@ static void CL_Skins_f ( void ) { } } -const char *CL_NickGenerator( const char *partial, int state ) { - static int length; - static int i; +void CL_Name_g( genctx_t *ctx ) { + int i; clientinfo_t *ci; - if( !state ) { - if( cls.state < ca_loading ) { - return NULL; - } - length = strlen( partial ); - i = 0; + if( cls.state < ca_loading ) { + return; } - while( i < MAX_CLIENTS ) { - ci = &cl.clientinfo[i++]; - if( ci->name[0] && !strncmp( ci->name, partial, length ) ) { - return ci->name; + + for( i = 0; i < MAX_CLIENTS; i++ ) { + ci = &cl.clientinfo[i]; + if( ci->name[0] && !Prompt_AddMatch( ctx, ci->name ) ) { + break; } } - return NULL; } @@ -2021,12 +2006,8 @@ static const cmd_option_t o_writeconfig[] = { { NULL } }; -static const char *CL_ConfigGenerator( const char *partial, int state ) { - return Com_FileNameGeneratorByFilter( "", "*.cfg", partial, qtrue, state ); -} - -static const char *CL_WriteConfig_g( const char *partial, int argnum, int state ) { - return Cmd_Completer( o_writeconfig, partial, argnum, state, CL_ConfigGenerator ); +static void CL_WriteConfig_c( genctx_t *ctx, int argnum ) { + Cmd_Option_c( o_writeconfig, Cmd_Config_g, ctx, argnum ); } /* @@ -2106,8 +2087,8 @@ static void CL_WriteConfig_f( void ) { Com_Printf( "Wrote %s.\n", buffer ); } -static const char *CL_Say_g( const char *partial, int argnum, int state ) { - return CL_NickGenerator( partial, state ); +static void CL_Say_c( genctx_t *ctx, int argnum ) { + CL_Name_g( ctx ); } static int CL_Mapname_m( char *buffer, int size ) { @@ -2194,9 +2175,7 @@ void CL_RestartFilesystem( void ) { return; } - Com_DPrintf( "CL_RestartFilesystem()\n" ); - - /* temporary switch to loading state */ + // temporary switch to loading state cls_state = cls.state; if ( cls.state >= ca_precached ) { cls.state = ca_loading; @@ -2225,7 +2204,7 @@ void CL_RestartFilesystem( void ) { CL_PrepRefresh(); } - /* switch back to original state */ + // switch back to original state cls.state = cls_state; } @@ -2238,9 +2217,7 @@ CL_RestartRefresh static void CL_RestartRefresh_f( void ) { int cls_state; - Com_DPrintf( "CL_RestartRefresh()\n" ); - - /* temporary switch to loading state */ + // temporary switch to loading state cls_state = cls.state; if ( cls.state >= ca_precached ) { cls.state = ca_loading; @@ -2267,7 +2244,7 @@ static void CL_RestartRefresh_f( void ) { CL_PrepRefresh(); } - /* switch back to original state */ + // switch back to original state cls.state = cls_state; } @@ -2340,17 +2317,18 @@ static const cmdreg_t c_client[] = { { "snd_restart", CL_Snd_Restart_f }, { "changing", CL_Changing_f }, { "disconnect", CL_Disconnect_f }, - { "connect", CL_Connect_f, CL_Connect_g }, + { "connect", CL_Connect_f, CL_Connect_c }, { "passive", CL_PassiveConnect_f }, { "reconnect", CL_Reconnect_f }, - { "rcon", CL_Rcon_f, CL_Rcon_g }, + { "rcon", CL_Rcon_f, CL_Rcon_c }, { "precache", CL_Precache_f }, { "download", CL_Download_f }, - { "serverstatus", CL_ServerStatus_f, CL_Server_g }, + { "serverstatus", CL_ServerStatus_f, CL_ServerStatus_c }, { "dumpclients", CL_DumpClients_f }, { "dumpstatusbar", CL_DumpStatusbar_f }, { "dumplayout", CL_DumpLayout_f }, - { "writeconfig", CL_WriteConfig_f, CL_WriteConfig_g }, + { "writeconfig", CL_WriteConfig_f, CL_WriteConfig_c }, +// { "msgtab", CL_Msgtab_f, CL_Msgtab_g }, { "vid_restart", CL_RestartRefresh_f }, // @@ -2359,8 +2337,8 @@ static const cmdreg_t c_client[] = { // the only thing this does is allow command completion // to work -- all unknown commands are automatically // forwarded to the server - { "say", NULL, CL_Say_g }, - { "say_team", NULL, CL_Say_g }, + { "say", NULL, CL_Say_c }, + { "say_team", NULL, CL_Say_c }, { "wave" }, { "inven" }, { "kill" }, { "use" }, { "drop" }, { "info" }, { "prog" }, @@ -2395,7 +2373,7 @@ static void CL_InitLocal ( void ) { for ( i = 0 ; i < MAX_LOCAL_SERVERS ; i++ ) { var = Cvar_Get( va( "adr%i", i ), "", CVAR_ARCHIVE ); - var->generator = Com_AddressGenerator; + var->generator = Com_Address_g; } // @@ -2425,7 +2403,7 @@ static void CL_InitLocal ( void ) { rcon_password = Cvar_Get ( "rcon_password", "", CVAR_PRIVATE ); rcon_address = Cvar_Get ( "rcon_address", "", CVAR_PRIVATE ); - rcon_address->generator = Com_AddressGenerator; + rcon_address->generator = Com_Address_g; cl_thirdperson = Cvar_Get( "cl_thirdperson", "0", CVAR_CHEAT ); cl_thirdperson_angle = Cvar_Get( "cl_thirdperson_angle", "0", 0 ); diff --git a/source/cl_parse.c b/source/cl_parse.c index cea58e4..1f904c1 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -24,10 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //============================================================================= -static const char *const validExts[] = { - ".pcx", ".wal", ".tga", ".jpg", ".png", - ".md2", ".md3", ".sp2", ".wav", ".dm2", - ".bsp", ".txt", ".loc", ".ent", NULL +static const char validExts[][4] = { + "pcx", "wal", "tga", "jpg", "png", + "md2", "md3", "sp2", "wav", "dm2", + "bsp", "txt", "loc", "ent", "" }; /* @@ -63,12 +63,16 @@ qboolean CL_CheckOrDownloadFile( const char *path ) { // a trivial attempt to prevent malicious server from // uploading trojan executables to the win32 client ext = COM_FileExtension( filename ); - for( i = 0; validExts[i]; i++ ) { - if( !strcmp( ext, validExts[i] ) ) { + if( *ext != '.' ) { + Com_WPrintf( "Refusing to download file without extension.\n" ); + return qtrue; + } + for( i = 0; validExts[i][0]; i++ ) { + if( !strcmp( ext + 1, validExts[i] ) ) { break; } } - if( !validExts[i] ) { + if( !validExts[i][0] ) { Com_WPrintf( "Refusing to download file with invalid extension.\n" ); return qtrue; } @@ -1297,7 +1301,7 @@ static void CL_ParsePrint( void ) { // play sound if( cl_chat_sound->string[0] ) { - S_StartLocalSound( cl_chat_sound->string ); + S_StartLocalSound_( cl_chat_sound->string ); } } diff --git a/source/cmd.c b/source/cmd.c index 71d4abe..adb5228 100644 --- a/source/cmd.c +++ b/source/cmd.c @@ -276,6 +276,17 @@ void Cmd_AliasSet( const char *name, const char *cmd ) { List_Append( &cmd_aliasHash[hash], &a->hashEntry ); } +void Cmd_Alias_g( genctx_t *ctx ) { + cmdalias_t *a; + + LIST_FOR_EACH( cmdalias_t, a, &cmd_alias, listEntry ) { + if( !Prompt_AddMatch( ctx, a->name ) ) { + break; + } + } +} + + /* =============== Cmd_Alias_f @@ -389,24 +400,18 @@ void Cmd_WriteAliases( fileHandle_t f ) { } #endif -const char *Cmd_Alias_g( const char *partial, int argnum, int state ) { - switch( argnum ) { - case 0: - return NULL; - case 1: - return Cmd_AliasGenerator( partial, state ); - case 2: - return Cmd_MixedGenerator( partial, state ); - default: - return NULL; +static void Cmd_Alias_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + Cmd_Alias_g( ctx ); + } else { + Com_Generic_c( ctx, argnum - 2 ); } } -const char *Cmd_UnAlias_g( const char *partial, int argnum, int state ) { +static void Cmd_UnAlias_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Cmd_AliasGenerator( partial, state ); + Cmd_Alias_g( ctx ); } - return NULL; } /* @@ -417,14 +422,6 @@ const char *Cmd_UnAlias_g( const char *partial, int argnum, int state ) { ============================================================================= */ -typedef struct cmd_macro_s { - struct cmd_macro_s *next; - struct cmd_macro_s *hashNext; - - const char *name; - xmacro_t function; -} cmd_macro_t; - #define MACRO_HASH_SIZE 64 static cmd_macro_t *cmd_macros; @@ -435,7 +432,7 @@ static cmd_macro_t *cmd_macroHash[MACRO_HASH_SIZE]; Cmd_FindMacro ============ */ -static cmd_macro_t *Cmd_FindMacro( const char *name ) { +cmd_macro_t *Cmd_FindMacro( const char *name ) { cmd_macro_t *macro; unsigned hash; @@ -449,15 +446,14 @@ static cmd_macro_t *Cmd_FindMacro( const char *name ) { return NULL; } -xmacro_t Cmd_FindMacroFunction( const char *name ) { - cmd_macro_t *macro; - - macro = Cmd_FindMacro( name ); - if( !macro ) { - return NULL; - } +void Cmd_Macro_g( genctx_t *ctx ) { + cmd_macro_t *m; - return macro->function; + for( m = cmd_macros; m; m = m->next ) { + if( !Prompt_AddMatch( ctx, m->name ) ) { + break; + } + } } /* @@ -814,47 +810,30 @@ void Cmd_PrintHint( void ) { Com_Printf( "Try '%s --help' for more information.\n", cmd_argv[0] ); } -const char *Cmd_Completer( const cmd_option_t *opt, const char *partial, - int argnum, int state, xgenerator_t generator ) -{ - static int length; - static const cmd_option_t *o; - const char *s; - - if( !state ) { - length = strlen( partial ); - o = opt; - } - - if( partial[0] == '-' ) { - while( o->sh ) { - if( partial[1] == '-' ) { - if( !strncmp( o->lo, partial + 2, length - 2 ) ) { - s = va( "--%s", o->lo ); - o++; - return s; +void Cmd_Option_c( const cmd_option_t *opt, xgenerator_t g, genctx_t *ctx, int argnum ) { + if( ctx->partial[0] == '-' ) { + for( ; opt->sh; opt++ ) { + if( ctx->count >= ctx->size ) { + break; + } + if( ctx->partial[1] == '-' ) { + if( !strncmp( opt->lo, ctx->partial + 2, ctx->length - 2 ) ) { + ctx->matches[ctx->count++] = Z_CopyString( va( "--%s", opt->lo ) ); } - } else if( !partial[1] || o->sh[0] == partial[1] ) { - s = va( "-%c", o->sh[0] ); - o++; - return s; - + } else if( !ctx->partial[1] || opt->sh[0] == ctx->partial[1] ) { + ctx->matches[ctx->count++] = Z_CopyString( va( "-%c", opt->sh[0] ) ); } - o++; } } else { /* if( argnum > 1 ) { s = cmd_argv[argnum - 1]; }*/ - if( generator ) { - return (*generator)( partial, state ); - } - if( !partial[0] ) { - return "-"; + if( g ) { + g( ctx ); + } else if( !ctx->partial[0] && ctx->count < ctx->size ) { + ctx->matches[ctx->count++] = Z_CopyString( "-" ); } } - - return NULL; } @@ -1236,80 +1215,16 @@ xcompleter_t Cmd_FindCompleter( const char *name ) { return cmd ? cmd->completer : NULL; } -const char *Cmd_CommandGenerator( const char *partial, int state ) { - static int length; - static cmd_function_t *cmd; - const char *name; - - if( !state ) { - length = strlen( partial ); - cmd = LIST_FIRST( cmd_function_t, &cmd_functions, listEntry ); - } - - while( !LIST_TERM( cmd, &cmd_functions, listEntry ) ) { - name = cmd->name; - cmd = LIST_NEXT( cmd_function_t, cmd, listEntry ); - if( !strncmp( partial, name, length ) ) { - return name; - } - } - - return NULL; -} - -const char *Cmd_AliasGenerator( const char *partial, int state ) { - static int length; - static cmdalias_t *alias; - const char *name; - - if( !state ) { - length = strlen( partial ); - alias = LIST_FIRST( cmdalias_t, &cmd_alias, listEntry ); - } - - while( !LIST_TERM( alias, &cmd_alias, listEntry ) ) { - name = alias->name; - alias = LIST_NEXT( cmdalias_t, alias, listEntry ); - if( !strncmp( partial, name, length ) ) { - return name; - } - } - - return NULL; -} - -const char *Cmd_MixedGenerator( const char *partial, int state ) { - static xgenerator_t g; - const char *match; - - if( state == 2 ) { - g( partial, 2 ); - return NULL; - } - - if( !state ) { - g = Cmd_CommandGenerator; - } - - match = g( partial, state ); - if( match ) { - return match; - } - - if( g == Cmd_CommandGenerator ) { - g( partial, 2 ); - g = Cmd_AliasGenerator; +void Cmd_Command_g( genctx_t *ctx ) { + cmd_function_t *cmd; - match = g( partial, 0 ); - if( match ) { - return match; + LIST_FOR_EACH( cmd_function_t, cmd, &cmd_functions, listEntry ) { + if( !Prompt_AddMatch( ctx, cmd->name ) ) { + break; } } - - return NULL; } - /* ============ Cmd_ExecuteString @@ -1405,11 +1320,14 @@ static void Cmd_Exec_f( void ) { FS_FreeFile( f ); } -const char *Cmd_Exec_g( const char *partial, int argnum, int state ) { +void Cmd_Config_g( genctx_t *ctx ) { + FS_File_g( "", "*.cfg", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | 0x80000000, ctx ); +} + +static void Cmd_Exec_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Com_FileNameGeneratorByFilter( "", "*.cfg", partial, qtrue, state ); + Cmd_Config_g( ctx ); } - return NULL; } /* @@ -1544,6 +1462,9 @@ static void Cmd_Complete_f( void ) { List_Append( &cmd_hash[hash], &cmd->hashEntry ); } +void Com_Mixed_c( genctx_t *ctx, int argnum ) { +} + /* ============ Cmd_FillAPI @@ -1559,17 +1480,16 @@ void Cmd_FillAPI( cmdAPI_t *api ) { api->ArgsFrom = Cmd_ArgsFrom; api->ExecuteText = Cbuf_ExecuteText; api->FindFunction = Cmd_FindFunction; - api->FindMacroFunction = Cmd_FindMacroFunction; } static const cmdreg_t c_cmd[] = { { "cmdlist", Cmd_List_f }, { "macrolist", Cmd_MacroList_f }, - { "exec", Cmd_Exec_f, Cmd_Exec_g }, + { "exec", Cmd_Exec_f, Cmd_Exec_c }, { "echo", Cmd_Echo_f }, { "_echo", Cmd_ColoredEcho_f }, - { "alias", Cmd_Alias_f, Cmd_Alias_g }, - { "unalias", Cmd_UnAlias_f, Cmd_UnAlias_g }, + { "alias", Cmd_Alias_f, Cmd_Alias_c }, + { "unalias", Cmd_UnAlias_f, Cmd_UnAlias_c }, { "wait", Cmd_Wait_f }, { "text", Cmd_Text_f }, { "complete", Cmd_Complete_f }, diff --git a/source/com_local.h b/source/com_local.h index 68e91d9..b777db4 100644 --- a/source/com_local.h +++ b/source/com_local.h @@ -111,22 +111,29 @@ typedef struct { const char *sh, *lo, *help; } cmd_option_t; +typedef struct cmd_macro_s { + struct cmd_macro_s *next, *hashNext; + const char *name; + xmacro_t function; +} cmd_macro_t; + void Cmd_Init( void ); qboolean Cmd_Exists( const char *cmd_name ); // used by the cvar code to check for cvar / command name overlap xcommand_t Cmd_FindFunction( const char *name ); -xmacro_t Cmd_FindMacroFunction( const char *name ); +cmd_macro_t *Cmd_FindMacro( const char *name ); xcompleter_t Cmd_FindCompleter( const char *name ); char *Cmd_AliasCommand( const char *name ); void Cmd_AliasSet( const char *name, const char *cmd ); -const char *Cmd_CommandGenerator( const char *partial, int state ); -const char *Cmd_AliasGenerator( const char *partial, int state ); -const char *Cmd_MixedGenerator( const char *partial, int state ); -const char *Cmd_Exec_g( const char *partial, int argnum, int state ); +void Cmd_Command_g( genctx_t *ctx ); +void Cmd_Alias_g( genctx_t *ctx ); +void Cmd_Macro_g( genctx_t *ctx ); +void Cmd_Config_g( genctx_t *ctx ); +void Cmd_Option_c( const cmd_option_t *opt, xgenerator_t g, genctx_t *ctx, int argnum ); // attempts to match a partial command for automatic command line completion // returns NULL if nothing fits @@ -246,9 +253,10 @@ cvar_t *Cvar_FullSet( const char *var_name, const char *value, void Cvar_ClampInteger( cvar_t *var, int min, int max ); void Cvar_ClampValue( cvar_t *var, float min, float max ); -const char *Cvar_Set_g( const char *partial, int argnum, int state ); +xgenerator_t Cvar_FindGenerator( const char *var_name ); -const char *Cvar_Generator( const char *partial, int state ); +void Cvar_Variable_g( genctx_t *ctx ); +void Cvar_Default_g( genctx_t *ctx ); // attempts to match a partial variable name for command line completion // returns NULL if nothing fits @@ -887,6 +895,8 @@ const char *FS_GetFileFullPath( fileHandle_t f ); char *FS_ReplaceSeparators( char *s, int separator ); +void FS_File_g( const char *path, const char *ext, int flags, genctx_t *ctx ); + void FS_FillAPI( fsAPI_t *api ); extern cvar_t *fs_game; @@ -934,11 +944,10 @@ byte COM_BlockSequenceCRCByte (byte *base, int length, int sequence); void Com_ProcessEvents( void ); -const char *Com_FileNameGenerator( const char *path, const char *ext, const char *partial, - qboolean stripExtension, int state ); -const char *Com_FileNameGeneratorByFilter( const char *path, const char *filter, const char *partial, - qboolean stripExtension, int state ); -const char *Com_AddressGenerator( const char *partial, int state ); +void Com_Address_g( genctx_t *ctx ); +void Com_Generic_c( genctx_t *ctx, int argnum ); + +qboolean Prompt_AddMatch( genctx_t *ctx, const char *s ); int Com_Time_m( char *buffer, int size ); int Com_Uptime_m( char *buffer, int size ); @@ -1120,6 +1129,3 @@ void SV_Shutdown( const char *finalmsg, killtype_t type ); void SV_Frame (int msec); qboolean MVD_GetDemoPercent( int *percent, int *bufferPercent ); -const char *Prompt_Completer( const char *partial, int firstarg, int argnum, int state ); - - diff --git a/source/com_public.h b/source/com_public.h index 2a9b4f7..892fcfa 100644 --- a/source/com_public.h +++ b/source/com_public.h @@ -39,7 +39,16 @@ typedef enum cbufExecWhen_e { typedef void ( *xcommand_t )( void ); typedef int ( *xmacro_t )( char *, int ); -typedef const char *( *xcompleter_t )( const char *, int, int ); +typedef void ( *xcompleter_t )( struct genctx_s *, int ); + +typedef struct genctx_s { + const char *partial; + int length; + int argnum; + char **matches; + int count, size; + void *data; +} genctx_t; typedef struct cmdreg_s { const char *name; @@ -60,7 +69,6 @@ typedef struct cmdAPI_s { void (*AddCommand)( const char *cmd_name, xcommand_t function ); void (*RemoveCommand)( const char *cmd_name ); xcommand_t (*FindFunction)( const char *name ); - xmacro_t (*FindMacroFunction)( const char *name ); } cmdAPI_t; extern cmdAPI_t cmd; diff --git a/source/common.c b/source/common.c index 51628ae..c1fd2f8 100644 --- a/source/common.c +++ b/source/common.c @@ -1058,106 +1058,45 @@ void Com_Crash_f( void ) { #endif -const char *Com_FileNameGenerator( const char *path, const char *ext, - const char *partial, qboolean stripExtension, int state ) { - static int length, numFiles; - static void **list; - static int curpos; - char *s, *p; - - if( state == 2 ) { - goto finish; - } - - if( !state ) { - length = strlen( partial ); - list = FS_ListFiles( path, ext, 0, &numFiles ); - curpos = 0; - } - - while( curpos < numFiles ) { - s = list[curpos++]; - if( stripExtension ) { - p = COM_FileExtension( s ); - *p = 0; - } - if( !strncmp( s, partial, length ) ) { - return s; - } - } - -finish: - if( list ) { - FS_FreeList( list ); - list = NULL; - } - return NULL; -} - -const char *Com_FileNameGeneratorByFilter( const char *path, const char *filter, - const char *partial, qboolean stripExtension, int state ) { - static int length, numFiles; - static void **list; - static int curpos; - char *s, *p; - - if( state == 2 ) { - goto finish; - } - - if( !state ) { - length = strlen( partial ); - list = FS_ListFiles( path, filter, FS_SEARCH_SAVEPATH | - FS_SEARCH_BYFILTER, &numFiles ); - curpos = 0; - } - - while( curpos < numFiles ) { - s = list[curpos++]; - if( stripExtension ) { - p = COM_FileExtension( s ); - *p = 0; - } - if( !strncmp( s, partial, length ) ) { - return s; - } - } - -finish: - if( list ) { - FS_FreeList( list ); - list = NULL; - } - return NULL; -} - -const char *Com_AddressGenerator( const char *partial, int state ) { - static int length; - static int index; +void Com_Address_g( genctx_t *ctx ) { + int i; cvar_t *var; - char buffer[MAX_QPATH]; - if( !state ) { - length = strlen( partial ); - index = 0; - } - - while( index < 1024 ) { - Com_sprintf( buffer, sizeof( buffer ), "adr%i", index ); - index++; - var = Cvar_FindVar( buffer ); + for( i = 0; i < 1024; i++ ) { + var = Cvar_FindVar( va( "adr%d", i ) ); if( !var ) { break; } if( !var->string[0] ) { continue; } - if( !strncmp( partial, var->string, length ) ) { - return var->string; - } + if( !Prompt_AddMatch( ctx, var->string ) ) { + break; + } } +} + +void Com_Generic_c( genctx_t *ctx, int argnum ) { + xcompleter_t c; + xgenerator_t g; + char *s; + + // complete command, alias or cvar name + if( !argnum ) { + Cmd_Command_g( ctx ); + Cvar_Variable_g( ctx ); + Cmd_Alias_g( ctx ); + return; + } - return NULL; + s = Cmd_Argv( ctx->argnum - argnum ); + + // complete command argument or cvar value + if( ( c = Cmd_FindCompleter( s ) ) != NULL ) { + c( ctx, argnum ); + } else if( argnum == 1 && ( g = Cvar_FindGenerator( s ) ) != NULL ) { + g( ctx ); + } } /* diff --git a/source/cvar.c b/source/cvar.c index 9cdf1ce..021afa5 100644 --- a/source/cvar.c +++ b/source/cvar.c @@ -56,6 +56,12 @@ cvar_t *Cvar_FindVar( const char *var_name ) { return NULL; } +xgenerator_t Cvar_FindGenerator( const char *var_name ) { + cvar_t *var = Cvar_FindVar( var_name ); + + return var ? var->generator : NULL; +} + /* ============ Cvar_Exists @@ -123,25 +129,25 @@ void Cvar_VariableStringBuffer( const char *var_name, char *buffer, int size ) { Q_strncpyz( buffer, Cvar_VariableString( var_name ), size ); } -const char *Cvar_Generator( const char *partial, int state ) { - static int length; - static cvar_t *cvar; - const char *name; +void Cvar_Variable_g( genctx_t *ctx ) { + cvar_t *c; - if( !state ) { - length = strlen( partial ); - cvar = cvar_vars; + for( c = cvar_vars; c; c = c->next ) { + if( !Prompt_AddMatch( ctx, c->name ) ) { + break; + } } +} - while( cvar ) { - name = cvar->name; - cvar = cvar->next; - if( !strncmp( partial, name, length ) ) { - return name; +void Cvar_Default_g( genctx_t *ctx ) { + cvar_t *c = ctx->data; + + if( c ) { + if( strcmp( c->string, c->default_string ) ) { + Prompt_AddMatch( ctx, c->string ); } + Prompt_AddMatch( ctx, c->default_string ); } - - return NULL; } static void Cvar_ParseString( cvar_t *var ) { @@ -156,6 +162,7 @@ static void Cvar_ParseString( cvar_t *var ) { } } + /* ============ Cvar_Get @@ -248,7 +255,7 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { Cvar_ParseString( var ); var->flags = flags; var->changed = NULL; - var->generator = NULL; + var->generator = Cvar_Default_g; var->modified = qtrue; // sort the variable in @@ -632,11 +639,18 @@ void Cvar_Command( cvar_t *v ) { } } -const char *Cvar_Set_g( const char *partial, int argnum, int state ) { +static void Cvar_Set_c( genctx_t *ctx, int argnum ) { + char *s; + xgenerator_t g; + if( argnum == 1 ) { - return Cvar_Generator( partial, state ); + Cvar_Variable_g( ctx ); + } else if( argnum == 2 ) { + s = Cmd_Argv( ctx->argnum - 1 ); + if( ( g = Cvar_FindGenerator( s ) ) != NULL ) { + g( ctx ); + } } - return NULL; } @@ -764,8 +778,8 @@ static const cmd_option_t o_cvarlist[] = { { NULL } }; -static const char *Cvar_List_g( const char *partial, int argnum, int state ) { - return Cmd_Completer( o_cvarlist, partial, argnum, state, NULL ); +static void Cvar_List_c( genctx_t *ctx, int argnum ) { + return Cmd_Option_c( o_cvarlist, NULL, ctx, argnum ); } static void Cvar_List_f( void ) { @@ -935,6 +949,20 @@ static void Cvar_Toggle_f( void ) { Com_Printf( "\"%s\" is \"%s\", can't cycle\n", var->name, var->string ); } +static void Cvar_Toggle_c( genctx_t *ctx, int argnum ) { + char *s; + xgenerator_t g; + + if( argnum == 1 ) { + Cvar_Variable_g( ctx ); + } else { + s = Cmd_Argv( ctx->argnum - argnum + 1 ); + if( ( g = Cvar_FindGenerator( s ) ) != NULL ) { + g( ctx ); + } + } +} + /* ============ Cvar_Inc_f @@ -994,6 +1022,12 @@ static void Cvar_Reset_f( void ) { Cvar_SetByVar( var, var->default_string, CVAR_SET_CONSOLE ); } +static void Cvar_Reset_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + Cvar_Variable_g( ctx ); + } +} + int Cvar_BitInfo( char *info, int bit ) { char newi[MAX_INFO_STRING]; cvar_t *var; @@ -1037,15 +1071,15 @@ void Cvar_FillAPI( cvarAPI_t *api ) { } static const cmdreg_t c_cvar[] = { - { "set", Cvar_Set_f, Cvar_Set_g }, - { "setu", Cvar_SetFlag_f, Cvar_Set_g }, - { "sets", Cvar_SetFlag_f, Cvar_Set_g }, - { "seta", Cvar_SetFlag_f, Cvar_Set_g }, - { "cvarlist", Cvar_List_f, Cvar_List_g }, - { "toggle", Cvar_Toggle_f, Cvar_Set_g }, - { "inc", Cvar_Inc_f, Cvar_Set_g }, - { "dec", Cvar_Inc_f, Cvar_Set_g }, - { "reset", Cvar_Reset_f, Cvar_Set_g }, + { "set", Cvar_Set_f, Cvar_Set_c }, + { "setu", Cvar_SetFlag_f, Cvar_Set_c }, + { "sets", Cvar_SetFlag_f, Cvar_Set_c }, + { "seta", Cvar_SetFlag_f, Cvar_Set_c }, + { "cvarlist", Cvar_List_f, Cvar_List_c }, + { "toggle", Cvar_Toggle_f, Cvar_Toggle_c }, + { "inc", Cvar_Inc_f, Cvar_Reset_c }, + { "dec", Cvar_Inc_f, Cvar_Reset_c }, + { "reset", Cvar_Reset_f, Cvar_Reset_c }, { NULL } }; diff --git a/source/files.c b/source/files.c index 738ffb0..f1a1f06 100644 --- a/source/files.c +++ b/source/files.c @@ -1971,6 +1971,33 @@ void FS_FreeList( void **list ) { Z_Free( list ); } +void FS_File_g( const char *path, const char *ext, int flags, genctx_t *ctx ) { + int i, numFiles; + void **list; + char *s, *p; + + list = FS_ListFiles( path, ext, flags, &numFiles ); + if( !list ) { + return; + } + + for( i = 0; i < numFiles; i++ ) { + s = list[i]; + if( flags & 0x80000000 ) { + p = COM_FileExtension( s ); + *p = 0; + } + if( ctx->count < ctx->size && !strncmp( s, ctx->partial, ctx->length ) ) { + ctx->matches[ctx->count++] = s; + } else { + Z_Free( s ); + } + } + + Z_Free( list ); +} + + /* ================= FS_CopyFile_f @@ -2221,29 +2248,20 @@ static void FS_Stats_f( void ) { } } -static const char *FS_Link_g( const char *partial, int argnum, int state ) { - static int length; - static fsLink_t *link; - char *name; +static void FS_Link_g( genctx_t *ctx ) { + fsLink_t *link; - if( argnum != 1 ) { - return NULL; + for( link = fs_links; link; link = link->next ) { + if( !Prompt_AddMatch( ctx, link->name ) ) { + break; + } } +} - if( !state ) { - length = strlen( partial ); - link = fs_links; +static void FS_Link_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + FS_Link_g( ctx ); } - - while( link ) { - name = link->name; - link = link->next; - if( !Q_stricmpn( partial, name, length ) ) { - return name; - } - } - - return NULL; } static void FS_UnLink_f( void ) { @@ -2593,8 +2611,8 @@ static const cmdreg_t c_fs[] = { { "copyfile", FS_CopyFile_f }, { "fs_stats", FS_Stats_f }, { "whereis", FS_WhereIs_f }, - { "link", FS_Link_f, FS_Link_g }, - { "unlink", FS_UnLink_f, FS_Link_g }, + { "link", FS_Link_f, FS_Link_c }, + { "unlink", FS_UnLink_f, FS_Link_c }, { "fs_restart", FS_Restart_f }, { NULL } diff --git a/source/mvd_client.c b/source/mvd_client.c index 96f1ecf..a6b199f 100644 --- a/source/mvd_client.c +++ b/source/mvd_client.c @@ -961,8 +961,8 @@ static const cmd_option_t o_mvdconnect[] = { { NULL } }; -const char *MVD_Connect_g( const char *partial, int argnum, int state ) { - return Cmd_Completer( o_mvdconnect, partial, argnum, state, Com_AddressGenerator ); +void MVD_Connect_c( genctx_t *ctx, int argnum ) { + Cmd_Option_c( o_mvdconnect, Com_Address_g, ctx, argnum ); } /* @@ -1239,13 +1239,12 @@ static const cmd_option_t o_mvdplay[] = { { NULL } }; -static const char *MVD_FileGenerator( const char *partial, int state ) { - return Com_FileNameGeneratorByFilter( "demos", "*.mvd2;*.mvd2.gz", - partial, qfalse, state ); +void MVD_File_g( genctx_t *ctx ) { + FS_File_g( "demos", "*.mvd2;*.mvd2.gz", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | 0x80000000, ctx ); } -const char *MVD_Play_g( const char *partial, int argnum, int state ) { - return Cmd_Completer( o_mvdplay, partial, argnum, state, MVD_FileGenerator ); +static void MVD_Play_c( genctx_t *ctx, int argnum ) { + Cmd_Option_c( o_mvdplay, MVD_File_g, ctx, argnum ); } void MVD_Play_f( void ) { @@ -1368,8 +1367,8 @@ void MVD_Shutdown( void ) { } static const cmdreg_t c_mvd[] = { - { "mvdplay", MVD_Play_f, MVD_Play_g }, - { "mvdconnect", MVD_Connect_f, MVD_Connect_g }, + { "mvdplay", MVD_Play_f, MVD_Play_c }, + { "mvdconnect", MVD_Connect_f, MVD_Connect_c }, { "mvdisconnect", MVD_Disconnect_f }, { "mvdkill", MVD_Kill_f }, { "mvdspawn", MVD_Spawn_f }, diff --git a/source/mvd_local.h b/source/mvd_local.h index 27ba581..520a47b 100644 --- a/source/mvd_local.h +++ b/source/mvd_local.h @@ -187,7 +187,7 @@ void MVD_Shutdown( void ); mvd_t *MVD_SetChannel( int arg ); -const char *MVD_Play_g( const char *partial, int argnum, int state ); +void MVD_File_g( genctx_t *ctx ); void MVD_Connect_f( void ); void MVD_Spawn_f( void ); diff --git a/source/prompt.c b/source/prompt.c index 0c92ae3..ca058fd 100644 --- a/source/prompt.c +++ b/source/prompt.c @@ -26,79 +26,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "q_field.h" #include "prompt.h" -static char *matches[MAX_MATCHES]; -static char *sortedMatches[MAX_MATCHES]; -static int numMatches; -static int numCommands; -static int numCvars; -static int numAliases; - static cvar_t *com_completion_mode; static cvar_t *com_completion_treshold; -/* -==================== -Prompt_FreeMatches -==================== -*/ -static void Prompt_FreeMatches( void ) { - int i; - - // free them - for( i = 0; i < numMatches; i++ ) { - Z_Free( matches[i] ); - } - - numMatches = 0; - numCommands = 0; - numCvars = 0; - numAliases = 0; - -} - -static void Prompt_RunCompleter( xcompleter_t completer, const char *partial, int argnum ) { - const char *match; - - match = (*completer)( partial, argnum, 0 ); - while( match ) { - matches[numMatches++] = Z_CopyString( match ); - if( numMatches == MAX_MATCHES ) { - (*completer)( partial, argnum, 2 ); - return; - } - match = (*completer)( partial, argnum, 1 ); - } -} - -static void Prompt_RunGenerator( xgenerator_t generator, const char *partial ) { - const char *match; - - match = (*generator)( partial, 0 ); - while( match ) { - matches[numMatches++] = Z_CopyString( match ); - if( numMatches == MAX_MATCHES ) { - (*generator)( partial, 2 ); - return; - } - match = (*generator)( partial, 1 ); - } -} - -static void Prompt_GenerateMatches( const char *partial ) { - Prompt_RunGenerator( Cmd_CommandGenerator, partial ); - numCommands = numMatches; - - if( numMatches != MAX_MATCHES ) { - Prompt_RunGenerator( Cvar_Generator, partial ); - numCvars = numMatches - numCommands; - - if( numMatches != MAX_MATCHES ) { - Prompt_RunGenerator( Cmd_AliasGenerator, partial ); - numAliases = numMatches - numCvars - numCommands; - } - } -} - static void Prompt_ShowMatches( commandPrompt_t *prompt, char **matches, int start, int end ) { @@ -152,75 +82,54 @@ static void Prompt_ShowMatches( commandPrompt_t *prompt, char **matches, } -static void Prompt_ShowIndividualMatches( commandPrompt_t *prompt ) { +static void Prompt_ShowIndividualMatches( + commandPrompt_t *prompt, + char **matches, + int numCommands, + int numAliases, + int numCvars ) +{ int offset = 0; if( numCommands ) { - qsort( matches + offset, numCommands, - sizeof( matches[0] ), SortStrcmp ); + qsort( matches + offset, numCommands, sizeof( matches[0] ), SortStrcmp ); prompt->printf( "\n" S_COLOR_YELLOW "%i possible command%s:\n", - numCommands, ( numCommands % 10 ) != 1 ? "s" : "" ); + numCommands, numCommands != 1 ? "s" : "" ); Prompt_ShowMatches( prompt, matches, offset, offset + numCommands ); offset += numCommands; } if( numCvars ) { - qsort( matches + offset, numCvars, - sizeof( matches[0] ), SortStrcmp ); + qsort( matches + offset, numCvars, sizeof( matches[0] ), SortStrcmp ); prompt->printf( "\n" S_COLOR_YELLOW "%i possible variable%s:\n", - numCvars, ( numCvars % 10 ) != 1 ? "s" : "" ); + numCvars, numCvars != 1 ? "s" : "" ); Prompt_ShowMatches( prompt, matches, offset, offset + numCvars ); offset += numCvars; } if( numAliases ) { - qsort( matches + offset, numAliases, - sizeof( matches[0] ), SortStrcmp ); + qsort( matches + offset, numAliases, sizeof( matches[0] ), SortStrcmp ); prompt->printf( "\n" S_COLOR_YELLOW "%i possible alias%s:\n", - numAliases, ( numAliases % 10 ) != 1 ? "es" : "" ); + numAliases, numAliases != 1 ? "es" : "" ); Prompt_ShowMatches( prompt, matches, offset, offset + numAliases ); offset += numAliases; } } -const char *Prompt_Completer( const char *partial, int firstarg, int argnum, int state ) { - static xcompleter_t completer; - static xgenerator_t generator; - int relative = argnum - firstarg; - - if( relative < 0 ) { - return NULL; +qboolean Prompt_AddMatch( genctx_t *ctx, const char *s ) { + if( ctx->count >= ctx->size ) { + return qfalse; } - - if( !state ) { - if( relative > 0 ) { - char *s = Cmd_Argv( firstarg ); - - generator = NULL; - completer = Cmd_FindCompleter( s ); - if( !completer && relative == 1 ) { - cvar_t *v = Cvar_FindVar( s ); - generator = v->generator; - } - } else { - completer = NULL; - generator = Cmd_MixedGenerator; - } - } - - if( completer ) { - return (*completer)( partial, relative, state ); - } else if( generator ) { - return (*generator)( partial, state ); - } else { - return NULL; + if( !strncmp( ctx->partial, s, ctx->length ) ) { + ctx->matches[ctx->count++] = Z_CopyString( s ); } + return qtrue; } /* @@ -231,18 +140,25 @@ Prompt_CompleteCommand void Prompt_CompleteCommand( commandPrompt_t *prompt, qboolean backslash ) { inputField_t *inputLine = &prompt->inputLine; char *text, *partial, *s; - int i, argc, pos, currentArg, size, length, relative; + int i, argc, pos, currentArg, size, length, argnum; char *first, *last; + genctx_t ctx; + char *matches[MAX_MATCHES], *sortedMatches[MAX_MATCHES]; + int numCommands = 0, numCvars = 0, numAliases = 0; text = inputLine->text; size = sizeof( inputLine->text ); pos = inputLine->cursorPos; + + // prepend backslash if missing if( backslash ) { if( inputLine->text[0] != '\\' && inputLine->text[0] != '/' ) { memmove( inputLine->text + 1, inputLine->text, size - 1 ); inputLine->text[0] = '\\'; } - text++; size--; pos--; + text++; + size--; + pos--; } Cmd_TokenizeString( text, qfalse ); @@ -256,14 +172,14 @@ void Prompt_CompleteCommand( commandPrompt_t *prompt, qboolean backslash ) { currentArg++; } } - relative = 0; + argnum = 0; s = Cmd_Argv( 0 ); for( i = 0; i < currentArg; i++ ) { partial = Cmd_Argv( i ); - relative++; + argnum++; if( *partial == ';' ) { s = Cmd_Argv( i + 1 ); - relative = 0; + argnum = 0; } } @@ -271,24 +187,31 @@ void Prompt_CompleteCommand( commandPrompt_t *prompt, qboolean backslash ) { if( *partial == ';' ) { currentArg++; partial = Cmd_Argv( currentArg ); - relative = 0; + argnum = 0; } - if( relative ) { - xcompleter_t completer = Cmd_FindCompleter( s ); - if( completer ) { - Prompt_RunCompleter( completer, partial, relative ); - } else if( relative == 1 ) { - cvar_t *v = Cvar_FindVar( s ); - if( v && v->generator ) { - Prompt_RunGenerator( v->generator, partial ); - } - } + // generate matches + memset( &ctx, 0, sizeof( ctx ) ); + ctx.partial = partial; + ctx.length = strlen( partial ); + ctx.argnum = currentArg; + ctx.matches = matches; + ctx.size = MAX_MATCHES; + + if( argnum ) { + Com_Generic_c( &ctx, argnum ); } else { - Prompt_GenerateMatches( partial ); + Cmd_Command_g( &ctx ); + numCommands = ctx.count; + + Cvar_Variable_g( &ctx ); + numCvars = ctx.count - numCommands; + + Cmd_Alias_g( &ctx ); + numAliases = ctx.count - numCvars - numCommands; } - if( !numMatches ) { + if( !ctx.count ) { inputLine->cursorPos = strlen( inputLine->text ); prompt->tooMany = qfalse; return; // nothing found @@ -298,7 +221,7 @@ void Prompt_CompleteCommand( commandPrompt_t *prompt, qboolean backslash ) { text += pos; size -= pos; - if( numMatches == 1 ) { + if( ctx.count == 1 ) { // we have finished completion! s = Cmd_RawArgsFrom( currentArg + 1 ); if( COM_HasSpaces( matches[0] ) ) { @@ -308,30 +231,28 @@ void Prompt_CompleteCommand( commandPrompt_t *prompt, qboolean backslash ) { } inputLine->cursorPos = pos + 1; prompt->tooMany = qfalse; - Prompt_FreeMatches(); - return; + goto finish; } - if( numMatches > com_completion_treshold->integer && !prompt->tooMany ) { + if( ctx.count > com_completion_treshold->integer && !prompt->tooMany ) { prompt->printf( "Press TAB again to display all %d possibilities.\n", - numMatches ); + ctx.count ); inputLine->cursorPos = strlen( inputLine->text ); prompt->tooMany = qtrue; - Prompt_FreeMatches(); - return; + goto finish; } prompt->tooMany = qfalse; // sort matches alphabethically - for( i = 0; i < numMatches; i++ ) { + for( i = 0; i < ctx.count; i++ ) { sortedMatches[i] = matches[i]; } - qsort( sortedMatches, numMatches, sizeof( sortedMatches[0] ), SortStrcmp ); + qsort( sortedMatches, ctx.count, sizeof( sortedMatches[0] ), SortStrcmp ); // copy matching part first = sortedMatches[0]; - last = sortedMatches[ numMatches - 1 ]; + last = sortedMatches[ ctx.count - 1 ]; length = 0; do { if( *first != *last ) { @@ -358,30 +279,34 @@ void Prompt_CompleteCommand( commandPrompt_t *prompt, qboolean backslash ) { inputLine->cursorPos = pos + 1; prompt->printf( "]\\%s\n", Cmd_ArgsFrom( 0 ) ); - if( relative ) { + if( argnum ) { goto multi; } switch( com_completion_mode->integer ) { case 0: // print in solid list - for( i = 0 ; i < numMatches; i++ ) { + for( i = 0 ; i < ctx.count; i++ ) { prompt->printf( "%s\n", sortedMatches[i] ); } break; case 1: multi: // print in multiple columns - Prompt_ShowMatches( prompt, sortedMatches, 0, numMatches ); + Prompt_ShowMatches( prompt, sortedMatches, 0, ctx.count ); break; case 2: default: // resort matches by type and print in multiple columns - Prompt_ShowIndividualMatches( prompt ); + Prompt_ShowIndividualMatches( prompt, matches, numCommands, numAliases, numCvars ); break; } - - Prompt_FreeMatches(); + +finish: + // free matches + for( i = 0; i < ctx.count; i++ ) { + Z_Free( matches[i] ); + } } /* diff --git a/source/q_shared.h b/source/q_shared.h index bb2955b..a62b2bf 100644 --- a/source/q_shared.h +++ b/source/q_shared.h @@ -591,9 +591,10 @@ CVARS (console variables) #define CVAR_LATCH 16 // save changes until server restart struct cvar_s; +struct genctx_s; typedef void (*xchanged_t)( struct cvar_s * ); -typedef const char *( *xgenerator_t )( const char *, int ); +typedef void (*xgenerator_t)( struct genctx_s * ); // nothing outside the cvar.*() functions should modify these fields! typedef struct cvar_s { diff --git a/source/snd_local.h b/source/snd_local.h index 51a84f9..3344222 100644 --- a/source/snd_local.h +++ b/source/snd_local.h @@ -135,9 +135,6 @@ void S_IssuePlaysound (playsound_t *ps); void S_PaintChannels(int endtime); -// picks a channel based on priorities, empty slots, number of channels -channel_t *S_PickChannel(int entnum, int entchannel); - // spatializes a channel void S_Spatialize(channel_t *ch); diff --git a/source/snd_main.c b/source/snd_main.c index 616957e..cfd8753 100644 --- a/source/snd_main.c +++ b/source/snd_main.c @@ -138,12 +138,8 @@ static void S_SoundInfo_f( void ) { } -const char *S_Play_g( const char *partial, int argnum, int state ) { - if( argnum == 1 ) { - return Com_FileNameGeneratorByFilter( "sound", "*.wav", partial, - qfalse, state ); - } - return NULL; +static void S_Play_c( genctx_t *ctx, int state ) { + FS_File_g( "sound", "*.wav", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER | 0x80000000, ctx ); } static void S_Play_f( void ) { @@ -193,7 +189,7 @@ static void S_SoundList_f( void ) { static const cmdreg_t c_sound[] = { - { "play", S_Play_f, S_Play_g }, + { "play", S_Play_f, S_Play_c }, { "stopsound", S_StopAllSounds }, { "soundlist", S_SoundList_f }, { "soundinfo", S_SoundInfo_f }, @@ -483,9 +479,11 @@ void S_EndRegistration( void ) { /* ================= S_PickChannel + +picks a channel based on priorities, empty slots, number of channels ================= */ -channel_t *S_PickChannel( int entnum, int entchannel ) { +static channel_t *S_PickChannel( int entnum, int entchannel ) { int ch_idx; int first_to_die; int life_left; @@ -497,24 +495,27 @@ channel_t *S_PickChannel( int entnum, int entchannel ) { // Check for replacement sound, or find the best one to replace first_to_die = -1; life_left = 0x7fffffff; - for( ch_idx=0 ; ch_idx<MAX_CHANNELS ; ch_idx++ ) { - if( entchannel != 0 // channel 0 never overrides - && channels[ch_idx].entnum == entnum - && channels[ch_idx].entchannel == entchannel ) - { // always override sound from same entity + for( ch_idx = 0; ch_idx < MAX_CHANNELS; ch_idx++ ) { + ch = &channels[ch_idx]; + // channel 0 never overrides unless out of channels + if( ch->entnum == entnum && ch->entchannel == entchannel && entchannel != 0 ) { + if( entchannel == 256 && ch->sfx ) { + return NULL; // channel 256 never overrides + } + // always override sound from same entity first_to_die = ch_idx; break; } // don't let monster sounds override player sounds - if( channels[ch_idx].entnum == listener_entnum && entnum != listener_entnum && channels[ch_idx].sfx ) + if( ch->entnum == listener_entnum && entnum != listener_entnum && ch->sfx ) continue; - if( channels[ch_idx].end - paintedtime < life_left ) { - life_left = channels[ch_idx].end - paintedtime; + if( ch->end - paintedtime < life_left ) { + life_left = ch->end - paintedtime; first_to_die = ch_idx; } - } + } if( first_to_die == -1 ) return NULL; @@ -821,13 +822,17 @@ S_StartLocalSound ================== */ void S_StartLocalSound( const char *sound ) { - qhandle_t sfx; + if( sound_started ) { + qhandle_t sfx = S_RegisterSound( sound ); + S_StartSound( NULL, listener_entnum, 0, sfx, 1, 1, 0 ); + } +} - if( !sound_started ) - return; - - sfx = S_RegisterSound( sound ); - S_StartSound( NULL, listener_entnum, 0, sfx, 1, 1, 0 ); +void S_StartLocalSound_( const char *sound ) { + if( sound_started ) { + qhandle_t sfx = S_RegisterSound( sound ); + S_StartSound( NULL, listener_entnum, 256, sfx, 1, 1, 0 ); + } } diff --git a/source/snd_public.h b/source/snd_public.h index f344121..9354743 100644 --- a/source/snd_public.h +++ b/source/snd_public.h @@ -23,9 +23,8 @@ void S_Shutdown (void); // if origin is NULL, the sound will be dynamically sourced from the entity void S_StartSound (const vec3_t origin, int entnum, int entchannel, qhandle_t sfx, float fvol, float attenuation, float timeofs); -void S_StartLocalSound (const char *s); - -void S_RawSamples (int samples, int rate, int width, int channels, byte *data); +void S_StartLocalSound( const char *s ); +void S_StartLocalSound_( const char *s ); void S_FreeAllSounds( void ); void S_StopAllSounds(void); @@ -37,10 +36,6 @@ void S_BeginRegistration (void); qhandle_t S_RegisterSound (const char *sample); void S_EndRegistration (void); -// the sound code makes callbacks to the client for entitiy position -// information, so entities can be dynamically re-spatialized -void CL_GetEntitySoundOrigin (int ent, vec3_t org); - extern vec3_t listener_origin; extern vec3_t listener_forward; extern vec3_t listener_right; diff --git a/source/sv_ccmds.c b/source/sv_ccmds.c index 9641cb6..c52a02e 100644 --- a/source/sv_ccmds.c +++ b/source/sv_ccmds.c @@ -75,34 +75,29 @@ static void SV_SetMaster_f( void ) { svs.last_heartbeat = 0; } -static const char *SV_SetPlayer_g( const char *partial, int argnum, int state ) { - static int length; - static int index; - client_t *client; +static void SV_Player_g( genctx_t *ctx ) { + int i; + client_t *c; if( !svs.initialized ) { - return NULL; + return; } - if( argnum != 1 ) { - return NULL; - } - if( !state ) { - length = strlen( partial ); - index = 0; - } - - while( index < sv_maxclients->integer ) { - client = &svs.udp_client_pool[index++]; - if( !client->state || client->protocol == -1 ) { + for( i = 0; i < sv_maxclients->integer; i++ ) { + c = &svs.udp_client_pool[i]; + if( !c->state || c->protocol == -1 ) { continue; } - if( !strncmp( partial, client->name, length ) ) { - return client->name; + if( !Prompt_AddMatch( ctx, c->name ) ) { + break; } } +} - return NULL; +static void SV_SetPlayer_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + SV_Player_g( ctx ); + } } @@ -219,11 +214,10 @@ static void SV_Map_f( void ) { SV_Map( Cmd_Argv( 1 ), qtrue ); } -static const char *SV_Map_g( const char *partial, int argnum, int state ) { +static void SV_Map_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { - return Com_FileNameGenerator( "maps", ".bsp", partial, qtrue, state ); + FS_File_g( "maps", ".bsp", 0x80000000, ctx ); } - return NULL; } //=============================================================== @@ -800,15 +794,15 @@ static int SV_ClientNum_m( char *buffer, int size ) { static const cmdreg_t c_server[] = { { "heartbeat", SV_Heartbeat_f }, - { "kick", SV_Kick_f, SV_SetPlayer_g }, + { "kick", SV_Kick_f, SV_SetPlayer_c }, { "status", SV_Status_f }, { "serverinfo", SV_Serverinfo_f }, - { "dumpuser", SV_DumpUser_f, SV_SetPlayer_g }, - { "stuff", SV_Stuff_f, SV_SetPlayer_g }, + { "dumpuser", SV_DumpUser_f, SV_SetPlayer_c }, + { "stuff", SV_Stuff_f, SV_SetPlayer_c }, { "stuffall", SV_Stuffall_f }, - { "map", SV_Map_f, SV_Map_g }, + { "map", SV_Map_f, SV_Map_c }, { "demomap", SV_DemoMap_f }, - { "gamemap", SV_GameMap_f, SV_Map_g }, + { "gamemap", SV_GameMap_f, SV_Map_c }, { "setmaster", SV_SetMaster_f }, { "killserver", SV_KillServer_f }, { "sv", SV_ServerCommand_f }, diff --git a/source/sv_mvd.c b/source/sv_mvd.c index 31c443e..04c1849 100644 --- a/source/sv_mvd.c +++ b/source/sv_mvd.c @@ -887,6 +887,12 @@ void SV_MvdRecStop( void ) { sv.mvd.file = 0; } +static void MVD_Record_c( genctx_t *ctx, int argnum ) { + if( argnum == 1 ) { + MVD_File_g( ctx ); + } +} + /* ============== MVD_Record_f @@ -990,7 +996,7 @@ static void MVD_Stuff_f( void ) { } static const cmdreg_t c_svmvd[] = { - { "mvdrecord", MVD_Record_f, MVD_Play_g }, + { "mvdrecord", MVD_Record_f, MVD_Record_c }, { "mvdstop", MVD_Stop_f }, { "mvdstuff", MVD_Stuff_f }, |