From f3baf608a243a8e83aa86216cee50a0cd944eed5 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 17 Jun 2018 18:45:03 +0100 Subject: [PATCH] Revamp of addons menu search! * Instead of iterating through the folder every time you change the search query by one letter, iterate through the "coredirmenu" (the game's interpretation of the folder) instead. MUCH, much less likely to lag to fuck and back. * Hide a bit of complexity in filesrch.c instead of having the entire thing exposed to mess with. For example, closefilemenu() instead of manually freeing the struct each time. * Refactor some stuff. --- src/filesrch.c | 210 ++++++++++++++++++++++++++++++++++--------------- src/filesrch.h | 2 + src/m_menu.c | 21 ++--- 3 files changed, 155 insertions(+), 78 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 2b5493642..3e1e5891a 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -326,8 +326,8 @@ size_t menudepthleft = menudepth; char menusearch[MAXSTRINGLENGTH+1]; -char **dirmenu; -size_t sizedirmenu; +char **dirmenu, **coredirmenu; // core only local for this file +size_t sizedirmenu, sizecoredirmenu; // ditto size_t dir_on[menudepth]; UINT8 refreshdirmenu = 0; @@ -446,7 +446,7 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -static boolean filemenusearch(char *haystack, char *needle) +static boolean filemenucmp(char *haystack, char *needle) { static char localhaystack[128]; strlcpy(localhaystack, haystack, 128); @@ -457,21 +457,126 @@ static boolean filemenusearch(char *haystack, char *needle) : (!strncmp(localhaystack, needle, menusearch[0]))); } -#define searchdir if (menusearch[0] && !filemenusearch(dent->d_name, localmenusearch))\ - {\ - rejected++;\ - continue;\ - }\ +void closefilemenu(boolean validsize) +{ + // search + if (dirmenu) + { + if (dirmenu != coredirmenu) + { + if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS)) + { + Z_Free(dirmenu[0]); + dirmenu[0] = NULL; + } + Z_Free(dirmenu); + } + dirmenu = NULL; + sizedirmenu = 0; + } + + if (coredirmenu) + { + // core + if (validsize) + { + for (; sizecoredirmenu > 0; sizecoredirmenu--) + { + Z_Free(coredirmenu[sizecoredirmenu-1]); + coredirmenu[sizecoredirmenu-1] = NULL; + } + } + else + sizecoredirmenu = 0; + + Z_Free(coredirmenu); + coredirmenu = NULL; + } +} + +void searchfilemenu(char *tempname) +{ + size_t i, first; + char localmenusearch[MAXSTRINGLENGTH] = ""; + + if (dirmenu) + { + if (dirmenu != coredirmenu) + { + if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS)) + { + Z_Free(dirmenu[0]); + dirmenu[0] = NULL; + } + //Z_Free(dirmenu); -- Z_Realloc later tho... + } + else + dirmenu = NULL; + } + + if (!menusearch[0]) + { + if (dirmenu) + Z_Free(dirmenu); + dirmenu = coredirmenu; + sizedirmenu = sizecoredirmenu; + if (tempname) + Z_Free(tempname); + return; + } + + strcpy(localmenusearch, menusearch+1); + if (!cv_addons_search_case.value) + strupr(localmenusearch); + + first = (((UINT8)(coredirmenu[0][DIR_TYPE]) == EXT_UP) ? 1 : 0); // skip UP... + + sizedirmenu = 0; + for (i = first; i < sizecoredirmenu; i++) + { + if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) + sizedirmenu++; + } + + if (!sizedirmenu) // no results... + { + if ((!(dirmenu = Z_Realloc(dirmenu, sizeof(char *), PU_STATIC, NULL))) + || !(dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + sizedirmenu = 1; + if (tempname) + Z_Free(tempname); + return; + } + + if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + + sizedirmenu = 0; + for (i = first; i < sizecoredirmenu; i++) + { + if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) + { + dirmenu[sizedirmenu++] = coredirmenu[i]; // pointer reuse + if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname)) + dir_on[menudepthleft] = i; + } + } + + if (dir_on[menudepthleft] >= sizedirmenu) + dir_on[menudepthleft] = sizedirmenu-1; + + if (tempname) + Z_Free(tempname); +} boolean preparefilemenu(boolean samedepth) { DIR *dirhandle; struct dirent *dent; struct stat fsstat; - size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0; + size_t pos = 0, folderpos = 0, numfolders = 0; char *tempname = NULL; - boolean noresults = false; - char localmenusearch[MAXSTRINGLENGTH] = ""; if (samedepth) { @@ -481,20 +586,16 @@ boolean preparefilemenu(boolean samedepth) else menusearch[0] = menusearch[1] = 0; // clear search - for (; sizedirmenu > 0; sizedirmenu--) // clear out existing items + if (!(dirhandle = opendir(menupath))) // get directory { - Z_Free(dirmenu[sizedirmenu-1]); - dirmenu[sizedirmenu-1] = NULL; + closefilemenu(true); + return false; } - if (!(dirhandle = opendir(menupath))) // get directory - return false; - - if (menusearch[0]) + for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items { - strcpy(localmenusearch, menusearch+1); - if (!cv_addons_search_case.value) - strupr(localmenusearch); + Z_Free(coredirmenu[sizecoredirmenu-1]); + coredirmenu[sizecoredirmenu-1] = NULL; } while (true) @@ -526,43 +627,42 @@ boolean preparefilemenu(boolean samedepth) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file } - searchdir; } else // directory - { - searchdir; numfolders++; - } - sizedirmenu++; + + sizecoredirmenu++; } } - if (!rejected && !sizedirmenu) + if (!sizecoredirmenu) { + closedir(dirhandle); + closefilemenu(false); if (tempname) Z_Free(tempname); - closedir(dirhandle); return false; } - if (((noresults = (menusearch[0] && !sizedirmenu))) - || (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry + if (menudepthleft != menudepth-1) // Make room for UP... { - sizedirmenu++; + sizecoredirmenu++; numfolders++; folderpos++; } - if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) + if (dirmenu && dirmenu == coredirmenu) + dirmenu = NULL; + + if (!(coredirmenu = Z_Realloc(coredirmenu, sizecoredirmenu*sizeof(char *), PU_STATIC, NULL))) { closedir(dirhandle); // just in case I_Error("Ran out of memory whilst preparing add-ons menu"); } - rejected = 0; rewinddir(dirhandle); - while ((pos+folderpos) < sizedirmenu) + while ((pos+folderpos) < sizecoredirmenu) { menupath[menupathindex[menudepthleft]] = 0; dent = readdir(dirhandle); @@ -588,14 +688,12 @@ boolean preparefilemenu(boolean samedepth) if (!S_ISDIR(fsstat.st_mode)) // file { - if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention + if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention for (; ext < NUM_EXT_TABLE; ext++) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position - searchdir; - if (ext >= EXT_LOADSTART) { size_t i; @@ -628,10 +726,7 @@ boolean preparefilemenu(boolean samedepth) folder = 0; } else // directory - { - searchdir; len += (folder = 1); - } if (len > 255) len = 255; @@ -644,45 +739,30 @@ boolean preparefilemenu(boolean samedepth) if (folder) { strcpy(temp+len, "/"); - dirmenu[folderpos++] = temp; + coredirmenu[folderpos++] = temp; } else - dirmenu[numfolders + pos++] = temp; + coredirmenu[numfolders + pos++] = temp; } } closedir(dirhandle); - if (noresults) // no results - dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)); - else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry - dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)); + if ((menudepthleft != menudepth-1) // now for UP... entry + && !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)))) + I_Error("Ran out of memory whilst preparing add-ons menu"); menupath[menupathindex[menudepthleft]] = 0; - sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind + sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind - if (tempname) - { - size_t i; - for (i = 0; i < sizedirmenu; i++) - { - if (!strcmp(dirmenu[i]+DIR_STRING, tempname)) - { - dir_on[menudepthleft] = i; - break; - } - } - Z_Free(tempname); - } - - if (!sizedirmenu) + if (!sizecoredirmenu) { dir_on[menudepthleft] = 0; - Z_Free(dirmenu); + closefilemenu(false); return false; } - else if (dir_on[menudepthleft] >= sizedirmenu) - dir_on[menudepthleft] = sizedirmenu-1; + + searchfilemenu(tempname); return true; } diff --git a/src/filesrch.h b/src/filesrch.h index e88242698..4cfa40e6c 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -87,6 +87,8 @@ typedef enum REFRESHDIR_MAX = 32 } refreshdir_enum; +void closefilemenu(boolean validsize); +void searchfilemenu(char *tempname); boolean preparefilemenu(boolean samedepth); #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index 5258f4b44..d23d5640f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5048,13 +5048,11 @@ static void M_DrawAddons(void) x -= (21 + 5 + 16); V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); -#define CANSAVE (!modifiedgame || savemoddata) x = BASEVIDWIDTH - x - 16; - V_DrawSmallScaledPatch(x, y + 4, (CANSAVE ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]); + V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]); if (modifiedgame) V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]); -#undef CANSAVE } #ifdef FIXUPO0 @@ -5119,11 +5117,15 @@ static void M_HandleAddons(INT32 choice) if (M_ChangeStringAddons(choice)) { - if (!preparefilemenu(true)) + char *tempname = NULL; + if (dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL + searchfilemenu(tempname); + /*if (!preparefilemenu(true)) { UNEXIST; return; - } + }*/ } switch (choice) @@ -5242,14 +5244,7 @@ static void M_HandleAddons(INT32 choice) } if (exitmenu) { - for (; sizedirmenu > 0; sizedirmenu--) - { - Z_Free(dirmenu[sizedirmenu-1]); - dirmenu[sizedirmenu-1] = NULL; - } - - Z_Free(dirmenu); - dirmenu = NULL; + closefilemenu(true); // secrets disabled by addfile... MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);