diff --git a/src/share/classes/javax/swing/text/DefaultStyledDocument.java b/src/share/classes/javax/swing/text/DefaultStyledDocument.java index 79da253623ddbd0776df033ec4b4017a99b05a96..938fd84f2b7cb21d7625a25e69175865d11d9a15 100644 --- a/src/share/classes/javax/swing/text/DefaultStyledDocument.java +++ b/src/share/classes/javax/swing/text/DefaultStyledDocument.java @@ -25,15 +25,12 @@ package javax.swing.text; import java.awt.Color; -import java.awt.Component; import java.awt.Font; -import java.awt.FontMetrics; import java.awt.font.TextAttribute; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.Enumeration; import java.util.HashMap; -import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Stack; @@ -41,15 +38,14 @@ import java.util.Vector; import java.util.ArrayList; import java.io.IOException; import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; -import javax.swing.Icon; import javax.swing.event.*; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoableEdit; import javax.swing.SwingUtilities; +import static sun.swing.SwingUtilities2.IMPLIED_CR; /** * A document that can be marked up with character and paragraph @@ -782,9 +778,18 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc // Check for the composed text element. If it is, merge the character attributes // into this element as well. if (Utilities.isComposedTextAttributeDefined(attr)) { - ((MutableAttributeSet)attr).addAttributes(cattr); - ((MutableAttributeSet)attr).addAttribute(AbstractDocument.ElementNameAttribute, - AbstractDocument.ContentElementName); + MutableAttributeSet mattr = (MutableAttributeSet) attr; + mattr.addAttributes(cattr); + mattr.addAttribute(AbstractDocument.ElementNameAttribute, + AbstractDocument.ContentElementName); + + // Assure that the composed text element is named properly + // and doesn't have the CR attribute defined. + mattr.addAttribute(StyleConstants.NameAttribute, + AbstractDocument.ContentElementName); + if (mattr.isDefined(IMPLIED_CR)) { + mattr.removeAttribute(IMPLIED_CR); + } } ElementSpec[] spec = new ElementSpec[parseBuffer.size()]; diff --git a/src/share/classes/javax/swing/text/GlyphView.java b/src/share/classes/javax/swing/text/GlyphView.java index abb46de25848f8bacbde90545a5e1345084be46c..72487eafc2b93388d86deebd11db3d3cfdc57987 100644 --- a/src/share/classes/javax/swing/text/GlyphView.java +++ b/src/share/classes/javax/swing/text/GlyphView.java @@ -32,6 +32,7 @@ import java.util.Locale; import javax.swing.UIManager; import sun.swing.SwingUtilities2; +import static sun.swing.SwingUtilities2.IMPLIED_CR; /** * A GlyphView is a styled chunk of text that represents a view @@ -1061,7 +1062,6 @@ public class GlyphView extends View implements TabableView, Cloneable { int length; // if it is an implied newline character boolean impliedCR; - private static final String IMPLIED_CR = "CR"; boolean skipWidth; /** diff --git a/src/share/classes/javax/swing/text/html/HTMLDocument.java b/src/share/classes/javax/swing/text/html/HTMLDocument.java index 5443ede76eb79d664c89f05f5114bf2aa1b38e59..d489b487d2727265287f894d4f5fcc65b10b6a90 100644 --- a/src/share/classes/javax/swing/text/html/HTMLDocument.java +++ b/src/share/classes/javax/swing/text/html/HTMLDocument.java @@ -24,20 +24,17 @@ */ package javax.swing.text.html; -import java.awt.Color; -import java.awt.Component; import java.awt.font.TextAttribute; import java.util.*; import java.net.URL; -import java.net.URLEncoder; import java.net.MalformedURLException; import java.io.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.undo.*; -import java.text.Bidi; import sun.swing.SwingUtilities2; +import static sun.swing.SwingUtilities2.IMPLIED_CR; /** * A document that models HTML. The purpose of this model is to @@ -1819,7 +1816,6 @@ public class HTMLDocument extends DefaultStyledDocument { static String MAP_PROPERTY = "__MAP__"; private static char[] NEWLINE; - private static final String IMPLIED_CR = "CR"; /** * I18N property key. diff --git a/src/share/classes/sun/swing/SwingUtilities2.java b/src/share/classes/sun/swing/SwingUtilities2.java index 6358d9870bb08b2b347a06608415be34dfd6445a..d1385316d449efbeba2ce72702487c63b3298a26 100644 --- a/src/share/classes/sun/swing/SwingUtilities2.java +++ b/src/share/classes/sun/swing/SwingUtilities2.java @@ -108,6 +108,12 @@ public class SwingUtilities2 { public static final Object AA_TEXT_PROPERTY_KEY = new StringBuffer("AATextInfoPropertyKey"); + /** + * Attribute key for the content elements. If it is set on an element, the + * element is considered to be a line break. + */ + public static final String IMPLIED_CR = "CR"; + /** * Used to tell a text component, being used as an editor for table * or tree, how many clicks it took to start editing. diff --git a/test/javax/swing/text/DefaultStyledDocument/6636983/bug6636983.java b/test/javax/swing/text/DefaultStyledDocument/6636983/bug6636983.java new file mode 100644 index 0000000000000000000000000000000000000000..15619c9909f85bfcfbb8df702272cae971ff141e --- /dev/null +++ b/test/javax/swing/text/DefaultStyledDocument/6636983/bug6636983.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010, 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 6636983 + * @summary test that composed text at the line starts is handled correctly + * @author Sergey Groznyh + * @run main bug6636983 + */ + +import sun.swing.SwingUtilities2; + +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.text.html.HTMLDocument; +import java.awt.*; +import java.awt.event.InputMethodEvent; +import java.awt.event.KeyEvent; +import java.text.AttributedString; + +public class bug6636983 { + private Robot robot; + + private final AttributedString Hiragana_A = new AttributedString("\u3042"); + + void sendInputMethodEvent() { + InputMethodEvent ime = new InputMethodEvent( + ep, + InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, + Hiragana_A.getIterator(), + 0, + null, + null); + ep.dispatchEvent(ime); + } + + void checkComposedTextRun() { + HTMLDocument d = (HTMLDocument) ep.getDocument(); + ElementIterator it = new ElementIterator(d.getDefaultRootElement()); + + while (true) { + Element e = it.next(); + if (e == null) { + throw new RuntimeException("no composed text found"); + } + AttributeSet a = e.getAttributes(); + if (a.isDefined(StyleConstants.ComposedTextAttribute)) { + if (!AbstractDocument.ContentElementName.equals(a.getAttribute(StyleConstants.NameAttribute))) { + throw new RuntimeException("AbstractDocument.ContentElementName.equals(a.getAttribute(StyleConstants.NameAttribute)) is false"); + } + + if (a.isDefined(SwingUtilities2.IMPLIED_CR)) { + throw new RuntimeException("a.isDefined(SwingUtilities2.IMPLIED_CR) is true"); + } + + return; + } + } + + } + + JEditorPane ep; + + void initAtParagraphStart() { + ep.setText("A

B"); + hitKey(KeyEvent.VK_LEFT); + } + + void sendAtParagraphStart() { + sendInputMethodEvent(); + } + + void checkAtParagraphStart() { + checkComposedTextRun(); + } + + void initAfterBRElement() { + ep.setText("A
B"); + hitKey(KeyEvent.VK_LEFT); + } + + void sendAtBRElement() { + sendInputMethodEvent(); + } + + void checkAtBrElement() { + checkComposedTextRun(); + } + + private void hitKey(int keycode) { + robot.keyPress(keycode); + robot.keyRelease(keycode); + robot.delay(550); // The magic number equals JRobot.DEFAULT_DELAY + } + + private void run() throws Exception { + robot = new Robot(); + + ep = new JEditorPane(); + ep.setContentType("text/html"); + ep.setPreferredSize(new Dimension(100, 100)); + + JFrame frame = new JFrame("Test: " + getClass().getName()); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(ep); + frame.setVisible(true); + } + + public static void main(String[] args) throws Throwable { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + bug6636983 bug6636983 = new bug6636983(); + + bug6636983.run(); + bug6636983.initAtParagraphStart(); + bug6636983.sendAtParagraphStart(); + bug6636983.checkAtParagraphStart(); + bug6636983.initAfterBRElement(); + bug6636983.sendAtBRElement(); + bug6636983.checkAtBrElement(); + + System.out.println("OK"); + } catch (Exception e) { + throw new RuntimeException("The test failed", e); + } + } + }); + } +}