From 6768824548aab07d9964d128bd85810ff8cd7e3e Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Fri, 10 Jan 2020 09:24:36 +0100 Subject: [PATCH] Dragdrop (#30) * add drap-n-drop support * move D_IsIWADName() down into the block where it is needed --- Source/d_main.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/Source/d_main.c b/Source/d_main.c index e654feab..334b6d67 100644 --- a/Source/d_main.c +++ b/Source/d_main.c @@ -36,6 +36,8 @@ #include #include +#include "SDL_stdinc.h" // [FG] SDL_qsort() + #include "doomdef.h" #include "doomstat.h" #include "dstrings.h" @@ -1073,6 +1075,168 @@ void FindResponseFile (void) } } +// [FG] compose a proper command line from loose file paths passed as arguments +// to allow for loading WADs and DEHACKED patches by drag-and-drop + +#if defined(_WIN32) +enum +{ + FILETYPE_UNKNOWN = 0x0, + FILETYPE_IWAD = 0x2, + FILETYPE_PWAD = 0x4, + FILETYPE_DEH = 0x8, +}; + +static boolean D_IsIWADName(const char *name) +{ + int i; + + for (i = 0; i < nstandard_iwads; i++) + { + if (!strcasecmp(name, standard_iwads[i])) + { + return true; + } + } + + return false; +} + +static int GuessFileType(const char *name) +{ + int ret = FILETYPE_UNKNOWN; + const char *base; + char *lower; + static boolean iwad_found = false; + + base = M_BaseName(name); + lower = M_StringDuplicate(base); + M_ForceLowercase(lower); + + // only ever add one argument to the -iwad parameter + + if (iwad_found == false && D_IsIWADName(lower)) + { + ret = FILETYPE_IWAD; + iwad_found = true; + } + else if (M_StringEndsWith(lower, ".wad") || + M_StringEndsWith(lower, ".lmp")) + { + ret = FILETYPE_PWAD; + } + else if (M_StringEndsWith(lower, ".deh") || + M_StringEndsWith(lower, ".bex")) + { + ret = FILETYPE_DEH; + } + + free(lower); + + return ret; +} + +typedef struct +{ + char *str; + int type, stable; +} argument_t; + +static int CompareByFileType(const void *a, const void *b) +{ + const argument_t *arg_a = (const argument_t *) a; + const argument_t *arg_b = (const argument_t *) b; + + const int ret = arg_a->type - arg_b->type; + + return ret ? ret : (arg_a->stable - arg_b->stable); +} + +static void M_AddLooseFiles(void) +{ + int i, types = 0; + char **newargv; + argument_t *arguments; + + if (myargc < 2) + { + return; + } + + // allocate space for up to three additional regular parameters + + arguments = malloc((myargc + 3) * sizeof(*arguments)); + memset(arguments, 0, (myargc + 3) * sizeof(*arguments)); + + // check the command line and make sure it does not already + // contain any regular parameters or response files + // but only fully-qualified LFS or UNC file paths + + for (i = 1; i < myargc; i++) + { + char *arg = myargv[i]; + int type; + + if (strlen(arg) < 3 || + arg[0] == '-' || + arg[0] == '@' || + ((!isalpha(arg[0]) || arg[1] != ':' || arg[2] != '\\') && + (arg[0] != '\\' || arg[1] != '\\'))) + { + free(arguments); + return; + } + + type = GuessFileType(arg); + arguments[i].str = arg; + arguments[i].type = type; + arguments[i].stable = i; + types |= type; + } + + // add space for one additional regular parameter + // for each discovered file type in the new argument list + // and sort parameters right before their corresponding file paths + + if (types & FILETYPE_IWAD) + { + arguments[myargc].str = M_StringDuplicate("-iwad"); + arguments[myargc].type = FILETYPE_IWAD - 1; + myargc++; + } + if (types & FILETYPE_PWAD) + { + arguments[myargc].str = M_StringDuplicate("-file"); + arguments[myargc].type = FILETYPE_PWAD - 1; + myargc++; + } + if (types & FILETYPE_DEH) + { + arguments[myargc].str = M_StringDuplicate("-deh"); + arguments[myargc].type = FILETYPE_DEH - 1; + myargc++; + } + + newargv = malloc(myargc * sizeof(*newargv)); + + // sort the argument list by file type, except for the zeroth argument + // which is the executable invocation itself + + SDL_qsort(arguments + 1, myargc - 1, sizeof(*arguments), CompareByFileType); + + newargv[0] = myargv[0]; + + for (i = 1; i < myargc; i++) + { + newargv[i] = arguments[i].str; + } + + free(arguments); + + myargv = newargv; +} +#endif + // killough 10/98: moved code to separate function static void D_ProcessDehCommandLine(void) @@ -1210,6 +1374,12 @@ void D_DoomMain(void) setbuf(stdout,NULL); +#if defined(_WIN32) + // [FG] compose a proper command line from loose file paths passed as arguments + // to allow for loading WADs and DEHACKED patches by drag-and-drop + M_AddLooseFiles(); +#endif + FindResponseFile(); // Append response file arguments to command-line // killough 10/98: set default savename based on executable's name