/* $Id: ta.java,v 1.2 2002/08/01 04:17:15 comoc Exp $ */ /* * `gnu.iou' I/O buffers and utilities. * Copyright (C) 1998, 1999, 2000, 2001, 2002 John Pritchard. * * This program is free software; you can redistribute it or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program 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 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package gnu.iou.sh; import gnu.iou.bbi; import gnu.iou.bbo; import gnu.iou.bbp; import java.awt.Font; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.DataInputStream; import java.io.IOException; import java.io.PrintStream; import java.util.Vector; import javax.swing.JTextArea; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.Segment; /** * An interpreter text area used by shell provides a stream based I/O * environment like the command- line. * * <p> * This object exports pipe streams that can be read and written by an * interpreter. * * @see Shell * * @author John Pritchard (john@syntelos.org) */ public class ShellTextArea extends JTextArea implements KeyListener, DocumentListener { /** * User reads pipe from GUI */ private final bbp pipe = new bbp(); /** * Shell GUI writes pipe */ private final PrintStream pipo; /** * User reads from GUI (reads pipe). */ private final DataInputStream stdin; /** * User writes to GUI using Shell Out. * * @see to */ private final PrintStream stdout; /** * User writes to GUI using Shell Out. * * @see to */ private final PrintStream stderr; private int docmark = 0; private volatile boolean docupd = true; private final Document doc; private final Segment segment = new Segment(); private final Vector history = new Vector(); private int historx = 0; /** * @param rows * Number of rows text area rows. * * @param columns * Number of text area columns. */ public ShellTextArea(int rows, int columns) { super(rows, columns); this.doc = super.getDocument(); this.doc.addDocumentListener(this); addKeyListener(this); setLineWrap(true); setFont(new Font("Monospaced", 0, 12)); this.pipo = new PrintStream(new bbo(this.pipe)); this.stdin = new DataInputStream(new bbi(this.pipe)); this.stdout = new PrintStream(new to(this)); this.stderr = this.stdout; } public DataInputStream getStdin() { return this.stdin; } public PrintStream getStdout() { return this.stdout; } public PrintStream getStderr() { return this.stderr; } /** * Send argument string to interpreter. */ public void println(String str) { append(str + "\n"); pipo.println(str); } /** * @see java.awt.event.KeyListener */ public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_LEFT) { if (this.docmark == getCaretPosition()) { e.consume(); } } else if (code == KeyEvent.VK_HOME) { int caretPos = getCaretPosition(); if (caretPos == this.docmark) { e.consume(); } else if (caretPos > this.docmark) { if (!e.isControlDown()) { if (e.isShiftDown()) moveCaretPosition(this.docmark); else setCaretPosition(this.docmark); e.consume(); } } } else if (code == KeyEvent.VK_ENTER) { returnPressed(); e.consume(); } else if (code == KeyEvent.VK_UP) { this.historx--; if (0 <= this.historx) { if (this.history.size() <= this.historx) this.historx = this.history.size() - 1; if (0 <= this.historx) { String str = (String) this.history.elementAt(this.historx); int len = this.doc.getLength(); replaceRange(str, this.docmark, len); int caretPos = this.docmark + str.length(); select(caretPos, caretPos); } else this.historx++; } else this.historx++; e.consume(); } else if (code == KeyEvent.VK_DOWN) { int caretPos = this.docmark; if (this.history.size() > 0) { this.historx++; if (this.historx < 0) this.historx = 0; int len = this.doc.getLength(); if (this.historx < this.history.size()) { String str = (String) this.history.elementAt(this.historx); replaceRange(str, this.docmark, len); caretPos = this.docmark + str.length(); } else { this.historx = this.history.size(); replaceRange("", this.docmark, len); } } select(caretPos, caretPos); e.consume(); } } /** * @see java.awt.event.KeyListener */ public void keyTyped(KeyEvent e) { int keyChar = e.getKeyChar(); if (keyChar == 0x8) { // KeyEvent.VK_BACK_SPACE if (this.docmark == getCaretPosition()) e.consume(); } else if (getCaretPosition() < this.docmark) { setCaretPosition(this.docmark); } } /** * @see java.awt.event.KeyListener */ public synchronized void keyReleased(KeyEvent e) { } /** * @see javax.swing.text.JTextComponent */ public void select(int start, int end) { requestFocus(); super.select(start, end); } /** * @see javax.swing.event.DocumentListener */ public synchronized void insertUpdate(DocumentEvent evt) { if (evt.getOffset() < this.docmark) this.docmark += evt.getLength(); } /** * @see javax.swing.event.DocumentListener */ public void removeUpdate(DocumentEvent evt) { int off = evt.getOffset(); if (off < this.docmark) { int len = evt.getLength(); if ((off + len) <= this.docmark) this.docmark -= len; else this.docmark = off; } } /** * @see javax.swing.event.DocumentListener */ public void changedUpdate(DocumentEvent evt) { } /** * Used from Shell Out. * * @see to#write(int) */ protected synchronized void _usr_write(int b) throws IOException { char[] cary = new char[] { (char) (b & 0xff) }; String txt = new String(cary); try { this.doc.insertString(this.doc.getLength(), txt, null); this.docmark = this.doc.getLength(); setCaretPosition(this.docmark); } catch (BadLocationException ignored) { ignored.printStackTrace(); } } /** * Used from Shell Out. * * @see to#write(byte[],int,int) */ protected synchronized void _usr_write(byte b[], int off, int len) throws IOException { String txt = new String(b, 0, off, len); try { this.doc.insertString(this.doc.getLength(), txt, null); this.docmark = this.doc.getLength(); setCaretPosition(this.docmark); } catch (BadLocationException ignored) { ignored.printStackTrace(); } } /** * Called from "key pressed" event. */ private synchronized void returnPressed() { int len = this.doc.getLength(); try { this.doc.getText(this.docmark, len - this.docmark, this.segment); if (0 < this.segment.count) this.history.addElement(this.segment.toString()); this.historx = this.history.size(); String str = new String(this.segment.array, this.segment.offset, this.segment.count); pipo.println(str); append("\n"); this.docmark = doc.getLength(); } catch (BadLocationException ignored) { ignored.printStackTrace(); } } }