diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java index b43e5d24c6c..f785e24d9ab 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -83,6 +83,7 @@ public class BasicOptionPaneUI extends OptionPaneUI { public static final int MinimumHeight = 90; private static String newline; + private static int recursionCount; /** * JOptionPane that the receiver is providing the @@ -317,6 +318,7 @@ protected Container createMessageArea() { "OptionPane.messageAnchor", GridBagConstraints.CENTER); cons.insets = new Insets(0,0,3,0); + recursionCount = 0; addMessageComponents(body, cons, getMessage(), getMaxCharactersPerLineCount(), false); top.add(realBody, BorderLayout.CENTER); @@ -391,41 +393,75 @@ protected void addMessageComponents(Container container, } else if ((nl = s.indexOf('\n')) >= 0) { nll = 1; } - if (nl >= 0) { - // break up newlines - if (nl == 0) { - JPanel breakPanel = new JPanel() { - public Dimension getPreferredSize() { - Font f = getFont(); - - if (f != null) { - return new Dimension(1, f.getSize() + 2); - } - return new Dimension(0, 0); - } - }; - breakPanel.setName("OptionPane.break"); - addMessageComponents(container, cons, breakPanel, maxll, - true); - } else { - addMessageComponents(container, cons, s.substring(0, nl), - maxll, false); + if (s.contains("")) { + /* line break in html text is done by
tag + * and not by /n so it's incorrect to address newline + * same as non-html text. + * Text between tags are extracted + * and rendered as JLabel text + */ + int index1 = s.indexOf(""); + int index2 = s.indexOf(""); + String str = ""; + if (index2 >= 0) { + str = s.substring(index2 + "".length()); + s = s.substring(index1, index2 + + "".length()); } - addMessageComponents(container, cons, s.substring(nl + nll), maxll, - false); - - } else if (len > maxll) { - Container c = Box.createVerticalBox(); - c.setName("OptionPane.verticalBox"); - burstStringInto(c, s, maxll); - addMessageComponents(container, cons, c, maxll, true ); - - } else { JLabel label; - label = new JLabel( s, JLabel.LEADING ); + label = new JLabel(s, JLabel.LEADING); label.setName("OptionPane.label"); configureMessageLabel(label); addMessageComponents(container, cons, label, maxll, true); + if (!str.isEmpty()) { + addMessageComponents(container, cons, str, maxll, false); + } + } else { + if (nl >= 0) { + // break up newlines + if (nl == 0) { + @SuppressWarnings("serial") // anonymous class + JPanel breakPanel = new JPanel() { + public Dimension getPreferredSize() { + Font f = getFont(); + + if (f != null) { + return new Dimension(1, f.getSize() + 2); + } + return new Dimension(0, 0); + } + }; + breakPanel.setName("OptionPane.break"); + addMessageComponents(container, cons, breakPanel, maxll, + true); + } else { + addMessageComponents(container, cons, s.substring(0, nl), + maxll, false); + } + // Prevent recursion of more than + // 200 successive newlines in a message + // and indicate message is truncated via ellipsis + if (recursionCount++ > 200) { + recursionCount = 0; + addMessageComponents(container, cons, new String("..."), + maxll, false); + return; + } + addMessageComponents(container, cons, s.substring(nl + nll), maxll, + false); + + } else if (len > maxll) { + Container c = Box.createVerticalBox(); + c.setName("OptionPane.verticalBox"); + burstStringInto(c, s, maxll); + addMessageComponents(container, cons, c, maxll, true); + + } else { + JLabel label; + label = new JLabel(s, JLabel.LEADING); + label.setName("OptionPane.label"); + configureMessageLabel(label); + addMessageComponents(container, cons, label, maxll, true); + } } } } diff --git a/jdk/test/javax/swing/JOptionPane/TestJOptionHTMLTag.java b/jdk/test/javax/swing/JOptionPane/TestJOptionHTMLTag.java new file mode 100644 index 00000000000..df85ab33353 --- /dev/null +++ b/jdk/test/javax/swing/JOptionPane/TestJOptionHTMLTag.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022, 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. + * + * 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. + */ +/* @test + * @bug 5074006 + * @key headful + * @library /java/awt/regtesthelpers + * @library /test/lib + * @summary Swing JOptionPane shows tag as a string after newline + * @run main/manual TestJOptionHTMLTag +*/ + +import java.awt.BorderLayout; +import static java.awt.Dialog.ModalityType; + +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +import jtreg.SkippedException; + +public class TestJOptionHTMLTag { + static String instructions + = "INSTRUCTIONS:\n" + + " Read the text in the above panel.\n" + + " If it does not contain string, press Pass else press Fail.\n"; + + private static boolean passed = false; + private static boolean skipped = false; + private static Thread mainThread = Thread.currentThread(); + public static void main(String[] args) throws Exception { + + try { + SwingUtilities.invokeLater(() -> { + String message = "" + "This is a test\n" + "\n\n\n\n"; + JOptionPane optionPane = new JOptionPane(); + optionPane.setMessage(message); + optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); + optionPane.setOptions(new Object[]{"Pass", "Fail"}); + JDialog dialog = optionPane.createDialog("Test"); + dialog.setModalityType(ModalityType.TOOLKIT_MODAL); + dialog.setContentPane(optionPane); + + JTextArea textArea = new JTextArea(instructions); + textArea.setEditable(false); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + dialog.add(mainPanel); + dialog.pack(); + dialog.show(); + Object value = optionPane.getValue(); + if (value == null) { + skipped = true; + } else if (value.equals("Pass")) { + passed = true; + } + mainThread.interrupt(); + }); + Thread.sleep(10000); + } catch (InterruptedException e) { + if (passed) { + return; + } else if (!skipped) { + throw new RuntimeException("Test failed."); + } + } + throw new SkippedException("Test skipped."); + } +} + diff --git a/jdk/test/javax/swing/JOptionPane/TestOptionPaneStackOverflow.java b/jdk/test/javax/swing/JOptionPane/TestOptionPaneStackOverflow.java new file mode 100644 index 00000000000..9cfaea13755 --- /dev/null +++ b/jdk/test/javax/swing/JOptionPane/TestOptionPaneStackOverflow.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022, 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. + * + * 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. + */ + +/* @test + @bug 8224267 8290162 + @key headful + @summary Verifies if StackOverflowError is not thrown for multiple newlines + @run main TestOptionPaneStackOverflow + */ + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +public class TestOptionPaneStackOverflow +{ + static JFrame frame; + + public static void main(String[] argv) throws Exception + { + try { + String message = java.nio.CharBuffer.allocate(5000).toString(). + replace('\0','\n'); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + JOptionPane optionPane = new JOptionPane(); + optionPane.createDialog(frame, null); + optionPane.setMessage(message); + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +}