1 /*
   2  * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.ui;
  26 
  27 import java.io.*;
  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import javax.swing.*;
  31 import javax.swing.event.*;
  32 import javax.swing.text.*;
  33 
  34 import sun.jvm.hotspot.CommandProcessor;
  35 import sun.jvm.hotspot.debugger.*;
  36 import sun.jvm.hotspot.utilities.*;
  37 
  38 /** A JPanel subclass containing a scrollable text area displaying the
  39     debugger's console, if it has one. This should not be created for
  40     a debugger which does not have a console. */
  41 
  42 public class CommandProcessorPanel extends JPanel {
  43     private CommandProcessor commands;
  44     private JTextArea editor;
  45     private boolean updating;
  46     private int     mark;
  47     private String  curText;  // handles multi-line input via '\'
  48 
  49     // Don't run the "main" method of this class unless this flag is set to true first
  50     private static final boolean DEBUGGING = false;
  51 
  52     ByteArrayOutputStream baos = new ByteArrayOutputStream(10240);
  53 
  54 
  55     public CommandProcessorPanel(CommandProcessor cp) {
  56 
  57         commands = cp;
  58 
  59         setLayout(new BorderLayout());
  60 
  61         editor = new JTextArea();
  62         editor.setDocument(new EditableAtEndDocument());
  63         editor.setFont(GraphicsUtilities.lookupFont("Courier"));
  64         JScrollPane scroller = new JScrollPane();
  65         scroller.getViewport().add(editor);
  66         add(scroller, BorderLayout.CENTER);
  67 
  68         // Set up out
  69         PrintStream o = new PrintStream(baos, true);
  70         cp.setOutput(o);
  71         cp.setErr(o);
  72 
  73         editor.getDocument().addDocumentListener(new DocumentListener() {
  74                 public void changedUpdate(DocumentEvent e) {
  75                 }
  76 
  77                 public void insertUpdate(DocumentEvent e) {
  78                     if (updating) return;
  79                     beginUpdate();
  80                     editor.setCaretPosition(editor.getDocument().getLength());
  81                     if (insertContains(e, '\n')) {
  82                         String cmd = getMarkedText();
  83                         // Handle multi-line input
  84                         if ((cmd.length() == 0) || (cmd.charAt(cmd.length() - 1) != '\\')) {
  85                             // Trim "\\n" combinations
  86                             final String ln = trimContinuations(cmd);
  87                             SwingUtilities.invokeLater(new Runnable() {
  88                                     public void run() {
  89                                         beginUpdate();
  90                                         try {
  91                                             commands.executeCommand(ln);
  92                                             commands.printPrompt();
  93                                             Document d = editor.getDocument();
  94                                             try {
  95                                                 d.insertString(d.getLength(), baos.toString(), null);
  96                                             }
  97                                             catch (BadLocationException ble) {
  98                                                 ble.printStackTrace();
  99                                             }
 100                                             baos.reset();
 101                                             editor.setCaretPosition(editor.getDocument().getLength());
 102                                             setMark();
 103                                         } finally {
 104                                             endUpdate();
 105                                         }
 106                                     }
 107                                 });
 108                         }
 109                     } else {
 110                         endUpdate();
 111                     }
 112                 }
 113 
 114                 public void removeUpdate(DocumentEvent e) {
 115                 }
 116             });
 117 
 118         // This is a bit of a hack but is probably better than relying on
 119         // the JEditorPane to update the caret's position precisely the
 120         // size of the insertion
 121         editor.addCaretListener(new CaretListener() {
 122                 public void caretUpdate(CaretEvent e) {
 123                     int len = editor.getDocument().getLength();
 124                     if (e.getDot() > len) {
 125                         editor.setCaretPosition(len);
 126                     }
 127                 }
 128             });
 129 
 130         Box hbox = Box.createHorizontalBox();
 131         hbox.add(Box.createGlue());
 132         JButton button = new JButton("Clear Saved Text");
 133         button.addActionListener(new ActionListener() {
 134                 public void actionPerformed(ActionEvent e) {
 135                     clear();
 136                 }
 137             });
 138         hbox.add(button);
 139         hbox.add(Box.createGlue());
 140         add(hbox, BorderLayout.SOUTH);
 141 
 142         clear();
 143     }
 144 
 145     public void requestFocus() {
 146         editor.requestFocus();
 147     }
 148 
 149     public void clear() {
 150         EditableAtEndDocument d = (EditableAtEndDocument) editor.getDocument();
 151         d.clear();
 152         commands.executeCommand("");
 153         setMark();
 154         editor.requestFocus();
 155     }
 156 
 157     public void setMark() {
 158         ((EditableAtEndDocument) editor.getDocument()).setMark();
 159     }
 160 
 161     public String getMarkedText() {
 162         try {
 163             String s = ((EditableAtEndDocument) editor.getDocument()).getMarkedText();
 164             int i = s.length();
 165             while ((i > 0) && (s.charAt(i - 1) == '\n')) {
 166                 i--;
 167             }
 168             return s.substring(0, i);
 169         }
 170         catch (BadLocationException e) {
 171             e.printStackTrace();
 172             return null;
 173         }
 174     }
 175 
 176     //--------------------------------------------------------------------------------
 177     // Internals only below this point
 178     //
 179 
 180     private void beginUpdate() {
 181         updating = true;
 182     }
 183 
 184     private void endUpdate() {
 185         updating = false;
 186     }
 187 
 188     private boolean insertContains(DocumentEvent e, char c) {
 189         String s = null;
 190         try {
 191             s = editor.getText(e.getOffset(), e.getLength());
 192             for (int i = 0; i < e.getLength(); i++) {
 193                 if (s.charAt(i) == c) {
 194                     return true;
 195                 }
 196             }
 197         }
 198         catch (BadLocationException ex) {
 199             ex.printStackTrace();
 200         }
 201         return false;
 202     }
 203 
 204     private String trimContinuations(String text) {
 205         int i;
 206         while ((i = text.indexOf("\\\n")) >= 0) {
 207             text = text.substring(0, i) + text.substring(i+2, text.length());
 208         }
 209         return text;
 210     }
 211 
 212     public static void main(String[] args) {
 213         JFrame frame = new JFrame();
 214         frame.getContentPane().setLayout(new BorderLayout());
 215         CommandProcessorPanel panel = new CommandProcessorPanel(null);
 216         frame.getContentPane().add(panel, BorderLayout.CENTER);
 217         frame.addWindowListener(new WindowAdapter() {
 218                 public void windowClosing(WindowEvent e) {
 219                     System.exit(0);
 220                 }
 221             });
 222         frame.setSize(500, 500);
 223         frame.setVisible(true);
 224         panel.requestFocus();
 225     }
 226 }