diff options
5 files changed, 553 insertions, 125 deletions
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java index 463920b9f..13b6029b8 100644 --- a/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java +++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java @@ -853,6 +853,13 @@ public class DebugPlugin extends Plugin { * @since 3.0 */ public static Process exec(String[] cmdLine, File workingDirectory, String[] envp) throws CoreException { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + String[] winCmdLine= new String[cmdLine.length]; + for (int i= 0; i < cmdLine.length; i++) { + winCmdLine[i]= winQuote(cmdLine[i]); + } + cmdLine= winCmdLine; + } Process p= null; try { if (workingDirectory == null) { @@ -876,7 +883,28 @@ public class DebugPlugin extends Plugin { } } return p; - } + } + + private static boolean needsQuoting(String s) { + int len = s.length(); + if (len == 0) // empty string has to be quoted + return true; + for (int i = 0; i < len; i++) { + switch (s.charAt(i)) { + case ' ': case '\t': case '\\': case '"': + return true; + } + } + return false; + } + + private static String winQuote(String s) { + if (! needsQuoting(s)) + return s; + s = s.replaceAll("([\\\\]*)\"", "$1$1\\\\\""); //$NON-NLS-1$ //$NON-NLS-2$ + s = s.replaceAll("([\\\\]*)\\z", "$1$1"); //$NON-NLS-1$ //$NON-NLS-2$ + return "\"" + s + "\""; //$NON-NLS-1$ //$NON-NLS-2$ + } /** * Returns whether this plug-in is in the process of @@ -1256,115 +1284,168 @@ public class DebugPlugin extends Plugin { throw new CoreException(status); } - /** - * Utility class to parse command line arguments. - * - * @since 3.1 - */ - private static class ArgumentParser { - private String fArgs; - private int fIndex= 0; - private int ch= -1; - - public ArgumentParser(String args) { - fArgs= args; - } - - public String[] parseArguments() { - List v= new ArrayList(); - - ch= getNext(); - while (ch > 0) { - if (Character.isWhitespace((char)ch)) { - ch= getNext(); + private static String[] parseArgumentsWindows(String args) { + // see http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + List result= new ArrayList(); + + final int DEFAULT= 0; + final int ARG= 1; + final int IN_DOUBLE_QUOTE= 2; + + int state= DEFAULT; + int backslashes= 0; + StringBuffer buf= new StringBuffer(); + int len= args.length(); + for (int i= 0; i < len; i++) { + char ch= args.charAt(i); + if (ch == '\\') { + backslashes++; + continue; + } else if (backslashes != 0) { + if (ch == '"') { + for (; backslashes >= 2; backslashes-= 2) { + buf.append('\\'); + } + if (backslashes == 1) { + if (state == DEFAULT) + state= ARG; + buf.append('"'); + backslashes= 0; + continue; + } // else fall through to switch } else { - if (ch == '"') { - StringBuffer buf = new StringBuffer(); - buf.append(parseString()); - if (buf.length() == 0 && Platform.getOS().equals(Constants.OS_WIN32)) { - // empty string on windows platform - buf.append("\"\""); //$NON-NLS-1$ - } - v.add(buf.toString()); - } else { - v.add(parseToken()); + // false alarm, treat passed backslashes literally... + if (state == DEFAULT) + state= ARG; + for (; backslashes > 0; backslashes--) { + buf.append('\\'); } + // fall through to switch } } - - String[] result= new String[v.size()]; - v.toArray(result); - return result; - } - - private int getNext() { - if (fIndex < fArgs.length()) - return fArgs.charAt(fIndex++); - return -1; - } - - private String parseString() { - ch= getNext(); - if (ch == '"') { - ch= getNext(); - return ""; //$NON-NLS-1$ + if (Character.isWhitespace(ch)) { + if (state == DEFAULT) { + // skip + continue; + } else if (state == ARG) { + state= DEFAULT; + result.add(buf.toString()); + buf.setLength(0); + continue; + } } - StringBuffer buf= new StringBuffer(); - while (ch > 0 && ch != '"') { - if (ch == '\\') { - ch= getNext(); - if (ch != '"') { // Only escape double quotes - buf.append('\\'); + switch (state) { + case DEFAULT: + case ARG: + if (ch == '"') { + state= IN_DOUBLE_QUOTE; } else { - if (Platform.getOS().equals(Constants.OS_WIN32)) { - // @see Bug 26870. Windows requires an extra escape for embedded strings - buf.append('\\'); + state= ARG; + buf.append(ch); + } + break; + + case IN_DOUBLE_QUOTE: + if (ch == '"') { + if (i + 1 < len && args.charAt(i + 1) == '"') { + /* Undocumented feature in Windows: + * Two consecutive double quotes inside a double-quoted argument are interpreted as + * a single double quote. + */ + buf.append('"'); + i++; + } else if (buf.length() == 0) { + // empty string on Windows platform. Account for bug in constructor of JDK's java.lang.ProcessImpl. + result.add("\"\""); //$NON-NLS-1$ + state= DEFAULT; + } else { + state= ARG; } + } else { + buf.append(ch); } - } - if (ch > 0) { - buf.append((char)ch); - ch= getNext(); - } + break; + + default: + throw new IllegalStateException(); } - ch= getNext(); - return buf.toString(); } - - private String parseToken() { - StringBuffer buf= new StringBuffer(); - - while (ch > 0 && !Character.isWhitespace((char)ch)) { - if (ch == '\\') { - ch= getNext(); - if (Character.isWhitespace((char)ch)) { - // end of token, don't lose trailing backslash - buf.append('\\'); - return buf.toString(); + if (buf.length() > 0) + result.add(buf.toString()); + + return (String[]) result.toArray(new String[result.size()]); + } + + private static String[] parseArgumentsImpl(String args) { + // man sh, see topic QUOTING + List result= new ArrayList(); + + final int DEFAULT= 0; + final int ARG= 1; + final int IN_DOUBLE_QUOTE= 2; + final int IN_SINGLE_QUOTE= 3; + + int state= DEFAULT; + StringBuffer buf= new StringBuffer(); + int len= args.length(); + for (int i= 0; i < len; i++) { + char ch= args.charAt(i); + if (Character.isWhitespace(ch)) { + if (state == DEFAULT) { + // skip + continue; + } else if (state == ARG) { + state= DEFAULT; + result.add(buf.toString()); + buf.setLength(0); + continue; + } + } + switch (state) { + case DEFAULT: + case ARG: + if (ch == '"') { + state= IN_DOUBLE_QUOTE; + } else if (ch == '\'') { + state= IN_SINGLE_QUOTE; + } else if (ch == '\\' && i + 1 < len) { + state= ARG; + ch= args.charAt(++i); + buf.append(ch); + } else { + state= ARG; + buf.append(ch); } - if (ch > 0) { - if (ch != '"') { // Only escape double quotes - buf.append('\\'); - } else { - if (Platform.getOS().equals(Constants.OS_WIN32)) { - // @see Bug 26870. Windows requires an extra escape for embedded strings - buf.append('\\'); - } - } - buf.append((char)ch); - ch= getNext(); - } else if (ch == -1) { // Don't lose a trailing backslash - buf.append('\\'); + break; + + case IN_DOUBLE_QUOTE: + if (ch == '"') { + state= ARG; + } else if (ch == '\\' && i + 1 < len && + (args.charAt(i + 1) == '\\' || args.charAt(i + 1) == '"')) { + ch= args.charAt(++i); + buf.append(ch); + } else { + buf.append(ch); } - } else if (ch == '"') { - buf.append(parseString()); - } else { - buf.append((char)ch); - ch= getNext(); - } + break; + + case IN_SINGLE_QUOTE: + if (ch == '\'') { + state= ARG; + } else { + buf.append(ch); + } + break; + + default: + throw new IllegalStateException(); } - return buf.toString(); } + if (buf.length() > 0) + result.add(buf.toString()); + + return (String[]) result.toArray(new String[result.size()]); } /** @@ -1379,13 +1460,89 @@ public class DebugPlugin extends Plugin { public static String[] parseArguments(String args) { if (args == null) return new String[0]; - ArgumentParser parser= new ArgumentParser(args); - String[] res= parser.parseArguments(); - return res; + if (Constants.OS_WIN32.equals(Platform.getOS())) + return parseArgumentsWindows(args); + + return parseArgumentsImpl(args); } /** + * Renders the given array of strings into a single command line. + * <p> + * If <code>segments</code> is not <code>null</code>, the array is filled + * with the offsets of the start positions of arguments 1 to + * <code>arguments.length - 1</code>, as rendered in the resulting string. + * </p> + * + * @param arguments + * the command line arguments + * @param segments + * an array of size <code>arguments.length - 1</code> or + * <code>null</code> + * @return the command line + * @since 3.8 + */ + public static String renderArguments(String[] arguments, int[] segments) { + boolean isWin32= Platform.getOS().equals(Constants.OS_WIN32); + StringBuffer buf = new StringBuffer(); + int count = arguments.length; + for (int i = 0; i < count; i++) { + if (i > 0) + buf.append(' '); + + boolean containsSpace = false; + char[] characters = arguments[i].toCharArray(); + for (int j = 0; j < characters.length; j++) { + char ch = characters[j]; + if (ch == ' ' || ch == '\t') { + containsSpace = true; + buf.append('"'); + break; + } + } + + int backslashes = 0; + for (int j = 0; j < characters.length; j++) { + char ch = characters[j]; + if (ch == '"') { + if (isWin32) { + if (j == 0 && characters.length == 2 && characters[1] == '"') { + // empty string on windows platform, see bug 130767. Bug in constructor of JDK's java.lang.ProcessImpl. + buf.append("\"\""); //$NON-NLS-1$ + break; + } + if (backslashes > 0) { + // Feature in Windows: need to double-escape backslashes in front of double quote. + for (; backslashes > 0; backslashes--) { + buf.append('\\'); + } + } + } + buf.append('\\'); + } else if (ch == '\\') { + if (isWin32) { + backslashes++; + } else { + buf.append('\\'); + } + } + buf.append(ch); + } + if (containsSpace) { + buf.append('"'); + } else if (characters.length == 0) { + buf.append("\"\""); //$NON-NLS-1$ + } + + if (segments != null && i < count - 1) { + segments[i] = buf.length() + 1; + } + } + return buf.toString(); + } + + /** * Sets whether step filters should be applied to step commands. This * setting is a global option applied to all registered debug targets. * diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/ArgumentParsingTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/ArgumentParsingTests.java new file mode 100644 index 000000000..33647b75e --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/ArgumentParsingTests.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * Copyright (c) 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.launching; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.tests.TestsPlugin; +import org.eclipse.osgi.service.environment.Constants; + +/** + * Tests {@link org.eclipse.debug.core.DebugPlugin#parseArguments(String)} and + * {@link org.eclipse.debug.core.DebugPlugin#renderCommandLine(String[], int[])}. + */ +public class ArgumentParsingTests extends TestCase { + + private void execute1Arg(String cmdLine) throws Exception { + execute1Arg(cmdLine, cmdLine); + } + + private void execute1Arg(String cmdLine, String argParsed) throws Exception { + execute1Arg(cmdLine, argParsed, cmdLine); + } + + private void execute1Arg(String cmdLine, String argParsed, String rendered) throws Exception { + execute("a " + cmdLine + " b", new String[] { "a", argParsed, "b" }, "a " + rendered + " b"); + } + + private static void execute(String commandLine, String[] expectedArgs) throws Exception { + execute(commandLine, expectedArgs, commandLine); + } + + private static void execute(String commandLine, String[] expectedArgs, String expectedRendered) throws Exception { + String[] arguments = DebugPlugin.parseArguments(commandLine); + assertEquals("unexpected parseArguments result;", + Arrays.asList(expectedArgs).toString(), + Arrays.asList(arguments).toString()); + + runCommandLine(commandLine, arguments); + + String rendered = DebugPlugin.renderArguments(arguments, null); + assertEquals("unexpected renderArguments result;", expectedRendered, rendered); + + if (!commandLine.equals(rendered)) { + String[] arguments2 = DebugPlugin.parseArguments(rendered); + assertEquals("parsing rendered command line doesn't yield original arguments;", + Arrays.asList(expectedArgs).toString(), + Arrays.asList(arguments2).toString()); + } + + } + + private static void runCommandLine(String commandLine, String[] arguments) throws IOException, + URISyntaxException, CoreException { + URL classFolderUrl = FileLocator.find(TestsPlugin.getDefault().getBundle(), new Path("bin/"), null); + classFolderUrl= FileLocator.toFileURL(classFolderUrl); + File classFolderFile = URIUtil.toFile(URIUtil.toURI(classFolderUrl)); + + String[] execArgs= new String[arguments.length + 2]; + execArgs[0]= new Path(System.getProperty("java.home")).append("bin/java").toOSString(); + execArgs[1]= ArgumentsPrinter.class.getName(); + System.arraycopy(arguments, 0, execArgs, 2, arguments.length); + + ArrayList resultArgs = runCommandLine(execArgs, classFolderFile); + + assertEquals("unexpected exec result;", + Arrays.asList(arguments).toString(), + resultArgs.toString()); + + if (! Platform.getOS().equals(Constants.OS_WIN32)) { + execArgs= new String[] { "sh", "-c", execArgs[0] + " " + execArgs[1] + " " + commandLine}; + resultArgs = runCommandLine(execArgs, classFolderFile); + assertEquals("unexpected sh exec result;", + Arrays.asList(arguments).toString(), + resultArgs.toString()); + + } + } + + private static ArrayList runCommandLine(String[] execArgs, File workingDir) + throws CoreException, IOException { + Process process = DebugPlugin.exec(execArgs, workingDir); + BufferedReader procOut = new BufferedReader(new InputStreamReader(process.getInputStream())); + + ArrayList procArgs= new ArrayList(); + String procArg; + while ((procArg = procOut.readLine()) != null) { + procArgs.add(procArg); + } + return procArgs; + } + + // -- tests: + + public void testEmpty() throws Exception { + execute("", new String[0]); + } + + public void test1arg() throws Exception { + execute("a", new String[] { "a" }); + } + + public void test2arg() throws Exception { + execute("a b", new String[] { "a", "b" }); + } + + public void test100arg() throws Exception { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < 100; i++) + buf.append("a "); + String[] args = new String[100]; + Arrays.fill(args, "a"); + execute(buf.toString(), args, buf.toString().trim()); + } + + public void testEscape() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute1Arg("\\1"); + } else { + execute1Arg("\\1", "1", "1"); + } + } + + public void testEscapeDoubleQuote1() throws Exception { + execute1Arg("\\\"", "\"", "\\\""); + } + + public void testEscapeDoubleQuote2() throws Exception { + execute1Arg("arg=\\\"bla\\\"", "arg=\"bla\"", "arg=\\\"bla\\\""); + } + + public void testDoubleQuoted1() throws Exception { + execute1Arg("\"1 2\"", "1 2"); + } + + public void testDoubleQuoted2() throws Exception { + execute1Arg("\"1\"", "1", "1"); + } + + public void testDoubleQuoted3() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { +// execute1Arg("\"\"", "", "\"\""); // would be correct, but ProcessImpl is buggy on Windows JDKs + execute1Arg("\"\""); + } else { + execute1Arg("\"\"", "", "\"\""); + } + } + + public void testDoubleQuoted4() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute1Arg("\"\"\"\"", "\"", "\\\""); + } else { + execute1Arg("\"\"\"\"", "", "\"\""); + } + } + + public void testDoubleQuoted5() throws Exception { + execute1Arg("ab\"cd\"ef\"gh\"", "abcdefgh", "abcdefgh"); + } + + public void testDoubleQuotedWithSpace1() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute1Arg("\"\"\"1\"\" 2\"", "\"1\" 2", "\"\\\"1\\\" 2\""); + } else { + execute1Arg("\"\"\"1\"\" 2\"", "1 2", "\"1 2\""); + } + } + + public void testDoubleQuotedWithSpace2() throws Exception { + execute1Arg("\"\\\"1\\\" 2\"", "\"1\" 2"); + } + + public void testSingleQuoted1() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute("'1 2'", new String[] { "'1", "2'" }); + } else { + execute("'1 2'", new String[] { "1 2" }, "\"1 2\""); + } + } + + public void testSingleQuoted2() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute1Arg("'1'", "'1'", "'1'"); + } else { + execute1Arg("'1'", "1", "1"); + } + } + + public void testWindows1() throws Exception { + execute("\"a b c\" d e", new String[] { "a b c", "d", "e" }); + } + + public void testWindows2() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute("\"ab\\\"c\" \"\\\\\" d", new String[] { "ab\"c", "\\", "d" }, "ab\\\"c \\ d"); + } else { + execute("\"ab\\\"c\" \"\\\\\" d", new String[] { "ab\"c", "\\", "d" }, "ab\\\"c \\\\ d"); + } + } + + public void testWindows3() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute("a\\\\\\b d\"e f\"g h", new String[] { "a\\\\\\b", "de fg", "h" }, "a\\\\\\b \"de fg\" h"); + } else { + execute("a\\\\\\b d\"e f\"g h", new String[] { "a\\b", "de fg", "h" }, "a\\\\b \"de fg\" h"); + } + } + + public void testWindows4() throws Exception { + execute("a\\\\\\\"b c d", new String[] { "a\\\"b", "c", "d" }); + } + + public void testWindows5() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute("a\\\\\\\\\"b c\" d e", new String[] { "a\\\\b c", "d", "e" }, "\"a\\\\b c\" d e"); + } else { + execute("a\\\\\\\\\"b c\" d e", new String[] { "a\\\\b c", "d", "e" }, "\"a\\\\\\\\b c\" d e"); + } + } + + public void testAllInOne() throws Exception { + if (Platform.getOS().equals(Constants.OS_WIN32)) { + execute("1 \"\" 2 \" \" 3 \\\" 4 \"a b\" 5 \\\"bla\\\" 6 \"ab\"cd 7 ef\"gh\" 8 i\"\"j 9 \"x\\\"y\\\\\" 10 z\\\\z 11 \"two-quotes:\"\"\"\"\" 12 \"g\"\"h\" 13 \"\"\"a\"\" b\"", + new String[] { "1", "\"\"", "2", " ", "3", "\"", "4", "a b", "5", "\"bla\"", "6", "abcd", "7", "efgh", "8", "ij", "9", "x\"y\\", "10", "z\\\\z", "11", "two-quotes:\"\"", "12", "g\"h", "13", "\"a\" b" }, + "1 \"\" 2 \" \" 3 \\\" 4 \"a b\" 5 \\\"bla\\\" 6 abcd 7 efgh 8 ij 9 x\\\"y\\ 10 z\\\\z 11 two-quotes:\\\"\\\" 12 g\\\"h 13 \"\\\"a\\\" b\""); + } else { + execute("1 \"\" 2 \" \" 3 \\\" 4 \"a b\" 5 \\\"bla\\\" 6 \"ab\"cd 7 ef\"gh\" 8 i\"\"j 9 \"x\\\"y\\\\\" 10 z\\\\z 11 \"two-quotes:\"\"\"\"\" 12 \"g\"\"h\" 13 \"\"\"a\"\" b\"", + new String[] { "1", "", "2", " ", "3", "\"", "4", "a b", "5", "\"bla\"", "6", "abcd", "7", "efgh", "8", "ij", "9", "x\"y\\", "10", "z\\z", "11", "two-quotes:", "12", "gh", "13", "a b" }, + "1 \"\" 2 \" \" 3 \\\" 4 \"a b\" 5 \\\"bla\\\" 6 abcd 7 efgh 8 ij 9 x\\\"y\\\\ 10 z\\\\z 11 two-quotes: 12 gh 13 \"a b\""); + } + } + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/ArgumentsPrinter.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/ArgumentsPrinter.java new file mode 100644 index 000000000..9651de25b --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/ArgumentsPrinter.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.launching; + +/** + * Used by {@link ArgumentParsingTests}. + */ +public class ArgumentsPrinter { + public static void main(String[] args) { + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + System.out.println(arg); + } + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java index 87fbb055c..7fb3eacdc 100644 --- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java +++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java @@ -15,6 +15,7 @@ import junit.framework.Test; import junit.framework.TestSuite; import org.eclipe.debug.tests.launching.AcceleratorSubstitutionTests; +import org.eclipe.debug.tests.launching.ArgumentParsingTests; import org.eclipe.debug.tests.launching.LaunchConfigurationTests; import org.eclipe.debug.tests.launching.LaunchFavoriteTests; import org.eclipe.debug.tests.launching.LaunchHistoryTests; @@ -83,6 +84,7 @@ public class AutomatedSuite extends TestSuite { addTest(new TestSuite(LaunchFavoriteTests.class)); addTest(new TestSuite(LaunchManagerTests.class)); addTest(new TestSuite(RefreshTabTests.class)); + addTest(new TestSuite(ArgumentParsingTests.class)); // Status handlers addTest(new TestSuite(StatusHandlerTests.class)); diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/preferences/ProcessPropertyPage.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/preferences/ProcessPropertyPage.java index 129b493ef..4e42fc0b6 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/preferences/ProcessPropertyPage.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/preferences/ProcessPropertyPage.java @@ -93,33 +93,24 @@ public class ProcessPropertyPage extends PropertyPage { ((GridData)text.getLayoutData()).horizontalIndent = 10; String commandLineText = getCommandLineText(proc); if (commandLineText != null) { - final String[] arguments = DebugPlugin.parseArguments(commandLineText); - StringBuffer renderedCommandLine = new StringBuffer(commandLineText.length()); - for (int i = 0; i < arguments.length; i++) { - if (i > 0) - renderedCommandLine.append(' '); - renderedCommandLine.append(arguments[i]); - } - text.addSegmentListener(new SegmentListener() { - public void getSegments(SegmentEvent event) { - int count = arguments.length; - if (count < 2) - return; - - int[] segments = new int[count - 1]; - int nextStart = arguments[0].length() + 1; - for (int i = 1; i < count; i++) { - segments[i - 1] = nextStart; - nextStart = nextStart + arguments[i].length() + 1; + String[] arguments = DebugPlugin.parseArguments(commandLineText); + int count = arguments.length; + if (count > 1) { + // render as one argument per line, but don't copy line delimiters to clipboard: + final int[] segments = new int[count - 1]; + final char[] chars = new char[count - 1]; + Arrays.fill(chars, '\n'); + + commandLineText = DebugPlugin.renderArguments(arguments, segments); + + text.addSegmentListener(new SegmentListener() { + public void getSegments(SegmentEvent event) { + event.segments = segments; + event.segmentsChars = chars; } - event.segments = segments; - - char[] chars = new char[count - 1]; - Arrays.fill(chars, '\n'); - event.segmentsChars = chars; - } - }); - text.setText(renderedCommandLine.toString()); + }); + } + text.setText(commandLineText); } //create environment section |