From fcaa4c25fbdf83cbebe37bdf5bda4237cd53669f Mon Sep 17 00:00:00 2001 From: Christopher Hermann Date: Tue, 7 Jan 2025 10:45:10 +0100 Subject: [PATCH] Display.withCrLf() is producing wrong line breaks on Windows Replacing all line breaks on windows with CrLf using regex, which is much safer. Fixes #1557 --- .../org/eclipse/swt/widgets/Display.java | 79 ++----------------- .../Test_org_eclipse_swt_widgets_Display.java | 46 ++++++++--- 2 files changed, 41 insertions(+), 84 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index 100b47e6daf..70576d85cea 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -5152,85 +5152,16 @@ String wrapText (String text, long handle, int width) { } static String withCrLf (String string) { - - /* If the string is empty, return the string. */ - int length = string.length (); - if (length == 0) return string; - - /* - * Check for an LF or CR/LF and assume the rest of - * the string is formated that way. This will not - * work if the string contains mixed delimiters. - */ - int i = string.indexOf ('\n', 0); - if (i == -1) return string; - if (i > 0 && string.charAt (i - 1) == '\r') { + if (string == null) { return string; } - - /* - * The string is formatted with LF. Compute the - * number of lines and the size of the buffer - * needed to hold the result - */ - i++; - int count = 1; - while (i < length) { - if ((i = string.indexOf ('\n', i)) == -1) break; - count++; i++; - } - count += length; - - /* Create a new string with the CR/LF line terminator. */ - i = 0; - StringBuilder result = new StringBuilder (count); - while (i < length) { - int j = string.indexOf ('\n', i); - if (j == -1) j = length; - result.append (string.substring (i, j)); - if ((i = j) < length) { - result.append ("\r\n"); //$NON-NLS-1$ - i++; - } - } - return result.toString (); + // Replace \r\n, \r, or \n with \r\n + return string.replaceAll("(\r\n|\r|\n)", "\r\n"); } static char [] withCrLf (char [] string) { - /* If the string is empty, return the string. */ - int length = string.length; - if (length == 0) return string; - - /* - * Check for an LF or CR/LF and assume the rest of - * the string is formated that way. This will not - * work if the string contains mixed delimiters. - * Also, compute the number of lines. - */ - int count = 0; - for (int i = 0; i < string.length; i++) { - if (string [i] == '\n') { - count++; - if (count == 1 && i > 0 && string [i - 1] == '\r') return string; - } - } - if (count == 0) return string; - - /* - * The string is formatted with LF. - */ - count += length; - - /* Create a new string with the CR/LF line terminator. */ - char [] result = new char [count]; - for (int i = 0, j = 0; i < length && j < count; i++) { - if (string [i] == '\n') { - result [j++] = '\r'; - } - result [j++] = string [i]; - } - - return result; + String withCrLf = withCrLf(new String(string)); + return withCrLf.toCharArray(); } static boolean isActivateShellOnForceFocus() { diff --git a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/widgets/Test_org_eclipse_swt_widgets_Display.java b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/widgets/Test_org_eclipse_swt_widgets_Display.java index 316fec13d82..a3c9ff77fcc 100644 --- a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/widgets/Test_org_eclipse_swt_widgets_Display.java +++ b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/widgets/Test_org_eclipse_swt_widgets_Display.java @@ -13,26 +13,52 @@ *******************************************************************************/ package org.eclipse.swt.tests.win32.widgets; +import static org.junit.Assert.assertEquals; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.junit.After; +import org.junit.Before; import org.junit.Test; public class Test_org_eclipse_swt_widgets_Display { + private Display display; + private Shell shell; + + @Before + public void setup() { + display = new Display(); + shell = new Shell(display); + } + + @After + public void teardown() { + shell.dispose(); + display.dispose(); + } + @Test public void test_isXMouseActive() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Display display = new Display(); - try { - Method method = display.getClass().getDeclaredMethod("isXMouseActive"); - method.setAccessible(true); - - boolean xMouseActive = (boolean) method.invoke(display); - System.out.println("org.eclipse.swt.widgets.Display.isXMouseActive(): " + xMouseActive); - } finally { - display.dispose(); - } + Method method = display.getClass().getDeclaredMethod("isXMouseActive"); + method.setAccessible(true); + + boolean xMouseActive = (boolean) method.invoke(display); + System.out.println("org.eclipse.swt.widgets.Display.isXMouseActive(): " + xMouseActive); + } + + @Test + public void test_mixedLfAndCrfl() { + //Use text control for testing since Display.withCrLf() is package private + Text text = new Text(shell, SWT.None); + + text.setText("First Line \n second line \r\n third line"); + assertEquals("First Line \r\n second line \r\n third line", text.getText()); } }