newlisp/guiserver/java/TextAreaWidget.java

416 lines
10 KiB
Java

//
// TextAreaWidget.java
// guiserver
//
// Created by Lutz Mueller on 5/16/07.
//
//
// Copyright (C) 2016 Lutz Mueller
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 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 General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.util.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
@SuppressWarnings("unchecked")
public class TextAreaWidget extends aTextWidget {
JTextArea textArea;
int lastCharCode = 65535;
int lastDot = 0;
Process process = null;
BufferedWriter stdOut;
BufferedReader stdInput;
BufferedReader stdError;
String command = "";
int historyIndex = 0;
Vector history;
String lastShellCommand;
String lastShellArgs;
String commandBatch = "";
boolean isInBatch = false;
public TextAreaWidget(StringTokenizer params)
{
id = params.nextToken();
action = params.nextToken();
textArea = new JTextArea();
textArea.setFont(new Font("SansSerif", Font.PLAIN, 12));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
areaScrollPane = new JScrollPane(textArea);
areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
container = areaScrollPane;
jcomponent = textArea;
component = areaScrollPane;
textcomp = textArea;
isScrollable = true;
if(params.hasMoreTokens())
areaScrollPane.setPreferredSize(
new Dimension(Integer.parseInt(params.nextToken()),Integer.parseInt(params.nextToken())));
gsObject.widgets.put(id, this);
KeyListener keyListener = new KeyAdapter() {
public void keyPressed(KeyEvent e)
{
Character chr = new Character(e.getKeyChar());
lastCharCode = chr.hashCode();
if(process != null)
{
if(lastCharCode == 12) // formfeed Ctrl-L
{
textArea.setText("");
lastDot = 0;
try {
stdOut.write(10);
stdOut.flush();
}
catch (IOException ioex) { System.out.println("clear screen:" + ioex); };
}
}
}
};
CaretListener caretListener = new CaretListener() {
public void caretUpdate(CaretEvent ce)
{
int mark = ce.getMark();
int dot = ce.getDot();
guiserver.out.println("(" + action + " \"" + id + "\" " + lastCharCode + " " + dot + " " + mark + ")");
guiserver.out.flush();
lastCharCode = 65535;
//System.out.println(":" + lastDot);
}
};
textArea.addCaretListener(caretListener);
textArea.addKeyListener(keyListener);
}
public void setTabSize(StringTokenizer tokens)
{
textArea.setTabSize(Integer.parseInt(tokens.nextToken()));
}
public void clearText(StringTokenizer params)
{
textcomp.setText("");
lastCharCode = 65535;
lastDot = 0;
if(process != null)
try {
stdOut.write(10);
stdOut.flush();
}
catch (IOException ioex) { System.out.println("clear screen:" + ioex); };
}
public void runShell(StringTokenizer tokens)
{
String command;
String args;
if(tokens == null)
{
command = lastShellCommand;
args = lastShellArgs;
}
else
{
command = Base64Coder.decodeString(tokens.nextToken());
lastShellCommand = command;
args = Base64Coder.decodeString(tokens.nextToken());
lastShellArgs = args;
}
history = new Vector();
historyIndex = 0;
commandBatch = "";
isInBatch = false;
if(process != null)
process.destroy();
InputMap im = textArea.getInputMap();
ActionMap am = textArea.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "history-up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK), "history-up");
am.put("history-up", new HistoryUpAction());
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "history-down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK), "history-down");
am.put("history-down", new HistoryDownAction());
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "command");
am.put("command", new CommandAction());
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK), "bol");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "bol");
am.put("bol", new BeginningOfLineAction());
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK), "eol");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "eol");
am.put("eol", new EndOfLineAction());
textArea.setText("");
lastCharCode = 65535;
lastDot = 0;
try { setupShell(command, args); }
catch (IOException ioex) {
ErrorDialog.show("run-shell", "Could not start " + command + " " + args);
process = null;
}
}
public void setupShell(String command, String args) throws IOException
{
String[] cmdArray = {"","","","","","","","","",""};
cmdArray[0] = command;
//System.out.println("--->" + command);
String[] argsArray = args.split("\\s");
for (int x = 0; x < argsArray.length; x++)
{
cmdArray[x + 1] = argsArray[x];
//System.out.println(argsArray[x]);
}
process = Runtime.getRuntime().exec(cmdArray);
if(guiserver.UTF8)
{
stdInput = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF8"));
stdError = new BufferedReader( new InputStreamReader(process.getErrorStream(), "UTF8"));
}
else
{
stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
stdError = new BufferedReader( new InputStreamReader(process.getErrorStream()));
}
stdOut = new BufferedWriter( new OutputStreamWriter(process.getOutputStream()));
new Thread(new stdinListener()).start();
new Thread(new stderrorListener()).start();
}
public void destroyShell(StringTokenizer params)
{
if(process != null) process.destroy();
process = null;
stdOut = null;
}
public void evalShell(StringTokenizer params)
{
String command = Base64Coder.decodeString(params.nextToken());
while(true)
{
if(process == null)
{
textArea.append("--- restarting shell ---");
runShell(null);
if(process == null) break;
}
else
{
try {
textArea.append("\n");
stdOut.write(command, 0, command.length());
stdOut.flush();
break;
}
catch (IOException ioex) {
textArea.append("--- eval shell: must restart shell ---");
process = null;
};
}
}
}
class stdinListener implements Runnable
{
int len;
char buff[];
String str;
String text;
stdinListener()
{
buff = new char[512];
}
public void run()
{
try {
while((len = stdInput.read(buff, 0, 512)) != -1)
{
str = new String(buff, 0, len);
text = textArea.getText();
if(text.length() > 100000)
textArea.setText(text.substring(50000));
textArea.append(str);
lastDot = textArea.getText().length();
textArea.setCaretPosition(lastDot);
}
}
catch (IOException ioex) {};
}
}
class stderrorListener implements Runnable
{
int len;
char buff[];
String str;
String text;
stderrorListener()
{
buff = new char[512];
}
public void run()
{
try {
while((len = stdError.read(buff, 0, 512)) != -1)
{
str = new String(buff, 0, len);
text = textArea.getText();
if(text.length() > 100000)
textArea.setText(text.substring(50000));
textArea.append(str);
lastDot = textArea.getText().length();
textArea.setCaretPosition(lastDot);
}
}
catch (IOException ioex) {};
}
}
private class BeginningOfLineAction extends AbstractAction {
public static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ev) {
textArea.setCaretPosition(lastDot);
}
}
private class EndOfLineAction extends AbstractAction {
public static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ev) {
textArea.setCaretPosition(textArea.getText().length());
}
}
private class HistoryUpAction extends AbstractAction {
public static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ev) {
textArea.setCaretPosition(lastDot);
textArea.moveCaretPosition(textArea.getText().length());
textArea.cut();
if(history.size() > 0)
{
textArea.append((String)history.elementAt(historyIndex));
if(historyIndex < (history.size() - 1))
historyIndex += 1;
}
}
}
private class HistoryDownAction extends AbstractAction {
public static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ev) {
textArea.setCaretPosition(lastDot);
textArea.moveCaretPosition(textArea.getText().length());
textArea.cut();
if(history.size() > 0)
{
textArea.append((String)history.elementAt(historyIndex));
if(historyIndex > 0)
historyIndex -= 1;
}
}
}
private class CommandAction extends AbstractAction {
public static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ev) {
String text = textArea.getText();
if(text.length() < lastDot) lastDot = text.length();
text = text.substring(lastDot);
if(guiserver.UTF8)
try {
text = new String(text.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {}
command = text;
if(command.equals("[cmd]"))
isInBatch = true;
textArea.append("\n");
try {
if(isInBatch == false)
{
stdOut.write(command, 0, command.length());
stdOut.write(10);
stdOut.flush();
}
if(command.length() > 0)
{
history.insertElementAt(new String(command), 0);
}
historyIndex = 0;
}
catch (IOException ioex) {
textArea.append("--- cannot execute: restart shell ---");
};
if(command.endsWith("\n[/cmd]"))
{
isInBatch = false;
try {
stdOut.write(command, 0, command.length());
stdOut.write(10);
stdOut.flush();
}
catch (IOException ioex) {
textArea.append("--- cannot execute command batch ---");
};
}
}
}
}
// eof //