diff --git a/src/doomtype.h b/src/doomtype.h index a711b466d..6ef847cfc 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -170,6 +170,10 @@ size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif +#if 1 // don't know what systems don't have this +char* stristr(char* haystack, const char* needle); +#endif + // Macro for use with char foo[FOOSIZE+1] type buffers. // Never use this with a buffer that is a "char *" or passed // into the function as an argument. diff --git a/src/filesrch.c b/src/filesrch.c index 75ba18d94..190913a5e 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -32,6 +32,7 @@ #include "d_netfil.h" #include "m_misc.h" #include "z_zone.h" +#include "doomtype.h" #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) @@ -313,6 +314,8 @@ char menupath[1024]; size_t menupathindex[menudepth]; size_t menudepthleft = menudepth; +char menusearch[MAXSTRINGLENGTH+1]; + char **dirmenu; size_t sizedirmenu; size_t dir_on[menudepth]; @@ -507,16 +510,27 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; +#define searchdir if (menusearch[0] && !stristr(dent->d_name, menusearch+1))\ + {\ + rejected++;\ + continue;\ + }\ + boolean preparefilemenu(boolean samedepth) { DIR *dirhandle; struct dirent *dent; struct stat fsstat; - size_t pos = 0, folderpos = 0, numfolders = 0; + size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0; char *tempname = NULL; - if (samedepth && 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 + if (samedepth) + { + 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 + } + else + menusearch[0] = menusearch[1] = 0; // clear search for (; sizedirmenu > 0; sizedirmenu--) { @@ -555,14 +569,18 @@ boolean preparefilemenu(boolean samedepth) for (ext = 0; ext < NUM_EXT_TABLE; ext++) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + searchdir; } else // directory + { + searchdir; numfolders++; + } sizedirmenu++; } } - if (!sizedirmenu) + if (!rejected && !sizedirmenu) { if (tempname) Z_Free(tempname); @@ -570,7 +588,7 @@ boolean preparefilemenu(boolean samedepth) return false; } - if (menudepthleft != menudepth-1) // Make room for UP... entry + if (menusearch[0] || menudepthleft != menudepth-1) // Make room for UP... or search entry { numfolders++; sizedirmenu++; @@ -583,6 +601,7 @@ boolean preparefilemenu(boolean samedepth) I_Error("Ran out of memory whilst preparing add-ons menu"); } + rejected = 0; rewinddir(dirhandle); while ((pos+folderpos) < sizedirmenu) @@ -617,6 +636,8 @@ boolean preparefilemenu(boolean samedepth) if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position + searchdir; + if (ext >= EXT_MD5) { size_t i; @@ -638,7 +659,10 @@ boolean preparefilemenu(boolean samedepth) folder = 0; } else // directory + { + searchdir; len += (folder = 1); + } if (len > 255) len = 255; @@ -658,8 +682,10 @@ boolean preparefilemenu(boolean samedepth) } } - if (menudepthleft != menudepth-1) // now for UP... entry - dirmenu[0] = Z_StrDup("\1\5UP..."); + if (menusearch[0]) + dirmenu[0] = Z_StrDup(va("%c\14Search results", EXT_SEARCH)); + else if (menudepthleft != menudepth-1) // now for UP... entry + dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)); menupath[menupathindex[menudepthleft]] = 0; sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind diff --git a/src/filesrch.h b/src/filesrch.h index 3a5194571..ff3a6ca50 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -6,6 +6,7 @@ #include "doomdef.h" #include "d_netfil.h" +#include "m_menu.h" // MAXSTRINGLENGTH /** \brief The filesearch function @@ -31,6 +32,8 @@ extern char menupath[1024]; extern size_t menupathindex[menudepth]; extern size_t menudepthleft; +extern char menusearch[MAXSTRINGLENGTH+1]; + extern char **dirmenu; extern size_t sizedirmenu; extern size_t dir_on[menudepth]; @@ -43,6 +46,7 @@ typedef enum { EXT_FOLDER = 0, EXT_UP, + EXT_SEARCH, EXT_START, EXT_TXT = EXT_START, EXT_CFG, diff --git a/src/m_menu.c b/src/m_menu.c index 3267f08b7..97234f199 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -77,7 +77,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define SMALLLINEHEIGHT 8 #define SLIDER_RANGE 10 #define SLIDER_WIDTH (8*SLIDER_RANGE+6) -#define MAXSTRINGLENGTH 32 #define SERVERS_PER_PAGE 11 typedef enum @@ -2134,9 +2133,12 @@ static void M_ChangeCvar(INT32 choice) static boolean M_ChangeStringCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; - char buf[255]; + char buf[MAXSTRINGLENGTH]; size_t len; + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + switch (choice) { case KEY_BACKSPACE: @@ -2434,8 +2436,6 @@ boolean M_Responder(event_t *ev) { if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) { - if (shiftdown && ch >= 32 && ch <= 127) - ch = shiftxform[ch]; if (M_ChangeStringCvar(ch)) return true; else @@ -4474,6 +4474,7 @@ static void M_Addons(INT32 choice) addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); + addonsp[EXT_SEARCH] = W_CachePatchName("M_FSRCH", PU_STATIC); addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); @@ -4552,14 +4553,16 @@ static char *M_AddonsHeaderPath(void) return header+len; } +#define UNEXIST S_StartSound(NULL, sfx_lose);\ + M_SetupNextMenu(MISC_AddonsDef.prevMenu);\ + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) + // returns whether to do message draw static boolean M_AddonsRefresh(void) { if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) { - S_StartSound(NULL, sfx_lose); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); + UNEXIST; return true; } @@ -4617,6 +4620,8 @@ static void M_DrawAddons(void) M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true); + V_DrawString(0, 0, V_ALLOWLOWERCASE, menusearch+1); + // get bottom... max = dir_on[menudepthleft] + 5; if (max > (ssize_t)sizedirmenu) @@ -4679,10 +4684,50 @@ static void M_AddonExec(INT32 ch) COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); } +#define len menusearch[0] +static boolean M_ChangeStringAddons(INT32 choice) +{ + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + + switch (choice) + { + case KEY_DEL: + len = menusearch[1] = 0; + return true; + case KEY_BACKSPACE: + if (len > 0) + menusearch[1+--len] = 0; + return true; + default: + if (choice >= 32 && choice <= 127) + { + if (len < MAXSTRINGLENGTH - 1) + { + menusearch[1+len++] = (char)choice; + menusearch[1+len] = 0; + } + return true; + } + break; + } + return false; +} +#undef len + static void M_HandleAddons(INT32 choice) { boolean exitmenu = false; // exit to previous menu + if (M_ChangeStringAddons(choice)) + { + if (!preparefilemenu(true)) + { + UNEXIST; + return; + } + } + switch (choice) { case KEY_DOWNARROW: @@ -4719,9 +4764,7 @@ static void M_HandleAddons(INT32 choice) if (!preparefilemenu(true)) { - S_StartSound(NULL, sfx_lose); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); + UNEXIST; return; } } diff --git a/src/m_menu.h b/src/m_menu.h index 2e20789ef..73da85de6 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_HEADER (IT_SPACE +IT_HEADERTEXT) #define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS) +#define MAXSTRINGLENGTH 32 + typedef union { struct menu_s *submenu; // IT_SUBMENU diff --git a/src/string.c b/src/string.c index d7f8b3679..5065553ae 100644 --- a/src/string.c +++ b/src/string.c @@ -50,3 +50,41 @@ size_t strlcpy(char *dst, const char *src, size_t siz) } #endif + +#if 1 // i don't know what specific OSes are missing this, oh well + +// stack overflow, eep... +char* stristr(char* haystack, const char* needle) +{ + char* p1 = haystack ; + const char* p2 = needle ; + char* r = ((*p2 == 0) ? haystack : 0); + + while (*p1 != 0 && *p2 != 0) + { + if (tolower(*p1) == tolower(*p2)) + { + if (r == 0) + r = p1; + + p2++; + } + else + { + p2 = needle; + if (tolower(*p1) == tolower(*p2)) + { + r = p1; + p2++; + } + else + r = 0; + } + + p1++; + } + + return ((*p2 == 0) ? r : 0); +} + +#endif \ No newline at end of file