diff --git a/quakespasm/Quake/cl_demo.c b/quakespasm/Quake/cl_demo.c index 18f5a50f..b49b9059 100644 --- a/quakespasm/Quake/cl_demo.c +++ b/quakespasm/Quake/cl_demo.c @@ -206,6 +206,9 @@ void CL_Stop_f (void) cls.demofile = NULL; cls.demorecording = false; Con_Printf ("Completed demo\n"); + +// ericw -- update demo tab-completion list + DemoList_Rebuild (); } /* diff --git a/quakespasm/Quake/common.c b/quakespasm/Quake/common.c index 6eaa11ba..98978703 100644 --- a/quakespasm/Quake/common.c +++ b/quakespasm/Quake/common.c @@ -2083,6 +2083,7 @@ static void COM_Game_f (void) R_NewGame (); } ExtraMaps_NewGame (); + DemoList_Rebuild (); Con_Printf("\"game\" changed to \"%s\"\n", COM_SkipPath(com_gamedir)); Con_Printf("enter \"exec quake.rc\" to load new configs\n"); diff --git a/quakespasm/Quake/console.c b/quakespasm/Quake/console.c index 2fec31bd..7428d65b 100644 --- a/quakespasm/Quake/console.c +++ b/quakespasm/Quake/console.c @@ -815,6 +815,7 @@ typedef struct filelist_item_s extern filelist_item_t *extralevels; extern filelist_item_t *modlist; +extern filelist_item_t *demolist; typedef struct arg_completion_type_s { @@ -826,7 +827,9 @@ static const arg_completion_type_t arg_completion_types[] = { { "map ", &extralevels }, { "changelevel ", &extralevels }, - { "game ", &modlist } + { "game ", &modlist }, + { "record ", &demolist }, + { "playdemo ", &demolist } }; static const int num_arg_completion_types = diff --git a/quakespasm/Quake/host.c b/quakespasm/Quake/host.c index 8670e58b..f7714b32 100644 --- a/quakespasm/Quake/host.c +++ b/quakespasm/Quake/host.c @@ -858,6 +858,7 @@ void Host_Init (void) M_Init (); ExtraMaps_Init (); //johnfitz Modlist_Init (); //johnfitz + DemoList_Init (); //ericw VID_Init (); IN_Init (); TexMgr_Init (); //johnfitz diff --git a/quakespasm/Quake/host_cmd.c b/quakespasm/Quake/host_cmd.c index 10a305c6..f69e6150 100644 --- a/quakespasm/Quake/host_cmd.c +++ b/quakespasm/Quake/host_cmd.c @@ -103,6 +103,18 @@ void FileList_Add (const char *name, filelist_item_t **list) } } +static void FileList_Clear (filelist_item_t **list) +{ + filelist_item_t *blah; + + while (*list) + { + blah = (*list)->next; + Z_Free(*list); + *list = blah; + } +} + filelist_item_t *extralevels; void ExtraMaps_Add (const char *name) @@ -180,16 +192,9 @@ void ExtraMaps_Init (void) } } -void ExtraMaps_Clear (void) +static void ExtraMaps_Clear (void) { - filelist_item_t *blah; - - while (extralevels) - { - blah = extralevels->next; - Z_Free(extralevels); - extralevels = blah; - } + FileList_Clear(&extralevels); } void ExtraMaps_NewGame (void) @@ -299,6 +304,92 @@ void Modlist_Init (void) } #endif +//============================================================================== +//ericw -- demo list management +//============================================================================== + +filelist_item_t *demolist; + +static void DemoList_Clear (void) +{ + FileList_Clear (&demolist); +} + +void DemoList_Rebuild (void) +{ + DemoList_Clear (); + DemoList_Init (); +} + +// TODO: Factor out to a general-purpose file searching function +void DemoList_Init (void) +{ +#ifdef _WIN32 + WIN32_FIND_DATA fdat; + HANDLE fhnd; +#else + DIR *dir_p; + struct dirent *dir_t; +#endif + char filestring[MAX_OSPATH]; + char demname[32]; + char ignorepakdir[32]; + searchpath_t *search; + pack_t *pak; + int i; + + // we don't want to list the demos in id1 pakfiles, + // because these are not "add-on" demos + q_snprintf (ignorepakdir, sizeof(ignorepakdir), "/%s/", GAMENAME); + + for (search = com_searchpaths; search; search = search->next) + { + if (*search->filename) //directory + { +#ifdef _WIN32 + q_snprintf (filestring, sizeof(filestring), "%s/*.dem", search->filename); + fhnd = FindFirstFile(filestring, &fdat); + if (fhnd == INVALID_HANDLE_VALUE) + continue; + do + { + COM_StripExtension(fdat.cFileName, demname, sizeof(demname)); + FileList_Add (demname, &demolist); + } while (FindNextFile(fhnd, &fdat)); + FindClose(fhnd); +#else + q_snprintf (filestring, sizeof(filestring), "%s/", search->filename); + dir_p = opendir(filestring); + if (dir_p == NULL) + continue; + while ((dir_t = readdir(dir_p)) != NULL) + { + if (q_strcasecmp(COM_FileGetExtension(dir_t->d_name), "dem") != 0) + continue; + COM_StripExtension(dir_t->d_name, demname, sizeof(demname)); + FileList_Add (demname, &demolist); + } + closedir(dir_p); +#endif + } + else //pakfile + { + if (!strstr(search->pack->filename, ignorepakdir)) + { //don't list standard id demos + for (i = 0, pak = search->pack; i < pak->numfiles; i++) + { + if (!strcmp(COM_FileGetExtension(pak->files[i].name), "dem")) + { + COM_StripExtension(pak->files[i].name, demname, sizeof(demname)); + FileList_Add (demname, &demolist); + } + } + } + } + } +} + + /* ================== Host_Mods_f -- johnfitz diff --git a/quakespasm/Quake/quakedef.h b/quakespasm/Quake/quakedef.h index 3051f011..47f546aa 100644 --- a/quakespasm/Quake/quakedef.h +++ b/quakespasm/Quake/quakedef.h @@ -294,6 +294,9 @@ void Host_WriteConfiguration (void); void ExtraMaps_Init (void); void Modlist_Init (void); +void DemoList_Init (void); + +void DemoList_Rebuild (void); extern int current_skill; // skill level for currently loaded level (in case // the user changes the cvar while the level is