diff options
-rw-r--r-- | source/cl_demo.c | 79 | ||||
-rw-r--r-- | source/cl_main.c | 1 | ||||
-rw-r--r-- | source/com_local.h | 2 | ||||
-rw-r--r-- | source/files.c | 33 | ||||
-rw-r--r-- | source/gl_images.c | 12 | ||||
-rw-r--r-- | source/mvd_client.c | 54 | ||||
-rw-r--r-- | source/q_shared.c | 22 | ||||
-rw-r--r-- | source/q_shared.h | 8 | ||||
-rw-r--r-- | source/sv_mvd.c | 47 | ||||
-rw-r--r-- | source/ui_atoms.c | 594 | ||||
-rw-r--r-- | source/ui_local.h | 15 | ||||
-rw-r--r-- | source/ui_menu.c | 1616 | ||||
-rw-r--r-- | source/ui_script.c | 177 |
13 files changed, 1492 insertions, 1168 deletions
diff --git a/source/cl_demo.c b/source/cl_demo.c index 4c3917e..41f7466 100644 --- a/source/cl_demo.c +++ b/source/cl_demo.c @@ -34,7 +34,7 @@ Dumps the current demo message, prefixed by the length. ==================== */ void CL_WriteDemoMessage( sizebuf_t *buf ) { - uint32_t length; + uint32_t msglen; if( buf->overflowed ) { SZ_Clear( buf ); @@ -45,8 +45,8 @@ void CL_WriteDemoMessage( sizebuf_t *buf ) { return; } - length = LittleLong( buf->cursize ); - FS_Write( &length, 4, cls.demorecording ); + msglen = LittleLong( buf->cursize ); + FS_Write( &msglen, 4, cls.demorecording ); FS_Write( buf->data, buf->cursize, cls.demorecording ); SZ_Clear( buf ); @@ -213,7 +213,7 @@ stop recording a demo ==================== */ void CL_Stop_f( void ) { - uint32_t length; + uint32_t msglen; if( !cls.demorecording ) { Com_Printf( "Not recording a demo.\n" ); @@ -229,19 +229,22 @@ void CL_Stop_f( void ) { } // finish up - length = ( uint32_t )-1; - FS_Write( &length, 4, cls.demorecording ); + msglen = ( uint32_t )-1; + FS_Write( &msglen, 4, cls.demorecording ); - length = FS_RawTell( cls.demorecording ); + FS_Flush( cls.demorecording ); + msglen = FS_RawTell( cls.demorecording ); // close demofile FS_FCloseFile( cls.demorecording ); cls.demorecording = 0; cls.demopaused = qfalse; - Com_Printf( "Stopped demo (%u bytes written).\n", length ); + Com_Printf( "Stopped demo (%u bytes written).\n", msglen ); } +extern const cmd_option_t o_mvdrecord[]; + /* ==================== CL_Record_f @@ -258,18 +261,8 @@ void CL_Record_f( void ) { entity_state_t *ent; char *string; fileHandle_t demofile; - qboolean compressed = qfalse; - - i = 1; - if( !strcmp( Cmd_Argv( i ), "-c" ) || !strcmp( Cmd_Argv( i ), "--compressed" ) ) { - compressed = qtrue; - i++; - } - - if( i >= Cmd_Argc() ) { - Com_Printf( "Usage: %s [-c|--compressed] [/]<filename>\n", Cmd_Argv( 0 ) ); - return; - } + qboolean gzip = qfalse; + int c; if( cls.demorecording ) { Com_Printf( "Already recording.\n" ); @@ -281,18 +274,36 @@ void CL_Record_f( void ) { return; } + while( ( c = Cmd_ParseOptions( o_mvdrecord ) ) != -1 ) { + switch( c ) { + case 'h': + Cmd_PrintUsage( o_mvdrecord, "[/]<filename>" ); + Com_Printf( "Begin client demo recording.\n" ); + Cmd_PrintHelp( o_mvdrecord ); + return; + case 'z': + gzip = qtrue; + break; + } + } + + if( !cmd_optarg[0] ) { + Com_Printf( "Missing filename argument.\n" ); + Cmd_PrintHint(); + return; + } + // // open the demo file // - string = Cmd_Argv( i ); - if( *string == '/' ) { - Q_strncpyz( name, string + 1, sizeof( name ) ); + if( cmd_optarg[0] == '/' ) { + Q_strncpyz( name, cmd_optarg + 1, sizeof( name ) ); } else { - Q_concat( name, sizeof( name ), "demos/", string, NULL ); + Q_concat( name, sizeof( name ), "demos/", cmd_optarg, NULL ); COM_AppendExtension( name, ".dm2", sizeof( name ) ); - } - if( compressed ) { - Q_strcat( name, sizeof( name ), ".gz" ); + if( gzip ) { + COM_AppendExtension( name, ".gz", sizeof( name ) ); + } } FS_FOpenFile( name, &demofile, FS_MODE_WRITE ); @@ -303,7 +314,7 @@ void CL_Record_f( void ) { Com_Printf( "Recording client demo to %s.\n", name ); - if( compressed ) { + if( gzip ) { FS_FilterFile( demofile ); } @@ -444,6 +455,18 @@ static int CL_ReadFirstDemoMessage( fileHandle_t f ) { return -1; } + if( ( ( LittleLong( ul ) & 0xe0ffffff ) == 0x00088b1f ) ) { + Com_DPrintf( "%s: looks like gzip file\n", __func__ ); + if( !FS_FilterFile( f ) ) { + Com_DPrintf( "%s: couldn't install gzip filter\n", __func__ ); + return -1; + } + if( FS_Read( &ul, 4, f ) != 4 ) { + Com_DPrintf( "%s: short read of msglen\n", __func__ ); + return -1; + } + } + if( ul == MVD_MAGIC ) { if( FS_Read( &us, 2, f ) != 2 ) { Com_DPrintf( "%s: short read of msglen\n", __func__ ); diff --git a/source/cl_main.c b/source/cl_main.c index a81b319..0f0de10 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -2911,7 +2911,6 @@ void CL_Shutdown( void ) { inflateEnd( &cls.z ); #endif - UI_Shutdown(); S_Shutdown(); IN_Shutdown(); Con_Shutdown(); diff --git a/source/com_local.h b/source/com_local.h index aa0a549..946593d 100644 --- a/source/com_local.h +++ b/source/com_local.h @@ -877,6 +877,8 @@ size_t FS_Write( const void *buffer, size_t len, fileHandle_t hFile ); void FS_FPrintf( fileHandle_t f, const char *format, ... ) q_printf( 2, 3 ); size_t FS_ReadLine( fileHandle_t f, char *buffer, int size ); +void FS_Flush( fileHandle_t f ); + int FS_Tell( fileHandle_t f ); int FS_RawTell( fileHandle_t f ); diff --git a/source/files.c b/source/files.c index 9d7cf2a..b6a8871 100644 --- a/source/files.c +++ b/source/files.c @@ -372,6 +372,7 @@ qboolean FS_FilterFile( fileHandle_t f ) { switch( mode ) { case FS_MODE_READ: modeStr = "rb"; + break; case FS_MODE_WRITE: modeStr = "wb"; break; @@ -379,6 +380,7 @@ qboolean FS_FilterFile( fileHandle_t f ) { return qfalse; } + fseek( file->fp, 0, SEEK_SET ); zfp = gzdopen( fileno( file->fp ), modeStr ); if( !zfp ) { return qfalse; @@ -448,14 +450,15 @@ static size_t FS_FOpenFileWrite( fsFile_t *file, const char *name ) { char *modeStr; unsigned mode; -#ifdef _WIN32 - // allow writing into basedir on Windows if( ( file->mode & FS_PATH_MASK ) == FS_PATH_BASE ) { - Q_concat( file->fullpath, sizeof( file->fullpath ), - sys_basedir->string, "/" BASEGAME "/", name, NULL ); - } else -#endif - { + if( sys_homedir->string[0] ) { + Q_concat( file->fullpath, sizeof( file->fullpath ), + sys_homedir->string, "/" BASEGAME "/", name, NULL ); + } else { + Q_concat( file->fullpath, sizeof( file->fullpath ), + sys_basedir->string, "/" BASEGAME "/", name, NULL ); + } + } else { Q_concat( file->fullpath, sizeof( file->fullpath ), fs_gamedir, "/", name, NULL ); } @@ -727,6 +730,22 @@ size_t FS_ReadLine( fileHandle_t f, char *buffer, int size ) { return len - 1; } +void FS_Flush( fileHandle_t f ) { + fsFile_t *file = FS_FileForHandle( f ); + + switch( file->type ) { + case FS_REAL: + fflush( file->fp ); + break; +#if USE_ZLIB + case FS_GZIP: + gzflush( file->zfp, Z_SYNC_FLUSH ); + break; +#endif + default: + break; + } +} /* ================= diff --git a/source/gl_images.c b/source/gl_images.c index 060a818..2ed691e 100644 --- a/source/gl_images.c +++ b/source/gl_images.c @@ -59,7 +59,7 @@ typedef struct { int minimize, maximize; } glmode_t; -static glmode_t filterModes[] = { +static const glmode_t filterModes[] = { { "GL_NEAREST", GL_NEAREST, GL_NEAREST }, { "GL_LINEAR", GL_LINEAR, GL_LINEAR }, { "GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST }, @@ -68,14 +68,14 @@ static glmode_t filterModes[] = { { "GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR } }; -static int numFilterModes = sizeof( filterModes ) / sizeof( filterModes[0] ); +static const int numFilterModes = sizeof( filterModes ) / sizeof( filterModes[0] ); typedef struct { char *name; int mode; } gltmode_t; -static gltmode_t alphaModes[] = { +static const gltmode_t alphaModes[] = { { "default", 4 }, { "GL_RGBA", GL_RGBA }, { "GL_RGBA8", GL_RGBA8 }, @@ -84,9 +84,9 @@ static gltmode_t alphaModes[] = { { "GL_RGBA2", GL_RGBA2 } }; -static int numAlphaModes = sizeof( alphaModes ) / sizeof( alphaModes[0] ); +static const int numAlphaModes = sizeof( alphaModes ) / sizeof( alphaModes[0] ); -static gltmode_t solidModes[] = { +static const gltmode_t solidModes[] = { { "default", 4 }, { "GL_RGB", GL_RGB }, { "GL_RGB8", GL_RGB8 }, @@ -99,7 +99,7 @@ static gltmode_t solidModes[] = { #endif }; -static int numSolidModes = sizeof( solidModes ) / sizeof( solidModes[0] ); +static const int numSolidModes = sizeof( solidModes ) / sizeof( solidModes[0] ); static void gl_texturemode_changed( cvar_t *self ) { int i; diff --git a/source/mvd_client.c b/source/mvd_client.c index 47f4080..bf27e7e 100644 --- a/source/mvd_client.c +++ b/source/mvd_client.c @@ -503,7 +503,17 @@ static void MVD_PlayNext( mvd_t *mvd, string_entry_t *entry ) { MVD_Destroyf( mvd, "Couldn't reopen %s", entry->string ); } - FS_Read( &magic, 4, mvd->demoplayback ); + if( FS_Read( &magic, 4, mvd->demoplayback ) != 4 ) { + MVD_Destroyf( mvd, "Couldn't read magic out of %s", entry->string ); + } + if( ( ( LittleLong( magic ) & 0xe0ffffff ) == 0x00088b1f ) ) { + if( !FS_FilterFile( mvd->demoplayback ) ) { + MVD_Destroyf( mvd, "Couldn't install gzip filter on %s", entry->string ); + } + if( FS_Read( &magic, 4, mvd->demoplayback ) != 4 ) { + MVD_Destroyf( mvd, "Couldn't read magic out of %s", entry->string ); + } + } if( magic != MVD_MAGIC ) { MVD_Destroyf( mvd, "%s is not a MVD2 file", entry->string ); } @@ -907,15 +917,37 @@ void MVD_StreamedStop_f( void ) { Com_Printf( "[%s] Stopped recording.\n", mvd->name ); } +extern const cmd_option_t o_mvdrecord[]; + void MVD_StreamedRecord_f( void ) { char buffer[MAX_OSPATH]; - char *name; fileHandle_t f; mvd_t *mvd; uint32_t magic; + qboolean gzip = qfalse; + int c; + + while( ( c = Cmd_ParseOptions( o_mvdrecord ) ) != -1 ) { + switch( c ) { + case 'h': + Cmd_PrintUsage( o_mvdrecord, "[/]<filename> [chanid]" ); + Com_Printf( "Begin MVD recording on the specified channel.\n" ); + Cmd_PrintHelp( o_mvdrecord ); + return; + case 'z': + gzip = qtrue; + break; + } + } + + if( !cmd_optarg[0] ) { + Com_Printf( "Missing filename argument.\n" ); + Cmd_PrintHint(); + return; + } - if( Cmd_Argc() < 2 || ( mvd = MVD_SetChannel( 2 ) ) == NULL ) { - Com_Printf( "Usage: %s [/]<filename> [chanid]\n", Cmd_Argv( 0 ) ); + if( ( mvd = MVD_SetChannel( cmd_optind + 1 ) ) == NULL ) { + Cmd_PrintHint(); return; } @@ -932,12 +964,14 @@ void MVD_StreamedRecord_f( void ) { // // open the demo file // - name = Cmd_Argv( 1 ); - if( name[0] == '/' ) { - Q_strncpyz( buffer, name + 1, sizeof( buffer ) ); + if( cmd_optarg[0] == '/' ) { + Q_strncpyz( buffer, cmd_optarg + 1, sizeof( buffer ) ); } else { - Q_concat( buffer, sizeof( buffer ), "demos/", name, NULL ); + Q_concat( buffer, sizeof( buffer ), "demos/", cmd_optarg, NULL ); COM_AppendExtension( buffer, ".mvd2", sizeof( buffer ) ); + if( gzip ) { + COM_AppendExtension( buffer, ".gz", sizeof( buffer ) ); + } } FS_FOpenFile( buffer, &f, FS_MODE_WRITE ); @@ -948,6 +982,10 @@ void MVD_StreamedRecord_f( void ) { Com_Printf( "[%s] Recording into %s.\n", mvd->name, buffer ); + if( gzip ) { + FS_FilterFile( f ); + } + mvd->demorecording = f; MVD_EmitGamestate( mvd ); diff --git a/source/q_shared.c b/source/q_shared.c index 2e6b523..3fb40fb 100644 --- a/source/q_shared.c +++ b/source/q_shared.c @@ -719,10 +719,10 @@ char *COM_SkipPath( const char *pathname ) { COM_StripExtension ============ */ -void COM_StripExtension( const char *in, char *out, int outSize ) { +void COM_StripExtension( const char *in, char *out, size_t size ) { char *s; - Q_strncpyz( out, in, outSize ); + Q_strncpyz( out, in, size ); s = out + strlen( out ); @@ -801,7 +801,7 @@ COM_FilePath Returns the path up to, but not including the last / ============ */ -void COM_FilePath( const char *in, char *out, int size ) { +void COM_FilePath( const char *in, char *out, size_t size ) { char *s; Q_strncpyz( out, in, size ); @@ -819,7 +819,7 @@ void COM_FilePath( const char *in, char *out, int size ) { COM_DefaultExtension ================== */ -void COM_DefaultExtension( char *path, const char *extension, int pathSize ) { +void COM_DefaultExtension( char *path, const char *ext, size_t size ) { char *src; // // if path doesn't have a .EXT, append extension @@ -835,12 +835,12 @@ void COM_DefaultExtension( char *path, const char *extension, int pathSize ) { } } - Q_strcat( path, pathSize, extension ); + Q_strcat( path, size, ext ); } -void COM_AppendExtension( char *path, const char *extension, int pathSize ) { - if( Q_stricmp( COM_FileExtension( path ), extension ) ) { - Q_strcat( path, pathSize, extension ); +void COM_AppendExtension( char *path, const char *ext, size_t size ) { + if( Q_stricmp( COM_FileExtension( path ), ext ) ) { + Q_strcat( path, size, ext ); } } @@ -1782,6 +1782,12 @@ int COM_Compress( char *data ) { continue; } + // handle line feed escape + if( *s == '\\' && s[1] == '\n' ) { + s += 2; + continue; + } + // parse a regular word do { *d++ = *s++; diff --git a/source/q_shared.h b/source/q_shared.h index 625daef..9a4bf6f 100644 --- a/source/q_shared.h +++ b/source/q_shared.h @@ -469,11 +469,11 @@ int QDECL SortStrcmp( const void *p1, const void *p2 ); char *Q_strchrnul( const char *s, int c ); char *COM_SkipPath( const char *pathname ); -void COM_StripExtension( const char *in, char *out, int outSize ); +void COM_StripExtension( const char *in, char *out, size_t size ); void COM_FileBase (char *in, char *out); -void COM_FilePath( const char *in, char *out, int outSize ); -void COM_DefaultExtension( char *path, const char *extension, int pathSize ); -void COM_AppendExtension( char *path, const char *extension, int pathSize ); +void COM_FilePath( const char *in, char *out, size_t size ); +void COM_DefaultExtension( char *path, const char *ext, size_t size ); +void COM_AppendExtension( char *path, const char *ext, size_t size ); char *COM_FileExtension( const char *in ); qboolean COM_IsFloat( const char *s ); diff --git a/source/sv_mvd.c b/source/sv_mvd.c index 446a7fe..3cf10be 100644 --- a/source/sv_mvd.c +++ b/source/sv_mvd.c @@ -890,6 +890,12 @@ void SV_MvdRecStop( void ) { sv.mvd.file = 0; } +const cmd_option_t o_mvdrecord[] = { + { "h", "help", "display this message" }, + { "z", "gzip", "compress file with gzip" }, + { NULL } +}; + static void MVD_Record_c( genctx_t *ctx, int argnum ) { if( argnum == 1 ) { MVD_File_g( ctx ); @@ -906,23 +912,38 @@ Every entity, every playerinfo and every message will be recorded. */ static void MVD_Record_f( void ) { char buffer[MAX_OSPATH]; - char *name; fileHandle_t demofile; uint32_t magic; + qboolean gzip = qfalse; + int c; if( sv.state != ss_game ) { if( sv.state == ss_broadcast ) { MVD_StreamedRecord_f(); } else { - Com_Printf( "Must be running a game server to record.\n" ); + Com_Printf( "No server running.\n" ); } return; } - if( Cmd_Argc() != 2 ) { - Com_Printf( "Usage: %s [/]<filename>\n", Cmd_Argv( 0 ) ); - return; - } + while( ( c = Cmd_ParseOptions( o_mvdrecord ) ) != -1 ) { + switch( c ) { + case 'h': + Cmd_PrintUsage( o_mvdrecord, "[/]<filename>" ); + Com_Printf( "Begin local MVD recording.\n" ); + Cmd_PrintHelp( o_mvdrecord ); + return; + case 'z': + gzip = qtrue; + break; + } + } + + if( !cmd_optarg[0] ) { + Com_Printf( "Missing filename argument.\n" ); + Cmd_PrintHint(); + return; + } if( !svs.mvd.entities ) { Com_Printf( "MVD recording is disabled on this server.\n" ); @@ -937,12 +958,14 @@ static void MVD_Record_f( void ) { // // open the demo file // - name = Cmd_Argv( 1 ); - if( name[0] == '/' ) { - Q_strncpyz( buffer, name + 1, sizeof( buffer ) ); + if( cmd_optarg[0] == '/' ) { + Q_strncpyz( buffer, cmd_optarg + 1, sizeof( buffer ) ); } else { - Q_concat( buffer, sizeof( buffer ), "demos/", name, NULL ); + Q_concat( buffer, sizeof( buffer ), "demos/", cmd_optarg, NULL ); COM_AppendExtension( buffer, ".mvd2", sizeof( buffer ) ); + if( gzip ) { + COM_AppendExtension( buffer, ".gz", sizeof( buffer ) ); + } } FS_FOpenFile( buffer, &demofile, FS_MODE_WRITE ); @@ -956,6 +979,10 @@ static void MVD_Record_f( void ) { return; } + if( gzip ) { + FS_FilterFile( demofile ); + } + sv.mvd.file = demofile; magic = MVD_MAGIC; diff --git a/source/ui_atoms.c b/source/ui_atoms.c index b13ed83..13ca51d 100644 --- a/source/ui_atoms.c +++ b/source/ui_atoms.c @@ -20,14 +20,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "ui_local.h" -uiStatic_t uis; +uiStatic_t uis; LIST_DECL( ui_menus ); -cvar_t *ui_debug; -static cvar_t *ui_open; -static cvar_t *ui_background; -static cvar_t *ui_scale; +cvar_t *ui_debug; +static cvar_t *ui_open; +static cvar_t *ui_background; +static cvar_t *ui_scale; // =========================================================================== @@ -37,30 +37,30 @@ UI_PushMenu ================= */ void UI_PushMenu( menuFrameWork_t *menu ) { - int i, j; + int i, j; if( !menu ) { return; } - // if this menu is already present, drop back to that level - // to avoid stacking menus by hotkeys - for( i = 0; i < uis.menuDepth; i++ ) { - if( uis.layers[i] == menu ) { - break; - } - } + // if this menu is already present, drop back to that level + // to avoid stacking menus by hotkeys + for( i = 0; i < uis.menuDepth; i++ ) { + if( uis.layers[i] == menu ) { + break; + } + } - if( i == uis.menuDepth ) { - if( uis.menuDepth >= MAX_MENU_DEPTH ) - Com_Error( ERR_FATAL, "UI_PushMenu: MAX_MENU_DEPTH" ); - uis.layers[uis.menuDepth++] = menu; - } else { + if( i == uis.menuDepth ) { + if( uis.menuDepth >= MAX_MENU_DEPTH ) + Com_Error( ERR_FATAL, "UI_PushMenu: MAX_MENU_DEPTH" ); + uis.layers[uis.menuDepth++] = menu; + } else { for( j = i; j < uis.menuDepth; j++ ) { UI_PopMenu(); } - uis.menuDepth = i + 1; - } + uis.menuDepth = i + 1; + } if( menu->push ) { if( !menu->push( menu ) ) { @@ -72,17 +72,17 @@ void UI_PushMenu( menuFrameWork_t *menu ) { Con_Close(); - Key_SetDest( ( Key_GetDest() & ~KEY_CONSOLE ) | KEY_MENU ); + Key_SetDest( ( Key_GetDest() & ~KEY_CONSOLE ) | KEY_MENU ); - if( !uis.activeMenu ) { - uis.entersound = qtrue; + if( !uis.activeMenu ) { + uis.entersound = qtrue; //CL_WarpMouse( 0, 0 ); - } + } uis.transparent |= menu->transparent; - uis.activeMenu = menu; + uis.activeMenu = menu; - UI_DoHitTest(); + UI_DoHitTest(); if( menu->expose ) { menu->expose( menu ); @@ -90,7 +90,7 @@ void UI_PushMenu( menuFrameWork_t *menu ) { } void UI_Resize( void ) { - int i; + int i; if( uis.glconfig.renderer == GL_RENDERER_SOFTWARE ) { uis.clipRect.left = 0; @@ -107,9 +107,9 @@ void UI_Resize( void ) { uis.height = uis.glconfig.vidHeight * uis.scale; } - for( i = 0; i < uis.menuDepth; i++ ) { + for( i = 0; i < uis.menuDepth; i++ ) { Menu_Init( uis.layers[i] ); - } + } //CL_WarpMouse( 0, 0 ); } @@ -122,19 +122,19 @@ UI_ForceMenuOff */ void UI_ForceMenuOff( void ) { menuFrameWork_t *menu; - int i; + int i; - for( i = 0; i < uis.menuDepth; i++ ) { + for( i = 0; i < uis.menuDepth; i++ ) { menu = uis.layers[i]; if( menu->pop ) { - menu->pop( menu ); - } - } - - Key_SetDest( Key_GetDest() & ~KEY_MENU ); - uis.menuDepth = 0; - uis.activeMenu = NULL; - uis.transparent = qfalse; + menu->pop( menu ); + } + } + + Key_SetDest( Key_GetDest() & ~KEY_MENU ); + uis.menuDepth = 0; + uis.activeMenu = NULL; + uis.transparent = qfalse; } /* @@ -144,32 +144,32 @@ UI_PopMenu */ void UI_PopMenu( void ) { menuFrameWork_t *menu; - int i; + int i; - if( uis.menuDepth < 1 ) - Com_Error( ERR_FATAL, "UI_PopMenu: depth < 1" ); + if( uis.menuDepth < 1 ) + Com_Error( ERR_FATAL, "UI_PopMenu: depth < 1" ); menu = uis.layers[--uis.menuDepth]; if( menu->pop ) { menu->pop( menu ); } - if( !uis.menuDepth ) { - UI_ForceMenuOff(); - return; - } + if( !uis.menuDepth ) { + UI_ForceMenuOff(); + return; + } - uis.activeMenu = uis.layers[uis.menuDepth - 1]; + uis.activeMenu = uis.layers[uis.menuDepth - 1]; - uis.transparent = qfalse; - for( i = uis.menuDepth - 1; i >= 0; i-- ) { - if( uis.layers[i]->transparent ) { - uis.transparent = qtrue; - break; - } - } + uis.transparent = qfalse; + for( i = uis.menuDepth - 1; i >= 0; i-- ) { + if( uis.layers[i]->transparent ) { + uis.transparent = qtrue; + break; + } + } - UI_DoHitTest(); + UI_DoHitTest(); } /* @@ -178,15 +178,15 @@ UI_IsTransparent ================= */ qboolean UI_IsTransparent( void ) { - if( !( Key_GetDest() & KEY_MENU ) ) { - return qtrue; - } + if( !( Key_GetDest() & KEY_MENU ) ) { + return qtrue; + } - if( !uis.activeMenu ) { - return qtrue; - } + if( !uis.activeMenu ) { + return qtrue; + } - return uis.transparent; + return uis.transparent; } menuFrameWork_t *UI_FindMenu( const char *name ) { @@ -208,38 +208,38 @@ UI_OpenMenu void UI_OpenMenu( uiMenu_t type ) { menuFrameWork_t *menu = NULL; - // close any existing menus - UI_ForceMenuOff(); + // close any existing menus + UI_ForceMenuOff(); - switch( type ) { - case UIMENU_MAIN: - if( ui_open->integer ) { + switch( type ) { + case UIMENU_MAIN: + if( ui_open->integer ) { menu = UI_FindMenu( "main" ); - } - break; - case UIMENU_MAIN_FORCE: + } + break; + case UIMENU_MAIN_FORCE: menu = UI_FindMenu( "main" ); - break; - case UIMENU_INGAME: + break; + case UIMENU_INGAME: menu = UI_FindMenu( "game" ); - break; - case UIMENU_NONE: - break; - default: - Com_Error( ERR_FATAL, "UI_OpenMenu: bad menu" ); - break; - } + break; + case UIMENU_NONE: + break; + default: + Com_Error( ERR_FATAL, "UI_OpenMenu: bad menu" ); + break; + } UI_PushMenu( menu ); } void UI_ErrorMenu( comErrorType_t type, const char *text ) { - // close any existing menus - UI_ForceMenuOff(); + // close any existing menus + UI_ForceMenuOff(); - if( ui_open->integer ) { + if( ui_open->integer ) { UI_PushMenu( UI_FindMenu( "main" ) ); - M_Menu_Error( type, text ); + M_Menu_Error( type, text ); } } @@ -252,32 +252,32 @@ UI_FormatColumns ================= */ void *UI_FormatColumns( int extrasize, ... ) { - va_list argptr; - char *buffer, *p; - int i, j; - size_t total = 0; - char *strings[MAX_COLUMNS]; - size_t lengths[MAX_COLUMNS]; - - va_start( argptr, extrasize ); + va_list argptr; + char *buffer, *p; + int i, j; + size_t total = 0; + char *strings[MAX_COLUMNS]; + size_t lengths[MAX_COLUMNS]; + + va_start( argptr, extrasize ); for( i = 0; i < MAX_COLUMNS; i++ ) { - if( ( p = va_arg( argptr, char * ) ) == NULL ) { + if( ( p = va_arg( argptr, char * ) ) == NULL ) { break; } - strings[i] = p; - total += lengths[i] = strlen( p ) + 1; - } - va_end( argptr ); + strings[i] = p; + total += lengths[i] = strlen( p ) + 1; + } + va_end( argptr ); - buffer = UI_Malloc( extrasize + total + 1 ); + buffer = UI_Malloc( extrasize + total + 1 ); p = buffer + extrasize; - for( j = 0; j < i; j++ ) { - memcpy( p, strings[j], lengths[j] ); - p += lengths[j]; - } - *p = 0; + for( j = 0; j < i; j++ ) { + memcpy( p, strings[j], lengths[j] ); + p += lengths[j]; + } + *p = 0; - return buffer; + return buffer; } char *UI_GetColumn( char *s, int n ) { @@ -292,73 +292,55 @@ char *UI_GetColumn( char *s, int n ) { /* ================= -UI_CopyString -================= -*/ -char *UI_CopyString( const char *in ) { - char *out; - - if( !in ) { - return NULL; - } - - out = UI_Malloc( strlen( in ) + 1 ); - strcpy( out, in ); - - return out; -} - -/* -================= UI_CursorInRect ================= */ qboolean UI_CursorInRect( vrect_t *rect ) { - if( uis.mouseCoords[0] < rect->x ) { + if( uis.mouseCoords[0] < rect->x ) { return qfalse; } - if( uis.mouseCoords[0] >= rect->x + rect->width ) { + if( uis.mouseCoords[0] >= rect->x + rect->width ) { return qfalse; } - if( uis.mouseCoords[1] < rect->y ) { + if( uis.mouseCoords[1] < rect->y ) { return qfalse; } if( uis.mouseCoords[1] >= rect->y + rect->height ) { - return qfalse; - } - return qtrue; + return qfalse; + } + return qtrue; } void UI_DrawString( int x, int y, const color_t color, int flags, const char *string ) { - if( color ) { - ref.SetColor( DRAW_COLOR_RGBA, color ); - } - - if( ( flags & UI_CENTER ) == UI_CENTER ) { - x -= Q_DrawStrlen( string ) * 8 / 2; - } else if( flags & UI_RIGHT ) { - x -= Q_DrawStrlen( string ) * 8; - } - - ref.DrawString( x, y, flags, MAX_STRING_CHARS, string, uis.fontHandle ); - if( color ) { - ref.SetColor( DRAW_COLOR_CLEAR, NULL ); - } + if( color ) { + ref.SetColor( DRAW_COLOR_RGBA, color ); + } + + if( ( flags & UI_CENTER ) == UI_CENTER ) { + x -= Q_DrawStrlen( string ) * 8 / 2; + } else if( flags & UI_RIGHT ) { + x -= Q_DrawStrlen( string ) * 8; + } + + ref.DrawString( x, y, flags, MAX_STRING_CHARS, string, uis.fontHandle ); + if( color ) { + ref.SetColor( DRAW_COLOR_CLEAR, NULL ); + } } void UI_DrawChar( int x, int y, int flags, int ch ) { - ref.DrawChar( x, y, flags, ch, uis.fontHandle ); + ref.DrawChar( x, y, flags, ch, uis.fontHandle ); } void UI_StringDimensions( vrect_t *rc, int flags, const char *string ) { - rc->height = 8; - rc->width = 8 * Q_DrawStrlen( string ); - - if( ( flags & UI_CENTER ) == UI_CENTER ) { - rc->x -= rc->width / 2; - } else if( flags & UI_RIGHT ) { - rc->x -= rc->width; - } + rc->height = 8; + rc->width = 8 * Q_DrawStrlen( string ); + + if( ( flags & UI_CENTER ) == UI_CENTER ) { + rc->x -= rc->width / 2; + } else if( flags & UI_RIGHT ) { + rc->x -= rc->width; + } } @@ -373,28 +355,28 @@ UI_DoHitTest ================= */ qboolean UI_DoHitTest( void ) { - menuCommon_t *item; + menuCommon_t *item; - if( !uis.activeMenu ) { - return qfalse; - } + if( !uis.activeMenu ) { + return qfalse; + } - if( !( item = Menu_HitTest( uis.activeMenu ) ) ) { - return qfalse; - } - if( !UI_IsItemSelectable( item ) ) { - return qfalse; - } + if( !( item = Menu_HitTest( uis.activeMenu ) ) ) { + return qfalse; + } + if( !UI_IsItemSelectable( item ) ) { + return qfalse; + } - Menu_MouseMove( item ); + Menu_MouseMove( item ); - if( item->flags & QMF_HASFOCUS ) { - return qfalse; - } + if( item->flags & QMF_HASFOCUS ) { + return qfalse; + } - Menu_SetFocus( item ); - - return qtrue; + Menu_SetFocus( item ); + + return qtrue; } /* @@ -403,17 +385,17 @@ UI_MouseEvent ================= */ void UI_MouseEvent( int x, int y ) { - if( !uis.activeMenu ) { - return; - } + if( !uis.activeMenu ) { + return; + } - clamp( x, 0, uis.glconfig.vidWidth ); - clamp( y, 0, uis.glconfig.vidHeight ); + clamp( x, 0, uis.glconfig.vidWidth ); + clamp( y, 0, uis.glconfig.vidHeight ); - uis.mouseCoords[0] = x * uis.scale; - uis.mouseCoords[1] = y * uis.scale; + uis.mouseCoords[0] = x * uis.scale; + uis.mouseCoords[1] = y * uis.scale; - UI_DoHitTest(); + UI_DoHitTest(); } /* @@ -422,85 +404,85 @@ UI_Draw ================= */ void UI_Draw( int realtime ) { - int i; + int i; - uis.realtime = realtime; + uis.realtime = realtime; - if( !( Key_GetDest() & KEY_MENU ) ) { - return; - } + if( !( Key_GetDest() & KEY_MENU ) ) { + return; + } - if( !uis.activeMenu ) { - return; - } + if( !uis.activeMenu ) { + return; + } - ref.SetColor( DRAW_COLOR_CLEAR, NULL ); + ref.SetColor( DRAW_COLOR_CLEAR, NULL ); if( uis.glconfig.renderer == GL_RENDERER_SOFTWARE ) { ref.SetClipRect( DRAW_CLIP_MASK, &uis.clipRect ); } else { - ref.SetScale( &uis.scale ); - } - - if( !uis.transparent ) { - // no transparent menus - if( uis.backgroundHandle ) { - ref.DrawStretchPic( 0, 0, uis.width, uis.height, - uis.backgroundHandle ); - } else { - ref.DrawFill( 0, 0, uis.width, uis.height, 0 ); - } - - if( uis.activeMenu->draw ) { - uis.activeMenu->draw( uis.activeMenu ); - } else { - Menu_Draw( uis.activeMenu ); - } - } else { - // draw all layers - for( i = 0; i < uis.menuDepth; i++ ) { - if( !uis.layers[i]->transparent ) { - if( uis.backgroundHandle ) { - ref.DrawStretchPic( 0, 0, uis.width, uis.height, - uis.backgroundHandle ); - } else { - ref.DrawFill( 0, 0, uis.width, uis.height, 0 ); - } - } - - if( uis.layers[i]->draw ) { - uis.layers[i]->draw( uis.layers[i] ); - } else { - Menu_Draw( uis.layers[i] ); - } - } - } + ref.SetScale( &uis.scale ); + } + + if( !uis.transparent ) { + // no transparent menus + if( uis.backgroundHandle ) { + ref.DrawStretchPic( 0, 0, uis.width, uis.height, + uis.backgroundHandle ); + } else { + ref.DrawFill( 0, 0, uis.width, uis.height, 0 ); + } + + if( uis.activeMenu->draw ) { + uis.activeMenu->draw( uis.activeMenu ); + } else { + Menu_Draw( uis.activeMenu ); + } + } else { + // draw all layers + for( i = 0; i < uis.menuDepth; i++ ) { + if( !uis.layers[i]->transparent ) { + if( uis.backgroundHandle ) { + ref.DrawStretchPic( 0, 0, uis.width, uis.height, + uis.backgroundHandle ); + } else { + ref.DrawFill( 0, 0, uis.width, uis.height, 0 ); + } + } + + if( uis.layers[i]->draw ) { + uis.layers[i]->draw( uis.layers[i] ); + } else { + Menu_Draw( uis.layers[i] ); + } + } + } // draw custom cursor in fullscreen mode if( uis.glconfig.flags & QVF_FULLSCREEN ) { - ref.DrawPic( uis.mouseCoords[0] - uis.cursorWidth / 2, - uis.mouseCoords[1] - uis.cursorHeight / 2, uis.cursorHandle ); + ref.DrawPic( uis.mouseCoords[0] - uis.cursorWidth / 2, + uis.mouseCoords[1] - uis.cursorHeight / 2, uis.cursorHandle ); } - if( ui_debug->integer ) { - Menu_HitTest( uis.activeMenu ); - UI_DrawString( uis.width - 4, 4, NULL, UI_RIGHT, - va( "%3i %3i", uis.mouseCoords[0], uis.mouseCoords[1] ) ); - } + if( ui_debug->integer ) { + Menu_HitTest( uis.activeMenu ); + UI_DrawString( uis.width - 4, 4, NULL, UI_RIGHT, + va( "%3i %3i", uis.mouseCoords[0], uis.mouseCoords[1] ) ); + } - // delay playing the enter sound until after the - // menu has been drawn, to avoid delay while - // caching images - if( uis.entersound ) { - uis.entersound = qfalse; - S_StartLocalSound( "misc/menu1.wav" ); - } + // delay playing the enter sound until after the + // menu has been drawn, to avoid delay while + // caching images + if( uis.entersound ) { + uis.entersound = qfalse; + S_StartLocalSound( "misc/menu1.wav" ); + } if( uis.glconfig.renderer == GL_RENDERER_SOFTWARE ) { ref.SetClipRect( DRAW_CLIP_DISABLED, NULL ); } else { - ref.SetScale( NULL ); + ref.SetScale( NULL ); } - ref.SetColor( DRAW_COLOR_CLEAR, NULL ); + ref.SetColor( DRAW_COLOR_CLEAR, NULL ); } /* @@ -509,30 +491,30 @@ UI_Keydown ================= */ void UI_Keydown( int key ) { - menuSound_t sound; + menuSound_t sound; - if( !uis.activeMenu ) { - return; - } + if( !uis.activeMenu ) { + return; + } sound = Menu_Keydown( uis.activeMenu, key ); - switch( sound ) { - case QMS_IN: - S_StartLocalSound( "misc/menu1.wav" ); - break; - case QMS_MOVE: - S_StartLocalSound( "misc/menu2.wav" ); - break; - case QMS_OUT: - S_StartLocalSound( "misc/menu3.wav" ); - break; - case QMS_BEEP: - S_StartLocalSound( "misc/talk1.wav" ); - break; - default: - break; - } + switch( sound ) { + case QMS_IN: + S_StartLocalSound( "misc/menu1.wav" ); + break; + case QMS_MOVE: + S_StartLocalSound( "misc/menu2.wav" ); + break; + case QMS_OUT: + S_StartLocalSound( "misc/menu3.wav" ); + break; + case QMS_BEEP: + S_StartLocalSound( "misc/talk1.wav" ); + break; + default: + break; + } } @@ -542,12 +524,12 @@ UI_CharEvent ================= */ void UI_CharEvent( int key ) { - menuCommon_t *item; - menuSound_t sound; + menuCommon_t *item; + menuSound_t sound; - if( !uis.activeMenu ) { - return; - } + if( !uis.activeMenu ) { + return; + } if( ( item = Menu_ItemAtCursor( uis.activeMenu ) ) == NULL || ( sound = Menu_CharEvent( item, key ) ) == QMS_NOTHANDLED ) @@ -555,23 +537,23 @@ void UI_CharEvent( int key ) { return; } - switch( sound ) { - case QMS_IN: - S_StartLocalSound( "misc/menu1.wav" ); - break; - case QMS_MOVE: - S_StartLocalSound( "misc/menu2.wav" ); - break; - case QMS_OUT: - S_StartLocalSound( "misc/menu3.wav" ); - break; - case QMS_BEEP: - S_StartLocalSound( "misc/talk1.wav" ); - break; - case QMS_NOTHANDLED: - default: - break; - } + switch( sound ) { + case QMS_IN: + S_StartLocalSound( "misc/menu1.wav" ); + break; + case QMS_MOVE: + S_StartLocalSound( "misc/menu2.wav" ); + break; + case QMS_OUT: + S_StartLocalSound( "misc/menu3.wav" ); + break; + case QMS_BEEP: + S_StartLocalSound( "misc/talk1.wav" ); + break; + case QMS_NOTHANDLED: + default: + break; + } } @@ -616,17 +598,17 @@ static void UI_PopMenu_f( void ) { static const cmdreg_t c_ui[] = { - { "forcemenuoff", UI_ForceMenuOff }, - { "pushmenu", UI_PushMenu_f, UI_PushMenu_c }, - { "popmenu", UI_PopMenu_f }, + { "forcemenuoff", UI_ForceMenuOff }, + { "pushmenu", UI_PushMenu_f, UI_PushMenu_c }, + { "popmenu", UI_PopMenu_f }, - { NULL, NULL } + { NULL, NULL } }; static void ui_background_changed( cvar_t *self ) { - if( self->string[0] ) { - uis.backgroundHandle = ref.RegisterPic( self->string ); - } else { + if( self->string[0] ) { + uis.backgroundHandle = ref.RegisterPic( self->string ); + } else { uis.backgroundHandle = 0; } } @@ -636,9 +618,9 @@ static void ui_scale_changed( cvar_t *self ) { } void UI_ModeChanged( void ) { - ui_scale = cvar.Get( "ui_scale", "1", 0 ); + ui_scale = cvar.Get( "ui_scale", "1", 0 ); ui_scale->changed = ui_scale_changed; - ref.GetConfig( &uis.glconfig ); + ref.GetConfig( &uis.glconfig ); UI_Resize(); } @@ -662,25 +644,25 @@ UI_Init qboolean UI_Init( void ) { Cmd_Register( c_ui ); - ui_debug = cvar.Get( "ui_debug", "0", 0 ); - ui_open = cvar.Get( "ui_open", "0", CVAR_ARCHIVE ); - ui_background = cvar.Get( "ui_background", "", 0 ); + ui_debug = cvar.Get( "ui_debug", "0", 0 ); + ui_open = cvar.Get( "ui_open", "0", CVAR_ARCHIVE ); + ui_background = cvar.Get( "ui_background", "", 0 ); UI_ModeChanged(); - uis.fontHandle = ref.RegisterFont( "conchars" ); - uis.cursorHandle = ref.RegisterPic( "ch1" ); - ref.DrawGetPicSize( &uis.cursorWidth, &uis.cursorHeight, uis.cursorHandle ); + uis.fontHandle = ref.RegisterFont( "conchars" ); + uis.cursorHandle = ref.RegisterPic( "ch1" ); + ref.DrawGetPicSize( &uis.cursorWidth, &uis.cursorHeight, uis.cursorHandle ); - if( uis.glconfig.renderer != GL_RENDERER_SOFTWARE ) { - if( ui_background->string[0] ) { - uis.backgroundHandle = ref.RegisterPic( ui_background->string ); - } - ui_background->changed = ui_background_changed; + if( uis.glconfig.renderer != GL_RENDERER_SOFTWARE ) { + if( ui_background->string[0] ) { + uis.backgroundHandle = ref.RegisterPic( ui_background->string ); + } + ui_background->changed = ui_background_changed; } - // Point to a nice location at startup - strcpy( uis.m_demos_browse, "/demos" ); + // Point to a nice location at startup + strcpy( uis.m_demos_browse, "/demos" ); // load built-in menus M_Menu_PlayerConfig(); @@ -690,7 +672,9 @@ qboolean UI_Init( void ) { // load custom menus UI_LoadStript(); - return qtrue; + Com_Printf( "Registered %d menus.\n", List_Count( &ui_menus ) ); + + return qtrue; } /* @@ -701,18 +685,18 @@ UI_Shutdown void UI_Shutdown( void ) { UI_ForceMenuOff(); - ui_background->changed = NULL; + ui_background->changed = NULL; ui_scale->changed = NULL; - PlayerModel_Free(); + PlayerModel_Free(); UI_FreeMenus(); Cmd_Deregister( c_ui ); - memset( &uis, 0, sizeof( uis ) ); + memset( &uis, 0, sizeof( uis ) ); - Z_LeakTest( TAG_UI ); + Z_LeakTest( TAG_UI ); } diff --git a/source/ui_local.h b/source/ui_local.h index bda131b..7c1cf3d 100644 --- a/source/ui_local.h +++ b/source/ui_local.h @@ -28,8 +28,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cl_public.h" #include "ui_public.h" -#define UI_Malloc( size ) Z_TagMalloc( size, TAG_UI ) -#define UI_Mallocz( size ) Z_TagMallocz( size, TAG_UI ) +#define UI_Malloc( s ) Z_TagMalloc( s, TAG_UI ) +#define UI_Mallocz( s ) Z_TagMallocz( s, TAG_UI ) +#define UI_CopyString( s ) Z_TagCopyString( s, TAG_UI ) #define MAXMENUITEMS 64 @@ -41,8 +42,9 @@ typedef enum { MTYPE_SPINCONTROL, MTYPE_SEPARATOR, MTYPE_FIELD, - MTYPE_BITMAP, - MTYPE_IMAGELIST, + MTYPE_BITFIELD, + MTYPE_PAIRS, + MTYPE_TOGGLE, MTYPE_STATIC, MTYPE_KEYBIND } menuType_t; @@ -185,8 +187,12 @@ typedef struct menuSpinControl_s { cvar_t *cvar; char **itemnames; + char **itemvalues; int numItems; int curvalue; + + int mask; + qboolean negate; } menuSpinControl_t; typedef struct menuAction_s { @@ -264,7 +270,6 @@ qboolean UI_CursorInRect( vrect_t *rect ); void *UI_FormatColumns( int extrasize, ... ) q_sentinel; char *UI_GetColumn( char *s, int n ); void UI_AddToServerList( const serverStatus_t *status ); -char *UI_CopyString( const char *in ); void UI_DrawLoading( int realtime ); void UI_SetupDefaultBanner( menuStatic_t *banner, const char *name ); void UI_DrawString( int x, int y, const color_t color, int flags, const char *string ); diff --git a/source/ui_menu.c b/source/ui_menu.c index f39a868..a4cc243 100644 --- a/source/ui_menu.c +++ b/source/ui_menu.c @@ -46,13 +46,13 @@ Action_Init ================= */ static void Action_Init( menuAction_t *a ) { - if( !a->generic.name ) { - Com_Error( ERR_FATAL, "Action_Init: NULL a->generic.name" ); - } + if( !a->generic.name ) { + Com_Error( ERR_FATAL, "Action_Init: NULL a->generic.name" ); + } - a->generic.rect.x = a->generic.x; - a->generic.rect.y = a->generic.y; - UI_StringDimensions( &a->generic.rect, a->generic.uiFlags, a->generic.name ); + a->generic.rect.x = a->generic.x; + a->generic.rect.y = a->generic.y; + UI_StringDimensions( &a->generic.rect, a->generic.uiFlags, a->generic.name ); } @@ -62,15 +62,15 @@ Action_Draw ================= */ static void Action_Draw( menuAction_t *a ) { - int flags; + int flags; - flags = a->generic.uiFlags; - if( a->generic.flags & QMF_HASFOCUS ) { - flags |= UI_ALTCOLOR; - } + flags = a->generic.uiFlags; + if( a->generic.flags & QMF_HASFOCUS ) { + flags |= UI_ALTCOLOR; + } - UI_DrawString( a->generic.x, a->generic.y, NULL, - flags, a->generic.name ); + UI_DrawString( a->generic.x, a->generic.y, NULL, + flags, a->generic.name ); } /* @@ -87,19 +87,19 @@ Static_Init ================= */ static void Static_Init( menuStatic_t *s ) { - if( !s->generic.name ) { - Com_Error( ERR_FATAL, "Static_Init: NULL s->generic.name" ); - } + if( !s->generic.name ) { + Com_Error( ERR_FATAL, "Static_Init: NULL s->generic.name" ); + } - if( !s->maxChars ) { - s->maxChars = MAX_STRING_CHARS; - } + if( !s->maxChars ) { + s->maxChars = MAX_STRING_CHARS; + } - s->generic.rect.x = s->generic.x; - s->generic.rect.y = s->generic.y; + s->generic.rect.x = s->generic.x; + s->generic.rect.y = s->generic.y; - UI_StringDimensions( &s->generic.rect, - s->generic.uiFlags, s->generic.name ); + UI_StringDimensions( &s->generic.rect, + s->generic.uiFlags, s->generic.name ); } /* @@ -108,9 +108,9 @@ Static_Draw ================= */ static void Static_Draw( menuStatic_t *s ) { - UI_DrawString( s->generic.x, s->generic.y, - ( s->generic.flags & QMF_CUSTOM_COLOR ) ? s->generic.color : NULL, - s->generic.uiFlags, s->generic.name ); + UI_DrawString( s->generic.x, s->generic.y, + ( s->generic.flags & QMF_CUSTOM_COLOR ) ? s->generic.color : NULL, + s->generic.uiFlags, s->generic.name ); } /* @@ -133,20 +133,20 @@ Keybind_Init ================= */ static void Keybind_Init( menuKeybind_t *k ) { - if( !k->generic.name ) { - Com_Error( ERR_FATAL, "Keybind_Init: NULL k->generic.name" ); - } + if( !k->generic.name ) { + Com_Error( ERR_FATAL, "Keybind_Init: NULL k->generic.name" ); + } - k->generic.uiFlags &= ~( UI_LEFT | UI_RIGHT ); + k->generic.uiFlags &= ~( UI_LEFT | UI_RIGHT ); - k->generic.rect.x = k->generic.x + LCOLUMN_OFFSET; - k->generic.rect.y = k->generic.y; + k->generic.rect.x = k->generic.x + LCOLUMN_OFFSET; + k->generic.rect.y = k->generic.y; - UI_StringDimensions( &k->generic.rect, - k->generic.uiFlags | UI_RIGHT, k->generic.name ); + UI_StringDimensions( &k->generic.rect, + k->generic.uiFlags | UI_RIGHT, k->generic.name ); - k->generic.rect.width += ( RCOLUMN_OFFSET - LCOLUMN_OFFSET ) + - Q_DrawStrlen( k->binding ) * CHAR_WIDTH; + k->generic.rect.width += ( RCOLUMN_OFFSET - LCOLUMN_OFFSET ) + + Q_DrawStrlen( k->binding ) * CHAR_WIDTH; } /* @@ -155,38 +155,38 @@ Keybind_Draw ================= */ static void Keybind_Draw( menuKeybind_t *k ) { - char string[MAX_STRING_CHARS]; - byte *color; - int flags; - - color = NULL; - flags = UI_ALTCOLOR; - if( k->generic.flags & QMF_HASFOCUS ) { - /*if( k->generic.parent->keywait ) { - UI_DrawChar( k->generic.x + RCOLUMN_OFFSET / 2, k->generic.y, k->generic.uiFlags | UI_RIGHT, '=' ); - } else*/ if( ( uis.realtime >> 8 ) & 1 ) { - UI_DrawChar( k->generic.x + RCOLUMN_OFFSET / 2, k->generic.y, k->generic.uiFlags | UI_RIGHT, 13 ); - } - } else { - if( k->generic.parent->keywait ) { - color = colorGray; - flags = 0; - } - } - - UI_DrawString( k->generic.x + LCOLUMN_OFFSET, k->generic.y, color, - k->generic.uiFlags | UI_RIGHT | flags, k->generic.name ); - - if( k->altbinding[0] ) { - Q_concat( string, sizeof( string ), k->binding, " or ", k->altbinding, NULL ); - } else if( k->binding[0] ) { - strcpy( string, k->binding ); - } else { - strcpy( string, "???" ); - } - - UI_DrawString( k->generic.x + RCOLUMN_OFFSET, k->generic.y, color, - k->generic.uiFlags | UI_LEFT, string ); + char string[MAX_STRING_CHARS]; + byte *color; + int flags; + + color = NULL; + flags = UI_ALTCOLOR; + if( k->generic.flags & QMF_HASFOCUS ) { + /*if( k->generic.parent->keywait ) { + UI_DrawChar( k->generic.x + RCOLUMN_OFFSET / 2, k->generic.y, k->generic.uiFlags | UI_RIGHT, '=' ); + } else*/ if( ( uis.realtime >> 8 ) & 1 ) { + UI_DrawChar( k->generic.x + RCOLUMN_OFFSET / 2, k->generic.y, k->generic.uiFlags | UI_RIGHT, 13 ); + } + } else { + if( k->generic.parent->keywait ) { + color = colorGray; + flags = 0; + } + } + + UI_DrawString( k->generic.x + LCOLUMN_OFFSET, k->generic.y, color, + k->generic.uiFlags | UI_RIGHT | flags, k->generic.name ); + + if( k->altbinding[0] ) { + Q_concat( string, sizeof( string ), k->binding, " or ", k->altbinding, NULL ); + } else if( k->binding[0] ) { + strcpy( string, k->binding ); + } else { + strcpy( string, "???" ); + } + + UI_DrawString( k->generic.x + RCOLUMN_OFFSET, k->generic.y, color, + k->generic.uiFlags | UI_LEFT, string ); } static menuSound_t Keybind_DoEnter( menuKeybind_t *k ) { @@ -215,8 +215,8 @@ static void Keybind_Update( menuFrameWork_t *menu ) { menuKeybind_t *k; int i; - for( i = 0; i < menu->nitems; i++ ) { - k = menu->items[i]; + for( i = 0; i < menu->nitems; i++ ) { + k = menu->items[i]; if( k->generic.type == MTYPE_KEYBIND ) { Keybind_Push( k ); } @@ -277,20 +277,20 @@ Field_Init static void Field_Init( menuField_t *f ) { int w = f->field.visibleChars * CHAR_WIDTH; - f->generic.uiFlags &= ~( UI_LEFT | UI_RIGHT ); - - if( f->generic.name ) { - f->generic.rect.x = f->generic.x + LCOLUMN_OFFSET; - f->generic.rect.y = f->generic.y; - UI_StringDimensions( &f->generic.rect, - f->generic.uiFlags | UI_RIGHT, f->generic.name ); - f->generic.rect.width += RCOLUMN_OFFSET + w; - } else { + f->generic.uiFlags &= ~( UI_LEFT | UI_RIGHT ); + + if( f->generic.name ) { + f->generic.rect.x = f->generic.x + LCOLUMN_OFFSET; + f->generic.rect.y = f->generic.y; + UI_StringDimensions( &f->generic.rect, + f->generic.uiFlags | UI_RIGHT, f->generic.name ); + f->generic.rect.width += RCOLUMN_OFFSET + w; + } else { f->generic.rect.x = f->generic.x - w / 2; f->generic.rect.y = f->generic.y; f->generic.rect.width = w; f->generic.rect.height = CHAR_HEIGHT; - } + } } @@ -300,21 +300,21 @@ Field_Draw ================= */ static void Field_Draw( menuField_t *f ) { - int flags = f->generic.uiFlags; + int flags = f->generic.uiFlags; - if( f->generic.flags & QMF_HASFOCUS ) { - flags |= UI_DRAWCURSOR; - } + if( f->generic.flags & QMF_HASFOCUS ) { + flags |= UI_DRAWCURSOR; + } - if( f->generic.name ) { - UI_DrawString( f->generic.x + LCOLUMN_OFFSET, f->generic.y, NULL, - f->generic.uiFlags | UI_RIGHT | UI_ALTCOLOR, f->generic.name ); + if( f->generic.name ) { + UI_DrawString( f->generic.x + LCOLUMN_OFFSET, f->generic.y, NULL, + f->generic.uiFlags | UI_RIGHT | UI_ALTCOLOR, f->generic.name ); - ref.DrawFillEx( f->generic.x + RCOLUMN_OFFSET, f->generic.y - 1, - f->field.visibleChars * CHAR_WIDTH, CHAR_HEIGHT + 2, colorField ); + ref.DrawFillEx( f->generic.x + RCOLUMN_OFFSET, f->generic.y - 1, + f->field.visibleChars * CHAR_WIDTH, CHAR_HEIGHT + 2, colorField ); - IF_Draw( &f->field, f->generic.x + RCOLUMN_OFFSET, f->generic.y, - flags, uis.fontHandle ); + IF_Draw( &f->field, f->generic.x + RCOLUMN_OFFSET, f->generic.y, + flags, uis.fontHandle ); } else { ref.DrawFillEx( f->generic.rect.x, f->generic.rect.y - 1, f->generic.rect.width, CHAR_HEIGHT + 2, colorField ); @@ -330,10 +330,10 @@ Field_Key ================= */ static int Field_Key( menuField_t *f, int key ) { - qboolean ret; + qboolean ret; - ret = IF_KeyEvent( &f->field, key ); - return ret ? QMS_SILENT : QMS_NOTHANDLED; + ret = IF_KeyEvent( &f->field, key ); + return ret ? QMS_SILENT : QMS_NOTHANDLED; } /* @@ -342,20 +342,20 @@ Field_Char ================= */ static int Field_Char( menuField_t *f, int key ) { - int ret; + int ret; - if( f->generic.flags & QMF_NUMBERSONLY ) { - if( key < '0' || key > '9' ) { - return QMS_BEEP; - } - } + if( f->generic.flags & QMF_NUMBERSONLY ) { + if( key < '0' || key > '9' ) { + return QMS_BEEP; + } + } - ret = IF_CharEvent( &f->field, key ); + ret = IF_CharEvent( &f->field, key ); if( f->generic.change ) { f->generic.change( &f->generic ); } - return ret ? QMS_SILENT : QMS_NOTHANDLED; + return ret ? QMS_SILENT : QMS_NOTHANDLED; } /* @@ -394,32 +394,32 @@ SpinControl_Init ================= */ void SpinControl_Init( menuSpinControl_t *s ) { - char **n; - int maxLength, length; + char **n; + int maxLength, length; - s->generic.uiFlags &= ~( UI_LEFT | UI_RIGHT ); + s->generic.uiFlags &= ~( UI_LEFT | UI_RIGHT ); - s->generic.rect.x = s->generic.x + LCOLUMN_OFFSET; - s->generic.rect.y = s->generic.y; + s->generic.rect.x = s->generic.x + LCOLUMN_OFFSET; + s->generic.rect.y = s->generic.y; - UI_StringDimensions( &s->generic.rect, - s->generic.uiFlags | UI_RIGHT, s->generic.name ); + UI_StringDimensions( &s->generic.rect, + s->generic.uiFlags | UI_RIGHT, s->generic.name ); - maxLength = 0; - s->numItems = 0; - n = s->itemnames; - while( *n ) { - length = Q_DrawStrlen( *n ); - - if( maxLength < length ) { - maxLength = length; - } - s->numItems++; - n++; - } + maxLength = 0; + s->numItems = 0; + n = s->itemnames; + while( *n ) { + length = Q_DrawStrlen( *n ); + + if( maxLength < length ) { + maxLength = length; + } + s->numItems++; + n++; + } - s->generic.rect.width += ( RCOLUMN_OFFSET - LCOLUMN_OFFSET ) + - maxLength * CHAR_WIDTH; + s->generic.rect.width += ( RCOLUMN_OFFSET - LCOLUMN_OFFSET ) + + maxLength * CHAR_WIDTH; } /* @@ -428,16 +428,16 @@ SpinControl_DoEnter ================= */ static int SpinControl_DoEnter( menuSpinControl_t *s ) { - s->curvalue++; + s->curvalue++; - if( s->curvalue >= s->numItems ) - s->curvalue = 0; + if( s->curvalue >= s->numItems ) + s->curvalue = 0; if( s->generic.change ) { s->generic.change( &s->generic ); } - return QMS_MOVE; + return QMS_MOVE; } /* @@ -446,19 +446,19 @@ SpinControl_DoSlide ================= */ static int SpinControl_DoSlide( menuSpinControl_t *s, int dir ) { - s->curvalue += dir; + s->curvalue += dir; - if( s->curvalue < 0 ) { - s->curvalue = s->numItems - 1; - } else if( s->curvalue >= s->numItems ) { - s->curvalue = 0; - } + if( s->curvalue < 0 ) { + s->curvalue = s->numItems - 1; + } else if( s->curvalue >= s->numItems ) { + s->curvalue = 0; + } if( s->generic.change ) { s->generic.change( &s->generic ); } - return QMS_MOVE; + return QMS_MOVE; } /* @@ -467,20 +467,99 @@ SpinControl_Draw ================= */ static void SpinControl_Draw( menuSpinControl_t *s ) { - UI_DrawString( s->generic.x + LCOLUMN_OFFSET, s->generic.y, NULL, - s->generic.uiFlags | UI_RIGHT | UI_ALTCOLOR, s->generic.name ); + UI_DrawString( s->generic.x + LCOLUMN_OFFSET, s->generic.y, NULL, + s->generic.uiFlags | UI_RIGHT | UI_ALTCOLOR, s->generic.name ); - if( s->generic.flags & QMF_HASFOCUS ) { - if( ( uis.realtime >> 8 ) & 1 ) { - UI_DrawChar( s->generic.x + RCOLUMN_OFFSET / 2, s->generic.y, - s->generic.uiFlags | UI_RIGHT, 13 ); - } - } + if( s->generic.flags & QMF_HASFOCUS ) { + if( ( uis.realtime >> 8 ) & 1 ) { + UI_DrawChar( s->generic.x + RCOLUMN_OFFSET / 2, s->generic.y, + s->generic.uiFlags | UI_RIGHT, 13 ); + } + } - UI_DrawString( s->generic.x + RCOLUMN_OFFSET, s->generic.y, NULL, - s->generic.uiFlags, s->itemnames[s->curvalue] ); + UI_DrawString( s->generic.x + RCOLUMN_OFFSET, s->generic.y, NULL, + s->generic.uiFlags, s->itemnames[s->curvalue] ); } +/* +=================================================================== + +BITFIELD CONTROL + +=================================================================== +*/ + +static void BitField_Push( menuSpinControl_t *s ) { + if( s->cvar->integer & s->mask ) { + s->curvalue = 1 ^ s->negate; + } else { + s->curvalue = 0 ^ s->negate; + } +} + +static void BitField_Pop( menuSpinControl_t *s ) { + int val = s->cvar->integer; + + if( s->curvalue ^ s->negate ) { + val |= s->mask; + } else { + val &= ~s->mask; + } + Cvar_SetInteger( s->cvar, val, CVAR_SET_CONSOLE ); +} + +static void BitField_Free( menuSpinControl_t *s ) { + Z_Free( s->generic.name ); + Z_Free( s ); +} + +/* +=================================================================== + +PAIRS CONTROL + +=================================================================== +*/ + +static void Pairs_Push( menuSpinControl_t *s ) { + int i; + + for( i = 0; i < s->numItems; i++ ) { + if( !Q_stricmp( s->itemvalues[i], s->cvar->string ) ) { + s->curvalue = i; + break; + } + } +} + +static void Pairs_Pop( menuSpinControl_t *s ) { + Cvar_SetByVar( s->cvar, s->itemvalues[s->curvalue], CVAR_SET_CONSOLE ); +} + +static void Pairs_Free( menuSpinControl_t *s ) { + int i; + + Z_Free( s->generic.name ); + for( i = 0; i < s->numItems; i++ ) { + Z_Free( s->itemnames[i] ); + Z_Free( s->itemvalues[i] ); + } + Z_Free( s->itemnames ); + Z_Free( s->itemvalues ); + Z_Free( s ); +} + +/* +=================================================================== + +TOGGLE CONTROL + +=================================================================== +*/ + +static void Toggle_Push( menuSpinControl_t *s ) { + s->curvalue = ( s->cvar->integer ? 1 : 0 ) ^ s->negate; +} /* =================================================================== @@ -496,24 +575,24 @@ MenuList_ValidatePrestep ================= */ static void MenuList_ValidatePrestep( menuList_t *l ) { - if( l->prestep > l->numItems - l->maxItems ) { - l->prestep = l->numItems - l->maxItems; - } - if( l->prestep < 0 ) { - l->prestep = 0; - } + if( l->prestep > l->numItems - l->maxItems ) { + l->prestep = l->numItems - l->maxItems; + } + if( l->prestep < 0 ) { + l->prestep = 0; + } } static void MenuList_AdjustPrestep( menuList_t *l ) { - if( l->numItems > l->maxItems ) { - if( l->prestep > l->curvalue ) { - l->prestep = l->curvalue; - } else if( l->prestep < l->curvalue - l->maxItems + 1 ) { - l->prestep = l->curvalue - l->maxItems + 1; - } - } else { - l->prestep = 0; - } + if( l->numItems > l->maxItems ) { + if( l->prestep > l->curvalue ) { + l->prestep = l->curvalue; + } else if( l->prestep < l->curvalue - l->maxItems + 1 ) { + l->prestep = l->curvalue - l->maxItems + 1; + } + } else { + l->prestep = 0; + } } /* @@ -522,36 +601,36 @@ MenuList_Init ================= */ void MenuList_Init( menuList_t *l ) { - int height; - int i; + int height; + int i; - height = l->generic.height; - if( !( l->mlFlags & MLF_HIDE_HEADER ) ) { - height -= MLIST_SPACING; - } + height = l->generic.height; + if( !( l->mlFlags & MLF_HIDE_HEADER ) ) { + height -= MLIST_SPACING; + } - l->maxItems = height / MLIST_SPACING; + l->maxItems = height / MLIST_SPACING; - clamp( l->curvalue, 0, l->numItems - 1 ); + clamp( l->curvalue, 0, l->numItems - 1 ); - MenuList_ValidatePrestep( l ); + MenuList_ValidatePrestep( l ); - l->generic.rect.x = l->generic.x; - l->generic.rect.y = l->generic.y; + l->generic.rect.x = l->generic.x; + l->generic.rect.y = l->generic.y; - l->generic.rect.width = 0; - for( i = 0; i < l->numcolumns; i++ ) { - l->generic.rect.width += l->columns[i].width; - } + l->generic.rect.width = 0; + for( i = 0; i < l->numcolumns; i++ ) { + l->generic.rect.width += l->columns[i].width; + } -// if( !( l->mlFlags & MLF_HIDE_SCROLLBAR ) ) { -// rc->width += MLIST_SCROLLBAR_WIDTH; -// } +// if( !( l->mlFlags & MLF_HIDE_SCROLLBAR ) ) { +// rc->width += MLIST_SCROLLBAR_WIDTH; +// } - l->generic.rect.height = l->generic.height; + l->generic.rect.height = l->generic.height; if( l->sortdir && l->sort ) { - l->sort( l, l->sortcol ); + l->sort( l, l->sortcol ); } } @@ -561,16 +640,16 @@ MenuList_SetValue ================= */ void MenuList_SetValue( menuList_t *l, int value ) { - clamp( value, 0, l->numItems - 1 ); + clamp( value, 0, l->numItems - 1 ); if( value != l->curvalue ) { - l->curvalue = value; + l->curvalue = value; if( l->generic.change ) { l->generic.change( &l->generic ); } } - MenuList_AdjustPrestep( l ); + MenuList_AdjustPrestep( l ); } static int MenuList_SetColumn( menuList_t *l, int value ) { @@ -581,7 +660,7 @@ static int MenuList_SetColumn( menuList_t *l, int value ) { l->sortdir = 1; } if( l->sort ) { - l->sort( l, l->sortcol ); + l->sort( l, l->sortcol ); } return QMS_SILENT; } @@ -593,21 +672,21 @@ MenuList_Click ================= */ static int MenuList_Click( menuList_t *l ) { - int i, j; - vrect_t rect; + int i, j; + vrect_t rect; - if( !l->items ) { - return QMS_SILENT; - } + if( !l->items ) { + return QMS_SILENT; + } - rect.x = l->generic.rect.x; - rect.y = l->generic.rect.y; - rect.width = l->generic.rect.width; - rect.height = MLIST_SPACING; + rect.x = l->generic.rect.x; + rect.y = l->generic.rect.y; + rect.width = l->generic.rect.width; + rect.height = MLIST_SPACING; // click on header - if( !( l->mlFlags & MLF_HIDE_HEADER ) ) { - if( l->sortdir && UI_CursorInRect( &rect ) ) { + if( !( l->mlFlags & MLF_HIDE_HEADER ) ) { + if( l->sortdir && UI_CursorInRect( &rect ) ) { for( j = 0; j < l->numcolumns; j++ ) { rect.width = l->columns[j].width; if( UI_CursorInRect( &rect ) ) { @@ -615,15 +694,15 @@ static int MenuList_Click( menuList_t *l ) { } rect.x += rect.width; } - return QMS_SILENT; + return QMS_SILENT; } - rect.y += MLIST_SPACING; - } + rect.y += MLIST_SPACING; + } // click on item - j = min( l->numItems, l->prestep + l->maxItems ); - for( i = l->prestep; i < j; i++ ) { - if( UI_CursorInRect( &rect ) ) { + j = min( l->numItems, l->prestep + l->maxItems ); + for( i = l->prestep; i < j; i++ ) { + if( UI_CursorInRect( &rect ) ) { if( l->curvalue == i && uis.realtime - l->clickTime < DOUBLE_CLICK_DELAY ) { @@ -638,11 +717,11 @@ static int MenuList_Click( menuList_t *l ) { return l->generic.change( &l->generic ); } return QMS_SILENT; - } - rect.y += MLIST_SPACING; - } + } + rect.y += MLIST_SPACING; + } - return QMS_SILENT; + return QMS_SILENT; } /* @@ -651,29 +730,29 @@ MenuList_Key ================= */ static int MenuList_Key( menuList_t *l, int key ) { - //int i; + //int i; - if( !l->items ) { - return QMS_NOTHANDLED; - } + if( !l->items ) { + return QMS_NOTHANDLED; + } if( Key_IsDown( K_ALT ) && Q_isdigit( key ) ) { int col = key == '0' ? 9 : key - '0' - 1; if( l->sortdir && col < l->numcolumns ) { return MenuList_SetColumn( l, col ); } - return QMS_NOTHANDLED; + return QMS_NOTHANDLED; } #if 0 - if( key > 32 && key < 127 ) { + if( key > 32 && key < 127 ) { if( uis.realtime > l->scratchTime + 1300 ) { l->scratchCount = 0; l->scratchTime = uis.realtime; } if( l->scratchCount >= sizeof( l->scratch ) - 1 ) { - return QMS_NOTHANDLED; + return QMS_NOTHANDLED; } l->scratch[l->scratchCount++] = key; @@ -687,21 +766,21 @@ static int MenuList_Key( menuList_t *l, int key ) { return QMS_NOTHANDLED; } - for( i = 0; i < l->numItems; i++ ) { - if( !Q_stricmpn( UI_GetColumn( ( char * )l->items[i] + l->extrasize, l->sortcol ), l->scratch, l->scratchCount ) ) { - MenuList_SetValue( l, i ); - return QMS_SILENT; - } - i++; - } + for( i = 0; i < l->numItems; i++ ) { + if( !Q_stricmpn( UI_GetColumn( ( char * )l->items[i] + l->extrasize, l->sortcol ), l->scratch, l->scratchCount ) ) { + MenuList_SetValue( l, i ); + return QMS_SILENT; + } + i++; + } - return QMS_NOTHANDLED; - } + return QMS_NOTHANDLED; + } #endif l->scratchCount = 0; - switch( key ) { + switch( key ) { case K_LEFTARROW: case 'h': if( l->sortdir ) { @@ -720,89 +799,89 @@ static int MenuList_Key( menuList_t *l, int key ) { return MenuList_SetColumn( l, 0 ); } break; - case K_UPARROW: - case K_KP_UPARROW: + case K_UPARROW: + case K_KP_UPARROW: case 'k': - if( l->curvalue > 0 ) { - l->curvalue--; + if( l->curvalue > 0 ) { + l->curvalue--; if( l->generic.change ) { l->generic.change( &l->generic ); } - MenuList_AdjustPrestep( l ); - return QMS_MOVE; - } - return QMS_BEEP; + MenuList_AdjustPrestep( l ); + return QMS_MOVE; + } + return QMS_BEEP; - case K_DOWNARROW: - case K_KP_DOWNARROW: + case K_DOWNARROW: + case K_KP_DOWNARROW: case 'j': - if( l->curvalue < l->numItems - 1 ) { - l->curvalue++; + if( l->curvalue < l->numItems - 1 ) { + l->curvalue++; if( l->generic.change ) { l->generic.change( &l->generic ); } - MenuList_AdjustPrestep( l ); - return QMS_MOVE; - } - return QMS_BEEP; - - case K_HOME: - case K_KP_HOME: - l->prestep = 0; - l->curvalue = 0; + MenuList_AdjustPrestep( l ); + return QMS_MOVE; + } + return QMS_BEEP; + + case K_HOME: + case K_KP_HOME: + l->prestep = 0; + l->curvalue = 0; if( l->generic.change ) { l->generic.change( &l->generic ); } - return QMS_MOVE; - - case K_END: - case K_KP_END: - if( l->numItems > l->maxItems ) { - l->prestep = l->numItems - l->maxItems; - } - l->curvalue = l->numItems - 1; + return QMS_MOVE; + + case K_END: + case K_KP_END: + if( l->numItems > l->maxItems ) { + l->prestep = l->numItems - l->maxItems; + } + l->curvalue = l->numItems - 1; if( l->generic.change ) { l->generic.change( &l->generic ); } - return QMS_MOVE; - - case K_MWHEELUP: - if( Key_IsDown( K_CTRL ) ) { - l->prestep -= 4; - } else { - l->prestep -= 2; - } - MenuList_ValidatePrestep( l ); - return QMS_SILENT; - - case K_MWHEELDOWN: - if( Key_IsDown( K_CTRL ) ) { - l->prestep += 4; - } else { - l->prestep += 2; - } - MenuList_ValidatePrestep( l ); - return QMS_SILENT; - - case K_PGUP: - case K_KP_PGUP: - l->prestep -= l->maxItems; - MenuList_ValidatePrestep( l ); - return QMS_SILENT; - - case K_PGDN: - case K_KP_PGDN: - l->prestep += l->maxItems; - MenuList_ValidatePrestep( l ); - return QMS_SILENT; - - case K_MOUSE1: + return QMS_MOVE; + + case K_MWHEELUP: + if( Key_IsDown( K_CTRL ) ) { + l->prestep -= 4; + } else { + l->prestep -= 2; + } + MenuList_ValidatePrestep( l ); + return QMS_SILENT; + + case K_MWHEELDOWN: + if( Key_IsDown( K_CTRL ) ) { + l->prestep += 4; + } else { + l->prestep += 2; + } + MenuList_ValidatePrestep( l ); + return QMS_SILENT; + + case K_PGUP: + case K_KP_PGUP: + l->prestep -= l->maxItems; + MenuList_ValidatePrestep( l ); + return QMS_SILENT; + + case K_PGDN: + case K_KP_PGDN: + l->prestep += l->maxItems; + MenuList_ValidatePrestep( l ); + return QMS_SILENT; + + case K_MOUSE1: case K_MOUSE2: //case K_MOUSE3: - return MenuList_Click( l ); - } + return MenuList_Click( l ); + } - return QMS_NOTHANDLED; + return QMS_NOTHANDLED; } /* @@ -811,26 +890,26 @@ MenuList_DrawString ================= */ static void MenuList_DrawString( int x, int y, int flags, - menuListColumn_t *column, - const char *string ) + menuListColumn_t *column, + const char *string ) { - clipRect_t rc; - - rc.left = x; - rc.right = x + column->width - 1; - rc.top = 0; - rc.bottom = 0; - - if( ( column->uiFlags & UI_CENTER ) == UI_CENTER ) { - x += column->width / 2; - } else if( column->uiFlags & UI_RIGHT ) { - x += column->width - MLIST_PRESTEP; - } else { - x += MLIST_PRESTEP; - } - - ref.SetClipRect( DRAW_CLIP_RIGHT|DRAW_CLIP_LEFT, &rc ); - UI_DrawString( x, y + 1, NULL, column->uiFlags | flags, string ); + clipRect_t rc; + + rc.left = x; + rc.right = x + column->width - 1; + rc.top = 0; + rc.bottom = 0; + + if( ( column->uiFlags & UI_CENTER ) == UI_CENTER ) { + x += column->width / 2; + } else if( column->uiFlags & UI_RIGHT ) { + x += column->width - MLIST_PRESTEP; + } else { + x += MLIST_PRESTEP; + } + + ref.SetClipRect( DRAW_CLIP_RIGHT|DRAW_CLIP_LEFT, &rc ); + UI_DrawString( x, y + 1, NULL, column->uiFlags | flags, string ); if( uis.glconfig.renderer == GL_RENDERER_SOFTWARE ) { ref.SetClipRect( DRAW_CLIP_MASK, &uis.clipRect ); } else { @@ -846,115 +925,115 @@ MenuList_Draw ================= */ static void MenuList_Draw( menuList_t *l ) { - char *s; - int x, y, xx, yy; - int i, j, k; - int width, height; - vrect_t rect; - float pageFrac, prestepFrac; - int barHeight; - - if( !l->items ) { - //return; - } - - x = l->generic.rect.x; - y = l->generic.rect.y; - width = l->generic.rect.width; - height = l->generic.rect.height; - - // draw header - if( !( l->mlFlags & MLF_HIDE_HEADER ) ) { - xx = x; - for( j = 0; j < l->numcolumns; j++ ) { - ref.DrawFillEx( xx, y, l->columns[j].width - 1, + char *s; + int x, y, xx, yy; + int i, j, k; + int width, height; + vrect_t rect; + float pageFrac, prestepFrac; + int barHeight; + + if( !l->items ) { + //return; + } + + x = l->generic.rect.x; + y = l->generic.rect.y; + width = l->generic.rect.width; + height = l->generic.rect.height; + + // draw header + if( !( l->mlFlags & MLF_HIDE_HEADER ) ) { + xx = x; + for( j = 0; j < l->numcolumns; j++ ) { + ref.DrawFillEx( xx, y, l->columns[j].width - 1, MLIST_SPACING - 1, colorField ); - if( l->columns[j].name ) { - MenuList_DrawString( xx, y, l->sortcol == j && l->sortdir ? 0 : UI_ALTCOLOR, - &l->columns[j], l->columns[j].name ); - } - xx += l->columns[j].width; - } - y += MLIST_SPACING; - height -= MLIST_SPACING; - } - - if( !( l->mlFlags & MLF_HIDE_SCROLLBAR ) && - ( !( l->mlFlags & MLF_HIDE_SCROLLBAR_EMPTY ) || l->numItems > l->maxItems ) ) - { - barHeight = height - MLIST_SPACING * 2; - yy = y + MLIST_SPACING; - - if( !( l->mlFlags & MLF_HIDE_BACKGROUND ) ) { - rect.x = x + width; - rect.y = yy; - rect.width = MLIST_SCROLLBAR_WIDTH - 1; - rect.height = barHeight; - - // draw scrollbar background - UIS_FillRectEx( &rect, colorField ); - } - - if( l->numItems > l->maxItems ) { - pageFrac = ( float )l->maxItems / l->numItems; - prestepFrac = ( float )l->prestep / l->numItems; - } else { - pageFrac = 1; - prestepFrac = 0; - } - - rect.x = x + width; - rect.y = yy + Q_rint( barHeight * prestepFrac ); - rect.width = MLIST_SCROLLBAR_WIDTH - 1; - rect.height = Q_rint( barHeight * pageFrac ); - - // draw scrollbar thumb - UIS_FillRectEx( &rect, colorField ); - - } - - xx = x; - for( j = 0; j < l->numcolumns; j++ ) { - ref.DrawFillEx( xx, y, l->columns[j].width - 1, - height, colorField ); - - xx += l->columns[j].width; - } - - yy = y; - k = min( l->numItems, l->prestep + l->maxItems ); - for( i = l->prestep; i < k; i++ ) { - // draw selection - if( !( l->generic.flags & QMF_DISABLED ) && i == l->curvalue ) { - ref.DrawFillEx( x, yy, width - 1, MLIST_SPACING, colorField ); - } - - // draw contents - s = ( char * )l->items[i] + l->extrasize; - xx = x; - for( j = 0; j < l->numcolumns; j++ ) { - if( !*s ) { - break; - } - - MenuList_DrawString( xx, yy, 0, &l->columns[j], s ); - - xx += l->columns[j].width; - s += strlen( s ) + 1; - } - - yy += MLIST_SPACING; - } + if( l->columns[j].name ) { + MenuList_DrawString( xx, y, l->sortcol == j && l->sortdir ? 0 : UI_ALTCOLOR, + &l->columns[j], l->columns[j].name ); + } + xx += l->columns[j].width; + } + y += MLIST_SPACING; + height -= MLIST_SPACING; + } + + if( !( l->mlFlags & MLF_HIDE_SCROLLBAR ) && + ( !( l->mlFlags & MLF_HIDE_SCROLLBAR_EMPTY ) || l->numItems > l->maxItems ) ) + { + barHeight = height - MLIST_SPACING * 2; + yy = y + MLIST_SPACING; + + if( !( l->mlFlags & MLF_HIDE_BACKGROUND ) ) { + rect.x = x + width; + rect.y = yy; + rect.width = MLIST_SCROLLBAR_WIDTH - 1; + rect.height = barHeight; + + // draw scrollbar background + UIS_FillRectEx( &rect, colorField ); + } + + if( l->numItems > l->maxItems ) { + pageFrac = ( float )l->maxItems / l->numItems; + prestepFrac = ( float )l->prestep / l->numItems; + } else { + pageFrac = 1; + prestepFrac = 0; + } + + rect.x = x + width; + rect.y = yy + Q_rint( barHeight * prestepFrac ); + rect.width = MLIST_SCROLLBAR_WIDTH - 1; + rect.height = Q_rint( barHeight * pageFrac ); + + // draw scrollbar thumb + UIS_FillRectEx( &rect, colorField ); + + } + + xx = x; + for( j = 0; j < l->numcolumns; j++ ) { + ref.DrawFillEx( xx, y, l->columns[j].width - 1, + height, colorField ); + + xx += l->columns[j].width; + } + + yy = y; + k = min( l->numItems, l->prestep + l->maxItems ); + for( i = l->prestep; i < k; i++ ) { + // draw selection + if( !( l->generic.flags & QMF_DISABLED ) && i == l->curvalue ) { + ref.DrawFillEx( x, yy, width - 1, MLIST_SPACING, colorField ); + } + + // draw contents + s = ( char * )l->items[i] + l->extrasize; + xx = x; + for( j = 0; j < l->numcolumns; j++ ) { + if( !*s ) { + break; + } + + MenuList_DrawString( xx, yy, 0, &l->columns[j], s ); + + xx += l->columns[j].width; + s += strlen( s ) + 1; + } + + yy += MLIST_SPACING; + } } void MenuList_Sort( menuList_t *l, int offset, int (*cmpfunc)( const void *, const void * ) ) { void *n; int i; - if( !l->items ) { - return; - } + if( !l->items ) { + return; + } n = l->items[l->curvalue]; @@ -967,7 +1046,7 @@ void MenuList_Sort( menuList_t *l, int offset, int (*cmpfunc)( const void *, con } } - MenuList_AdjustPrestep( l ); + MenuList_AdjustPrestep( l ); } /* @@ -997,31 +1076,31 @@ static void Slider_Free( menuSlider_t *s ) { } static void Slider_Init( menuSlider_t *s ) { - int len = strlen( s->generic.name ) * CHAR_WIDTH; + int len = strlen( s->generic.name ) * CHAR_WIDTH; - s->generic.rect.x = s->generic.x + LCOLUMN_OFFSET - len; - s->generic.rect.y = s->generic.y; + s->generic.rect.x = s->generic.x + LCOLUMN_OFFSET - len; + s->generic.rect.y = s->generic.y; - s->generic.rect.width = 32 + len + ( SLIDER_RANGE + 2 ) * CHAR_WIDTH; - s->generic.rect.height = CHAR_HEIGHT; + s->generic.rect.width = 32 + len + ( SLIDER_RANGE + 2 ) * CHAR_WIDTH; + s->generic.rect.height = CHAR_HEIGHT; - if( s->curvalue > s->maxvalue ) - s->curvalue = s->maxvalue; - else if( s->curvalue < s->minvalue ) - s->curvalue = s->minvalue; + if( s->curvalue > s->maxvalue ) + s->curvalue = s->maxvalue; + else if( s->curvalue < s->minvalue ) + s->curvalue = s->minvalue; } static int Slider_Key( menuSlider_t *s, int key ) { - switch( key ) { - case K_END: - s->curvalue = s->maxvalue; - return QMS_MOVE; - case K_HOME: - s->curvalue = s->minvalue; - return QMS_MOVE; - } + switch( key ) { + case K_END: + s->curvalue = s->maxvalue; + return QMS_MOVE; + case K_HOME: + s->curvalue = s->minvalue; + return QMS_MOVE; + } - return QMS_NOTHANDLED; + return QMS_NOTHANDLED; } @@ -1031,21 +1110,21 @@ Slider_DoSlide ================= */ static int Slider_DoSlide( menuSlider_t *s, int dir ) { - s->curvalue += dir; + s->curvalue += dir; - if( s->curvalue > s->maxvalue ) - s->curvalue = s->maxvalue; - else if( s->curvalue < s->minvalue ) - s->curvalue = s->minvalue; + if( s->curvalue > s->maxvalue ) + s->curvalue = s->maxvalue; + else if( s->curvalue < s->minvalue ) + s->curvalue = s->minvalue; if( s->generic.change ) { menuSound_t sound = s->generic.change( &s->generic ); - if( sound != QMS_NOTHANDLED ) { - return sound; - } + if( sound != QMS_NOTHANDLED ) { + return sound; + } } - return QMS_SILENT; + return QMS_SILENT; } /* @@ -1054,36 +1133,36 @@ Slider_Draw ================= */ static void Slider_Draw( menuSlider_t *s ) { - int i, flags; + int i, flags; float pos; - flags = s->generic.uiFlags & ~( UI_LEFT | UI_RIGHT ); + flags = s->generic.uiFlags & ~( UI_LEFT | UI_RIGHT ); - if( s->generic.flags & QMF_HASFOCUS ) { - if( ( uis.realtime >> 8 ) & 1 ) { - UI_DrawChar( s->generic.x + RCOLUMN_OFFSET / 2, s->generic.y, s->generic.uiFlags | UI_RIGHT, 13 ); - } - } + if( s->generic.flags & QMF_HASFOCUS ) { + if( ( uis.realtime >> 8 ) & 1 ) { + UI_DrawChar( s->generic.x + RCOLUMN_OFFSET / 2, s->generic.y, s->generic.uiFlags | UI_RIGHT, 13 ); + } + } - UI_DrawString( s->generic.x + LCOLUMN_OFFSET, s->generic.y, NULL, - flags | UI_RIGHT | UI_ALTCOLOR, s->generic.name ); + UI_DrawString( s->generic.x + LCOLUMN_OFFSET, s->generic.y, NULL, + flags | UI_RIGHT | UI_ALTCOLOR, s->generic.name ); - UI_DrawChar( s->generic.x + RCOLUMN_OFFSET, s->generic.y, flags | UI_LEFT, 128 ); + UI_DrawChar( s->generic.x + RCOLUMN_OFFSET, s->generic.y, flags | UI_LEFT, 128 ); - for( i = 0 ; i < SLIDER_RANGE ; i++ ) - UI_DrawChar( RCOLUMN_OFFSET + s->generic.x + i * CHAR_WIDTH + CHAR_WIDTH, s->generic.y, flags | UI_LEFT, 129 ); + for( i = 0 ; i < SLIDER_RANGE ; i++ ) + UI_DrawChar( RCOLUMN_OFFSET + s->generic.x + i * CHAR_WIDTH + CHAR_WIDTH, s->generic.y, flags | UI_LEFT, 129 ); - UI_DrawChar( RCOLUMN_OFFSET + s->generic.x + i * CHAR_WIDTH + CHAR_WIDTH, s->generic.y, flags | UI_LEFT, 130 ); + UI_DrawChar( RCOLUMN_OFFSET + s->generic.x + i * CHAR_WIDTH + CHAR_WIDTH, s->generic.y, flags | UI_LEFT, 130 ); if( s->maxvalue <= s->minvalue ) { pos = 0; } else { - pos = ( s->curvalue - s->minvalue ) / + pos = ( s->curvalue - s->minvalue ) / ( float )( s->maxvalue - s->minvalue ); - clamp( pos, 0, 1 ); + clamp( pos, 0, 1 ); } - UI_DrawChar( CHAR_WIDTH + RCOLUMN_OFFSET + s->generic.x + ( SLIDER_RANGE - 1 ) * CHAR_WIDTH * pos, s->generic.y, flags | UI_LEFT, 131 ); + UI_DrawChar( CHAR_WIDTH + RCOLUMN_OFFSET + s->generic.x + ( SLIDER_RANGE - 1 ) * CHAR_WIDTH * pos, s->generic.y, flags | UI_LEFT, 131 ); } /* @@ -1100,8 +1179,8 @@ Separator_Init ================= */ static void Separator_Init( menuSeparator_t *s ) { - s->generic.rect.x = s->generic.rect.y = 999999; - s->generic.rect.width = s->generic.rect.height = -999999; + s->generic.rect.x = s->generic.rect.y = 999999; + s->generic.rect.width = s->generic.rect.height = -999999; } /* @@ -1110,8 +1189,8 @@ Separator_Draw ================= */ static void Separator_Draw( menuSeparator_t *s ) { - if( s->generic.name ) - UI_DrawString( s->generic.x, s->generic.y, NULL, UI_RIGHT, s->generic.name ); + if( s->generic.name ) + UI_DrawString( s->generic.x, s->generic.y, NULL, UI_RIGHT, s->generic.name ); } /* @@ -1131,11 +1210,11 @@ static int Common_DoEnter( menuCommon_t *item ) { if( item->activate ) { menuSound_t sound = item->activate( item ); if( sound != QMS_NOTHANDLED ) { - return sound; + return sound; } - } + } - return QMS_SILENT; + return QMS_SILENT; } @@ -1145,18 +1224,18 @@ Menu_AddItem ================= */ void Menu_AddItem( menuFrameWork_t *menu, void *item ) { - if( menu->nitems >= MAXMENUITEMS ) { + if( menu->nitems >= MAXMENUITEMS ) { Com_Error( ERR_FATAL, "Menu_AddItem: too many items" ); - return; - } + return; + } - menu->items[menu->nitems++] = item; - ((menuCommon_t *)item)->parent = menu; + menu->items[menu->nitems++] = item; + ((menuCommon_t *)item)->parent = menu; } void Menu_Init( menuFrameWork_t *menu ) { - void *item; - int i; + void *item; + int i; int focus = 0; if( !menu->size ) { @@ -1164,8 +1243,8 @@ void Menu_Init( menuFrameWork_t *menu ) { } menu->size( menu ); - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; focus |= ((menuCommon_t *)item)->flags & QMF_HASFOCUS; switch( ((menuCommon_t *)item)->type ) { @@ -1179,6 +1258,9 @@ void Menu_Init( menuFrameWork_t *menu ) { MenuList_Init( item ); break; case MTYPE_SPINCONTROL: + case MTYPE_BITFIELD: + case MTYPE_PAIRS: + case MTYPE_TOGGLE: SpinControl_Init( item ); break; case MTYPE_ACTION: @@ -1201,81 +1283,81 @@ void Menu_Init( menuFrameWork_t *menu ) { // set focus to the first item by default if( !focus && menu->nitems ) { - item = menu->items[0]; + item = menu->items[0]; ((menuCommon_t *)item)->flags |= QMF_HASFOCUS; } } void Menu_Size( menuFrameWork_t *menu ) { - menuCommon_t *item; + menuCommon_t *item; int x, y; - int i, count; + int i, count; // count visible items - for( i = 0, count = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; - if( item->flags & QMF_HIDDEN ) { - continue; - } + for( i = 0, count = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; + if( item->flags & QMF_HIDDEN ) { + continue; + } count++; } - x = uis.width / 2; - y = ( uis.height - MENU_SPACING * count ) / 2; + x = uis.width / 2; + y = ( uis.height - MENU_SPACING * count ) / 2; // align items - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; - if( item->flags & QMF_HIDDEN ) { - continue; - } + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; + if( item->flags & QMF_HIDDEN ) { + continue; + } item->x = x; item->y = y; - y += MENU_SPACING; + y += MENU_SPACING; } } menuCommon_t *Menu_ItemAtCursor( menuFrameWork_t *m ) { - menuCommon_t *item; - int i; + menuCommon_t *item; + int i; - for( i = 0; i < m->nitems; i++ ) { - item = m->items[i]; - if( item->flags & QMF_HASFOCUS ) { - return item; - } - } + for( i = 0; i < m->nitems; i++ ) { + item = m->items[i]; + if( item->flags & QMF_HASFOCUS ) { + return item; + } + } - return NULL; + return NULL; } void Menu_SetFocus( menuCommon_t *focus ) { - menuFrameWork_t *menu; - menuCommon_t *item; - int i; + menuFrameWork_t *menu; + menuCommon_t *item; + int i; - if( focus->flags & QMF_HASFOCUS ) { - return; - } + if( focus->flags & QMF_HASFOCUS ) { + return; + } - menu = focus->parent; + menu = focus->parent; - for( i = 0; i < menu->nitems ; i++ ) { - item = (menuCommon_t *)menu->items[i]; + for( i = 0; i < menu->nitems ; i++ ) { + item = (menuCommon_t *)menu->items[i]; - if( item == focus ) { - item->flags |= QMF_HASFOCUS; + if( item == focus ) { + item->flags |= QMF_HASFOCUS; if( item->focus ) { item->focus( item, qtrue ); } - } else if( item->flags & QMF_HASFOCUS ) { - item->flags &= ~QMF_HASFOCUS; + } else if( item->flags & QMF_HASFOCUS ) { + item->flags &= ~QMF_HASFOCUS; if( item->focus ) { item->focus( item, qfalse ); } - } - } + } + } } @@ -1289,49 +1371,49 @@ slot. ================= */ menuSound_t Menu_AdjustCursor( menuFrameWork_t *m, int dir ) { - menuCommon_t *item; - int cursor, pos; - int i; - - pos = 0; - for( i=0 ; i<m->nitems ; i++ ) { - item = (menuCommon_t *)m->items[i]; - - if( item->flags & QMF_HASFOCUS ) { - pos = i; - break; - } - } - - /* - ** crawl in the direction indicated until we find a valid spot - */ - cursor = pos; - if( dir == 1 ) { - do { - cursor++; - if( cursor >= m->nitems ) - cursor = 0; + menuCommon_t *item; + int cursor, pos; + int i; + + pos = 0; + for( i=0 ; i<m->nitems ; i++ ) { + item = (menuCommon_t *)m->items[i]; - item = (menuCommon_t *)m->items[cursor]; - if( UI_IsItemSelectable( item ) ) - break; - } while( cursor != pos ); - } else { - do { - cursor--; - if( cursor < 0 ) - cursor = m->nitems - 1; + if( item->flags & QMF_HASFOCUS ) { + pos = i; + break; + } + } - item = (menuCommon_t *)m->items[cursor]; - if( UI_IsItemSelectable( item ) ) - break; - } while( cursor != pos ); - } + /* + ** crawl in the direction indicated until we find a valid spot + */ + cursor = pos; + if( dir == 1 ) { + do { + cursor++; + if( cursor >= m->nitems ) + cursor = 0; + + item = (menuCommon_t *)m->items[cursor]; + if( UI_IsItemSelectable( item ) ) + break; + } while( cursor != pos ); + } else { + do { + cursor--; + if( cursor < 0 ) + cursor = m->nitems - 1; + + item = (menuCommon_t *)m->items[cursor]; + if( UI_IsItemSelectable( item ) ) + break; + } while( cursor != pos ); + } - Menu_SetFocus( item ); + Menu_SetFocus( item ); - return QMS_MOVE; + return QMS_MOVE; } /* @@ -1340,244 +1422,251 @@ Menu_Draw ================= */ void Menu_Draw( menuFrameWork_t *menu ) { - void *item; - int i; + void *item; + int i; // // draw title bar // - if( menu->title ) { - UI_DrawString( uis.width / 2, 0, NULL, UI_CENTER|UI_ALTCOLOR, menu->title ); - } + if( menu->title ) { + UI_DrawString( uis.width / 2, 0, NULL, UI_CENTER|UI_ALTCOLOR, menu->title ); + } // // draw contents // - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; - if( (( menuCommon_t * )item)->flags & QMF_HIDDEN ) { - continue; - } - - switch( (( menuCommon_t * )item)->type ) { - case MTYPE_FIELD: - Field_Draw( item ); - break; - case MTYPE_SLIDER: - Slider_Draw( item ); - break; - case MTYPE_LIST: - MenuList_Draw( item ); - break; - case MTYPE_SPINCONTROL: - SpinControl_Draw( item ); - break; - case MTYPE_ACTION: - Action_Draw( item ); - break; - case MTYPE_SEPARATOR: - Separator_Draw( item ); - break; - case MTYPE_STATIC: - Static_Draw( item ); - break; - case MTYPE_KEYBIND: - Keybind_Draw( item ); - break; - default: - Com_Error( ERR_FATAL, "Menu_Draw: unknown item type" ); - break; - } - - if( ui_debug->integer ) { - UIS_DrawRect( &(( menuCommon_t * )item)->rect, 1, 223 ); - } - } + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; + if( (( menuCommon_t * )item)->flags & QMF_HIDDEN ) { + continue; + } + + switch( (( menuCommon_t * )item)->type ) { + case MTYPE_FIELD: + Field_Draw( item ); + break; + case MTYPE_SLIDER: + Slider_Draw( item ); + break; + case MTYPE_LIST: + MenuList_Draw( item ); + break; + case MTYPE_SPINCONTROL: + case MTYPE_BITFIELD: + case MTYPE_PAIRS: + case MTYPE_TOGGLE: + SpinControl_Draw( item ); + break; + case MTYPE_ACTION: + Action_Draw( item ); + break; + case MTYPE_SEPARATOR: + Separator_Draw( item ); + break; + case MTYPE_STATIC: + Static_Draw( item ); + break; + case MTYPE_KEYBIND: + Keybind_Draw( item ); + break; + default: + Com_Error( ERR_FATAL, "Menu_Draw: unknown item type" ); + break; + } + + if( ui_debug->integer ) { + UIS_DrawRect( &(( menuCommon_t * )item)->rect, 1, 223 ); + } + } // // draw status bar // - if( menu->status ) { - ref.DrawFill( 0, uis.height - 8, uis.width, 8, 4 ); - UI_DrawString( uis.width / 2, uis.height - 8, NULL, UI_CENTER, menu->status ); - } + if( menu->status ) { + ref.DrawFill( 0, uis.height - 8, uis.width, 8, 4 ); + UI_DrawString( uis.width / 2, uis.height - 8, NULL, UI_CENTER, menu->status ); + } } menuSound_t Menu_SelectItem( menuFrameWork_t *s ) { - menuCommon_t *item; - - if( !( item = Menu_ItemAtCursor( s ) ) ) { - return QMS_NOTHANDLED; - } - - switch( item->type ) { - //case MTYPE_SLIDER: - // return Slider_DoSlide( (menuSlider_t *)item, 1 ); - case MTYPE_SPINCONTROL: - return SpinControl_DoEnter( (menuSpinControl_t *)item ); - case MTYPE_KEYBIND: + menuCommon_t *item; + + if( !( item = Menu_ItemAtCursor( s ) ) ) { + return QMS_NOTHANDLED; + } + + switch( item->type ) { + //case MTYPE_SLIDER: + // return Slider_DoSlide( (menuSlider_t *)item, 1 ); + case MTYPE_SPINCONTROL: + case MTYPE_BITFIELD: + case MTYPE_PAIRS: + case MTYPE_TOGGLE: + return SpinControl_DoEnter( (menuSpinControl_t *)item ); + case MTYPE_KEYBIND: return Keybind_DoEnter( ( menuKeybind_t * )item ); - case MTYPE_FIELD: - case MTYPE_ACTION: - case MTYPE_BITMAP: - case MTYPE_LIST: - case MTYPE_IMAGELIST: - return Common_DoEnter( item ); + case MTYPE_FIELD: + case MTYPE_ACTION: + case MTYPE_LIST: + return Common_DoEnter( item ); default: - return QMS_NOTHANDLED; - } + return QMS_NOTHANDLED; + } } menuSound_t Menu_SlideItem( menuFrameWork_t *s, int dir ) { - menuCommon_t *item; + menuCommon_t *item; - if( !( item = Menu_ItemAtCursor( s ) ) ) { - return QMS_NOTHANDLED; - } + if( !( item = Menu_ItemAtCursor( s ) ) ) { + return QMS_NOTHANDLED; + } - switch( item->type ) { - case MTYPE_SLIDER: - return Slider_DoSlide( (menuSlider_t *)item, dir ); - case MTYPE_SPINCONTROL: - return SpinControl_DoSlide( (menuSpinControl_t *)item, dir ); + switch( item->type ) { + case MTYPE_SLIDER: + return Slider_DoSlide( (menuSlider_t *)item, dir ); + case MTYPE_SPINCONTROL: + case MTYPE_BITFIELD: + case MTYPE_PAIRS: + case MTYPE_TOGGLE: + return SpinControl_DoSlide( (menuSpinControl_t *)item, dir ); default: - return QMS_NOTHANDLED; - } + return QMS_NOTHANDLED; + } } menuSound_t Menu_KeyEvent( menuCommon_t *item, int key ) { if( item->keydown ) { - menuSound_t sound = item->keydown( item, key ); + menuSound_t sound = item->keydown( item, key ); if( sound != QMS_NOTHANDLED ) { return sound; } - } - - switch( item->type ) { - case MTYPE_FIELD: - return Field_Key( ( menuField_t * )item, key ); - case MTYPE_LIST: - return MenuList_Key( ( menuList_t * )item, key ); - case MTYPE_SLIDER: - return Slider_Key( ( menuSlider_t * )item, key ); - case MTYPE_KEYBIND: - return Keybind_Key( ( menuKeybind_t * )item, key ); + } + + switch( item->type ) { + case MTYPE_FIELD: + return Field_Key( ( menuField_t * )item, key ); + case MTYPE_LIST: + return MenuList_Key( ( menuList_t * )item, key ); + case MTYPE_SLIDER: + return Slider_Key( ( menuSlider_t * )item, key ); + case MTYPE_KEYBIND: + return Keybind_Key( ( menuKeybind_t * )item, key ); default: - return QMS_NOTHANDLED; - } + return QMS_NOTHANDLED; + } } menuSound_t Menu_CharEvent( menuCommon_t *item, int key ) { - switch( item->type ) { - case MTYPE_FIELD: - return Field_Char( (menuField_t *)item, key ); + switch( item->type ) { + case MTYPE_FIELD: + return Field_Char( (menuField_t *)item, key ); default: - return QMS_NOTHANDLED; - } + return QMS_NOTHANDLED; + } } menuSound_t Menu_MouseMove( menuCommon_t *item ) { - return QMS_NOTHANDLED; + return QMS_NOTHANDLED; } menuSound_t Menu_DefaultKey( menuFrameWork_t *m, int key ) { - menuCommon_t *item; - - switch( key ) { - case K_ESCAPE: - UI_PopMenu(); - return QMS_OUT; - - case K_KP_UPARROW: - case K_UPARROW: + menuCommon_t *item; + + switch( key ) { + case K_ESCAPE: + UI_PopMenu(); + return QMS_OUT; + + case K_KP_UPARROW: + case K_UPARROW: case 'k': - return Menu_AdjustCursor( m, -1 ); - - case K_KP_DOWNARROW: - case K_DOWNARROW: - case K_TAB: + return Menu_AdjustCursor( m, -1 ); + + case K_KP_DOWNARROW: + case K_DOWNARROW: + case K_TAB: case 'j': - return Menu_AdjustCursor( m, 1 ); + return Menu_AdjustCursor( m, 1 ); - case K_KP_LEFTARROW: - case K_LEFTARROW: - case K_MWHEELDOWN: + case K_KP_LEFTARROW: + case K_LEFTARROW: + case K_MWHEELDOWN: case 'h': - return Menu_SlideItem( m, -1 ); + return Menu_SlideItem( m, -1 ); - case K_KP_RIGHTARROW: - case K_RIGHTARROW: - case K_MWHEELUP: + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + case K_MWHEELUP: case 'l': - return Menu_SlideItem( m, 1 ); - - case K_MOUSE1: - case K_MOUSE2: - case K_MOUSE3: - item = Menu_HitTest( m ); - if( !item ) { - return QMS_NOTHANDLED; - } - - if( !( item->flags & QMF_HASFOCUS ) ) { - return QMS_NOTHANDLED; - } - - // fall through - - case K_JOY1: - case K_JOY2: - case K_JOY3: - case K_JOY4: - case K_AUX1: - case K_AUX2: - case K_AUX3: - case K_AUX4: - case K_AUX5: - case K_AUX6: - case K_AUX7: - case K_AUX8: - case K_AUX9: - case K_AUX10: - case K_AUX11: - case K_AUX12: - case K_AUX13: - case K_AUX14: - case K_AUX15: - case K_AUX16: - case K_AUX17: - case K_AUX18: - case K_AUX19: - case K_AUX20: - case K_AUX21: - case K_AUX22: - case K_AUX23: - case K_AUX24: - case K_AUX25: - case K_AUX26: - case K_AUX27: - case K_AUX28: - case K_AUX29: - case K_AUX30: - case K_AUX31: - case K_AUX32: - case K_KP_ENTER: - case K_ENTER: - return Menu_SelectItem( m ); - } - - return QMS_NOTHANDLED; + return Menu_SlideItem( m, 1 ); + + case K_MOUSE1: + case K_MOUSE2: + case K_MOUSE3: + item = Menu_HitTest( m ); + if( !item ) { + return QMS_NOTHANDLED; + } + + if( !( item->flags & QMF_HASFOCUS ) ) { + return QMS_NOTHANDLED; + } + + // fall through + + case K_JOY1: + case K_JOY2: + case K_JOY3: + case K_JOY4: + case K_AUX1: + case K_AUX2: + case K_AUX3: + case K_AUX4: + case K_AUX5: + case K_AUX6: + case K_AUX7: + case K_AUX8: + case K_AUX9: + case K_AUX10: + case K_AUX11: + case K_AUX12: + case K_AUX13: + case K_AUX14: + case K_AUX15: + case K_AUX16: + case K_AUX17: + case K_AUX18: + case K_AUX19: + case K_AUX20: + case K_AUX21: + case K_AUX22: + case K_AUX23: + case K_AUX24: + case K_AUX25: + case K_AUX26: + case K_AUX27: + case K_AUX28: + case K_AUX29: + case K_AUX30: + case K_AUX31: + case K_AUX32: + case K_KP_ENTER: + case K_ENTER: + return Menu_SelectItem( m ); + } + + return QMS_NOTHANDLED; } menuSound_t Menu_Keydown( menuFrameWork_t *menu, int key ) { - menuCommon_t *item; + menuCommon_t *item; menuSound_t sound; if( menu->keywait ) { } - if( menu->keydown ) { + if( menu->keydown ) { sound = menu->keydown( menu, key ); if( sound != QMS_NOTHANDLED ) { return sound; @@ -1586,53 +1675,62 @@ menuSound_t Menu_Keydown( menuFrameWork_t *menu, int key ) { item = Menu_ItemAtCursor( menu ); if( item ) { - sound = Menu_KeyEvent( item, key ); + sound = Menu_KeyEvent( item, key ); if( sound != QMS_NOTHANDLED ) { return sound; } } - - sound = Menu_DefaultKey( menu, key ); + + sound = Menu_DefaultKey( menu, key ); return sound; } menuCommon_t *Menu_HitTest( menuFrameWork_t *menu ) { - int i; - menuCommon_t *item; + int i; + menuCommon_t *item; if( menu->keywait ) { return NULL; } - - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; - if( item->flags & QMF_HIDDEN ) { - continue; - } + + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; + if( item->flags & QMF_HIDDEN ) { + continue; + } - if( UI_CursorInRect( &item->rect ) ) { - return item; - } - } + if( UI_CursorInRect( &item->rect ) ) { + return item; + } + } - return NULL; + return NULL; } qboolean Menu_Push( menuFrameWork_t *menu ) { - void *item; + void *item; int i; - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; switch( ((menuCommon_t *)item)->type ) { case MTYPE_SLIDER: Slider_Push( item ); break; + case MTYPE_BITFIELD: + BitField_Push( item ); + break; + case MTYPE_PAIRS: + Pairs_Push( item ); + break; case MTYPE_SPINCONTROL: SpinControl_Push( item ); break; + case MTYPE_TOGGLE: + Toggle_Push( item ); + break; case MTYPE_KEYBIND: Keybind_Push( item ); break; @@ -1644,17 +1742,24 @@ qboolean Menu_Push( menuFrameWork_t *menu ) { } void Menu_Pop( menuFrameWork_t *menu ) { - void *item; + void *item; int i; - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; switch( ((menuCommon_t *)item)->type ) { case MTYPE_SLIDER: Slider_Pop( item ); break; + case MTYPE_BITFIELD: + BitField_Pop( item ); + break; + case MTYPE_PAIRS: + Pairs_Pop( item ); + break; case MTYPE_SPINCONTROL: + case MTYPE_TOGGLE: SpinControl_Pop( item ); break; default: @@ -1664,11 +1769,11 @@ void Menu_Pop( menuFrameWork_t *menu ) { } void Menu_Free( menuFrameWork_t *menu ) { - void *item; + void *item; int i; - for( i = 0; i < menu->nitems; i++ ) { - item = menu->items[i]; + for( i = 0; i < menu->nitems; i++ ) { + item = menu->items[i]; switch( ((menuCommon_t *)item)->type ) { case MTYPE_ACTION: @@ -1677,6 +1782,13 @@ void Menu_Free( menuFrameWork_t *menu ) { case MTYPE_SLIDER: Slider_Free( item ); break; + case MTYPE_BITFIELD: + case MTYPE_TOGGLE: + BitField_Free( item ); + break; + case MTYPE_PAIRS: + Pairs_Free( item ); + break; case MTYPE_SPINCONTROL: SpinControl_Free( item ); break; diff --git a/source/ui_script.c b/source/ui_script.c index a2452ec..e7f5888 100644 --- a/source/ui_script.c +++ b/source/ui_script.c @@ -38,12 +38,13 @@ static void Draw( menuFrameWork_t *self ) { Menu_Draw( self ); } -static void ParseSpin( menuFrameWork_t *menu ) { +static void Parse_Values( menuFrameWork_t *menu ) { menuSpinControl_t *s; int numItems = Cmd_Argc() - 3; int i; if( numItems < 1 ) { + Com_Printf( "Usage: %s <name> <cvar> <desc1> [...]\n", Cmd_Argv( 0 ) ); return; } @@ -60,9 +61,43 @@ static void ParseSpin( menuFrameWork_t *menu ) { Menu_AddItem( menu, s ); } -static void ParseSlider( menuFrameWork_t *menu ) { - menuSlider_t *s = UI_Mallocz( sizeof( *s ) ); +static void Parse_Pairs( menuFrameWork_t *menu ) { + menuSpinControl_t *s; + int numItems = Cmd_Argc() - 3; + int i; + + if( numItems < 2 || ( numItems & 1 ) ) { + Com_Printf( "Usage: %s <name> <cvar> <desc1> <value1> [...]\n", Cmd_Argv( 0 ) ); + return; + } + + s = UI_Mallocz( sizeof( *s ) ); + s->generic.type = MTYPE_PAIRS; + s->generic.name = UI_CopyString( Cmd_Argv( 1 ) ); + s->cvar = Cvar_Get( Cmd_Argv( 2 ), NULL, CVAR_USER_CREATED ); + numItems >>= 1; + s->itemnames = UI_Mallocz( sizeof( char * ) * ( numItems + 1 ) ); + for( i = 0; i < numItems; i++ ) { + s->itemnames[i] = UI_CopyString( Cmd_Argv( 3 + i*2 ) ); + } + s->itemvalues = UI_Mallocz( sizeof( char * ) * ( numItems + 1 ) ); + for( i = 0; i < numItems; i++ ) { + s->itemvalues[i] = UI_CopyString( Cmd_Argv( 4 + i*2 ) ); + } + s->numItems = numItems; + + Menu_AddItem( menu, s ); +} + +static void Parse_Range( menuFrameWork_t *menu ) { + menuSlider_t *s; + if( Cmd_Argc() < 7 ) { + Com_Printf( "Usage: %s <name> <cvar> <add> <mul> <min> <max>\n", Cmd_Argv( 0 ) ); + return; + } + + s = UI_Mallocz( sizeof( *s ) ); s->generic.type = MTYPE_SLIDER; s->generic.name = UI_CopyString( Cmd_Argv( 1 ) ); s->cvar = Cvar_Get( Cmd_Argv( 2 ), NULL, CVAR_USER_CREATED ); @@ -74,9 +109,15 @@ static void ParseSlider( menuFrameWork_t *menu ) { Menu_AddItem( menu, s ); } -static void ParseAction( menuFrameWork_t *menu ) { - menuAction_t *a = UI_Mallocz( sizeof( *a ) ); +static void Parse_Action( menuFrameWork_t *menu ) { + menuAction_t *a; + + if( Cmd_Argc() < 3 ) { + Com_Printf( "Usage: %s <name> <command>\n", Cmd_Argv( 0 ) ); + return; + } + a = UI_Mallocz( sizeof( *a ) ); a->generic.type = MTYPE_ACTION; a->generic.name = UI_CopyString( Cmd_Argv( 1 ) ); a->generic.activate = Activate; @@ -86,9 +127,15 @@ static void ParseAction( menuFrameWork_t *menu ) { Menu_AddItem( menu, a ); } -static void ParseBind( menuFrameWork_t *menu ) { - menuKeybind_t *k = UI_Mallocz( sizeof( *k ) ); +static void Parse_Bind( menuFrameWork_t *menu ) { + menuKeybind_t *k; + + if( Cmd_Argc() < 3 ) { + Com_Printf( "Usage: %s <name> <command>\n", Cmd_Argv( 0 ) ); + return; + } + k = UI_Mallocz( sizeof( *k ) ); k->generic.type = MTYPE_KEYBIND; k->generic.name = UI_CopyString( Cmd_Argv( 1 ) ); k->generic.uiFlags = UI_CENTER; @@ -97,14 +144,53 @@ static void ParseBind( menuFrameWork_t *menu ) { Menu_AddItem( menu, k ); } -static qboolean ParseFile( const char *path ) { +static void Parse_Toggle( menuFrameWork_t *menu ) { + static const char *yes_no_names[] = { "no", "yes", NULL }; + menuSpinControl_t *s; + qboolean negate = qfalse; + menuType_t type = MTYPE_TOGGLE; + int bit = 0; + char *b; + + if( Cmd_Argc() < 3 ) { + Com_Printf( "Usage: %s <name> <cvar> [~][bit]\n", Cmd_Argv( 0 ) ); + return; + } + + b = Cmd_Argv( 3 ); + if( *b == '~' ) { + negate = qtrue; + b++; + } + if( *b ) { + bit = atoi( b ); + if( bit < 0 || bit >= 32 ) { + Com_Printf( "Invalid bit number: %d\n", bit ); + return; + } + type = MTYPE_BITFIELD; + } + + s = UI_Mallocz( sizeof( *s ) ); + s->generic.type = type; + s->generic.name = UI_CopyString( Cmd_Argv( 1 ) ); + s->cvar = Cvar_Get( Cmd_Argv( 2 ), NULL, CVAR_USER_CREATED ); + s->itemnames = ( char ** )yes_no_names; + s->numItems = 2; + s->negate = negate; + s->mask = 1 << bit; + + Menu_AddItem( menu, s ); +} + +static qboolean Parse_File( const char *path, int depth ) { char *data, *p, *cmd; - int linenum = 1; int argc; menuFrameWork_t *menu = NULL; FS_LoadFile( path, ( void ** )&data ); if( !data ) { + Com_Printf( "Couldn't load %s\n", path ); return qfalse; } @@ -123,50 +209,74 @@ static qboolean ParseFile( const char *path ) { cmd = Cmd_Argv( 0 ); if( menu ) { if( !strcmp( cmd, "end" ) ) { - if( !menu->title ) { - menu->transparent = qtrue; - menu->draw = Draw; + if( menu->nitems ) { + if( !menu->title ) { + menu->transparent = qtrue; + menu->draw = Draw; + } + List_Append( &ui_menus, &menu->entry ); + } else { + menu->free( menu ); } - List_Append( &ui_menus, &menu->entry ); menu = NULL; } else if( !strcmp( cmd, "title" ) ) { if( menu->title ) { Z_Free( menu->title ); } menu->title = UI_CopyString( Cmd_Argv( 1 ) ); - } else if( !strcmp( cmd, "spin" ) ) { - if( argc < 4 ) { - Com_WPrintf( "Insufficient arguments to '%s' on line %d in %s\n", - cmd, linenum, path ); - } - ParseSpin( menu ); - } else if( !strcmp( cmd, "slider" ) ) { - ParseSlider( menu ); + } else if( !strcmp( cmd, "values" ) ) { + Parse_Values( menu ); + } else if( !strcmp( cmd, "pairs" ) ) { + Parse_Pairs( menu ); + } else if( !strcmp( cmd, "range" ) ) { + Parse_Range( menu ); } else if( !strcmp( cmd, "action" ) ) { - ParseAction( menu ); - } else if( !strcmp( cmd, "confirm" ) ) { + Parse_Action( menu ); } else if( !strcmp( cmd, "bind" ) ) { - ParseBind( menu ); + Parse_Bind( menu ); + } else if( !strcmp( cmd, "toggle" ) ) { + Parse_Toggle( menu ); } else { - Com_WPrintf( "Unexpected '%s' on line %d in %s\n", - cmd, linenum, path ); + Com_WPrintf( "Unknown keyword '%s'\n", cmd ); + menu->free( menu ); + menu = NULL; break; } } else { if( !strcmp( cmd, "begin" ) ) { - if( argc < 2 ) { - Com_WPrintf( "Insufficient arguments to '%s' on line %d in %s\n", - cmd, linenum, path ); + char *s = Cmd_Argv( 1 ); + if( !*s ) { + Com_WPrintf( "Expected menu name after '%s'\n", cmd ); break; } + menu = UI_FindMenu( s ); + if( menu ) { + if( menu->free ) { + List_Remove( &menu->entry ); + menu->free( menu ); + } else { + Com_WPrintf( "Attempted to override built-in menu '%s'\n", s ); + break; + } + } menu = UI_Mallocz( sizeof( *menu ) ); - menu->name = UI_CopyString( Cmd_Argv( 1 ) ); + menu->name = UI_CopyString( s ); menu->push = Menu_Push; menu->pop = Menu_Pop; menu->free = Menu_Free; + } else if( !strcmp( cmd, "include" ) ) { + char *s = Cmd_Argv( 1 ); + if( !*s ) { + Com_WPrintf( "Expected file name after '%s'\n", cmd ); + break; + } + if( depth == 16 ) { + Com_WPrintf( "Includes too deeply nested\n" ); + } else { + Parse_File( s, depth + 1 ); + } } else { - Com_WPrintf( "Unexpected '%s' on line %d in %s\n", - cmd, linenum, path ); + Com_WPrintf( "Unknown keyword '%s'\n", cmd ); break; } } @@ -176,7 +286,6 @@ static qboolean ParseFile( const char *path ) { break; } - linenum++; // FIXME: meaniningless data = p + 1; } @@ -186,6 +295,6 @@ static qboolean ParseFile( const char *path ) { } void UI_LoadStript( void ) { - ParseFile( "q2pro.menu" ); + Parse_File( "q2pro.menu", 0 ); } |