diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/karin/KStr.java b/Q3E/src/main/java/com/n0n3m4/q3e/karin/KStr.java index 1984a0ff5..f4374f2b4 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/karin/KStr.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/karin/KStr.java @@ -149,8 +149,8 @@ public static String CmdStr(String str) { if(null == str) return ""; - if(str.contains(" ")) - return '"' + str + '"'; + if(str.contains(" ") || str.contains("\"")) + return KidTechCommand.EscapeQuotes(str); else return str; } diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/karin/KidTechCommand.java b/Q3E/src/main/java/com/n0n3m4/q3e/karin/KidTechCommand.java index 45a9620ec..ff441e5f6 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/karin/KidTechCommand.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/karin/KidTechCommand.java @@ -606,7 +606,7 @@ private void InsertPart(int i, int type, Object value) cmdParts.add(i, part); } - private String SkipBlank(String str, int start) + private static String SkipBlank(String str, int start) { StringBuilder ret = new StringBuilder(); int i = start; @@ -621,7 +621,7 @@ private String SkipBlank(String str, int start) return ret.toString(); } - private String ReadWord(String str, int start) + private static String ReadWord(String str, int start) { if(str.charAt(start) == '\"') { @@ -641,7 +641,7 @@ private String ReadWord(String str, int start) return ret.toString(); } - private String ReadWordWithQuotes(String str, int start) + private static String ReadWordWithQuotes(String str, int start) { char quoteStart = str.charAt(start); StringBuilder ret = new StringBuilder(); @@ -658,7 +658,7 @@ private String ReadWordWithQuotes(String str, int start) return ret.toString(); // with quotes } - private String ReadUtil(String str, int start, String chars) + private static String ReadUtil(String str, int start, String chars) { StringBuilder ret = new StringBuilder(); int i = start; @@ -761,6 +761,90 @@ private static String ValueToString(Object o) return o.toString(); } + public static List SplitValue(String value, boolean unescape) + { + value = value.trim(); + List ret = new ArrayList<>(); + int i = 0; + while(i < value.length()) + { + char c = value.charAt(i); + if(Character.isSpaceChar(c)) + { + i += SkipBlank(value, i).length(); + } + else + { + String val = ReadWord(value, i); + i += val.length(); + if(unescape && val.startsWith("\"")) + val = UnEscapeQuotes(val); + ret.add(val); + } + } + return ret; + } + + public static String UnEscapeQuotes( String arg ) + { + char[] arr = arg.toCharArray(); + char first = '"'; + char last = 0; + int _i = 0; + int last_i = 0; + while( _i < arr.length ) { + char ch = arr[_i]; + if( ch == first && last == '\\' ) { + int c_curr = _i; + int c_last = last_i; + while( c_curr < arr.length ) { + arr[c_last] = arr[c_curr]; + c_last = c_curr; + c_curr++; + } + arr[c_last] = '\0'; + } + last_i = _i; + last = ch; + _i++; + } + + StringBuilder buf = new StringBuilder(); + for(_i = 1; _i < arr.length; _i++) + { + if(arr[_i] == 0) + break; + buf.append(arr[_i]); + } + if(buf.length() == 0) + return ""; + buf.delete(buf.length() - 1, buf.length()); + return buf.toString(); + } + + public static String JoinValue(List list, boolean escape) + { + String split = " "; + StringBuilder buf = new StringBuilder(); + for(int i = 0; i < list.size(); i++) + { + String str = list.get(i); + if(null == str) + str = ""; + else if(escape && (str.contains(split) || str.contains("\""))) + str = EscapeQuotes(str); + buf.append(str); + if(i < list.size() - 1) + buf.append(split); + } + return buf.toString(); + } + + public static String EscapeQuotes( String arg ) + { + return "\"" + arg.replaceAll("\"", "\\\\\"") + "\""; + } + private CmdPart GetPart(int index) { if(index < 0 || index >= cmdParts.size()) diff --git a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java index f4f7fa257..42aae9f39 100644 --- a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java +++ b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java @@ -3244,30 +3244,30 @@ public void run() { String files = mod.substring(1); String[] split = files.split(ChooseGameModFunc.FILE_SEP); - StringBuilder file = new StringBuilder(); - StringBuilder deh = new StringBuilder(); - StringBuilder bex = new StringBuilder(); + List file = new ArrayList<>(); + List deh = new ArrayList<>(); + List bex = new ArrayList<>(); for (String s : split) { if(s.toLowerCase().endsWith(".deh")) - deh.append(" ").append(s); + deh.add(s); else if(s.toLowerCase().endsWith(".bex")) - bex.append(" ").append(s); + bex.add(s); else - file.append(" ").append(s); + file.add(s); } RemoveParam("file"); RemoveParam("deh"); RemoveParam("bex"); - if(file.length() > 0) - SetParam("file", file.toString().trim()); - if(deh.length() > 0) - SetParam("deh", deh.toString().trim()); - if(bex.length() > 0) - SetParam("bex", bex.toString().trim()); + if(!file.isEmpty()) + SetParam("file", KidTechCommand.JoinValue(file, true)); + if(!deh.isEmpty()) + SetParam("deh", KidTechCommand.JoinValue(deh, true)); + if(!bex.isEmpty()) + SetParam("bex", KidTechCommand.JoinValue(bex, true)); } } else @@ -3278,7 +3278,8 @@ else if(s.toLowerCase().endsWith(".bex")) String path = KStr.AppendPath(preference.getString(Q3EPreference.pref_datapath, default_gamedata), Q3EUtils.q3ei.subdatadir, Q3EUtils.q3ei.GetGameModSubDirectory()); bundle.putString("mod", preference.getString(preferenceKey, "")); bundle.putString("path", path); - bundle.putString("file", GetParam("file") + " " + GetParam("deh") + " " + GetParam("bex")); + if(Q3EUtils.q3ei.isDOOM) + bundle.putString("file", GetParam("file") + " " + GetParam("deh") + " " + GetParam("bex")); m_chooseGameModFunc.Start(bundle); } diff --git a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ChooseGameModFunc.java b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ChooseGameModFunc.java index 47b32b964..540c6c3e4 100644 --- a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ChooseGameModFunc.java +++ b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ChooseGameModFunc.java @@ -18,6 +18,7 @@ import com.n0n3m4.q3e.Q3EPreference; import com.n0n3m4.q3e.Q3EUtils; import com.n0n3m4.q3e.karin.KStr; +import com.n0n3m4.q3e.karin.KidTechCommand; import java.io.File; import java.util.ArrayList; @@ -439,8 +440,8 @@ public void ChooseExtraFiles(String excludes) // 3. load selected from command line if(KStr.NotBlank(m_file)) { - String[] split = m_file.split("\\s+"); - files.addAll(Arrays.asList(split)); + List strings = KidTechCommand.SplitValue(m_file, true); + files.addAll(strings); } // 4. remove not exists files from command line @@ -480,10 +481,7 @@ public void onClick(DialogInterface dialog, int which, boolean isChecked) builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int p) { - List norFiles = new ArrayList<>(files.size()); - for(String file : files) - norFiles.add(KStr.CmdStr(file)); - String join = KStr.Join(norFiles, FILE_SEP); + String join = KStr.Join(files, FILE_SEP); Callback(":" + join); dialog.dismiss(); }