diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinTextRangeProvider.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinTextRangeProvider.java index 61246b42605..db82424f9b8 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinTextRangeProvider.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinTextRangeProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ import static javafx.scene.AccessibleAttribute.*; import java.text.BreakIterator; + +import com.sun.javafx.util.Utils; import javafx.geometry.Bounds; import javafx.scene.AccessibleAction; import javafx.scene.AccessibleAttribute; @@ -98,8 +100,26 @@ private void validateRange(String text) { } int length = text.length(); - start = Math.max(0, Math.min(start, length)); - end = Math.max(start, Math.min(end, length)); + start = Utils.clamp(0, start, length); + end = Utils.clamp(start, end, length); + } + + /** + * In the context of substrings, this method calculates the end index based on the start index, + * requested string length, and the maximum end index. 0 <= start <= end <= length; + * see {@link #validateRange(String)}. + * + * @param startIndex The start index in a string. Needs to be 0 or more (not checked in the code). + * @param length The requested length of a string when starting from "start". + * Negative numbers are treated as full length. + * @param endIndex The maximum end index to return. Needs to be equal or greater than startIndex + * (not checked in the code). + */ + static int getEndIndex(int startIndex, int length, int endIndex) { + if (length < 0 || (endIndex - startIndex) <= length) { + return endIndex; + } + return startIndex + length; } void setRange(int start, int end) { @@ -358,11 +378,16 @@ private long GetEnclosingElement() { return accessible.getNativeAccessible(); } + /** + * Returns the text contained in the TEXT attribute, starting from the start index and ending at the end index. + * + * @param maxLength The maximum length of the returned string + */ private String GetText(int maxLength) { String text = (String)getAttribute(TEXT); if (text == null) return null; validateRange(text); - int endOffset = maxLength != -1 ? Math.min(end, start + maxLength) : end; + int endOffset = getEndIndex(start, maxLength, end); // System.out.println("+GetText [" + text.substring(start, endOffset)+"]"); return text.substring(start, endOffset); } diff --git a/modules/javafx.graphics/src/shims/java/com/sun/glass/ui/win/WinTextRangeProviderShim.java b/modules/javafx.graphics/src/shims/java/com/sun/glass/ui/win/WinTextRangeProviderShim.java new file mode 100644 index 00000000000..d0246a552c8 --- /dev/null +++ b/modules/javafx.graphics/src/shims/java/com/sun/glass/ui/win/WinTextRangeProviderShim.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.glass.ui.win; + +/** + * Provides access to the {@link WinTextRangeProvider} class by making its + * package-private fields and methods public for test cases in + * {@link test.com.sun.glass.ui.win.WinTextRangeProviderTest WinTextRangeProviderTest}. + */ +public class WinTextRangeProviderShim { + public static int getEndIndex(int start, int length, int maxEndIndex) { + return WinTextRangeProvider.getEndIndex(start, length, maxEndIndex); + } +} diff --git a/tests/system/src/test/.classpath b/tests/system/src/test/.classpath index 2ced868591c..3887b5741c0 100644 --- a/tests/system/src/test/.classpath +++ b/tests/system/src/test/.classpath @@ -14,7 +14,7 @@ - + diff --git a/tests/system/src/test/addExports b/tests/system/src/test/addExports index 8ed570ad6a2..d066db88f41 100644 --- a/tests/system/src/test/addExports +++ b/tests/system/src/test/addExports @@ -6,6 +6,7 @@ --add-exports javafx.graphics/com.sun.glass.ui=ALL-UNNAMED --add-exports javafx.graphics/com.sun.glass.ui.mac=ALL-UNNAMED --add-exports javafx.graphics/com.sun.glass.ui.monocle=ALL-UNNAMED +--add-exports javafx.graphics/com.sun.glass.ui.win=ALL-UNNAMED --add-exports javafx.graphics/com.sun.javafx.animation=ALL-UNNAMED --add-exports javafx.graphics/com.sun.javafx.application=ALL-UNNAMED --add-exports javafx.graphics/com.sun.javafx.css=ALL-UNNAMED diff --git a/tests/system/src/test/java/test/com/sun/glass/ui/win/WinTextRangeProviderTest.java b/tests/system/src/test/java/test/com/sun/glass/ui/win/WinTextRangeProviderTest.java new file mode 100644 index 00000000000..9c5b0ae8ed3 --- /dev/null +++ b/tests/system/src/test/java/test/com/sun/glass/ui/win/WinTextRangeProviderTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test.com.sun.glass.ui.win; + +import com.sun.javafx.PlatformUtil; +import com.sun.glass.ui.win.WinTextRangeProviderShim; + +import java.util.concurrent.CountDownLatch; +import java.util.stream.Stream; + +import test.util.Util; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class WinTextRangeProviderTest { + + private static final CountDownLatch startupLatch = new CountDownLatch(1); + + @BeforeAll + static void initFX() throws Exception { + assumeTrue(PlatformUtil.isWindows()); + Util.startup(startupLatch, () -> startupLatch.countDown()); + } + + @AfterAll + static void shutdown() { + assumeTrue(PlatformUtil.isWindows()); + Util.shutdown(); + } + + static Stream getEndIndexParameters() { + return Stream.of( + Arguments.of(1, 0, 1, 2), + Arguments.of(1, 0, 2, 1), + Arguments.of(55, 50, 10, 55), + Arguments.of(60, 50, 10, Integer.MAX_VALUE), + Arguments.of(1, 0, Integer.MAX_VALUE, 1), + Arguments.of(50, 50, Integer.MAX_VALUE, 50), + Arguments.of(Integer.MAX_VALUE, 0, Integer.MAX_VALUE, Integer.MAX_VALUE), + Arguments.of(60, 50, -1, 60), + Arguments.of(60, 50, Integer.MIN_VALUE, 60) + ); + } + + @ParameterizedTest + @MethodSource("getEndIndexParameters") + public void testGetEndIndex(Integer expected, Integer startIndex, Integer length, Integer maxEndIndex) { + assumeTrue(PlatformUtil.isWindows()); + assertEquals(expected, WinTextRangeProviderShim.getEndIndex(startIndex, length, maxEndIndex)); + } +}