2005-02-28 07:16:19 +00:00
|
|
|
//read menu.h
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
#include "quakedef.h"
|
|
|
|
#include "winquake.h"
|
|
|
|
#ifndef CLIENTONLY
|
|
|
|
//=============================================================================
|
|
|
|
/* LOAD/SAVE MENU */
|
|
|
|
|
|
|
|
#define FTESAVEGAME_VERSION 25000
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int issave;
|
|
|
|
int cursorpos;
|
|
|
|
menutext_t *cursoritem;
|
|
|
|
} loadsavemenuinfo_t;
|
|
|
|
|
|
|
|
#define MAX_SAVEGAMES 20
|
|
|
|
char m_filenames[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH+1];
|
|
|
|
int loadable[MAX_SAVEGAMES];
|
|
|
|
|
|
|
|
menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int x, int y, char *text, char *command, ...);
|
|
|
|
|
|
|
|
void M_ScanSaves (void)
|
|
|
|
{
|
|
|
|
int i, j;
|
2006-01-02 22:43:59 +00:00
|
|
|
char line[MAX_OSPATH];
|
|
|
|
vfsfile_t *f;
|
2004-08-23 00:15:46 +00:00
|
|
|
int version;
|
|
|
|
|
|
|
|
for (i=0 ; i<MAX_SAVEGAMES ; i++)
|
|
|
|
{
|
|
|
|
strcpy (m_filenames[i], "--- UNUSED SLOT ---");
|
|
|
|
loadable[i] = false;
|
|
|
|
|
2006-03-06 01:41:09 +00:00
|
|
|
snprintf (line, sizeof(line), "saves/s%i/info.fsv", i);
|
2006-01-02 22:43:59 +00:00
|
|
|
f = FS_OpenVFS (line, "rb", FS_GAME);
|
2004-08-23 00:15:46 +00:00
|
|
|
if (f)
|
|
|
|
{
|
2006-01-02 22:43:59 +00:00
|
|
|
VFS_GETS(f, line, sizeof(line));
|
|
|
|
version = atoi(line);
|
2006-02-11 18:08:35 +00:00
|
|
|
if (version < FTESAVEGAME_VERSION || version >= FTESAVEGAME_VERSION+GT_MAX)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2007-10-05 18:08:47 +00:00
|
|
|
Q_strncpyz (m_filenames[i], "Incompatible version", sizeof(m_filenames[i]));
|
2006-01-02 22:43:59 +00:00
|
|
|
VFS_CLOSE (f);
|
2004-08-23 00:15:46 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-01-02 22:43:59 +00:00
|
|
|
VFS_GETS(f, line, sizeof(line));
|
|
|
|
Q_strncpyz (m_filenames[i], line, sizeof(m_filenames[i]));
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
// change _ back to space
|
|
|
|
for (j=0 ; j<SAVEGAME_COMMENT_LENGTH ; j++)
|
|
|
|
if (m_filenames[i][j] == '_')
|
|
|
|
m_filenames[i][j] = ' ';
|
|
|
|
loadable[i] = true;
|
2006-01-02 22:43:59 +00:00
|
|
|
VFS_CLOSE (f);
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_Menu_Save_f (void)
|
|
|
|
{
|
|
|
|
menuoption_t *op = NULL;
|
|
|
|
menu_t *menu;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!sv.state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cl.intermission)
|
|
|
|
return;
|
|
|
|
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_state = m_complex;
|
|
|
|
|
|
|
|
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
|
|
|
|
menu->data = menu+1;
|
|
|
|
|
|
|
|
MC_AddCenterPicture (menu, 4, "gfx/p_save.lmp");
|
|
|
|
menu->cursoritem = (menuoption_t *)MC_AddRedText(menu, 8, 32, NULL, false);
|
|
|
|
|
|
|
|
M_ScanSaves ();
|
|
|
|
|
|
|
|
for (i=0 ; i< MAX_SAVEGAMES; i++)
|
|
|
|
{
|
|
|
|
op = (menuoption_t *)MC_AddConsoleCommandf(menu, 16, 32+8*i, m_filenames[i], "savegame s%i\ntogglemenu\n", i);
|
|
|
|
if (!menu->selecteditem)
|
|
|
|
menu->selecteditem = op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void M_Menu_Load_f (void)
|
|
|
|
{
|
|
|
|
menuoption_t *op = NULL;
|
|
|
|
menu_t *menu;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_state = m_complex;
|
|
|
|
|
|
|
|
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
|
|
|
|
menu->data = menu+1;
|
|
|
|
|
|
|
|
MC_AddCenterPicture(menu, 4, "gfx/p_load.lmp");
|
|
|
|
menu->cursoritem = (menuoption_t *)MC_AddRedText(menu, 8, 32, NULL, false);
|
|
|
|
|
|
|
|
M_ScanSaves ();
|
|
|
|
|
|
|
|
for (i=0 ; i< MAX_SAVEGAMES; i++)
|
|
|
|
{
|
|
|
|
if (loadable[i])
|
|
|
|
op = (menuoption_t *)MC_AddConsoleCommandf(menu, 16, 32+8*i, m_filenames[i], "loadgame s%i\ntogglemenu\n", i);
|
|
|
|
else
|
|
|
|
MC_AddWhiteText(menu, 16, 32+8*i, m_filenames[i], false);
|
|
|
|
if (!menu->selecteditem && op)
|
|
|
|
menu->selecteditem = op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void M_Menu_SinglePlayer_f (void)
|
|
|
|
{
|
2005-03-15 22:51:01 +00:00
|
|
|
int mgt;
|
2005-04-18 17:12:18 +00:00
|
|
|
#ifndef CLIENTONLY
|
2004-08-23 00:15:46 +00:00
|
|
|
menubutton_t *b;
|
2005-04-18 17:12:18 +00:00
|
|
|
#endif
|
2004-08-23 00:15:46 +00:00
|
|
|
menu_t *menu;
|
2004-12-24 08:45:56 +00:00
|
|
|
mpic_t *p;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_state = m_complex;
|
|
|
|
|
2005-03-15 22:51:01 +00:00
|
|
|
mgt = M_GameType();
|
|
|
|
if (mgt == MGT_QUAKE2)
|
2004-08-23 00:15:46 +00:00
|
|
|
{ //q2...
|
|
|
|
menu = M_CreateMenu(0);
|
|
|
|
|
2005-03-15 22:51:01 +00:00
|
|
|
MC_AddCenterPicture(menu, 4, "pics/m_banner_game");
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
menu->selecteditem = (menuoption_t*)
|
|
|
|
MC_AddConsoleCommand (menu, 64, 40, "Easy", "skill 0;deathmatch 0; coop 0;newgame\n");
|
|
|
|
MC_AddConsoleCommand (menu, 64, 48, "Medium", "skill 1;deathmatch 0; coop 0;newgame\n");
|
|
|
|
MC_AddConsoleCommand (menu, 64, 56, "Hard", "skill 2;deathmatch 0; coop 0;newgame\n");
|
|
|
|
|
|
|
|
MC_AddConsoleCommand (menu, 64, 72, "Load Game", "menu_load\n");
|
|
|
|
MC_AddConsoleCommand (menu, 64, 80, "Save Game", "menu_save\n");
|
2005-03-15 22:51:01 +00:00
|
|
|
|
|
|
|
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 48, 40, NULL, false);
|
2004-08-23 00:15:46 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-03-15 22:51:01 +00:00
|
|
|
else if (mgt == MGT_HEXEN2)
|
2004-08-23 00:15:46 +00:00
|
|
|
{ //h2
|
2006-03-23 18:54:06 +00:00
|
|
|
cvar_t *pc;
|
|
|
|
static char *classlist[] = {
|
|
|
|
"Random",
|
|
|
|
"Paladin",
|
2008-11-09 22:29:28 +00:00
|
|
|
"Crusader",
|
|
|
|
"Necromancer",
|
2006-03-23 18:54:06 +00:00
|
|
|
"Assasin",
|
2008-11-09 22:29:28 +00:00
|
|
|
"Demoness",
|
2006-03-23 18:54:06 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
static char *classvalues[] = {
|
|
|
|
"",
|
|
|
|
"1",
|
|
|
|
"2",
|
|
|
|
"3",
|
|
|
|
"4",
|
2008-11-09 22:29:28 +00:00
|
|
|
"5",
|
2006-03-23 18:54:06 +00:00
|
|
|
NULL
|
|
|
|
};
|
2004-08-23 00:15:46 +00:00
|
|
|
menu = M_CreateMenu(0);
|
|
|
|
MC_AddPicture(menu, 16, 0, "gfx/menu/hplaque.lmp");
|
|
|
|
MC_AddCenterPicture(menu, 0, "gfx/menu/title1.lmp");
|
|
|
|
|
|
|
|
menu->selecteditem = (menuoption_t*)
|
|
|
|
MC_AddConsoleCommand (menu, 64, 64, "Easy", "togglemenu\nskill 0;deathmatch 0; coop 0;map demo1\n");
|
|
|
|
MC_AddConsoleCommand (menu, 64, 72, "Medium", "togglemenu\nskill 1;deathmatch 0; coop 0;map demo1\n");
|
|
|
|
MC_AddConsoleCommand (menu, 64, 80, "Hard", "togglemenu\nskill 2;deathmatch 0; coop 0;map demo1\n");
|
|
|
|
|
2006-03-06 01:41:09 +00:00
|
|
|
MC_AddConsoleCommand (menu, 64, 96, "Load Game", "menu_load\n");
|
2004-08-23 00:15:46 +00:00
|
|
|
MC_AddConsoleCommand (menu, 64, 104, "Save Game", "menu_save\n");
|
|
|
|
|
2006-03-23 18:54:06 +00:00
|
|
|
pc = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2");
|
|
|
|
if (pc)
|
2007-08-20 02:13:51 +00:00
|
|
|
MC_AddCvarCombo (menu, 64, 104+16, "Player class", pc, (const char **)classlist, (const char **)classvalues);
|
2006-03-23 18:54:06 +00:00
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-03-06 01:41:09 +00:00
|
|
|
else if (QBigFontWorks())
|
|
|
|
{
|
|
|
|
menu = M_CreateMenu(0);
|
|
|
|
MC_AddPicture(menu, 16, 0, "gfx/qplaque.lmp");
|
|
|
|
MC_AddCenterPicture(menu, 0, "gfx/p_option.lmp");
|
|
|
|
|
|
|
|
menu->selecteditem = (menuoption_t*)
|
|
|
|
MC_AddConsoleCommandQBigFont (menu, 72, 32, "New Game", "togglemenu\nmaxclients 1;deathmatch 0;coop 0;map start\n");
|
|
|
|
MC_AddConsoleCommandQBigFont (menu, 72, 52, "Load Game", "menu_load\n");
|
|
|
|
MC_AddConsoleCommandQBigFont (menu, 72, 72, "Save Game", "menu_save\n");
|
|
|
|
|
|
|
|
menu->cursoritem = (menuoption_t*)MC_AddCursor(menu, 54, 32);
|
|
|
|
return;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
|
|
|
{ //q1
|
|
|
|
menu = M_CreateMenu(0);
|
|
|
|
MC_AddPicture(menu, 16, 4, "gfx/qplaque.lmp");
|
|
|
|
MC_AddCenterPicture(menu, 4, "gfx/p_option.lmp");
|
|
|
|
}
|
|
|
|
|
2006-04-02 08:11:17 +00:00
|
|
|
p = Draw_SafeCachePic("gfx/sp_menu.lmp");
|
2004-08-23 00:15:46 +00:00
|
|
|
if (!p)
|
|
|
|
{
|
|
|
|
MC_AddBox (menu, 60, 10*8, 23, 4);
|
|
|
|
|
|
|
|
MC_AddWhiteText(menu, 92, 12*8, "Could find file", false);
|
|
|
|
MC_AddWhiteText(menu, 92, 13*8, "gfx/sp_menu.lmp", false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef CLIENTONLY
|
|
|
|
MC_AddBox (menu, 60, 10*8, 23, 4);
|
|
|
|
|
|
|
|
MC_AddWhiteText(menu, 92, 12*8, "QuakeWorld is for", false);
|
|
|
|
MC_AddWhiteText(menu, 92, 13*8, "Internet play only", false);
|
|
|
|
#else
|
|
|
|
MC_AddPicture(menu, 72, 32, "gfx/sp_menu.lmp");
|
|
|
|
|
|
|
|
b = MC_AddConsoleCommand (menu, 16, 32, "", "togglemenu\nmaxclients 1;deathmatch 0;coop 0;map start\n");
|
|
|
|
menu->selecteditem = (menuoption_t *)b;
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
b = MC_AddConsoleCommand (menu, 16, 52, "", "menu_load\n");
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
b = MC_AddConsoleCommand (menu, 16, 72, "", "menu_save\n");
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
|
2006-03-06 01:41:09 +00:00
|
|
|
menu->cursoritem = (menuoption_t*)MC_AddCursor(menu, 54, 32);
|
2004-08-23 00:15:46 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
typedef struct demoitem_s {
|
2008-02-05 00:31:34 +00:00
|
|
|
char name[MAX_QPATH];
|
2008-02-05 00:19:57 +00:00
|
|
|
qboolean isdir;
|
|
|
|
int size;
|
|
|
|
struct demoitem_s *next;
|
|
|
|
struct demoitem_s *prev;
|
|
|
|
} demoitem_t;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
menucustom_t *list;
|
2008-02-05 00:19:57 +00:00
|
|
|
demoitem_t *selected;
|
|
|
|
demoitem_t *firstitem;
|
2004-08-23 00:15:46 +00:00
|
|
|
int pathlen;
|
|
|
|
|
|
|
|
char *command[64]; //these let the menu be used for nearly any sort of file browser.
|
|
|
|
char *ext[64];
|
|
|
|
int numext;
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
demoitem_t *items;
|
2004-08-23 00:15:46 +00:00
|
|
|
} demomenu_t;
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
static void M_DemoDraw(int x, int y, menucustom_t *control, menu_t *menu)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
demomenu_t *info = menu->data;
|
2008-02-05 00:19:57 +00:00
|
|
|
demoitem_t *item, *lostit;
|
|
|
|
int ty;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
ty = vid.height-24;
|
|
|
|
item = info->selected;
|
|
|
|
while(item)
|
|
|
|
{
|
|
|
|
if (info->firstitem == item)
|
|
|
|
break;
|
|
|
|
if (ty < y)
|
|
|
|
{
|
|
|
|
//we couldn't find it
|
|
|
|
for (lostit = info->firstitem; lostit; lostit = lostit->prev)
|
|
|
|
{
|
|
|
|
if (info->selected == lostit)
|
|
|
|
{
|
|
|
|
item = lostit;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
info->firstitem = item;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
item = item->prev;
|
|
|
|
ty-=8;
|
|
|
|
}
|
|
|
|
if (!item)
|
|
|
|
info->firstitem = info->items;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
|
|
|
|
item = info->firstitem;
|
|
|
|
while(item)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2008-02-05 00:19:57 +00:00
|
|
|
if (y+8 >= vid.height)
|
|
|
|
return;
|
|
|
|
if (!item->isdir)
|
|
|
|
text = va("%-32.32s%6iKB", item->name+info->pathlen, item->size/1024);
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
2008-02-05 00:19:57 +00:00
|
|
|
text = item->name+info->pathlen;
|
|
|
|
if (item == info->selected)
|
|
|
|
Draw_Alt_String(x, y+8, text);
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
2008-02-05 00:19:57 +00:00
|
|
|
Draw_String(x, y+8, text);
|
2004-08-23 00:15:46 +00:00
|
|
|
y+=8;
|
2008-02-05 00:19:57 +00:00
|
|
|
item = item->next;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
2008-02-05 00:19:57 +00:00
|
|
|
static void ShowDemoMenu (menu_t *menu, char *path);
|
|
|
|
static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
demomenu_t *info = menu->data;
|
2008-02-05 00:19:57 +00:00
|
|
|
int i;
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
switch (key)
|
|
|
|
{
|
2008-02-05 00:19:57 +00:00
|
|
|
case K_MWHEELUP:
|
2004-08-23 00:15:46 +00:00
|
|
|
case K_UPARROW:
|
2008-02-05 00:19:57 +00:00
|
|
|
if (info->selected && info->selected->prev)
|
|
|
|
info->selected = info->selected->prev;
|
2004-08-23 00:15:46 +00:00
|
|
|
return true;
|
2008-02-05 00:19:57 +00:00
|
|
|
case K_MWHEELDOWN:
|
2004-08-23 00:15:46 +00:00
|
|
|
case K_DOWNARROW:
|
2008-02-05 00:19:57 +00:00
|
|
|
if (info->selected && info->selected->next)
|
|
|
|
info->selected = info->selected->next;
|
|
|
|
return true;
|
|
|
|
case K_HOME:
|
|
|
|
info->selected = info->items;
|
|
|
|
return true;
|
|
|
|
case K_END:
|
|
|
|
info->selected = info->items;
|
|
|
|
while(info->selected->next)
|
|
|
|
info->selected = info->selected->next;
|
2004-08-23 00:15:46 +00:00
|
|
|
return true;
|
|
|
|
case K_PGUP:
|
2008-02-05 00:19:57 +00:00
|
|
|
for (i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
if (info->selected && info->selected->prev)
|
|
|
|
info->selected = info->selected->prev;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
return true;
|
|
|
|
case K_PGDN:
|
2008-02-05 00:19:57 +00:00
|
|
|
for (i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
if (info->selected && info->selected->next)
|
|
|
|
info->selected = info->selected->next;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
return true;
|
|
|
|
case K_ENTER:
|
2008-02-05 00:19:57 +00:00
|
|
|
if (info->selected)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2008-02-05 00:19:57 +00:00
|
|
|
if (info->selected->isdir)
|
|
|
|
ShowDemoMenu(menu, va("%s", info->selected->name));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int extnum;
|
|
|
|
for (extnum = 0; extnum < info->numext; extnum++)
|
|
|
|
if (!stricmp(info->selected->name + strlen(info->selected->name)-4, info->ext[extnum]))
|
|
|
|
break;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
if (extnum == info->numext) //wasn't on our list of extensions.
|
|
|
|
extnum = 0;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
Cbuf_AddText(va("%s \"%s\"\n", info->command[extnum], info->selected->name), RESTRICT_LOCAL);
|
2008-02-23 09:52:55 +00:00
|
|
|
M_ToggleMenu_f();
|
2008-02-22 22:57:28 +00:00
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
static int DemoAddItem(char *filename, int size, void *parm)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
int extnum;
|
|
|
|
demomenu_t *menu = parm;
|
2008-02-05 00:19:57 +00:00
|
|
|
demoitem_t *link, *newi;
|
|
|
|
int side;
|
|
|
|
qboolean isdir;
|
2008-02-05 00:31:34 +00:00
|
|
|
char tempfname[MAX_QPATH];
|
2008-02-05 00:19:57 +00:00
|
|
|
|
|
|
|
char *i;
|
|
|
|
|
|
|
|
i = strchr(filename+menu->pathlen, '/');
|
|
|
|
if (i == NULL)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
for (extnum = 0; extnum < menu->numext; extnum++)
|
|
|
|
if (!stricmp(filename + strlen(filename)-4, menu->ext[extnum]))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (extnum == menu->numext) //wasn't on our list of extensions.
|
|
|
|
return true;
|
2008-02-05 00:19:57 +00:00
|
|
|
isdir = false;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
2006-09-17 00:59:22 +00:00
|
|
|
else
|
|
|
|
{
|
2008-02-05 00:19:57 +00:00
|
|
|
i++;
|
|
|
|
if (i-filename > sizeof(tempfname)-2)
|
|
|
|
return true; //too long to fit in our buffers anyway
|
|
|
|
strncpy(tempfname, filename, i-filename);
|
|
|
|
tempfname[i-filename] = 0;
|
|
|
|
filename = tempfname;
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
isdir = true;
|
2006-09-17 00:59:22 +00:00
|
|
|
}
|
2008-02-05 00:19:57 +00:00
|
|
|
|
|
|
|
if (!menu->items)
|
|
|
|
menu->items = newi = BZ_Malloc(sizeof(*newi));
|
|
|
|
else
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2008-02-05 00:19:57 +00:00
|
|
|
link = menu->items;
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
if (link->isdir != isdir) //bias directories, so they sink
|
|
|
|
side = (link->isdir > isdir)?1:-1;
|
|
|
|
else
|
|
|
|
side = stricmp(link->name, filename);
|
|
|
|
if (side == 0)
|
|
|
|
return true; //already got this file
|
|
|
|
else if (side > 0)
|
|
|
|
{
|
|
|
|
if (!link->prev)
|
|
|
|
{
|
|
|
|
link->prev = newi = BZ_Malloc(sizeof(*newi));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
link = link->prev;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!link->next)
|
|
|
|
{
|
|
|
|
link->next = newi = BZ_Malloc(sizeof(*newi));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
link = link->next;
|
|
|
|
}
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
2008-02-05 00:19:57 +00:00
|
|
|
|
|
|
|
Q_strncpyz(newi->name, filename, sizeof(newi->name));
|
|
|
|
newi->size = size;
|
|
|
|
newi->isdir = isdir;
|
|
|
|
newi->prev = NULL;
|
|
|
|
newi->next = NULL;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
//converts the binary tree into sorted linked list
|
|
|
|
static void M_Demo_Flatten(demomenu_t *info)
|
|
|
|
{
|
|
|
|
demoitem_t *btree = info->items, *item, *lastitem;
|
|
|
|
demoitem_t *listhead = NULL, *listlast = NULL;
|
|
|
|
|
|
|
|
while(btree)
|
|
|
|
{
|
|
|
|
if (!btree->prev)
|
|
|
|
{ //none on left side, descend down right removing head node
|
|
|
|
item = btree;
|
|
|
|
btree = btree->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item = btree;
|
|
|
|
lastitem = item;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!item->prev)
|
|
|
|
{
|
|
|
|
lastitem->prev = item->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lastitem = item;
|
|
|
|
item = lastitem->prev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (listlast)
|
|
|
|
{
|
|
|
|
listlast->next = item;
|
|
|
|
item->prev = listlast;
|
|
|
|
listlast = item;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
listhead = listlast = item;
|
|
|
|
item->prev = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (listlast)
|
|
|
|
listlast->next = NULL;
|
|
|
|
info->items = listhead;
|
|
|
|
info->selected = listhead;
|
|
|
|
info->firstitem = listhead;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_Demo_Flush (demomenu_t *info)
|
|
|
|
{
|
|
|
|
demoitem_t *item;
|
|
|
|
while (info->items)
|
|
|
|
{
|
|
|
|
item = info->items;
|
|
|
|
info->items = item->next;
|
|
|
|
BZ_Free(item);
|
|
|
|
}
|
|
|
|
info->items = NULL;
|
|
|
|
info->selected = NULL;
|
|
|
|
info->firstitem = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_Demo_Remove (menu_t *menu)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
demomenu_t *info = menu->data;
|
2008-02-05 00:19:57 +00:00
|
|
|
M_Demo_Flush(info);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
static void ShowDemoMenu (menu_t *menu, char *path)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
char *s;
|
|
|
|
char match[256];
|
|
|
|
while (!strcmp(path+strlen(path)-3, "../"))
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
for (s = path+strlen(path)-3; s >= path; s--)
|
|
|
|
{
|
|
|
|
if (*s == '/')
|
|
|
|
{
|
|
|
|
c++;
|
|
|
|
s[1] = '\0';
|
|
|
|
if (c == 2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (c<2)
|
|
|
|
*path = '\0';
|
|
|
|
}
|
2008-02-05 00:19:57 +00:00
|
|
|
((demomenu_t*)menu->data)->selected = NULL;
|
2004-08-23 00:15:46 +00:00
|
|
|
((demomenu_t*)menu->data)->pathlen = strlen(path);
|
|
|
|
|
2008-02-05 00:19:57 +00:00
|
|
|
M_Demo_Flush(menu->data);
|
2004-08-23 00:15:46 +00:00
|
|
|
if (*path)
|
|
|
|
{
|
|
|
|
sprintf(match, "%s../", path);
|
|
|
|
DemoAddItem(match, 0, menu->data);
|
|
|
|
}
|
|
|
|
sprintf(match, "%s*", path);
|
2004-12-23 03:16:37 +00:00
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
COM_EnumerateFiles(match, DemoAddItem, menu->data);
|
2008-02-05 00:19:57 +00:00
|
|
|
M_Demo_Flatten(menu->data);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void M_Menu_Demos_f (void)
|
|
|
|
{
|
|
|
|
demomenu_t *info;
|
|
|
|
menu_t *menu;
|
|
|
|
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_state = m_complex;
|
|
|
|
|
|
|
|
menu = M_CreateMenu(sizeof(demomenu_t));
|
|
|
|
menu->remove = M_Demo_Remove;
|
|
|
|
info = menu->data;
|
|
|
|
|
|
|
|
info->command[0] = "playdemo";
|
|
|
|
info->ext[0] = ".qwd";
|
|
|
|
info->command[1] = "playdemo";
|
|
|
|
info->ext[1] = ".dem";
|
|
|
|
info->command[2] = "playdemo";
|
|
|
|
info->ext[2] = ".dm2";
|
2004-12-23 03:16:37 +00:00
|
|
|
info->command[3] = "playdemo";
|
2004-08-23 00:15:46 +00:00
|
|
|
info->ext[3] = ".mvd";
|
2006-09-17 00:59:22 +00:00
|
|
|
//there are also qizmo demos (.qwz) out there...
|
2004-08-23 00:15:46 +00:00
|
|
|
//we don't support them, but if we were to ask quizmo to decode them for us, we could do.
|
2004-12-23 03:16:37 +00:00
|
|
|
info->numext = 4;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2005-03-28 00:11:59 +00:00
|
|
|
MC_AddWhiteText(menu, 24, 8, "Choose a Demo", false);
|
2004-08-23 00:15:46 +00:00
|
|
|
MC_AddWhiteText(menu, 16, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
|
|
|
|
|
|
|
|
info->list = MC_AddCustom(menu, 0, 32, NULL);
|
|
|
|
info->list->draw = M_DemoDraw;
|
|
|
|
info->list->key = M_DemoKey;
|
|
|
|
|
|
|
|
menu->selecteditem = (menuoption_t*)info->list;
|
|
|
|
|
|
|
|
ShowDemoMenu(menu, "");
|
|
|
|
}
|
|
|
|
|
2005-03-28 00:11:59 +00:00
|
|
|
void M_Menu_ParticleSets_f (void)
|
|
|
|
{
|
|
|
|
demomenu_t *info;
|
|
|
|
menu_t *menu;
|
|
|
|
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_state = m_complex;
|
|
|
|
|
|
|
|
menu = M_CreateMenu(sizeof(demomenu_t));
|
|
|
|
menu->remove = M_Demo_Remove;
|
|
|
|
info = menu->data;
|
|
|
|
|
|
|
|
info->command[0] = "r_particlesdesc";
|
|
|
|
info->ext[0] = ".cfg";
|
|
|
|
info->numext = 1;
|
|
|
|
|
|
|
|
MC_AddWhiteText(menu, 24, 8, "Choose a Particle Set", false);
|
|
|
|
MC_AddWhiteText(menu, 16, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
|
|
|
|
|
|
|
|
info->list = MC_AddCustom(menu, 0, 32, NULL);
|
|
|
|
info->list->draw = M_DemoDraw;
|
|
|
|
info->list->key = M_DemoKey;
|
|
|
|
|
|
|
|
menu->selecteditem = (menuoption_t*)info->list;
|
|
|
|
|
|
|
|
ShowDemoMenu(menu, "particles/");
|
|
|
|
}
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
void M_Menu_MediaFiles_f (void)
|
|
|
|
{
|
|
|
|
demomenu_t *info;
|
|
|
|
menu_t *menu;
|
|
|
|
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_state = m_complex;
|
|
|
|
|
|
|
|
menu = M_CreateMenu(sizeof(demomenu_t));
|
|
|
|
menu->remove = M_Demo_Remove;
|
|
|
|
info = menu->data;
|
|
|
|
|
|
|
|
info->ext[0] = ".m3u";
|
|
|
|
info->command[0] = "mediaplaylist";
|
|
|
|
info->ext[1] = ".mp3";
|
|
|
|
info->command[1] = "mediaadd";
|
|
|
|
info->ext[2] = ".wav";
|
|
|
|
info->command[2] = "mediaadd";
|
|
|
|
info->ext[3] = ".ogg"; //will this ever be added properly?
|
|
|
|
info->command[3] = "mediaadd";
|
|
|
|
info->ext[4] = ".roq";
|
|
|
|
info->command[4] = "playfilm";
|
|
|
|
info->numext = 5;
|
|
|
|
|
|
|
|
#ifdef _WIN32 //avis are only playable on windows due to a windows dll being used to decode them.
|
|
|
|
info->ext[info->numext] = ".avi";
|
|
|
|
info->command[info->numext] = "playfilm";
|
|
|
|
info->numext++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
MC_AddWhiteText(menu, 24, 8, "Media List", false);
|
|
|
|
MC_AddWhiteText(menu, 16, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
|
|
|
|
|
|
|
|
info->list = MC_AddCustom(menu, 0, 32, NULL);
|
|
|
|
info->list->draw = M_DemoDraw;
|
|
|
|
info->list->key = M_DemoKey;
|
|
|
|
|
|
|
|
menu->selecteditem = (menuoption_t*)info->list;
|
|
|
|
|
|
|
|
ShowDemoMenu(menu, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
|