diff --git a/include/QF/console.h b/include/QF/console.h index ff08c84d0..f0f019790 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -131,5 +131,7 @@ void Con_Demolist_DEM_f (void); void Menu_Init (void); void Menu_Load (void); +void Menu_Draw (void); +void Menu_KeyEvent (knum_t key, short unicode, qboolean down); #endif // __console_h diff --git a/include/QF/keys.h b/include/QF/keys.h index 3d80be1a9..87190c2c8 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -365,7 +365,7 @@ typedef enum { } imt_t; // Input Mapping Table // key_none should, preferably, be last -typedef enum {key_game, key_console, key_message, key_none} keydest_t; +typedef enum {key_game, key_console, key_message, key_menu, key_none} keydest_t; extern keydest_t key_dest; extern imt_t game_target; diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index d5c6dd683..b266e4aa2 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -37,7 +37,7 @@ typedef void (QFPLUGIN *P_C_Print) (const char *fmt, va_list args); typedef void (QFPLUGIN *P_C_ProcessInput) (void); -typedef void (QFPLUGIN *P_C_KeyEvent) (key_t key, short unicode, qboolean down); +typedef void (QFPLUGIN *P_C_KeyEvent) (knum_t key, short unicode, qboolean down); typedef void (QFPLUGIN *P_C_DrawConsole) (int lines); typedef void (QFPLUGIN *P_C_CheckResize) (void); typedef void (QFPLUGIN *P_C_NewMap) (void); diff --git a/include/QF/progs.h b/include/QF/progs.h index d204629ad..2448423da 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -168,6 +168,7 @@ pr_type_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, const char *field); void PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num); builtin_t *PR_FindBuiltin (progs_t *pr, const char *name); int PR_RelocateBuiltins (progs_t *pr); +int PR_ResolveGlobals (progs_t *pr); // // PR Strings stuff diff --git a/libs/console/client.c b/libs/console/client.c index 840ed6edd..548741979 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -462,7 +462,7 @@ C_Print (const char *fmt, va_list args) } static void -C_KeyEvent (key_t key, short unicode, qboolean down) +C_KeyEvent (knum_t key, short unicode, qboolean down) { inputline_t *il; @@ -508,6 +508,8 @@ C_KeyEvent (key_t key, short unicode, qboolean down) if (con->display > con->current) con->display = con->current; return; + default: + break; } il = input_line; } @@ -698,6 +700,8 @@ C_DrawConsole (int lines) } else { if (key_dest == key_game || key_dest == key_message) DrawNotify (); // only draw notify in game + else if (key_dest == key_menu) + Menu_Draw (); } } diff --git a/libs/console/menu.c b/libs/console/menu.c index 3c4b7b01b..fef53c6af 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -34,6 +34,7 @@ static const char rcsid[] = #include #include "QF/console.h" +#include "QF/hash.h" #include "QF/plugin.h" #include "QF/progs.h" #include "QF/vfs.h" @@ -58,6 +59,58 @@ typedef struct menu_item_s { static progs_t menu_pr_state; static menu_item_t *menu; +static hashtab_t *menu_hash; +static func_t menu_init; +static func_t menu_keyevent; +static func_t menu_draw; + +static int +menu_resolve_globals (void) +{ + char *sym; + dfunction_t *f; + + if (!(f = ED_FindFunction (&menu_pr_state, sym = "menu_init"))) + goto error; + menu_init = (func_t)(f - menu_pr_state.pr_functions); + if ((f = ED_FindFunction (&menu_pr_state, "menu_keyevent"))) + menu_keyevent = (func_t)(f - menu_pr_state.pr_functions); + if ((f = ED_FindFunction (&menu_pr_state, "menu_draw"))) + menu_draw = (func_t)(f - menu_pr_state.pr_functions); + return 1; +error: + Con_Printf ("%s: undefined function %s\n", menu_pr_state.progs_name, sym); + return 0; +} + +static const char * +menu_get_key (void *m, void *unused) +{ + return ((menu_item_t *)m)->text; +} + +static void +menu_free (void *_m, void *unused) +{ + menu_item_t *m = (menu_item_t *)_m; + + if (m->text) + free ((char*)m->text); + if (m->items) { + int i; + + for (i = 0; i < m->num_items; i++) + menu_free (m->items[i], 0); + free (m->items); + } + while (m->pics) { + menu_pic_t *p = m->pics; + m->pics = p->next; + if (p->name) + free ((char*)p->name); + free (p); + } +} static void menu_add_item (menu_item_t *m, menu_item_t *i) @@ -67,6 +120,7 @@ menu_add_item (menu_item_t *m, menu_item_t *i) (m->max_items + 8) * sizeof (menu_item_t *)); m->max_items += 8; } + i->parent = m; m->items[m->num_items++] = i; } @@ -80,10 +134,11 @@ bi_Menu_Begin (progs_t *pr) m->x = x; m->y = y; - m->text = text; - m->parent = menu; - menu_add_item (menu, m); + m->text = strdup (text); + if (menu) + menu_add_item (menu, m); menu = m; + Hash_Add (menu_hash, m); } static void @@ -127,7 +182,7 @@ bi_Menu_Item (progs_t *pr) mi->x = x; mi->y = y; - mi->text = text; + mi->text = strdup (text); mi->func = func; mi->parent = menu; menu_add_item (menu, mi); @@ -151,6 +206,8 @@ Menu_Init (void) { menu_pr_state.progs_name = "menu.dat"; + menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0); + PR_AddBuiltin (&menu_pr_state, "Menu_Begin", bi_Menu_Begin, -1); PR_AddBuiltin (&menu_pr_state, "Menu_Pic", bi_Menu_Pic, -1); PR_AddBuiltin (&menu_pr_state, "Menu_CenterPic", bi_Menu_CenterPic, -1); @@ -171,23 +228,48 @@ Menu_Load (void) free (menu_pr_state.progs); menu_pr_state.progs = 0; } + Hash_FlushTable (menu_hash); + menu = 0; - if ((size = COM_FOpenFile ("menu.dat", &file)) != -1) { + if ((size = COM_FOpenFile (menu_pr_state.progs_name, &file)) != -1) { menu_pr_state.progs = malloc (size + 256 * 1024); Qread (file, menu_pr_state.progs, size); Qclose (file); memset ((char *)menu_pr_state.progs + size, 0, 256 * 1024); - PR_LoadProgs (&menu_pr_state, 0); - if (!PR_RelocateBuiltins (&menu_pr_state)) { + PR_LoadProgsFile (&menu_pr_state, 0); + + if (!PR_RelocateBuiltins (&menu_pr_state) + || !PR_ResolveGlobals (&menu_pr_state) + || !menu_resolve_globals ()) { free (menu_pr_state.progs); menu_pr_state.progs = 0; + } else { + PR_LoadStrings (&menu_pr_state); + PR_LoadDebug (&menu_pr_state); + PR_Check_Opcodes (&menu_pr_state); } } if (!menu_pr_state.progs) { // Not a fatal error, just means no menus Con_SetOrMask (0x80); - Con_Printf ("Menu_Load: could not load menu.dat\n"); + Con_Printf ("Menu_Load: could not load %s\n", + menu_pr_state.progs_name); Con_SetOrMask (0x00); return; } + PR_ExecuteProgram (&menu_pr_state, menu_init); +} + +void +Menu_Draw (void) +{ + if (!menu) + return; +} + +void +Menu_KeyEvent (knum_t key, short unicode, qboolean down) +{ + if (!menu) + return; } diff --git a/libs/gamecode/engine/pr_edict.c b/libs/gamecode/engine/pr_edict.c index 72ce9b1ae..815ec3ebe 100644 --- a/libs/gamecode/engine/pr_edict.c +++ b/libs/gamecode/engine/pr_edict.c @@ -1193,11 +1193,32 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname) ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); } +int +PR_ResolveGlobals (progs_t *pr) +{ + char *sym; + + if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, sym = "time"))) + goto error; + if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, sym = "self"))) + goto error; + if ((pr->fields.nextthink = ED_GetFieldIndex (pr, sym = "nextthink")) == -1) + goto error; + if ((pr->fields.frame = ED_GetFieldIndex (pr, sym = "frame")) == -1) + goto error; + if ((pr->fields.think = ED_GetFieldIndex (pr, sym = "think")) == -1) + goto error; + return 1; +error: + Sys_Printf ("%s: undefined symbol: %s", pr->progs_name, sym); + return 0; +} + /* PR_LoadProgs */ void -PR_LoadProgs (progs_t * pr, const char *progsname) +PR_LoadProgs (progs_t *pr, const char *progsname) { PR_LoadProgsFile (pr, progsname); if (!pr->progs) @@ -1206,17 +1227,6 @@ PR_LoadProgs (progs_t * pr, const char *progsname) if (!progsname) progsname = "(preloaded)"; - if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, "time"))) - PR_Error (pr, "%s: undefined symbol: time", progsname); - if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, "self"))) - PR_Error (pr, "%s: undefined symbol: self", progsname); - if ((pr->fields.nextthink = ED_GetFieldIndex (pr, "nextthink")) == -1) - PR_Error (pr, "%s: undefined field: nextthink", progsname); - if ((pr->fields.frame = ED_GetFieldIndex (pr, "frame")) == -1) - PR_Error (pr, "%s: undefined field: frame", progsname); - if ((pr->fields.think = ED_GetFieldIndex (pr, "think")) == -1) - PR_Error (pr, "%s: undefined field: think", progsname); - // initialise the strings managment code PR_LoadStrings (pr);