@Override
  protected Transferable createTransferable(JComponent c) {
    JTextPane aTextPane = (JTextPane) c;

    HTMLEditorKit kit = ((HTMLEditorKit) aTextPane.getEditorKit());
    StyledDocument sdoc = aTextPane.getStyledDocument();
    int sel_start = aTextPane.getSelectionStart();
    int sel_end = aTextPane.getSelectionEnd();

    int i = sel_start;
    StringBuilder output = new StringBuilder();
    while (i < sel_end) {
      Element e = sdoc.getCharacterElement(i);
      Object nameAttr = e.getAttributes().getAttribute(StyleConstants.NameAttribute);
      int start = e.getStartOffset(), end = e.getEndOffset();
      if (nameAttr == HTML.Tag.BR) {
        output.append("\n");
      } else if (nameAttr == HTML.Tag.CONTENT) {
        if (start < sel_start) {
          start = sel_start;
        }
        if (end > sel_end) {
          end = sel_end;
        }
        try {
          String str = sdoc.getText(start, end - start);
          output.append(str);
        } catch (BadLocationException ble) {
          Debug.error(me + "Copy-paste problem!\n%s", ble.getMessage());
        }
      }
      i = end;
    }
    return new StringSelection(output.toString());
  }
  public EditorConsolePane() {
    super();
    textArea = new JTextPane();
    textArea.setEditorKit(new HTMLEditorKit());
    textArea.setTransferHandler(new JTextPaneHTMLTransferHandler());
    String css = PreferencesUser.getInstance().getConsoleCSS();
    ((HTMLEditorKit) textArea.getEditorKit()).getStyleSheet().addRule(css);
    textArea.setEditable(false);

    setLayout(new BorderLayout());
    add(new JScrollPane(textArea), BorderLayout.CENTER);

    if (ENABLE_IO_REDIRECT) {
      Debug.log(3, "EditorConsolePane: starting redirection to message area");
      int npipes = 2;
      NUM_PIPES = npipes * ScriptRunner.scriptRunner.size();
      pin = new PipedInputStream[NUM_PIPES];
      reader = new Thread[NUM_PIPES];
      for (int i = 0; i < NUM_PIPES; i++) {
        pin[i] = new PipedInputStream();
      }

      int irunner = 0;
      for (IScriptRunner srunner : ScriptRunner.scriptRunner.values()) {
        Debug.log(3, "EditorConsolePane: redirection for %s", srunner.getName());
        if (srunner.doSomethingSpecial(
            "redirect", Arrays.copyOfRange(pin, irunner * npipes, irunner * npipes + 2))) {
          Debug.log(3, "EditorConsolePane: redirection success for %s", srunner.getName());
          quit = false; // signals the Threads that they should exit
          // TODO Hack to avoid repeated redirect of stdout/err
          ScriptRunner.systemRedirected = true;

          // Starting two seperate threads to read from the PipedInputStreams
          for (int i = irunner * npipes; i < irunner * npipes + npipes; i++) {
            reader[i] = new Thread(this);
            reader[i].setDaemon(true);
            reader[i].start();
          }
          irunner++;
        }
      }
    }

    // Create the popup menu.
    popup = new JPopupMenu();
    JMenuItem menuItem = new JMenuItem("Clear messages");
    // Add ActionListener that clears the textArea
    menuItem.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            textArea.setText("");
          }
        });
    popup.add(menuItem);

    // Add listener to components that can bring up popup menus.
    MouseListener popupListener = new PopupListener(popup);
    textArea.addMouseListener(popupListener);
  }
 private void appendMsg(String msg) {
   HTMLDocument doc = (HTMLDocument) textArea.getDocument();
   HTMLEditorKit kit = (HTMLEditorKit) textArea.getEditorKit();
   try {
     kit.insertHTML(doc, doc.getLength(), msg, 0, 0, null);
   } catch (Exception e) {
     Debug.error(me + "Problem appending text to message area!\n%s", e.getMessage());
   }
 }