summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/cl_console.c36
-rw-r--r--source/cl_demo.c10
-rw-r--r--source/cl_draw.c41
-rw-r--r--source/cl_keys.c37
-rw-r--r--source/cl_local.h5
-rw-r--r--source/cl_main.c94
-rw-r--r--source/cl_parse.c20
-rw-r--r--source/cmd.c196
-rw-r--r--source/com_local.h36
-rw-r--r--source/com_public.h12
-rw-r--r--source/common.c119
-rw-r--r--source/cvar.c92
-rw-r--r--source/files.c60
-rw-r--r--source/mvd_client.c17
-rw-r--r--source/mvd_local.h2
-rw-r--r--source/prompt.c213
-rw-r--r--source/q_shared.h3
-rw-r--r--source/snd_local.h3
-rw-r--r--source/snd_main.c51
-rw-r--r--source/snd_public.h9
-rw-r--r--source/sv_ccmds.c48
-rw-r--r--source/sv_mvd.c8
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 },