shithub: choc

Download patch

ref: 23c7d01a5a2a4f4a804ebe36c63e079f80c97fbb
parent: 5e6377aa3bd2c7d4999a180c8131284b94b50457
parent: 0abcb12fbbf199fa561da03794326e242b94018d
author: Simon Howard <fraggle@soulsphere.org>
date: Sun Jun 2 15:29:28 EDT 2019

Merge pull request #1168 from chocolate-doom/drag-and-drop3

allow for loading WAD files and DEHACKED patches by drag-and-drop (take 3)

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,8 +35,11 @@
 
 DEDSERV_FILES=\
 d_dedicated.c                              \
+d_iwad.c             d_iwad.h              \
 d_mode.c             d_mode.h              \
+deh_str.c            deh_str.h             \
 i_timer.c            i_timer.h             \
+m_config.c           m_config.h            \
 net_common.c         net_common.h          \
 net_dedicated.c      net_dedicated.h       \
 net_io.c             net_io.h              \
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -50,6 +50,21 @@
     { "strife1.wad",  strife,    commercial, "Strife" },
 };
 
+boolean D_IsIWADName(const char *name)
+{
+    int i;
+
+    for (i = 0; i < arrlen(iwads); i++)
+    {
+        if (!strcasecmp(name, iwads[i].name))
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 // Array of locations to search for IWAD files
 //
 // "128 IWAD search directories should be enough for anybody".
--- a/src/d_iwad.h
+++ b/src/d_iwad.h
@@ -39,6 +39,7 @@
     const char *description;
 } iwad_t;
 
+boolean D_IsIWADName(const char *name);
 char *D_FindWADByName(const char *filename);
 char *D_TryFindWADByName(const char *filename);
 char *D_FindIWAD(int mask, GameMission_t *mission);
--- a/src/i_main.c
+++ b/src/i_main.c
@@ -49,6 +49,12 @@
         exit(0);
     }
 
+#if defined(_WIN32)
+    // 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
+
     M_FindResponseFile();
 
     #ifdef SDL_HINT_NO_SIGNAL_HANDLERS
--- a/src/m_argv.c
+++ b/src/m_argv.c
@@ -21,7 +21,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "SDL_stdinc.h"
+
 #include "doomtype.h"
+#include "d_iwad.h"
 #include "i_system.h"
 #include "m_misc.h"
 #include "m_argv.h"  // haleyjd 20110212: warning fix
@@ -260,6 +263,152 @@
         LoadResponseFile(i + 1, myargv[i + 1]);
     }
 }
+
+#if defined(_WIN32)
+enum
+{
+    FILETYPE_UNKNOWN = 0x0,
+    FILETYPE_IWAD =    0x2,
+    FILETYPE_PWAD =    0x4,
+    FILETYPE_DEH =     0x8,
+};
+
+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") ||
+             M_StringEndsWith(lower, ".hhe") ||
+             M_StringEndsWith(lower, ".seh"))
+    {
+        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);
+}
+
+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("-merge");
+        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
 
 // Return the name of the executable used to start the program:
 
--- a/src/m_argv.h
+++ b/src/m_argv.h
@@ -37,6 +37,7 @@
 int M_CheckParmWithArgs(const char *check, int num_args);
 
 void M_FindResponseFile(void);
+void M_AddLooseFiles(void);
 
 // Parameter has been specified?