Word like special font chooser : Font Chooser « Swing Components « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Collections Data Structure
8. Database SQL JDBC
9. Design Pattern
10. Development Class
11. Email
12. Event
13. File Input Output
14. Game
15. Hibernate
16. J2EE
17. J2ME
18. JDK 6
19. JSP
20. JSTL
21. Language Basics
22. Network Protocol
23. PDF RTF
24. Regular Expressions
25. Security
26. Servlets
27. Spring
28. Swing Components
29. Swing JFC
30. SWT JFace Eclipse
31. Threads
32. Tiny Application
33. Velocity
34. Web Services SOA
35. XML
Microsoft Office Word 2007 Tutorial
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java » Swing Components » Font ChooserScreenshots 
Word like special font chooser
 

/*
 * @(#)Font2DTest.java  1.28 05/11/17
 
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 
 * -Redistribution in binary form must reproduce the above copyright notice, 
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may 
 * be used to endorse or promote products derived from this software without 
 * specific prior written permission.
 
 * This software is provided "AS IS," without a warranty of any kind. ALL 
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST 
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY 
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */

/*
 * @(#)Font2DTest.java  1.28 05/11/17
 */

import static java.awt.RenderingHints.KEY_ANTIALIASING;
import static java.awt.RenderingHints.KEY_FRACTIONALMETRICS;
import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
import static java.awt.RenderingHints.KEY_TEXT_LCD_CONTRAST;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_OFF;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON;
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT;
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF;
import static java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_GASP;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterJob;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.AttributedString;
import java.util.BitSet;
import java.util.EnumSet;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Font2DTest.java
 
 @version
 * @(#)Font2DTest.java 1.2 00/08/22
 @author Shinsuke Fukuda
 @author Ankit Patel [Conversion to Swing - 01/07/30]
 */

// / Main Font2DTest Class
public final class Font2DTest extends JPanel implements ActionListener, ItemListener,
    ChangeListener {

  // / JFrame that will contain Font2DTest
  private final JFrame parent;

  // / FontPanel class that will contain all graphical output
  private final FontPanel fp;

  // / RangeMenu class that contains info about the unicode ranges
  private final RangeMenu rm;

  // / Other menus to set parameters for text drawing
  private final ChoiceV2 fontMenu;

  private final JTextField sizeField;

  private final ChoiceV2 styleMenu;

  private final ChoiceV2 textMenu;

  private int currentTextChoice = 0;

  private final ChoiceV2 transformMenu;

  private final ChoiceV2 transformMenuG2;

  private final ChoiceV2 methodsMenu;

  private final JComboBox antiAliasMenu;

  private final JComboBox fracMetricsMenu;

  private final JSlider contrastSlider;

  // / CheckboxMenuItems
  private CheckboxMenuItemV2 displayGridCBMI;

  private CheckboxMenuItemV2 force16ColsCBMI;

  private CheckboxMenuItemV2 showFontInfoCBMI;

  // / JDialog boxes
  private JDialog userTextDialog;

  private JTextArea userTextArea;

  private JDialog printDialog;

  private JDialog fontInfoDialog;

  private LabelV2 fontInfos[] new LabelV2[2];

  private JFileChooser filePromptDialog = null;

  private ButtonGroup printCBGroup;

  private JRadioButton printModeCBs[] new JRadioButton[3];

  // / Status bar
  private final LabelV2 statusBar;

  private int fontStyles[] Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC };

  // / Text filename
  private String tFileName;

  // Enabled or disabled status of canDisplay check
  private static boolean canDisplayCheck = true;

  // / Initialize GUI variables and its layouts
  public Font2DTest(JFrame f, boolean isApplet) {
    parent = f;

    rm = new RangeMenu(this, parent);
    fp = new FontPanel(this, parent);
    statusBar = new LabelV2("");

    fontMenu = new ChoiceV2(this, canDisplayCheck);
    sizeField = new JTextField("12"3);
    sizeField.addActionListener(this);
    styleMenu = new ChoiceV2(this);
    textMenu = new ChoiceV2()// listener added later
    transformMenu = new ChoiceV2(this);
    transformMenuG2 = new ChoiceV2(this);
    methodsMenu = new ChoiceV2(this);

    antiAliasMenu = new JComboBox(EnumSet.allOf(FontPanel.AAValues.class).toArray());
    antiAliasMenu.addActionListener(this);
    fracMetricsMenu = new JComboBox(EnumSet.allOf(FontPanel.FMValues.class).toArray());
    fracMetricsMenu.addActionListener(this);

    contrastSlider = new JSlider(JSlider.HORIZONTAL, 100250, FontPanel.getDefaultLCDContrast()
        .intValue());
    contrastSlider.setEnabled(false);
    contrastSlider.setMajorTickSpacing(20);
    contrastSlider.setMinorTickSpacing(10);
    contrastSlider.setPaintTicks(true);
    contrastSlider.setPaintLabels(true);
    contrastSlider.addChangeListener(this);
    setupPanel();
    setupMenu(isApplet);
    setupDialog(isApplet);

    if (canDisplayCheck) {
      fireRangeChanged();
    }
  }

  // / Set up the main interface panel
  private void setupPanel() {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 1;
    gbc.insets = new Insets(2022);
    this.setLayout(gbl);

    addLabeledComponentToGBL("Font: ", fontMenu, gbl, gbc, this);
    addLabeledComponentToGBL("Size: ", sizeField, gbl, gbc, this);
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    addLabeledComponentToGBL("Font Transform:", transformMenu, gbl, gbc, this);
    gbc.gridwidth = 1;

    addLabeledComponentToGBL("Range: ", rm, gbl, gbc, this);
    addLabeledComponentToGBL("Style: ", styleMenu, gbl, gbc, this);
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    addLabeledComponentToGBL("Graphics Transform: ", transformMenuG2, gbl, gbc, this);
    gbc.gridwidth = 1;

    gbc.anchor = GridBagConstraints.WEST;
    addLabeledComponentToGBL("Method: ", methodsMenu, gbl, gbc, this);
    addLabeledComponentToGBL("", null, gbl, gbc, this);
    gbc.anchor = GridBagConstraints.EAST;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    addLabeledComponentToGBL("Text to use:", textMenu, gbl, gbc, this);

    gbc.weightx = 1;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.anchor = GridBagConstraints.WEST;
    addLabeledComponentToGBL("LCD contrast: ", contrastSlider, gbl, gbc, this);

    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.NONE;
    addLabeledComponentToGBL("Antialiasing: ", antiAliasMenu, gbl, gbc, this);

    gbc.anchor = GridBagConstraints.EAST;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    addLabeledComponentToGBL("Fractional metrics: ", fracMetricsMenu, gbl, gbc, this);

    gbc.weightx = 1;
    gbc.weighty = 1;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.insets = new Insets(2002);
    gbc.fill = GridBagConstraints.BOTH;
    gbl.setConstraints(fp, gbc);
    this.add(fp);

    gbc.weighty = 0;
    gbc.insets = new Insets(0200);
    gbl.setConstraints(statusBar, gbc);
    this.add(statusBar);
  }

  // / Adds a component to a container with a label to its left in GridBagLayout
  private void addLabeledComponentToGBL(String name, JComponent c, GridBagLayout gbl,
      GridBagConstraints gbc, Container target) {
    LabelV2 l = new LabelV2(name);
    GridBagConstraints gbcLabel = (GridBagConstraintsgbc.clone();
    gbcLabel.insets = new Insets(2220);
    gbcLabel.gridwidth = 1;
    gbcLabel.weightx = 0;

    if (c == null)
      c = new JLabel("");

    gbl.setConstraints(l, gbcLabel);
    target.add(l);
    gbl.setConstraints(c, gbc);
    target.add(c);
  }

  // / Sets up menu entries
  private void setupMenu(boolean isApplet) {
    JMenu fileMenu = new JMenu("File");
    JMenu optionMenu = new JMenu("Option");

    fileMenu.add(new MenuItemV2("Save Selected Options..."this));
    fileMenu.add(new MenuItemV2("Load Options..."this));
    fileMenu.addSeparator();
    fileMenu.add(new MenuItemV2("Save as PNG..."this));
    fileMenu.add(new MenuItemV2("Load PNG File to Compare..."this));
    fileMenu.add(new MenuItemV2("Page Setup..."this));
    fileMenu.add(new MenuItemV2("Print..."this));
    fileMenu.addSeparator();
    if (!isApplet)
      fileMenu.add(new MenuItemV2("Exit"this));
    else
      fileMenu.add(new MenuItemV2("Close"this));

    displayGridCBMI = new CheckboxMenuItemV2("Display Grid", true, this);
    force16ColsCBMI = new CheckboxMenuItemV2("Force 16 Columns", false, this);
    showFontInfoCBMI = new CheckboxMenuItemV2("Display Font Info", false, this);
    optionMenu.add(displayGridCBMI);
    optionMenu.add(force16ColsCBMI);
    optionMenu.add(showFontInfoCBMI);

    JMenuBar mb = parent.getJMenuBar();
    if (mb == null)
      mb = new JMenuBar();
    mb.add(fileMenu);
    mb.add(optionMenu);

    parent.setJMenuBar(mb);

    String fontList[] = GraphicsEnvironment.getLocalGraphicsEnvironment()
        .getAvailableFontFamilyNames();

    for (int i = 0; i < fontList.length; i++)
      fontMenu.addItem(fontList[i]);
    fontMenu.setSelectedItem("Dialog");

    styleMenu.addItem("Plain");
    styleMenu.addItem("Bold");
    styleMenu.addItem("Italic");
    styleMenu.addItem("Bold Italic");

    transformMenu.addItem("None");
    transformMenu.addItem("Scale");
    transformMenu.addItem("Shear");
    transformMenu.addItem("Rotate");

    transformMenuG2.addItem("None");
    transformMenuG2.addItem("Scale");
    transformMenuG2.addItem("Shear");
    transformMenuG2.addItem("Rotate");

    methodsMenu.addItem("drawString");
    methodsMenu.addItem("drawChars");
    methodsMenu.addItem("drawBytes");
    methodsMenu.addItem("drawGlyphVector");
    methodsMenu.addItem("TextLayout.draw");
    methodsMenu.addItem("GlyphVector.getOutline + draw");
    methodsMenu.addItem("TextLayout.getOutline + draw");

    textMenu.addItem("Unicode Range");
    textMenu.addItem("All Glyphs");
    textMenu.addItem("User Text");
    textMenu.addItem("Text File");
    textMenu.addActionListener(this)// listener added later so unneeded events
                                      // not thrown
  }

  // / Sets up the all dialogs used in Font2DTest...
  private void setupDialog(boolean isApplet) {
    if (!isApplet)
      filePromptDialog = new JFileChooser();
    else
      filePromptDialog = null;

    // / Prepare user text dialog...
    userTextDialog = new JDialog(parent, "User Text"false);
    JPanel dialogTopPanel = new JPanel();
    JPanel dialogBottomPanel = new JPanel();
    LabelV2 message1 = new LabelV2("Enter text below and then press update");
    LabelV2 message2 = new LabelV2("(Unicode char can be denoted by \\uXXXX)");
    LabelV2 message3 = new LabelV2("(Supplementary chars can be denoted by \\UXXXXXX)");
    userTextArea = new JTextArea("Java2D!");
    ButtonV2 bUpdate = new ButtonV2("Update"this);
    userTextArea.setFont(new Font("dialog", Font.PLAIN, 12));
    dialogTopPanel.setLayout(new GridLayout(31));
    dialogTopPanel.add(message1);
    dialogTopPanel.add(message2);
    dialogTopPanel.add(message3);
    dialogBottomPanel.add(bUpdate);
    // ABP
    JScrollPane userTextAreaSP = new JScrollPane(userTextArea);
    userTextAreaSP.setPreferredSize(new Dimension(300100));

    userTextDialog.getContentPane().setLayout(new BorderLayout());
    userTextDialog.getContentPane().add("North", dialogTopPanel);
    userTextDialog.getContentPane().add("Center", userTextAreaSP);
    userTextDialog.getContentPane().add("South", dialogBottomPanel);
    userTextDialog.pack();
    userTextDialog.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        userTextDialog.hide();
      }
    });

    // / Prepare printing dialog...
    printCBGroup = new ButtonGroup();
    printModeCBs[fp.ONE_PAGEnew JRadioButton(
        "Print one page from currently displayed character/line"true);
    printModeCBs[fp.CUR_RANGEnew JRadioButton(
        "Print all characters in currently selected range"false);
    printModeCBs[fp.ALL_TEXTnew JRadioButton("Print all lines of text"false);
    LabelV2 l = new LabelV2(
        "Note: Page range in native \"Print\" dialog will not affect the result");
    JPanel buttonPanel = new JPanel();
    printModeCBs[fp.ALL_TEXT].setEnabled(false);
    buttonPanel.add(new ButtonV2("Print"this));
    buttonPanel.add(new ButtonV2("Cancel"this));

    printDialog = new JDialog(parent, "Print..."true);
    printDialog.setResizable(false);
    printDialog.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        printDialog.hide();
      }
    });
    printDialog.getContentPane().setLayout(new GridLayout(printModeCBs.length + 21));
    printDialog.getContentPane().add(l);
    for (int i = 0; i < printModeCBs.length; i++) {
      printCBGroup.add(printModeCBs[i]);
      printDialog.getContentPane().add(printModeCBs[i]);
    }
    printDialog.getContentPane().add(buttonPanel);
    printDialog.pack();

    // / Prepare font information dialog...
    fontInfoDialog = new JDialog(parent, "Font info"false);
    fontInfoDialog.setResizable(false);
    fontInfoDialog.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        fontInfoDialog.hide();
        showFontInfoCBMI.setState(false);
      }
    });
    JPanel fontInfoPanel = new JPanel();
    fontInfoPanel.setLayout(new GridLayout(fontInfos.length, 1));
    for (int i = 0; i < fontInfos.length; i++) {
      fontInfos[inew LabelV2("");
      fontInfoPanel.add(fontInfos[i]);
    }
    fontInfoDialog.getContentPane().add(fontInfoPanel);

    // / Move the location of the dialog...
    userTextDialog.setLocation(200300);
    fontInfoDialog.setLocation(0400);
  }

  // / RangeMenu object signals using this function
  // / when Unicode range has been changed and text needs to be redrawn
  public void fireRangeChanged() {
    int range[] = rm.getSelectedRange();
    fp.setTextToDraw(fp.RANGE_TEXT, range, null, null);
    if (canDisplayCheck) {
      setupFontList(range[0], range[1]);
    }
    if (showFontInfoCBMI.getState())
      fireUpdateFontInfo();
  }

  // / Changes the message on the status bar
  public void fireChangeStatus(String message, boolean error) {
    // / If this is not ran as an applet, use own status bar,
    // / Otherwise, use the appletviewer/browser's status bar
    statusBar.setText(message);
    if (error)
      fp.showingError = true;
    else
      fp.showingError = false;
  }

  // / Updates the information about the selected font
  public void fireUpdateFontInfo() {
    if (showFontInfoCBMI.getState()) {
      String infos[] = fp.getFontInfo();
      for (int i = 0; i < fontInfos.length; i++)
        fontInfos[i].setText(infos[i]);
      fontInfoDialog.pack();
    }
  }

  private void setupFontList(int rangeStart, int rangeEnd) {

    int listCount = fontMenu.getItemCount();
    int size = 16;

    try {
      size = Float.valueOf(sizeField.getText()).intValue();
    catch (Exception e) {
      System.out.println("Invalid font size in the size textField. Using default value of 16");
    }

    int style = fontStyles[styleMenu.getSelectedIndex()];
    Font f;
    for (int i = 0; i < listCount; i++) {
      String fontName = (StringfontMenu.getItemAt(i);
      f = new Font(fontName, style, size);
      if ((rm.getSelectedIndex() != RangeMenu.SURROGATES_AREA_INDEX)
          && canDisplayRange(f, rangeStart, rangeEnd)) {
        fontMenu.setBit(i, true);
      else {
        fontMenu.setBit(i, false);
      }
    }

    fontMenu.repaint();
  }

  protected boolean canDisplayRange(Font font, int rangeStart, int rangeEnd) {
    for (int i = rangeStart; i < rangeEnd; i++) {
      if (font.canDisplay(i)) {
        return true;
      }
    }
    return false;
  }

  // / Displays a file load/save dialog and returns the specified file
  private String promptFile(boolean isSave, String initFileName) {
    int retVal;
    String str;

    // / ABP
    if (filePromptDialog == null)
      return null;

    if (isSave) {
      filePromptDialog.setDialogType(JFileChooser.SAVE_DIALOG);
      filePromptDialog.setDialogTitle("Save...");
      str = "Save";

    else {
      filePromptDialog.setDialogType(JFileChooser.OPEN_DIALOG);
      filePromptDialog.setDialogTitle("Load...");
      str = "Load";
    }

    if (initFileName != null)
      filePromptDialog.setSelectedFile(new File(initFileName));
    retVal = filePromptDialog.showDialog(this, str);

    if (retVal == JFileChooser.APPROVE_OPTION) {
      File file = filePromptDialog.getSelectedFile();
      String fileName = file.getAbsolutePath();
      if (fileName != null) {
        return fileName;
      }
    }

    return null;
  }

  // / Converts user text into arrays of String, delimited at newline character
  // / Also replaces any valid escape sequence with appropriate unicode
  // character
  // / Support \\UXXXXXX notation for surrogates
  private String[] parseUserText(String orig) {
    int length = orig.length();
    StringTokenizer perLine = new StringTokenizer(orig, "\n");
    String textLines[] new String[perLine.countTokens()];
    int lineNumber = 0;

    while (perLine.hasMoreElements()) {
      StringBuffer converted = new StringBuffer();
      String oneLine = perLine.nextToken();
      int lineLength = oneLine.length();
      int prevEscapeEnd = 0;
      int nextEscape = -1;
      do {
        int nextBMPEscape = oneLine.indexOf("\\u", prevEscapeEnd);
        int nextSupEscape = oneLine.indexOf("\\U", prevEscapeEnd);