gt:         Element run = doc.getCharacterElement(getCaretPosition());
context: /*
   * Copyright (c) 1997, 2008, 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 javax.swing;
  
  import java.awt.*;
  import java.awt.event.ActionEvent;
  
  import java.io.ObjectOutputStream;
  import java.io.ObjectInputStream;
  import java.io.IOException;
  
  import javax.swing.text.*;
  import javax.swing.event.*;
  import javax.swing.plaf.*;
  
  /**
   * A text component that can be marked up with attributes that are
   * represented graphically.
   * You can find how-to information and examples of using text panes in
   * <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/text.html">Using Text Components</a>,
   * a section in <em>The Java Tutorial.</em>
   *
   * <p>
   * This component models paragraphs
   * that are composed of runs of character level attributes.  Each
   * paragraph may have a logical style attached to it which contains
   * the default attributes to use if not overridden by attributes set
   * on the paragraph or character run.  Components and images may
   * be embedded in the flow of text.
   * <p>
   * <dl>
   * <dt><b><font size=+1>Newlines</font></b>
   * <dd>
   * For a discussion on how newlines are handled, see
   * <a href="text/DefaultEditorKit.html">DefaultEditorKit</a>.
   * </dl>
   *
   * <p>
   * <strong>Warning:</strong> Swing is not thread safe. For more
   * information see <a
   * href="package-summary.html#threading">Swing's Threading
   * Policy</a>.
   * <p>
   * <strong>Warning:</strong>
   * Serialized objects of this class will not be compatible with
   * future Swing releases. The current serialization support is
   * appropriate for short term storage or RMI between applications running
   * the same version of Swing.  As of 1.4, support for long term storage
   * of all JavaBeans<sup><font size="-2">TM</font></sup>
   * has been added to the <code>java.beans</code> package.
   * Please see {@link java.beans.XMLEncoder}.
   *
   * @beaninfo
   *   attribute: isContainer true
   * description: A text component that can be marked up with attributes that are graphically represented.
   *
   * @author  Timothy Prinzing
   * @see javax.swing.text.StyledEditorKit
   */
  public class JTextPane extends JEditorPane {
  
      /**
       * Creates a new <code>JTextPane</code>.  A new instance of
       * <code>StyledEditorKit</code> is
       * created and set, and the document model set to <code>null</code>.
       */
      public JTextPane() {
          super();
          EditorKit editorKit = createDefaultEditorKit();
          String contentType = editorKit.getContentType();
          if (contentType != null
              && getEditorKitClassNameForContentType(contentType) ==
                   defaultEditorKitMap.get(contentType)) {
              setEditorKitForContentType(contentType, editorKit);
          }
          setEditorKit(editorKit);
      }
  
      /**
       * Creates a new <code>JTextPane</code>, with a specified document model.
       * A new instance of <code>javax.swing.text.StyledEditorKit</code>
       *  is created and set.
       *
       * @param doc the document model
       */
      public JTextPane(StyledDocument doc) {
          this();
          setStyledDocument(doc);
      }
  
      /**
       * Returns the class ID for the UI.
       *
       * @return the string "TextPaneUI"
       *
       * @see JComponent#getUIClassID
       * @see UIDefaults#getUI
       */
      public String getUIClassID() {
          return uiClassID;
      }
  
      /**
       * Associates the editor with a text document.  This
       * must be a <code>StyledDocument</code>.
       *
       * @param doc  the document to display/edit
       * @exception IllegalArgumentException  if <code>doc</code> can't
       *   be narrowed to a <code>StyledDocument</code> which is the
       *   required type of model for this text component
       */
      public void setDocument(Document doc) {
          if (doc instanceof StyledDocument) {
              super.setDocument(doc);
          } else {
              throw new IllegalArgumentException("Model must be StyledDocument");
          }
      }
  
      /**
       * Associates the editor with a text document.
       * The currently registered factory is used to build a view for
       * the document, which gets displayed by the editor.
       *
       * @param doc  the document to display/edit
       */
      public void setStyledDocument(StyledDocument doc) {
          super.setDocument(doc);
      }
  
      /**
       * Fetches the model associated with the editor.
       *
       * @return the model
       */
      public StyledDocument getStyledDocument() {
          return (StyledDocument) getDocument();
      }
  
      /**
       * Replaces the currently selected content with new content
       * represented by the given string.  If there is no selection
       * this amounts to an insert of the given text.  If there
       * is no replacement text this amounts to a removal of the
       * current selection.  The replacement text will have the
       * attributes currently defined for input at the point of
       * insertion.  If the document is not editable, beep and return.
       *
       * @param content  the content to replace the selection with
       */
      @Override
      public void replaceSelection(String content) {
          replaceSelection(content, true);
      }
  
      private void replaceSelection(String content, boolean checkEditable) {
          if (checkEditable && !isEditable()) {
              UIManager.getLookAndFeel().provideErrorFeedback(JTextPane.this);
              return;
          }
          Document doc = getStyledDocument();
          if (doc != null) {
              try {
                  Caret caret = getCaret();
                  boolean composedTextSaved = saveComposedText(caret.getDot());
                  int p0 = Math.min(caret.getDot(), caret.getMark());
                  int p1 = Math.max(caret.getDot(), caret.getMark());
                  AttributeSet attr = getInputAttributes().copyAttributes();
                  if (doc instanceof AbstractDocument) {
                      ((AbstractDocument)doc).replace(p0, p1 - p0, content,attr);
                  }
                  else {
                      if (p0 != p1) {
                          doc.remove(p0, p1 - p0);
                      }
                      if (content != null && content.length() > 0) {
                          doc.insertString(p0, content, attr);
                      }
                  }
                  if (composedTextSaved) {
                      restoreComposedText();
                  }
              } catch (BadLocationException e) {
                  UIManager.getLookAndFeel().provideErrorFeedback(JTextPane.this);
              }
          }
      }
  
      /**
       * Inserts a component into the document as a replacement
       * for the currently selected content.  If there is no
       * selection the component is effectively inserted at the
       * current position of the caret.  This is represented in
       * the associated document as an attribute of one character
       * of content.
       * <p>
       * The component given is the actual component used by the
       * JTextPane.  Since components cannot be a child of more than
       * one container, this method should not be used in situations
       * where the model is shared by text components.
       * <p>
       * The component is placed relative to the text baseline
       * according to the value returned by
       * <code>Component.getAlignmentY</code>.  For Swing components
       * this value can be conveniently set using the method
       * <code>JComponent.setAlignmentY</code>.  For example, setting
       * a value of <code>0.75</code> will cause 75 percent of the
       * component to be above the baseline, and 25 percent of the
       * component to be below the baseline.
       *
       * @param c    the component to insert
       */
      public void insertComponent(Component c) {
          MutableAttributeSet inputAttributes = getInputAttributes();
          inputAttributes.removeAttributes(inputAttributes);
          StyleConstants.setComponent(inputAttributes, c);
          replaceSelection(" ", false);
          inputAttributes.removeAttributes(inputAttributes);
      }
  
      /**
       * Inserts an icon into the document as a replacement
       * for the currently selected content.  If there is no
       * selection the icon is effectively inserted at the
       * current position of the caret.  This is represented in
       * the associated document as an attribute of one character
       * of content.
       *
       * @param g    the icon to insert
       * @see Icon
       */
      public void insertIcon(Icon g) {
          MutableAttributeSet inputAttributes = getInputAttributes();
          inputAttributes.removeAttributes(inputAttributes);
          StyleConstants.setIcon(inputAttributes, g);
          replaceSelection(" ", false);
          inputAttributes.removeAttributes(inputAttributes);
      }
  
      /**
       * Adds a new style into the logical style hierarchy.  Style attributes
       * resolve from bottom up so an attribute specified in a child
       * will override an attribute specified in the parent.
       *
       * @param nm   the name of the style (must be unique within the
       *   collection of named styles).  The name may be <code>null</code>
       *   if the style is unnamed, but the caller is responsible
       *   for managing the reference returned as an unnamed style can't
       *   be fetched by name.  An unnamed style may be useful for things
       *   like character attribute overrides such as found in a style
       *   run.
       * @param parent the parent style.  This may be <code>null</code>
       *   if unspecified
       *   attributes need not be resolved in some other style.
       * @return the new <code>Style</code>
       */
      public Style addStyle(String nm, Style parent) {
          StyledDocument doc = getStyledDocument();
          return doc.addStyle(nm, parent);
      }
  
      /**
       * Removes a named non-<code>null</code> style previously added to
       * the document.
       *
       * @param nm  the name of the style to remove
       */
      public void removeStyle(String nm) {
          StyledDocument doc = getStyledDocument();
          doc.removeStyle(nm);
      }
  
      /**
       * Fetches a named non-<code>null</code> style previously added.
       *
       * @param nm  the name of the style
       * @return the <code>Style</code>
       */
      public Style getStyle(String nm) {
          StyledDocument doc = getStyledDocument();
          return doc.getStyle(nm);
      }
  
      /**
       * Sets the logical style to use for the paragraph at the
       * current caret position.  If attributes aren't explicitly set
       * for character and paragraph attributes they will resolve
       * through the logical style assigned to the paragraph, which
       * in term may resolve through some hierarchy completely
       * independent of the element hierarchy in the document.
       *
       * @param s  the logical style to assign to the paragraph,
       *          or <code>null</code> for no style
       */
      public void setLogicalStyle(Style s) {
          StyledDocument doc = getStyledDocument();
          doc.setLogicalStyle(getCaretPosition(), s);
      }
  
      /**
       * Fetches the logical style assigned to the paragraph represented
       * by the current position of the caret, or <code>null</code>.
       *
       * @return the <code>Style</code>
       */
      public Style getLogicalStyle() {
          StyledDocument doc = getStyledDocument();
          return doc.getLogicalStyle(getCaretPosition());
      }
  
      /**
       * Fetches the character attributes in effect at the
       * current location of the caret, or <code>null</code>.
       *
       * @return the attributes, or <code>null</code>
       */
      public AttributeSet getCharacterAttributes() {
          StyledDocument doc = getStyledDocument();
  