diff --git a/cs-code/Makefile.am b/cs-code/Makefile.am index 0413d522e..5a57d5941 100644 --- a/cs-code/Makefile.am +++ b/cs-code/Makefile.am @@ -19,7 +19,7 @@ STRIP=$(shell echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c) pkgdata_DATA= menu.dat$(GZ) menu_src= \ - cbuf_def.qc controls_o.qc cvar_def.qc draw_def.qc file_def.qc \ + cbuf_def.qc cmd_def.qc controls_o.qc cvar_def.qc draw_def.qc file_def.qc \ game_def.qc inputline_def.qc inputline_util.qc key_defs.qc menu.qc \ menu_def.qc menu_pics.qc menu_util.qc options.qc options_util.qc \ servlist.qc string_def.qc stringh_def.qc diff --git a/cs-code/cmd_def.qc b/cs-code/cmd_def.qc new file mode 100644 index 000000000..a9cc73ecc --- /dev/null +++ b/cs-code/cmd_def.qc @@ -0,0 +1,5 @@ +void (string name, void () func) Cmd_AddCommand = #0; +integer () Cmd_Argc = #0; +string (integer arg) Cmd_Argv = #0; +string (integer arg) Cmd_Args = #0; +string (integer arg) Cmd_Argu = #0; diff --git a/cs-code/menu.qc b/cs-code/menu.qc index 601760ca7..8f092ad5d 100644 --- a/cs-code/menu.qc +++ b/cs-code/menu.qc @@ -88,6 +88,14 @@ integer (string text, integer key) save_f = return 0; }; +void () load_save_f = +{ + if (Cmd_Argv (0) == "menu_load") + Menu_SelectMenu ("load"); + else + Menu_SelectMenu ("save"); +}; + integer () load_draw = { local integer i; @@ -103,7 +111,7 @@ integer () save_draw = { local integer i; - Draw_CenterPic (160, 4, Draw_CachePic ("p_save.lmp", 1)); + Draw_CenterPic (160, 4, Draw_CachePic ("gfx/p_save.lmp", 1)); for (i=0 ; i< MAX_SAVEGAMES; i++) Draw_String (16, 32 + 8 * i, filenames[i]); Draw_Character (8, 32 + save_cursor * 8, 12 + (integer (time * 4) & 1)); @@ -163,6 +171,7 @@ void () load_menu = Menu_KeyEvent (load_keyevent); Menu_Draw (load_draw); Menu_End (); + Cmd_AddCommand ("menu_load", load_save_f); }; void () save_menu = @@ -172,6 +181,7 @@ void () save_menu = Menu_KeyEvent (save_keyevent); Menu_Draw (save_draw); Menu_End (); + Cmd_AddCommand ("menu_save", load_save_f); }; // ********* QUIT diff --git a/cs-code/menu.src.in b/cs-code/menu.src.in index 53850d52f..b13e30ff7 100644 --- a/cs-code/menu.src.in +++ b/cs-code/menu.src.in @@ -1,7 +1,8 @@ menu.dat -@srcdir@/cvar_def.qc @srcdir@/cbuf_def.qc +@srcdir@/cmd_def.qc +@srcdir@/cvar_def.qc @srcdir@/draw_def.qc @srcdir@/file_def.qc @srcdir@/game_def.qc diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 8f435e686..cd053871a 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -128,7 +128,8 @@ void Cmd_Init_Hash (void); void Cmd_Init (void); void cl_Cmd_Init (void); -void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description); +int Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description); +int Cmd_RemoveCommand (const char *cmd_name); // called by the init functions of other parts of the program to // register commands and functions to call for them. // The cmd_name is referenced later, so it should not be in temp memory diff --git a/include/QF/csqc.h b/include/QF/csqc.h index f00be1a4a..597f913a4 100644 --- a/include/QF/csqc.h +++ b/include/QF/csqc.h @@ -37,11 +37,12 @@ void BI_Init (); struct progs_s; void Cbuf_Progs_Init (struct progs_s *pr); +void Cmd_Progs_Init (struct progs_s *pr); +void Cvar_Progs_Init (struct progs_s *pr); void File_Progs_Init (struct progs_s *pr); void InputLine_Progs_Init (struct progs_s *pr); +void Key_Progs_Init (struct progs_s *pr); void String_Progs_Init (struct progs_s *pr); void StringHash_Progs_Init (struct progs_s *pr); -void Cvar_Progs_Init (struct progs_s *pr); -void Key_Progs_Init (struct progs_s *pr); #endif//__QF_csqc_h diff --git a/libs/console/menu.c b/libs/console/menu.c index fb347eb12..339a3abb5 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -378,14 +378,15 @@ Menu_Init (void) PR_AddBuiltin (&menu_pr_state, "Menu_GetIndex", bi_Menu_GetIndex, -1); Cbuf_Progs_Init (&menu_pr_state); + Cmd_Progs_Init (&menu_pr_state); + Cvar_Progs_Init (&menu_pr_state); File_Progs_Init (&menu_pr_state); InputLine_Progs_Init (&menu_pr_state); - String_Progs_Init (&menu_pr_state); - StringHash_Progs_Init (&menu_pr_state); - Cvar_Progs_Init (&menu_pr_state); Key_Progs_Init (&menu_pr_state); PR_Cmds_Init (&menu_pr_state); R_Progs_Init (&menu_pr_state); + String_Progs_Init (&menu_pr_state); + StringHash_Progs_Init (&menu_pr_state); confirm_quit = Cvar_Get ("confirm_quit", "1", CVAR_ARCHIVE, NULL, "confirm quit command"); diff --git a/libs/gamecode/builtins/Makefile.am b/libs/gamecode/builtins/Makefile.am index 912dbdc28..700cf9be9 100644 --- a/libs/gamecode/builtins/Makefile.am +++ b/libs/gamecode/builtins/Makefile.am @@ -8,4 +8,6 @@ libQFgamecode_builtins_la_LDFLAGS= -version-info 1:0:0 libQFgamecode_builtins_la_SOURCES= pr_cmds.c libQFcsqc_la_LDFLAGS= -version-info 1:0:0 -libQFcsqc_la_SOURCES= bi_init.c bi_cbuf.c bi_file.c bi_inputline.c bi_string.c bi_cvar.c bi_keys.c bi_strhash.c +libQFcsqc_la_SOURCES=\ + bi_cbuf.c bi_cmd.c bi_cvar.c bi_file.c bi_init.c bi_inputline.c \ + bi_keys.c bi_string.c bi_strhash.c diff --git a/libs/gamecode/builtins/bi_cmd.c b/libs/gamecode/builtins/bi_cmd.c new file mode 100644 index 000000000..12a81b682 --- /dev/null +++ b/libs/gamecode/builtins/bi_cmd.c @@ -0,0 +1,171 @@ +/* + bi_cmd.c + + Command api for csqc + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2002/4/12 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmd.h" +#include "QF/hash.h" +#include "QF/progs.h" +#include "QF/sys.h" + +typedef struct bi_cmd_s { + struct bi_cmd_s *next; + char *name; + progs_t *pr; + func_t func; +} bi_cmd_t; + +typedef struct { + bi_cmd_t *cmds; +} cmd_resources_t; + +static hashtab_t *bi_cmds; + +static const char * +bi_cmd_get_key (void *c, void *unused) +{ + return ((bi_cmd_t *)c)->name; +} + +static void +bi_cmd_free (void *_c, void *unused) +{ + bi_cmd_t *c = (bi_cmd_t *) _c; + + free (c->name); + free (c); +} + +static void +bi_cmd_f (void *pr) +{ + bi_cmd_t *cmd = Hash_Find (bi_cmds, Cmd_Argv (0)); + + if (!cmd) + Sys_Error ("bi_cmd_f: unexpected call %s\n", Cmd_Argv (0)); + PR_ExecuteProgram (cmd->pr, cmd->func); +} + +static void +bi_Cmd_AddCommand (progs_t *pr) +{ + cmd_resources_t *res = PR_Resources_Find (pr, "Cmd"); + bi_cmd_t *cmd = malloc (sizeof (bi_cmd_t)); + char *name = strdup (G_STRING (pr, OFS_PARM0)); + func_t func = G_FUNCTION (pr, OFS_PARM1); + + if (!cmd || !name || !Cmd_AddCommand (name, (void(*)(void))bi_cmd_f, "CSQC command")) { + if (name) + free (name); + if (cmd) + free (cmd); + G_INT (pr, OFS_RETURN) = 0; + return; + } + cmd->name = name; + cmd->func = func; + cmd->pr = pr; + Hash_Add (bi_cmds, cmd); + cmd->next = res->cmds; + res->cmds = cmd; + G_INT (pr, OFS_RETURN) = 1; +} + +static void +bi_cmd_clear (progs_t *pr, void *data) +{ + cmd_resources_t *res = (cmd_resources_t *)data; + bi_cmd_t *cmd; + + while ((cmd = res->cmds)) { + Cmd_RemoveCommand (cmd->name); + Hash_Del (bi_cmds, cmd->name); + res->cmds = cmd->next; + bi_cmd_free (cmd, 0); + } +} + +static void +bi_Cmd_Argc (progs_t *pr) +{ + G_INT (pr, OFS_RETURN) = Cmd_Argc (); +} + +static void +bi_Cmd_Argv (progs_t *pr) +{ + RETURN_STRING (pr, Cmd_Argv (G_INT (pr, OFS_PARM0))); +} + +static void +bi_Cmd_Args (progs_t *pr) +{ + RETURN_STRING (pr, Cmd_Args (G_INT (pr, OFS_PARM0))); +} + +static void +bi_Cmd_Argu (progs_t *pr) +{ + RETURN_STRING (pr, Cmd_Argu (G_INT (pr, OFS_PARM0))); +} + +//Cmd_CheckParm +//Cmd_TokenizeString +//Cmd_ExecuteString +//Cmd_ForwardToServer + +void +Cmd_Progs_Init (progs_t *pr) +{ + cmd_resources_t *res = malloc (sizeof (cmd_resources_t)); + + res->cmds = 0; + PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); + + bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0); + + PR_AddBuiltin (pr, "Cmd_AddCommand", bi_Cmd_AddCommand, -1); + PR_AddBuiltin (pr, "Cmd_Argc", bi_Cmd_Argc, -1); + PR_AddBuiltin (pr, "Cmd_Argv", bi_Cmd_Argv, -1); + PR_AddBuiltin (pr, "Cmd_Args", bi_Cmd_Args, -1); + PR_AddBuiltin (pr, "Cmd_Argu", bi_Cmd_Argu, -1); +} diff --git a/libs/gamecode/builtins/bi_init.c b/libs/gamecode/builtins/bi_init.c index 7cf7be214..b78a957ce 100644 --- a/libs/gamecode/builtins/bi_init.c +++ b/libs/gamecode/builtins/bi_init.c @@ -33,13 +33,14 @@ static const char rcsid[] = #include "QF/csqc.h" #include "QF/progs.h" -static void (*const cbuf_progs_init)(struct progs_s *) = Cbuf_Progs_Init; -static void (*const file_progs_init)(struct progs_s *) = File_Progs_Init; -static void (*const inputline_progs_init)(struct progs_s *) = InputLine_Progs_Init; -static void (*const string_progs_init)(struct progs_s *) = String_Progs_Init; -static void (*const stringhashe_progs_init)(struct progs_s *) = StringHash_Progs_Init; -static void (*const cvar_progs_init)(struct progs_s *) = Cvar_Progs_Init; -static void (*const key_progs_init)(struct progs_s *) = Key_Progs_Init; +static void (*const cbuf_progs_init)(progs_t *) = Cbuf_Progs_Init; +static void (*const cvar_progs_init)(progs_t *) = Cvar_Progs_Init; +static void (*const cmd_progs_init)(progs_t *) = Cmd_Progs_Init; +static void (*const file_progs_init)(progs_t *) = File_Progs_Init; +static void (*const key_progs_init)(progs_t *) = Key_Progs_Init; +static void (*const inputline_progs_init)(progs_t *) = InputLine_Progs_Init; +static void (*const string_progs_init)(progs_t *) = String_Progs_Init; +static void (*const stringhashe_progs_init)(progs_t *) = StringHash_Progs_Init; void BI_Init () diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 2a422cd7e..2415b3550 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -779,6 +779,7 @@ typedef struct cmd_function_s { const char *name; xcommand_t function; const char *description; + void *data; qboolean pure; } cmd_function_t; @@ -1349,7 +1350,7 @@ Cmd_TokenizeString (const char *text, qboolean legacy) cmd_activebuffer->argc = cmd_argc; } -void +int Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description) { @@ -1359,13 +1360,13 @@ Cmd_AddCommand (const char *cmd_name, xcommand_t function, // fail if the command is a variable name if (Cvar_FindVar (cmd_name)) { Sys_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name); - return; + return 0; } // fail if the command already exists cmd = (cmd_function_t *) Hash_Find (cmd_hash, cmd_name); if (cmd) { Sys_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); - return; + return 0; } cmd = calloc (1, sizeof (cmd_function_t)); @@ -1380,6 +1381,24 @@ Cmd_AddCommand (const char *cmd_name, xcommand_t function, break; cmd->next = *c; *c = cmd; + return 1; +} + +int +Cmd_RemoveCommand (const char *name) +{ + cmd_function_t *cmd; + cmd_function_t **c; + + cmd = (cmd_function_t *) Hash_Del (cmd_hash, name); + if (!cmd) + return 0; + for (c = &cmd_functions; *c; c = &(*c)->next) + if ((*c)->next == cmd) + break; + (*c)->next = cmd->next; + free (cmd); + return 1; } void