commit - e8dbb7eedfb0f9bd8407e0364bc6a309239c89f6
commit + ef6cad1d6b21c1dcbcbef21861969aa85b54fa0b
blob - /dev/null
blob + 57b7661b720a1b4a082494847edc4af1663cc840 (mode 644)
--- /dev/null
+++ Makefile
+JAVA = java
+JAR = jar
+JAVAC = javac
+DEBUG = -g -deprecation
+JFLAGS = -classpath $(CLASSPATH):.
+SRCDIR = de
+
+.SUFFIXES: .java .class
+
+# compile java files to class
+.java.class:
+ $(JAVAC) $(DEBUG) $(JFLAGS) $<
+
+#
+# major rules to create files
+#
+all: app doc jar
+
+doc: app
+ javadoc -d doc -version -author \
+ `find de/mud -type d -print | \
+ grep -v CVS | grep -v '^de/mud$$' | sed 's/\//./g'`
+
+run: app
+ $(JAVA) $(JFLAGS) de.mud.jta.Main
+
+jar: app
+ $(JAR) cvf jar/jta.jar `find $(SRCDIR) -name *.class`
+
+#
+# application dependencies
+#
+app:
+ @find $(SRCDIR) -name \*.java | sed 's/java$$/class/' | xargs make
+
+clean:
+ -find . -name *.class -print | xargs rm > /dev/null 2>&1
+ -find . -name *~ -print | xargs rm > /dev/null 2>&1
blob - /dev/null
blob + 9dd433cc278852d40893a22cf85717e89e88e689 (mode 644)
--- /dev/null
+++ de/mud/jta/Common.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+import de.mud.jta.PluginLoader;
+import de.mud.jta.VisualPlugin;
+import de.mud.jta.Plugin;
+import de.mud.jta.event.ConfigurationRequest;
+import de.mud.jta.event.SocketRequest;
+
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import java.awt.Component;
+import java.awt.Menu;
+
+/**
+ * The common part of the <B>The Java<SUP>tm</SUP> Telnet Application</B>
+ * is handled here. Mainly this includes the loading of the plugins and
+ * the screen setup of the visual plugins.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Common extends PluginLoader {
+
+ private Hashtable plugins, components, menus;
+
+ public Common(Properties config) {
+ System.err.println("** The Java(tm) Telnet Application");
+ System.err.println("** Copyright (c) 1996-1999 Matthias L. Jugel, "
+ +"Marcus Meißner");
+
+ plugins = new Hashtable();
+ components = new Hashtable();
+ menus = new Hashtable();
+
+ Vector names = split(config.getProperty("plugins"));
+ Enumeration e = names.elements();
+ while(e.hasMoreElements()) {
+ String name = (String)e.nextElement();
+ System.err.println("jta: loading plugin '"+name+"' ...");
+ Plugin plugin = addPlugin(name);
+ if(plugin instanceof VisualPlugin) {
+ Component c = ((VisualPlugin)plugin).getPluginVisual();
+ if(c != null) components.put(name, c);
+ Menu menu = ((VisualPlugin)plugin).getPluginMenu();
+ if(menu != null) menus.put(name, menu);
+ }
+ }
+
+ broadcast(new ConfigurationRequest(config));
+ }
+
+ public Hashtable getComponents() {
+ return components;
+ }
+
+ public Hashtable getMenus() {
+ return menus;
+ }
+
+ /**
+ * Split up comma separated lists of strings. This is quite strict, no
+ * whitespace characters are allowed.
+ * @param s the string to be split up
+ * @return an array of strings
+ */
+ private static Vector split(String s) {
+ Vector v = new Vector();
+ int old = -1, idx = s.indexOf(',');
+ while(idx >= 0) {
+ v.addElement(s.substring(old + 1, idx));
+ old = idx;
+ idx = s.indexOf(',', old + 1);
+ }
+ v.addElement(s.substring(old + 1));
+ return v;
+ }
+}
blob - /dev/null
blob + 418ed0c04e9f06512128d4f146ff8a1f852e2dbb (mode 644)
--- /dev/null
+++ de/mud/jta/FilterPlugin.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+import java.io.IOException;
+
+/**
+ * The filter plugin is the base interface for plugins that want to intercept
+ * the communication between front end and back end plugins. Filters and
+ * protocol handlers are a good example.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface FilterPlugin {
+ /**
+ * Set the source plugin where we get our data from and where the data
+ * sink (write) is. The actual data handling should be done in the
+ * read() and write() methods.
+ * @param source the data source
+ */
+ public void setFilterSource(FilterPlugin source)
+ throws IllegalArgumentException;
+
+ /**
+ * Read a block of data from the back end.
+ * @param b the buffer to read the data into
+ * @return the amount of bytes actually read
+ */
+ public int read(byte[] b)
+ throws IOException;
+
+ /**
+ * Write a block of data to the back end.
+ * @param b the buffer to be sent
+ */
+ public void write(byte[] b)
+ throws IOException;
+}
blob - /dev/null
blob + 1ffa2588dc4fd21f04886389031e71be9fa64e3b (mode 644)
--- /dev/null
+++ de/mud/jta/Main.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+import de.mud.jta.event.OnlineStatusListener;
+import de.mud.jta.event.SocketRequest;
+
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import java.io.IOException;
+
+import java.awt.Frame;
+import java.awt.Color;
+import java.awt.Component;
+
+/**
+ * <B>The Java Telnet Application</B><P>
+ * This is the implementation of whole set of applications. It's modular
+ * structure allows to configure the software to act either as a sophisticated
+ * terminal emulation and/or, adding the network backend, as telnet
+ * implementation. Additional modules provide features like scripting or an
+ * improved graphical user interface.<P>
+ * This software is written entirely in Java<SUP>tm</SUP>.<P>
+ * This is the main program for the command line telnet. It initializes the
+ * system and adds all needed components, such as the telnet backend and
+ * the terminal front end. In contrast to applet functionality it parses
+ * command line arguments used for configuring the software. Additionally
+ * this application is not restricted in the sense of Java<SUP>tmp</SUP>
+ * security.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Main extends Frame {
+
+ public static void main(String args[]) {
+ Properties options = new Properties();
+ try {
+ options.load(options.getClass()
+ .getResourceAsStream("/de/mud/jta/defaults.opt"));
+ } catch(IOException e) {
+ System.err.println("jta: cannot load defaults");
+ }
+ String error = parseOptions(options, args);
+ if(error != null) {
+ System.err.println(error);
+ System.err.println("usage: de.mud.jta.Main [-term id] [host [port]]");
+ System.exit(0);
+ }
+
+ final Frame frame = new Frame("jta: "
+ +options.getProperty("Socket.host")
+ +options.getProperty("Socket.port"));
+
+ // configure the application and load all plugins
+ Common setup = new Common(options);
+
+ setup.registerPluginListener(new OnlineStatusListener() {
+ public void online() { /* nothing to do */ }
+ public void offline() {
+/* frame.dispose();
+ System.exit(0);
+*/ }
+ });
+
+ Hashtable componentList = setup.getComponents();
+ Enumeration names = componentList.keys();
+ while(names.hasMoreElements()) {
+ String name = (String)names.nextElement();
+ Component c = (Component)componentList.get(name);
+ if(options.getProperty("layout."+name) == null) {
+ System.err.println("jta: no layout property set for '"+name+"'");
+ frame.add("South", c);
+ } else
+ frame.add(options.getProperty("layout."+name), c);
+ }
+
+ frame.pack();
+ frame.show();
+
+ setup.broadcast(new SocketRequest(options.getProperty("Socket.host"),
+ Integer.parseInt(options.getProperty("Socket.port"))));
+ }
+
+ /**
+ * Parse the command line argumens and override any standard options
+ * with the new values if applicable.
+ * <P><SMALL>
+ * This method does not work with jdk 1.1.x as the setProperty()
+ * method is not available. You need to comment this method out
+ * and replace the class for the old jdk!
+ * </SMALL>
+ * @param options the original options
+ * @param args the command line parameters
+ * @return a possible error message if problems occur
+ */
+ private static String parseOptions(Properties options, String args[]) {
+ for(int n = 0; n < args.length; n++) {
+ if(args[n].equals("-term"))
+ if(!args[n+1].startsWith("-"))
+ /* options.setProperty("Terminal.id", args[++n]) */;
+ else
+ return "missing parameter for -term";
+ }
+ return null;
+ }
+}
blob - /dev/null
blob + 35d11b8466bc032fee5cbbdc0b9f0cb2c3f35897 (mode 644)
--- /dev/null
+++ de/mud/jta/Plugin.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+import java.io.IOException;
+
+/**
+ * Plugin base class for the Java Telnet Application.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Plugin {
+ /** holds the plugin bus used for communication between plugins */
+ protected PluginBus bus;
+
+ /**
+ * Create a new plugin and set the plugin bus used by this plugin.
+ * @param bus the plugin bus
+ */
+ public Plugin(PluginBus bus) {
+ this.bus = bus;
+ }
+}
blob - /dev/null
blob + a2efaff27698bcebb5db824a5ac0cf7473fecf06 (mode 644)
--- /dev/null
+++ de/mud/jta/PluginBus.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+/**
+ * A plugin bus is used for communication between plugins. The interface
+ * describes the broadcast method that should broad cast the message
+ * to all plugins known and return an answer message immediatly.<P>
+ * The functionality is just simuliar to a bus, but depends on the
+ * actual implementation of the bus.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface PluginBus {
+ /** Broadcast a plugin message to all listeners. */
+ public Object broadcast(PluginMessage message);
+ /** Register a plugin listener with this bus object */
+ public void registerPluginListener(PluginListener listener);
+}
blob - /dev/null
blob + 430e191d5bebc822c8ec6a8719427aabf2ef30d9 (mode 644)
--- /dev/null
+++ de/mud/jta/PluginListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+/**
+ * A tag interface for a plugin message listener.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface PluginListener {
+}
blob - /dev/null
blob + 3084a81a3cda1649e2c0cf0d3c984bc4b7302fe5 (mode 644)
--- /dev/null
+++ de/mud/jta/PluginLoader.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.jta;
+
+import java.util.Properties;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * The plugin loader tries to load the plugin by name and returns a
+ * corresponding plugin object. It takes care of connecting filter
+ * plugins
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class PluginLoader implements PluginBus {
+ /** holds the current version id */
+ public final static String ID = "$Id$";
+
+ private final static int debug = 0;
+
+ /** the path to standard plugins */
+ private final static String PATH = "de.mud.jta.plugin.";
+
+ /** holds all the filters */
+ private Vector filter = new Vector();
+
+ /**
+ * Add a new plugin to the system and register the plugin load as its
+ * communication bus. If the plugin is a filter plugin and if it is
+ * not the first filter the last added filter will be set as its filter
+ * source.
+ * @param name the string name of the plugin
+ * @return the newly created plugin or null in case of an error
+ */
+ public Plugin addPlugin(String name) {
+ Plugin plugin = null;
+
+ // load the plugin by name and instantiate it
+ try {
+ Class c = Class.forName(PATH+name);
+ Constructor cc = c.getConstructor(new Class[] { PluginBus.class });
+ plugin = (Plugin)cc.newInstance(new Object[] { this });
+ } catch(Exception e) {
+ System.err.println("plugin loader: cannot load "+name);
+ e.printStackTrace();
+ return null;
+ }
+
+ // configure the filter plugins
+ if(plugin instanceof FilterPlugin) {
+ if(filter.size() > 0)
+ ((FilterPlugin)plugin)
+ .setFilterSource((FilterPlugin)filter.lastElement());
+ filter.addElement(plugin);
+ }
+
+ return plugin;
+ }
+
+ /** holds the plugin listener we serve */
+ private Vector listener = new Vector();
+
+ /**
+ * Register a new plugin listener.
+ */
+ public void registerPluginListener(PluginListener l) {
+ listener.addElement(l);
+ }
+
+ /**
+ * Implementation of the plugin bus. Broadcast a message to all
+ * listeners we know of. The message takes care that the right
+ * methods are called in the listeners.
+ * @param message the plugin message to be sent
+ * @return the answer to the sent message
+ */
+ public Object broadcast(PluginMessage message) {
+ if(debug>0) System.err.println("broadcast("+message+")");
+ if(message == null || listener == null)
+ return null;
+ Enumeration e = listener.elements();
+ Object res = null;
+ while(res == null && e.hasMoreElements())
+ res = message.firePluginMessage((PluginListener)e.nextElement());
+ return res;
+ }
+}
+
blob - /dev/null
blob + e878d8cce59274a53433983a7451d5c300779748 (mode 644)
--- /dev/null
+++ de/mud/jta/PluginMessage.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+/**
+ * The base interface for a plugin message.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface PluginMessage {
+ /**
+ * Fire the message to all listeners that are compatible with this
+ * message and return the result.
+ * @param pl the list of plugin message listeners
+ * @return the result message
+ */
+ public Object firePluginMessage(PluginListener pl);
+}
blob - /dev/null
blob + 979af0594e61d6b90b55bf2ffe803379806e6895 (mode 644)
--- /dev/null
+++ de/mud/jta/VisualPlugin.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta;
+
+import java.awt.Component;
+import java.awt.Menu;
+
+/**
+ * To show data on-screen a plugin may have a visible component. That component
+ * may either be a single awt component or a container with severel elements.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface VisualPlugin {
+ /**
+ * Get the visible components from the plugin.
+ * @return a component that represents the plugin
+ */
+ public Component getPluginVisual();
+
+ /**
+ * Get the menu entry for this component.
+ * @return a menu that can be used to change the plugin state
+ */
+ public Menu getPluginMenu();
+}
blob - /dev/null
blob + a06711c2c95d10315bc14c67bfde1d57ee491278 (mode 644)
--- /dev/null
+++ de/mud/jta/defaults.opt
+# This file is part of "The Java Telnet Application".
+#
+# This 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 2, or (at your option)
+# any later version.
+#
+# "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# =======================================================================
+# common program defaults
+# =======================================================================
+plugins = Socket,Telnet,Terminal,Status
+layout = BorderLayout
+layout.Terminal = Center
+layout.Status = South
+
+# =======================================================================
+# Socket defaults
+# =======================================================================
+Socket.host = 10.1.1.1
+Socket.port = 23
+
+# =======================================================================
+# Terminal defaults
+# =======================================================================
+Terminal.foreground = #000080
+Terminal.background = #a0fff6
+Terminal.border = 0
+Terminal.borderRaised = false
+Terminal.borderColor = #a0fff6
+Terminal.colorSet = @/de/mud/terminal/default.colorset
+Terminal.scrollBar = West
+# now the real configuration
+Terminal.id = vt320
+Terminal.buffer = 100
+Terminal.size = [80,24]
+Terminal.resize = none
+Terminal.font = Courier
+Terminal.fontStyle = bold
+Terminal.fontSize = 18
+Terminal.keyCodes = @/de/mud/terminal/default.keycodes
+Terminal.VMS = false
+Terminal.IBM = false
blob - /dev/null
blob + 2ded6f0459a190c4cbfd3ee9142da911023dd655 (mode 644)
--- /dev/null
+++ de/mud/jta/event/ConfigurationListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginListener;
+
+import java.util.Properties;
+
+/**
+ * Configuration listener will be notified of configuration events.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface ConfigurationListener extends PluginListener {
+ /** Called for configuration changes. */
+ public void setConfiguration(Properties config);
+}
blob - /dev/null
blob + dd390d3a48eccea9a0cca23a9171c7e37f919b93 (mode 644)
--- /dev/null
+++ de/mud/jta/event/ConfigurationRequest.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginMessage;
+import de.mud.jta.PluginListener;
+import de.mud.jta.event.ConfigurationListener;
+
+import java.util.Properties;
+
+/**
+ * Configuration request message. Subclassing this message can be used to
+ * make the configuration more specific and efficient.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class ConfigurationRequest implements PluginMessage {
+ Properties config;
+
+ public ConfigurationRequest(Properties config) {
+ this.config = config;
+ }
+
+ /**
+ * Notify all listeners of a configuration event.
+ * @param pl the list of plugin message listeners
+ */
+ public Object firePluginMessage(PluginListener pl) {
+ if(pl instanceof ConfigurationListener) {
+ ((ConfigurationListener)pl).setConfiguration(config);
+ }
+ return null;
+ }
+}
blob - /dev/null
blob + dd22c9a85d0adc75082d4f73f650ed58b343ba1b (mode 644)
--- /dev/null
+++ de/mud/jta/event/LocalEchoListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginListener;
+
+/**
+ * This interface should be used by plugins who would like to be notified
+ * about the local echo property.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface LocalEchoListener extends PluginListener {
+ /** Called if the local echo property changes. */
+ public void setLocalEcho(boolean echo);
+}
blob - /dev/null
blob + 63dadb1c5aa4bc8a9a899b961b1e8d1d04965164 (mode 644)
--- /dev/null
+++ de/mud/jta/event/LocalEchoRequest.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginMessage;
+import de.mud.jta.PluginListener;
+import de.mud.jta.event.LocalEchoListener;
+
+/**
+ * Notification of the local echo property. The terminal should echo all
+ * typed in characters locally of this is true.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class LocalEchoRequest implements PluginMessage {
+ protected boolean echo;
+
+ /** Create a new local echo request with the specified value. */
+ public LocalEchoRequest(boolean echo) {
+ this.echo = echo;
+ }
+
+ /**
+ * Notify all listeners about the status of local echo.
+ * @param pl the list of plugin message listeners
+ * @return always null
+ */
+ public Object firePluginMessage(PluginListener pl) {
+ if(pl instanceof LocalEchoListener)
+ ((LocalEchoListener)pl).setLocalEcho(echo);
+ return null;
+ }
+}
blob - /dev/null
blob + 8da05583f4ecebda6eaa5755d0d521596943105f (mode 644)
--- /dev/null
+++ de/mud/jta/event/OnlineStatus.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginMessage;
+import de.mud.jta.PluginListener;
+
+/**
+ * Notify all listeners that we on or offline.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class OnlineStatus implements PluginMessage {
+ protected boolean online;
+
+ /** Create a new online status message with the specified value. */
+ public OnlineStatus(boolean online) {
+ this.online = online;
+ }
+
+ /**
+ * Notify the listers about the online status.
+ * @param pl the list of plugin message listeners
+ * @return the window size or null
+ */
+ public Object firePluginMessage(PluginListener pl) {
+ if(pl instanceof OnlineStatusListener)
+ if(online)
+ ((OnlineStatusListener)pl).online();
+ else
+ ((OnlineStatusListener)pl).offline();
+ return null;
+ }
+}
blob - /dev/null
blob + a5125bf7234df3e11fb5214ef5d7b7ac64afa1ad (mode 644)
--- /dev/null
+++ de/mud/jta/event/OnlineStatusListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginListener;
+
+import java.awt.Dimension;
+
+/**
+ * This is the interface for a online status listener.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface OnlineStatusListener extends PluginListener {
+ /** Called when the system is online. */
+ public void online();
+ /** Called when the system is offline. */
+ public void offline();
+}
blob - /dev/null
blob + 856bb296752ffc2bce2839ca8db4374b0e678443 (mode 644)
--- /dev/null
+++ de/mud/jta/event/SocketListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginListener;
+
+import java.net.UnknownHostException;
+import java.io.IOException;
+
+/**
+ * The socket listener should be implemented by plugins that want to know
+ * when the whole systems connects or disconnects.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface SocketListener extends PluginListener {
+ /** Called if a connection should be established. */
+ public void connect(String host, int port)
+ throws UnknownHostException, IOException;
+ /** Called if the connection should be stopped. */
+ public void disconnect()
+ throws IOException;
+}
blob - /dev/null
blob + d21dc3415ebe488cfaf21d207390f61bc0685dfd (mode 644)
--- /dev/null
+++ de/mud/jta/event/SocketRequest.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginMessage;
+import de.mud.jta.PluginListener;
+import de.mud.jta.event.SocketListener;
+
+/**
+ * Notification of a socket request. Send this message if the system
+ * should connect or disconnect.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class SocketRequest implements PluginMessage {
+ String host;
+ int port;
+
+ /** Create a new disconnect message */
+ public SocketRequest() {
+ host = null;
+ }
+
+ /** Create a new connect message */
+ public SocketRequest(String host, int port) {
+ this.host = host;
+ this.port = port;
+ }
+
+ /**
+ * Tell all listeners that we would like to connect.
+ * @param pl the list of plugin message listeners
+ * @return the terminal type or null
+ */
+ public Object firePluginMessage(PluginListener pl) {
+ if(pl instanceof SocketListener) try {
+ if(host != null)
+ ((SocketListener)pl).connect(host, port);
+ else
+ ((SocketListener)pl).disconnect();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
blob - /dev/null
blob + 2be5aea01d0ec57773b6446d5cb63ec2152d6e67 (mode 644)
--- /dev/null
+++ de/mud/jta/event/TerminalTypeListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginListener;
+
+/**
+ * This is the interface for a terminal type listener. It should return
+ * the terminal type id as a string. Valid terminal types include
+ * VT52, VT100, VT200, VT220, VT320, ANSI etc.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface TerminalTypeListener extends PluginListener {
+ /** Return the terminal type string */
+ public String getTerminalType();
+}
blob - /dev/null
blob + dc2d8cbd1b7d883d5880fbe05ccf88e6e71b6fb4 (mode 644)
--- /dev/null
+++ de/mud/jta/event/TerminalTypeRequest.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginMessage;
+import de.mud.jta.PluginListener;
+import de.mud.jta.event.TerminalTypeListener;
+
+/**
+ * Request message for the current terminal type.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class TerminalTypeRequest implements PluginMessage {
+ /**
+ * Ask all terminal type listener about the terminal type and return
+ * the first answer.
+ * @param pl the list of plugin message listeners
+ * @return the terminal type or null
+ */
+ public Object firePluginMessage(PluginListener pl) {
+ if(pl instanceof TerminalTypeListener) {
+ Object ret = ((TerminalTypeListener)pl).getTerminalType();
+ if(ret != null) return ret;
+ }
+ return null;
+ }
+}
blob - /dev/null
blob + 5a1b866b2bb1a0644e02fd98af2058570ed8aa3b (mode 644)
--- /dev/null
+++ de/mud/jta/event/WindowSizeListener.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginListener;
+
+import java.awt.Dimension;
+
+/**
+ * This is the interface for a window size listener.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public interface WindowSizeListener extends PluginListener {
+ /** Return the current window size of the terminal in rows and columns. */
+ public Dimension getWindowSize();
+}
blob - /dev/null
blob + a1d991f2e4518857c7665eb7d18a2182a4768bed (mode 644)
--- /dev/null
+++ de/mud/jta/event/WindowSizeRequest.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+package de.mud.jta.event;
+
+import de.mud.jta.PluginMessage;
+import de.mud.jta.PluginListener;
+import de.mud.jta.event.WindowSizeListener;
+
+/**
+ * Request the current window size of the terminal.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class WindowSizeRequest implements PluginMessage {
+ /**
+ * Return the size of the window
+ * @param pl the list of plugin message listeners
+ */
+ public Object firePluginMessage(PluginListener pl) {
+ if(pl instanceof WindowSizeListener) {
+ Object ret = ((WindowSizeListener)pl).getWindowSize();
+ if(ret != null) return ret;
+ }
+ return null;
+ }
+}
blob - /dev/null
blob + a20b2ea4a49ceecd7565981ad06fb7fda047fcec (mode 644)
--- /dev/null
+++ de/mud/jta/plugin/Shell.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.jta.plugin;
+
+import de.mud.jta.Plugin;
+import de.mud.jta.FilterPlugin;
+import de.mud.jta.PluginBus;
+import de.mud.jta.event.LocalEchoRequest;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * The shell plugin is the backend component for terminal emulation using
+ * a shell. It provides the i/o streams of the shell as data source.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Shell extends Plugin implements FilterPlugin {
+
+ private final static int debug = 1;
+
+ protected InputStream in, err;
+ protected OutputStream out;
+
+ public Shell(PluginBus bus) {
+ super(bus);
+ Runtime rt = Runtime.getRuntime();
+
+ try {
+ Process p = rt.exec("/bin/bash -i"); System.err.println(p);
+ in = p.getInputStream();
+ out = p.getOutputStream();
+ err = p.getErrorStream();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ bus.broadcast(new LocalEchoRequest(true));
+ }
+
+ public void setFilterSource(FilterPlugin plugin) {
+ // we do not have a source other than our socket
+ }
+
+ public int read(byte[] b) throws IOException {
+ if(err.available() > 0) return err.read(b);
+ return in.read(b);
+ }
+
+ public void write(byte[] b) throws IOException {
+ out.write(b);
+ out.flush();
+ }
+}
blob - /dev/null
blob + bde73e12b93315bdf2e1597d748230a04dd7d15e (mode 644)
--- /dev/null
+++ de/mud/jta/plugin/Socket.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.jta.plugin;
+
+import de.mud.jta.Plugin;
+import de.mud.jta.FilterPlugin;
+import de.mud.jta.PluginBus;
+import de.mud.jta.event.SocketListener;
+import de.mud.jta.event.OnlineStatus;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.net.UnknownHostException;
+
+/**
+ * The socket plugin acts as the data source for networked operations.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Socket extends Plugin implements FilterPlugin, SocketListener {
+
+ private final static int debug = 0;
+ protected java.net.Socket socket;
+ protected InputStream in;
+ protected OutputStream out;
+
+ /**
+ * Create a new socket plugin.
+ */
+ public Socket(PluginBus pbus) {
+ super(pbus);
+ final PluginBus bus = pbus;
+
+ // register socket listener
+ bus.registerPluginListener(this);
+ }
+
+ /** Connect to the host and port passed. */
+ public void connect(String host, int port)
+ throws UnknownHostException, IOException {
+ if(debug>0) System.err.println("Socket: connect("+host+","+port+")");
+ socket = new java.net.Socket(host, port);
+ in = socket.getInputStream();
+ out = socket.getOutputStream();
+ bus.broadcast(new OnlineStatus(true));
+ }
+
+ /** Disconnect the socket and close the connection. */
+ public void disconnect() throws IOException {
+ if(debug>0) System.err.println("Socket: disconnect()");
+ bus.broadcast(new OnlineStatus(false));
+ socket.close();
+ }
+
+ public void setFilterSource(FilterPlugin plugin) {
+ // we do not have a source other than our socket
+ }
+
+ public int read(byte[] b) throws IOException {
+ int n = in.read(b);
+ if(n < 0) disconnect();
+ return n;
+ }
+
+ public void write(byte[] b) throws IOException {
+ out.write(b);
+ }
+}
blob - /dev/null
blob + 48e9f00eb584bc57cf24da9cfdff27547b5c6156 (mode 644)
--- /dev/null
+++ de/mud/jta/plugin/Status.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.jta.plugin;
+
+import de.mud.jta.Plugin;
+import de.mud.jta.PluginBus;
+import de.mud.jta.VisualPlugin;
+import de.mud.jta.event.OnlineStatusListener;
+
+import java.awt.Component;
+import java.awt.Menu;
+import java.awt.Label;
+import java.awt.Color;
+
+/**
+ * A simple plugin showing the current status of the application whether
+ * it is online or not.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Status extends Plugin implements VisualPlugin {
+
+ private final static int debug = 1;
+
+ private Label status;
+
+ public Status(PluginBus bus) {
+ super(bus);
+ status = new Label("offline", Label.RIGHT);
+ bus.registerPluginListener(new OnlineStatusListener() {
+ public void online() {
+ status.setText("online");
+ status.setBackground(Color.green);
+ }
+ public void offline() {
+ status.setText("offline");
+ status.setBackground(Color.red);
+ }
+ });
+ }
+
+ public Component getPluginVisual() {
+ return status;
+ }
+
+ public Menu getPluginMenu() {
+ return null;
+ }
+}
blob - /dev/null
blob + 61aa353cc35440bb5a71404113eb8923830e8e63 (mode 644)
--- /dev/null
+++ de/mud/jta/plugin/Telnet.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.jta.plugin;
+
+import de.mud.jta.Plugin;
+import de.mud.jta.FilterPlugin;
+import de.mud.jta.PluginBus;
+
+import de.mud.jta.event.TerminalTypeRequest;
+import de.mud.jta.event.WindowSizeRequest;
+import de.mud.jta.event.LocalEchoRequest;
+
+import de.mud.telnet.TelnetProtocolHandler;
+
+import java.awt.Dimension;
+
+import java.io.IOException;
+
+/**
+ * The telnet plugin utilizes a telnet protocol handler to filter
+ * telnet negotiation requests from the data stream.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Telnet extends Plugin implements FilterPlugin {
+
+ protected FilterPlugin source;
+ protected TelnetProtocolHandler handler;
+
+ private final static int debug = 0;
+
+ /**
+ * Create a new telnet plugin.
+ */
+ public Telnet(PluginBus pbus) {
+ super(pbus);
+ final PluginBus bus = pbus;
+
+ // create a new telnet protocol handler
+ handler = new TelnetProtocolHandler() {
+ /** get the current terminal type */
+ public String getTerminalType() {
+ return (String)bus.broadcast(new TerminalTypeRequest());
+ }
+ /** get the current window size */
+ public Dimension getWindowSize() {
+ return (Dimension)bus.broadcast(new WindowSizeRequest());
+ }
+ /** notify about local echo */
+ public void setLocalEcho(boolean echo) {
+ bus.broadcast(new LocalEchoRequest(echo));
+ }
+ /** write data to our back end */
+ public void write(byte[] b) throws IOException {
+ source.write(b);
+ }
+ };
+ }
+
+ public void setFilterSource(FilterPlugin source) {
+ if(debug>0) System.err.println("Telnet: connected to: "+source);
+ this.source = source;
+ }
+
+ public int read(byte[] b) throws IOException {
+ int n = source.read(b);
+ if(n > 0) n = handler.negotiate(b, n);
+ return n;
+ }
+
+ public void write(byte[] b) throws IOException {
+ source.write(b);
+ }
+}
blob - /dev/null
blob + d4bc46654fc3165ebb188932cdde2c68bcc50b89 (mode 644)
--- /dev/null
+++ de/mud/jta/plugin/Terminal.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.jta.plugin;
+
+import de.mud.jta.Plugin;
+import de.mud.jta.FilterPlugin;
+import de.mud.jta.VisualPlugin;
+import de.mud.jta.PluginBus;
+
+import de.mud.terminal.vt320;
+
+import de.mud.jta.event.ConfigurationListener;
+import de.mud.jta.event.OnlineStatusListener;
+import de.mud.jta.event.TerminalTypeListener;
+import de.mud.jta.event.WindowSizeListener;
+import de.mud.jta.event.LocalEchoListener;
+
+import java.awt.Component;
+import java.awt.Menu;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Color;
+
+import java.io.IOException;
+
+import java.util.Properties;
+import java.util.Enumeration;
+
+/**
+ * The terminal plugin represents the actual terminal where the
+ * data will be displayed and the gets the keyboard input to sent
+ * back to the remote host,
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class Terminal extends Plugin
+ implements FilterPlugin, VisualPlugin, Runnable {
+
+ private final static int debug = 0;
+
+ /** holds the actual terminal emulation */
+ protected vt320 terminal;
+
+ private Thread reader = null;
+
+ /**
+ * Create a new terminal plugin and initialize the terminal emulation.
+ */
+ public Terminal(PluginBus bus) {
+ super(bus);
+ terminal = new vt320() {
+ public void write(byte[] b) {
+ try {
+ Terminal.this.write(b);
+ } catch(IOException e) {
+ reader = null;
+ }
+ }
+ };
+
+ // register an online status listener
+ bus.registerPluginListener(new OnlineStatusListener() {
+ public void online() {
+ if(debug > 0) System.err.println("Terminal: online");
+ if(reader == null) {
+ reader = new Thread(Terminal.this);
+ reader.start();
+ }
+ }
+
+ public void offline() {
+ if(debug > 0) System.err.println("Terminal: offline");
+ if(reader != null)
+ reader = null;
+ }
+ });
+
+ bus.registerPluginListener(new TerminalTypeListener() {
+ public String getTerminalType() {
+ return terminal.getTerminalID();
+ }
+ });
+
+ bus.registerPluginListener(new WindowSizeListener() {
+ public Dimension getWindowSize() {
+ return terminal.getScreenSize();
+ }
+ });
+
+ bus.registerPluginListener(new LocalEchoListener() {
+ public void setLocalEcho(boolean echo) {
+ terminal.setLocalEcho(echo);
+ }
+ });
+
+ bus.registerPluginListener(new ConfigurationListener() {
+ public void setConfiguration(Properties config) {
+ configure(config);
+ }
+ });
+ }
+
+ private void configure(Properties config) {
+ Enumeration p = config.keys();
+
+ while(p.hasMoreElements()) {
+ String key = (String)p.nextElement();
+ if(key.startsWith("Terminal.")) {
+ if(key.equals("Terminal.foreground"))
+ terminal.setForeground(Color.decode(config.getProperty(key)));
+ else if(key.equals("Terminal.background"))
+ terminal.setBackground(Color.decode(config.getProperty(key)));
+ else if(key.equals("Terminal.colorSet"))
+ System.err.println("Terminal.colorSet not implemented yet");
+ else if(key.equals("Terminal.borderRaised"))
+ /* do nothing */ ;
+ else if(key.equals("Terminal.border")) {
+ boolean raised = false;
+ if(config.contains("Terminal.borderStyle"))
+ raised = Boolean.getBoolean("Terminal.borderRaised");
+ terminal.setBorder(Integer.parseInt(config.getProperty(key)),
+ raised);
+ } else if(key.equals("Terminal.borderColor"))
+ terminal.setBackground(Color.decode(config.getProperty(key)));
+ else if(key.equals("Terminal.scrollBar"))
+ System.err.println("Terminal.scrollBar not implemented yet");
+ else if(key.equals("Terminal.id"))
+ terminal.setTerminalID(config.getProperty(key));
+ else if(key.equals("Terminal.buffer"))
+ terminal.setBufferSize(Integer.parseInt(config.getProperty(key)));
+ else if(key.equals("Terminal.size"))
+ System.err.println("Terminal.size not implemented yet");
+ else if(key.equals("Terminal.resize")) {
+ String resize = config.getProperty("Terminal.resize");
+ if(resize.equals("font"))
+ terminal.setResizeStrategy(terminal.RESIZE_FONT);
+ else if(resize.equals("screen"))
+ terminal.setResizeStrategy(terminal.RESIZE_SCREEN);
+ else
+ terminal.setResizeStrategy(terminal.RESIZE_NONE);
+ } else if(key.equals("Terminal.fontSize") ||
+ key.equals("Terminal.fontStyle"))
+ /* do nothing */ ;
+ else if(key.equals("Terminal.font")) {
+ int style = Font.PLAIN, fsize = 12;
+ if(config.containsKey("Terminal.fontSize"))
+ fsize = Integer.parseInt(config.getProperty("Terminal.fontSize"));
+ String fontStyle = config.getProperty("Terminal.fontStyle");
+ if(fontStyle == null || fontStyle.equals("plain"))
+ style = Font.PLAIN;
+ else if(fontStyle.equals("bold"))
+ style = Font.BOLD;
+ else if(fontStyle.equals("italic"))
+ style = Font.ITALIC;
+ System.err.println(new Font(config.getProperty(key), style, fsize));
+ terminal.setFont(new Font(config.getProperty(key), style, fsize));
+ } else if(key.equals("Terminal.keyCodes"))
+ System.err.println("Terminal.keyCodes not implemented yet");
+ else if(key.equals("Terminal.VMS"))
+ terminal.setVMS(Boolean.getBoolean(config.getProperty(key)));
+ else if(key.equals("Terminal.IBM"))
+ terminal.setIBMCharset(Boolean.getBoolean(config.getProperty(key)));
+ else
+ System.err.println("Error: '"+key+"' is not a Terminal property");
+ }
+ }
+ }
+
+ /**
+ * Continuously read from our back end and display the data on screen.
+ */
+ public void run() {
+ byte[] t, b = new byte[256];
+ int n = 0;
+ while(n >= 0) try {
+ n = read(b);
+ if(n > 0) terminal.putString(new String(b, 0, n));
+ } catch(IOException e) {
+ reader = null;
+ return;
+ }
+ }
+
+ protected FilterPlugin source;
+
+ public void setFilterSource(FilterPlugin source) {
+ if(debug > 0) System.err.println("Terminal: connected to: "+source);
+ this.source = source;
+ }
+
+ public int read(byte[] b) throws IOException {
+ return source.read(b);
+ }
+
+ public void write(byte[] b) throws IOException {
+ source.write(b);
+ }
+
+ public Component getPluginVisual() {
+ return terminal;
+ }
+
+ public Menu getPluginMenu() {
+ return null;
+ }
+}
blob - /dev/null
blob + a28236e63498f21f2d5ae26e722d0210006f450d (mode 644)
--- /dev/null
+++ de/mud/telnet/TelnetProtocolHandler.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.telnet;
+
+import java.io.IOException;
+import java.awt.Dimension;
+
+/**
+ * This is a telnet protocol handler. The handler needs implementations
+ * for several methods to handle the telnet options and to be able to
+ * read and write the buffer.
+ * <P>
+ * <B>Maintainer:</B> Marcus Meißner
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public abstract class TelnetProtocolHandler {
+ /** contains the current revision id */
+ public final static String ID = "$Id$";
+
+ /** debug level */
+ private final static int debug = 0;
+
+ /**
+ * Create a new telnet protocol handler.
+ */
+ public TelnetProtocolHandler() {
+ reset();
+ }
+
+ /**
+ * Get the current terminal type for TTYPE telnet option.
+ * @return the string id of the terminal
+ */
+ protected abstract String getTerminalType();
+
+ /**
+ * Get the current window size of the terminal for the
+ * NAWS telnet option.
+ * @return the size of the terminal as Dimension
+ */
+ protected abstract Dimension getWindowSize();
+
+ /**
+ * Set the local echo option of telnet.
+ * @param echo true for local echo, false for no local echo
+ */
+ protected abstract void setLocalEcho(boolean echo);
+
+ /**
+ * Send data to the remote host.
+ * @param b array of bytes to send
+ */
+ protected abstract void write(byte[] b) throws IOException;
+
+ /**
+ * Send one byte to the remote host.
+ * @param b the byte to be sent
+ * @see #write(byte[] b)
+ */
+ private static byte[] one = new byte[1];
+ private void write(byte b) throws IOException {
+ one[0] = b;
+ write(one);
+ }
+
+ /**
+ * Reset the protocol handler. This may be necessary after the
+ * connection was closed or some other problem occured.
+ */
+ public void reset() {
+ neg_state = 0;
+ receivedDX = new byte[256];
+ sentDX = new byte[256];
+ receivedWX = new byte[256];
+ sentWX = new byte[256];
+ }
+
+ // ===================================================================
+ // the actual negotiation handling for the telnet protocol follows:
+ // ===================================================================
+
+ /** state variable for telnet negotiation reader */
+ private byte neg_state = 0;
+
+ /** constants for the negotiation state */
+ private final static byte STATE_DATA = 0;
+ private final static byte STATE_IAC = 1;
+ private final static byte STATE_IACSB = 2;
+ private final static byte STATE_IACWILL = 3;
+ private final static byte STATE_IACDO = 4;
+ private final static byte STATE_IACWONT = 5;
+ private final static byte STATE_IACDONT = 6;
+ private final static byte STATE_IACSBIAC = 7;
+ private final static byte STATE_IACSBDATA = 8;
+ private final static byte STATE_IACSBDATAIAC = 9;
+
+ /** What IAC SB <xx> we are handling right now */
+ private byte current_sb;
+
+ /** IAC - init sequence for telnet negotiation. */
+ private final static byte IAC = (byte)255;
+ /** [IAC] End Of Record */
+ private final static byte EOR = (byte)239;
+ /** [IAC] WILL */
+ private final static byte WILL = (byte)251;
+ /** [IAC] WONT */
+ private final static byte WONT = (byte)252;
+ /** [IAC] DO */
+ private final static byte DO = (byte)253;
+ /** [IAC] DONT */
+ private final static byte DONT = (byte)254;
+ /** [IAC] Sub Begin */
+ private final static byte SB = (byte)250;
+ /** [IAC] Sub End */
+ private final static byte SE = (byte)240;
+ /** Telnet option: echo text */
+ private final static byte TELOPT_ECHO = (byte)1; /* echo on/off */
+ /** Telnet option: End Of Record */
+ private final static byte TELOPT_EOR = (byte)25; /* end of record */
+ /** Telnet option: Negotiate About Window Size */
+ private final static byte TELOPT_NAWS = (byte)31; /* NA-WindowSize*/
+ /** Telnet option: Terminal Type */
+ private final static byte TELOPT_TTYPE = (byte)24; /* terminal type */
+
+ private final static byte[] IACWILL = { IAC, WILL };
+ private final static byte[] IACWONT = { IAC, WONT };
+ private final static byte[] IACDO = { IAC, DO };
+ private final static byte[] IACDONT = { IAC, DONT };
+ private final static byte[] IACSB = { IAC, SB };
+ private final static byte[] IACSE = { IAC, SE };
+
+ /** Telnet option qualifier 'IS' */
+ private final static byte TELQUAL_IS = (byte)0;
+ /** Telnet option qualifier 'SEND' */
+ private final static byte TELQUAL_SEND = (byte)1;
+
+ /** What IAC DO(NT) request do we have received already ? */
+ private byte[] receivedDX;
+ /** What IAC WILL/WONT request do we have received already ? */
+ private byte[] receivedWX;
+ /** What IAC DO/DONT request do we have sent already ? */
+ private byte[] sentDX;
+ /** What IAC WILL/WONT request do we have sent already ? */
+ private byte[] sentWX;
+
+ /**
+ * Handle an incoming IAC SB <type> <bytes> IAC SE
+ * @param type type of SB
+ * @param sbata byte array as <bytes>
+ * @param sbcount nr of bytes. may be 0 too.
+ */
+ private void handle_sb(byte type, byte[] sbdata, int sbcount)
+ throws IOException {
+ if(debug > 1)
+ System.err.println("TelnetIO.handle_sb("+type+")");
+ switch (type) {
+ case TELOPT_TTYPE:
+ if (sbcount>0 && sbdata[0]==TELQUAL_SEND) {
+ write(IACSB);write(TELOPT_TTYPE);write(TELQUAL_IS);
+ /* FIXME: need more logic here if we use
+ * more than one terminal type
+ */
+ String ttype = getTerminalType();
+ if(ttype == null) ttype = "dumb";
+ write(ttype.getBytes());
+ write(IACSE);
+ }
+
+ }
+ }
+
+ /**
+ * Handle telnet protocol negotiation. The buffer will be parsed
+ * and necessary actions are taken according to the telnet protocol.
+ * See <A HREF="RFC-Telnet-URL">RFC-Telnet</A>
+ * @param buf the byte buffer used for negotiation
+ * @param count the amount of bytes in the buffer
+ * @return a new buffer after negotiation
+ */
+ public int negotiate(byte buf[], int count) throws IOException {
+ // wo faengt buf an bei buf[0] oder bei buf[1]
+ // Leo: bei buf[0]
+ if(debug > 1)
+ System.err.println("TelnetIO.negotiate("+buf+","+count+")");
+ byte nbuf[] = new byte[count];
+ byte sbbuf[] = new byte[count];
+ byte sendbuf[] = new byte[3];
+ byte b,reply;
+ int sbcount = 0;
+ int boffset = 0, noffset = 0;
+
+ while(boffset < count) {
+ b=buf[boffset++];
+ // of course, byte is a signed entity (-128 -> 127)
+ // but apparently the SGI Netscape 3.0 doesn't seem
+ // to care and provides happily values up to 255
+ if (b>=128)
+ b=(byte)((int)b-256);
+ switch (neg_state) {
+ case STATE_DATA:
+ if (b==IAC)
+ neg_state = STATE_IAC;
+ else
+ nbuf[noffset++]=b;
+ break;
+ case STATE_IAC:
+ switch (b) {
+ case IAC:
+ if(debug > 2) System.err.print("IAC ");
+ neg_state = STATE_DATA;
+ nbuf[noffset++]=IAC;
+ break;
+ case WILL:
+ if(debug > 2) System.err.print("WILL ");
+ neg_state = STATE_IACWILL;
+ break;
+ case WONT:
+ if(debug > 2) System.err.print("WONT ");
+ neg_state = STATE_IACWONT;
+ break;
+ case DONT:
+ if(debug > 2) System.err.print("DONT ");
+ neg_state = STATE_IACDONT;
+ break;
+ case DO:
+ if(debug > 2) System.err.print("DO ");
+ neg_state = STATE_IACDO;
+ break;
+ case EOR:
+ if(debug > 2) System.err.print("EOR ");
+ neg_state = STATE_DATA;
+ break;
+ case SB:
+ if(debug > 2) System.err.print("SB ");
+ neg_state = STATE_IACSB;
+ sbcount = 0;
+ break;
+ default:
+ if(debug > 2) System.err.print("<UNKNOWN "+b+" > ");
+ neg_state = STATE_DATA;
+ break;
+ }
+ break;
+ case STATE_IACWILL:
+ switch(b) {
+ case TELOPT_ECHO:
+ if(debug > 2) System.err.println("ECHO");
+ reply = DO;
+ setLocalEcho(false);
+ break;
+ case TELOPT_EOR:
+ if(debug > 2) System.err.println("EOR");
+ reply = DO;
+ break;
+ default:
+ if(debug > 2) System.err.println("<UNKNOWN,"+b+">");
+ reply = DONT;
+ break;
+ }
+ if(debug > 1) System.err.println("<"+b+", WILL ="+WILL+">");
+ if (reply != sentDX[b+128] || WILL != receivedWX[b+128]) {
+ sendbuf[0]=IAC;
+ sendbuf[1]=reply;
+ sendbuf[2]=b;
+ write(sendbuf);
+ sentDX[b+128] = reply;
+ receivedWX[b+128] = WILL;
+ }
+ neg_state = STATE_DATA;
+ break;
+ case STATE_IACWONT:
+ switch(b) {
+ case TELOPT_ECHO:
+ if(debug > 2) System.err.println("ECHO");
+ setLocalEcho(true);
+ reply = DONT;
+ break;
+ case TELOPT_EOR:
+ if(debug > 2) System.err.println("EOR");
+ reply = DONT;
+ break;
+ default:
+ if(debug > 2) System.err.println("<UNKNOWN,"+b+">");
+ reply = DONT;
+ break;
+ }
+ if(reply != sentDX[b+128] || WONT != receivedWX[b+128]) {
+ sendbuf[0]=IAC;
+ sendbuf[1]=reply;
+ sendbuf[2]=b;
+ write(sendbuf);
+ sentDX[b+128] = reply;
+ receivedWX[b+128] = WILL;
+ }
+ neg_state = STATE_DATA;
+ break;
+ case STATE_IACDO:
+ switch (b) {
+ case TELOPT_ECHO:
+ if(debug > 2) System.err.println("ECHO");
+ reply = WILL;
+ setLocalEcho(true);
+ break;
+ case TELOPT_TTYPE:
+ if(debug > 2) System.err.println("TTYPE");
+ reply = WILL;
+ break;
+ case TELOPT_NAWS:
+ if(debug > 2) System.err.println("NAWS");
+ Dimension size = getWindowSize();
+ receivedDX[b] = DO;
+ if(size == null) {
+ // this shouldn't happen
+ write(IAC);
+ write(WONT);
+ write(TELOPT_NAWS);
+ reply = WONT;
+ sentWX[b] = WONT;
+ break;
+ }
+ reply = WILL;
+ sentWX[b] = WILL;
+ sendbuf[0]=IAC;
+ sendbuf[1]=WILL;
+ sendbuf[2]=TELOPT_NAWS;
+ write(sendbuf);
+ write(IAC);write(SB);write(TELOPT_NAWS);
+ write((byte) (size.width >> 8));
+ write((byte) (size.width & 0xff));
+ write((byte) (size.height >> 8));
+ write((byte) (size.height & 0xff));
+ write(IAC);write(SE);
+ break;
+ default:
+ if(debug > 2) System.err.println("<UNKNOWN,"+b+">");
+ reply = WONT;
+ break;
+ }
+ if(reply != sentWX[128+b] || DO != receivedDX[128+b]) {
+ sendbuf[0]=IAC;
+ sendbuf[1]=reply;
+ sendbuf[2]=b;
+ write(sendbuf);
+ sentWX[b+128] = reply;
+ receivedDX[b+128] = DO;
+ }
+ neg_state = STATE_DATA;
+ break;
+ case STATE_IACDONT:
+ switch (b) {
+ case TELOPT_ECHO:
+ if(debug > 2) System.err.println("ECHO");
+ reply = WONT;
+ setLocalEcho(false);
+ break;
+ case TELOPT_NAWS:
+ if(debug > 2) System.err.println("NAWS");
+ reply = WONT;
+ break;
+ default:
+ if(debug > 2) System.err.println("<UNKNOWN,"+b+">");
+ reply = WONT;
+ break;
+ }
+ if(reply != sentWX[b+128] || DONT != receivedDX[b+128]) {
+ write(IAC);write(reply);write(b);
+ sentWX[b+128] = reply;
+ receivedDX[b+128] = DONT;
+ }
+ neg_state = STATE_DATA;
+ break;
+ case STATE_IACSBIAC:
+ if(debug > 2) System.err.println(""+b+" ");
+ if (b == IAC) {
+ sbcount = 0;
+ current_sb = b;
+ neg_state = STATE_IACSBDATA;
+ } else {
+ System.err.println("(bad) "+b+" ");
+ neg_state = STATE_DATA;
+ }
+ break;
+ case STATE_IACSB:
+ if(debug > 2) System.err.println(""+b+" ");
+ switch (b) {
+ case IAC:
+ neg_state = STATE_IACSBIAC;
+ break;
+ default:
+ current_sb = b;
+ sbcount = 0;
+ neg_state = STATE_IACSBDATA;
+ break;
+ }
+ break;
+ case STATE_IACSBDATA:
+ if (debug > 2) System.err.println(""+b+" ");
+ switch (b) {
+ case IAC:
+ neg_state = STATE_IACSBDATAIAC;
+ break;
+ default:
+ sbbuf[sbcount++] = b;
+ break;
+ }
+ break;
+ case STATE_IACSBDATAIAC:
+ if (debug > 2) System.err.println(""+b+" ");
+ switch (b) {
+ case IAC:
+ neg_state = STATE_IACSBDATA;
+ sbbuf[sbcount++] = IAC;
+ break;
+ case SE:
+ handle_sb(current_sb,sbbuf,sbcount);
+ current_sb = 0;
+ neg_state = STATE_DATA;
+ break;
+ case SB:
+ handle_sb(current_sb,sbbuf,sbcount);
+ neg_state = STATE_IACSB;
+ break;
+ default:
+ neg_state = STATE_DATA;
+ break;
+ }
+ break;
+ default:
+ if (debug > 2)
+ System.err.println("This should not happen: "+neg_state+" ");
+ neg_state = STATE_DATA;
+ break;
+ }
+ }
+ System.arraycopy(nbuf, 0, buf, 0, noffset);
+ return noffset;
+ }
+}
blob - /dev/null
blob + 53d4cdc95f2c62d72298b476293c3bf00e6c47b5 (mode 644)
--- /dev/null
+++ de/mud/terminal/SoftFont.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.terminal;
+
+import java.awt.*;
+import java.util.*;
+
+/**
+ * Any characters that are not available in standard java fonts may be
+ * drawn using the softfont utility. This utility class was derived from
+ * the cpi fonts used in linux console drivers.<P>
+ * <small>Font file generated by cpi2fnt</small>
+ * <P>
+ * <B>Maintainer:</B> Marcus Meißner
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class SoftFont {
+ final static private char SF_BITMAP = 0;
+ final static private char SF_FILLRECT = 1;
+
+
+ final static private char SF_CHAR = 0;
+ final static private char SF_WIDTH= 1;
+ final static private char SF_HEIGHT= 2;
+ final static private char SF_TYPE = 3;
+ final static private char SF_DATA = 4;
+ java.util.Hashtable font;
+ /** softfont characterdata */
+ private static char[][] fontdata = {
+
+ {0x01,8,8,SF_BITMAP, /* 1 0x01 '^A' */
+ 0x7e, /* 01111110 */
+ 0x81, /* 10000001 */
+ 0xa5, /* 10100101 */
+ 0x81, /* 10000001 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0x81, /* 10000001 */
+ 0x7e, /* 01111110 */
+ },{ 0x02,8,8,SF_BITMAP,/* 2 0x02 '^B' */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xdb, /* 11011011 */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ },{ 0x03,8,8,SF_BITMAP,/* 3 0x03 '^C' */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ },{ 0x04,8,8,SF_BITMAP,/* 4 0x04 '^D' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ },{ 0x05,8,8,SF_BITMAP,/* 5 0x05 '^E' */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ },{ 0x06,8,8,SF_BITMAP,/* 6 0x06 '^F' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ },{ 0x2666,8,8,SF_BITMAP,/* 9830 0x2666 BLACK DIAMOND */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x07,8,8,SF_BITMAP,/* 7 0x07 '^G' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x08,8,8,SF_BITMAP,/* 8 0x08 '^H' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xe7, /* 11100111 */
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ },{ 0x09,8,8,SF_BITMAP,/* 9 0x09 '^I' */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x42, /* 01000010 */
+ 0x42, /* 01000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ },{ 0x0a,8,8,SF_BITMAP,/* 10 0x0a '^J' */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0x99, /* 10011001 */
+ 0xbd, /* 10111101 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0xc3, /* 11000011 */
+ 0xff, /* 11111111 */
+ },{ 0x0b,8,8,SF_BITMAP,/* 11 0x0b '^K' */
+ 0x0f, /* 00001111 */
+ 0x07, /* 00000111 */
+ 0x0f, /* 00001111 */
+ 0x7d, /* 01111101 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ },{ 0x0c,8,8,SF_BITMAP,/* 12 0x0c '^L' */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ },{ 0x0d,8,8,SF_BITMAP,/* 13 0x0d '^M' */
+ 0x3f, /* 00111111 */
+ 0x33, /* 00110011 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x70, /* 01110000 */
+ 0xf0, /* 11110000 */
+ 0xe0, /* 11100000 */
+ },{ 0x0e,8,8,SF_BITMAP,/* 14 0x0e '^N' */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x67, /* 01100111 */
+ 0xe6, /* 11100110 */
+ 0xc0, /* 11000000 */
+ },{ 0x0f,8,8,SF_BITMAP,/* 15 0x0f '^O' */
+ 0x18, /* 00011000 */
+ 0xdb, /* 11011011 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0x3c, /* 00111100 */
+ 0xdb, /* 11011011 */
+ 0x18, /* 00011000 */
+ },{ 0x10,8,8,SF_BITMAP,/* 16 0x10 '^P' */
+ 0x80, /* 10000000 */
+ 0xe0, /* 11100000 */
+ 0xf8, /* 11111000 */
+ 0xfe, /* 11111110 */
+ 0xf8, /* 11111000 */
+ 0xe0, /* 11100000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+ },{ 0x11,8,8,SF_BITMAP,/* 17 0x11 '^Q' */
+ 0x02, /* 00000010 */
+ 0x0e, /* 00001110 */
+ 0x3e, /* 00111110 */
+ 0xfe, /* 11111110 */
+ 0x3e, /* 00111110 */
+ 0x0e, /* 00001110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+ },{ 0x12,8,8,SF_BITMAP,/* 18 0x12 '^R' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ },{ 0x13,8,8,SF_BITMAP,/* 19 0x13 '^S' */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ },{ 0x14,8,8,SF_BITMAP,/* 20 0x14 '^T' */
+ 0x7f, /* 01111111 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7b, /* 01111011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x00, /* 00000000 */
+ },{ 0x15,8,8,SF_BITMAP,/* 21 0x15 '^U' */
+ 0x3e, /* 00111110 */
+ 0x61, /* 01100001 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x86, /* 10000110 */
+ 0x7c, /* 01111100 */
+ },{ 0x16,8,8,SF_BITMAP,/* 22 0x16 '^V' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ },{ 0x17,8,8,SF_BITMAP,/* 23 0x17 '^W' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ },{ 0x18,8,8,SF_BITMAP,/* 24 0x18 '^X' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ },{ 0x19,8,8,SF_BITMAP,/* 25 0x19 '^Y' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ },{ 0x1a,8,8,SF_BITMAP,/* 26 0x1a '^Z' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x1b,8,8,SF_BITMAP,/* 27 0x1b '^[' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x1c,8,8,SF_BITMAP,/* 28 0x1c '^\' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x1d,8,8,SF_BITMAP,/* 29 0x1d '^]' */
+ 0x00, /* 00000000 */
+ 0x24, /* 00100100 */
+ 0x66, /* 01100110 */
+ 0xff, /* 11111111 */
+ 0x66, /* 01100110 */
+ 0x24, /* 00100100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x1e,8,8,SF_BITMAP,/* 30 0x1e '^^' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x1f,8,8,SF_BITMAP,/* 31 0x1f '^_' */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x7f,8,8,SF_BITMAP,/* 127 0x7f '' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ },{ 0x2591,8,8,SF_BITMAP,/* LIGHT SHADE */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ },{ 0x2592,8,8,SF_BITMAP,/* MEDIUM SHADE */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ },{ 0x2593,8,8,SF_BITMAP,/* DARK SHADE */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ },{ 0x221a,8,8,SF_BITMAP,/* SQUARE ROOT */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ },{ 0x2320,8,8,SF_BITMAP,/* UPPER INTERVAL*/
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ },{ 0x25a0,8,8,SF_FILLRECT,/* BLACK SQUARE */
+ 0x2244,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00111100 */
+ /* 00111100 */
+ /* 00111100 */
+ /* 00111100 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2502,8,8,SF_FILLRECT,/*BOX DRAWINGS LIGHT VERTICAL*/
+ 0x3028,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2524,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+ 0x3028,
+ 0x0431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2561,8,8,SF_FILLRECT,/*BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE*/
+ 0x3028,
+ 0x0231,
+ 0x0431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2562,8,8,SF_FILLRECT,/* BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE */
+ 0x2028,
+ 0x5028,
+ 0x0421,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 11110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2556,8,8,SF_FILLRECT,/* BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE */
+ 0x0471,
+ 0x2523,
+ 0x5523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2555,8,8,SF_FILLRECT,/* BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE */
+ 0x3226,
+ 0x0231,
+ 0x0431,
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2563,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE VERTICAL AND LEFT*/
+ 0x2022,
+ 0x0221,
+ 0x0421,
+ 0x2424,
+ 0x5028,
+ /* 00110110 */
+ /* 00110110 */
+ /* 11110110 */
+ /* 00000110 */
+ /* 11110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2551,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE VERTICAL */
+ 0x2028,
+ 0x5028,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2557,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE DOWN AND LEFT */
+ 0x0271,
+ 0x5325,
+ 0x0441,
+ 0x2523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111110 */
+ /* 00000110 */
+ /* 11110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x255d,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE UP AND LEFT */
+ 0x2022,
+ 0x0241,
+ 0x5025,
+ 0x0451,
+ /* 00110110 */
+ /* 00110110 */
+ /* 11110110 */
+ /* 00000110 */
+ /* 11111110 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x255c,8,8,SF_FILLRECT,/* BOX DRAWINGS UP DOUBLE AND LEFT SINGLE */
+ 0x2024,
+ 0x5024,
+ 0x0471,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 11111110 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x255b,8,8,SF_FILLRECT,/* BOX DRAWINGS UP SINGLE AND LEFT DOUBLE */
+ 0x3025,
+ 0x0231,
+ 0x0431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2510,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT DOWN AND LEFT */
+ 0x0451,
+ 0x3523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2514,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT UP AND RIGHT */
+ 0x3025,
+ 0x5431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2534,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+ 0x3024,
+ 0x0481,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x252c,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+ 0x0481,
+ 0x3523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x251c,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+ 0x3028,
+ 0x5431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2500,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT HORIZONTAL */
+ 0x0481,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x253c,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+ 0x3028,
+ 0x0481,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x255e,8,8,SF_FILLRECT,/* BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE */
+ 0x3028,
+ 0x5231,
+ 0x5431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x255f,8,8,SF_FILLRECT,/* BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE */
+ 0x2028,
+ 0x5028,
+ 0x7411,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x255a,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE UP AND RIGHT */
+ 0x2025,
+ 0x5023,
+ 0x7211,
+ 0x4441,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110111 */
+ /* 00110000 */
+ /* 00111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2554,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE DOWN AND RIGHT */
+ 0x2261,
+ 0x2325,
+ 0x5424,
+ 0x7411,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00111111 */
+ /* 00110000 */
+ /* 00110111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2569,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE UP AND HORIZONTAL */
+ 0x2022,
+ 0x0241,
+ 0x5022,
+ 0x5231,
+ 0x0481,
+ /* 00110110 */
+ /* 00110110 */
+ /* 11110111 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2566,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL */
+ 0x0281,
+ 0x0441,
+ 0x2523,
+ 0x5431,
+ 0x5523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 11110111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2560,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE VERTICAL AND RIGHT */
+ 0x2028,
+ 0x5022,
+ 0x5231,
+ 0x5431,
+ 0x5623,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110111 */
+ /* 00110000 */
+ /* 00110111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2550,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE HORIZONTAL */
+ 0x0281,
+ 0x0481,
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x256c,8,8,SF_FILLRECT,/* BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL */
+ 0x2022,
+ 0x0241,
+ 0x5022,
+ 0x5231,
+ 0x0441,
+ 0x2523,
+ 0x5431,
+ 0x5523,
+ /* 00110110 */
+ /* 00110110 */
+ /* 11110111 */
+ /* 00000000 */
+ /* 11110111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2567,8,8,SF_FILLRECT,/* BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE */
+ 0x3022,
+ 0x0281,
+ 0x0481,
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2568,8,8,SF_FILLRECT,/* BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE */
+ 0x2024,
+ 0x5024,
+ 0x0481,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2564,8,8,SF_FILLRECT,/* BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE */
+ 0x0281,
+ 0x0481,
+ 0x3523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2565,8,8,SF_FILLRECT,/* BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE */
+ 0x0481,
+ 0x2523,
+ 0x5523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x2559,8,8,SF_FILLRECT,/* BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE */
+ 0x2024,
+ 0x5024,
+ 0x2461,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2558,8,8,SF_FILLRECT,/* BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE */
+ 0x3025,
+ 0x5231,
+ 0x5431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x2552,8,8,SF_FILLRECT,/* BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE */
+ 0x3226,
+ 0x5231,
+ 0x5431,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2553,8,8,SF_FILLRECT,/* BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE */
+ 0x2461,
+ 0x2523,
+ 0x5523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00111111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x256b,8,8,SF_FILLRECT,/* BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE */
+ 0x2028,
+ 0x5028,
+ 0x0481,
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 11111111 */
+ /* 00110110 */
+ /* 00110110 */
+ /* 00110110 */
+ },{ 0x256a,8,8,SF_FILLRECT,/* BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE */
+ 0x3028,
+ 0x0281,
+ 0x0481,
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111111 */
+ /* 00011000 */
+ /* 11111111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2518,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT UP AND LEFT */
+ 0x3025,
+ 0x0431,
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 11111000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ },{ 0x250c,8,8,SF_FILLRECT,/* BOX DRAWINGS LIGHT DOWN AND RIGHT */
+ 0x3451,
+ 0x3523,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00011111 */
+ /* 00011000 */
+ /* 00011000 */
+ /* 00011000 */
+ },{ 0x2588,8,8,SF_FILLRECT,/* FULL BLOCK */
+ 0x0088,
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ },{ 0x2584,8,8,SF_FILLRECT,/* LOWER HALF BLOCK */
+ 0x0484,
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ },{ 0x258c,8,8,SF_FILLRECT,/* LEFT HALF BLOCK */
+ 0x0048,
+ /* 11110000 */
+ /* 11110000 */
+ /* 11110000 */
+ /* 11110000 */
+ /* 11110000 */
+ /* 11110000 */
+ /* 11110000 */
+ /* 11110000 */
+ },{ 0x2590,8,8,SF_FILLRECT,/* RIGHT HALF BLOCK */
+ 0x4048,
+ /* 00001111 */
+ /* 00001111 */
+ /* 00001111 */
+ /* 00001111 */
+ /* 00001111 */
+ /* 00001111 */
+ /* 00001111 */
+ /* 00001111 */
+ },{ 0x2580,8,8,SF_FILLRECT,/* UPPER HALF BLOCK */
+ 0x0084,
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 11111111 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ /* 00000000 */
+ }};
+
+ public SoftFont() {
+ font = new java.util.Hashtable();
+ for (int i=0;i<fontdata.length;i++)
+ font.put(new Integer(fontdata[i][0]),new Integer(i));
+
+ }
+
+ public boolean inSoftFont(char c) {
+ boolean insoftfont;
+
+ insoftfont = (null!=font.get(new Integer(c)));
+ if (!insoftfont && (int)c>=0x100) {
+ System.out.println("Character "+((int)c)+" not in softfont");
+ }
+ return insoftfont;
+ }
+
+ public void drawChar(Graphics g,char c,int x,int y,int cw,int ch) {
+ double dw,dh;
+ Object Ientry;
+ int w,h,entry,i,fontwidth,fontheight;
+
+ Ientry = font.get(new Integer(c));
+ if (Ientry == null)
+ return;
+ entry = ((Integer)Ientry).intValue();
+ fontwidth = fontdata[entry][SF_WIDTH];
+ fontheight = fontdata[entry][SF_HEIGHT];
+
+ dw = cw*1.0/fontwidth;
+ dh = ch*1.0/fontheight;
+
+ switch (fontdata[entry][SF_TYPE]) {
+ case SF_BITMAP:
+ for (h=0;h<fontheight;h++) {
+ for (w=0;w<fontwidth;w++) {
+ //FIXME: 8 bit max currently...
+ if (0!=(fontdata[entry][h+SF_DATA] & (1<<(7-w)))) {
+ g.fillRect(
+ x+(int)(w*dw),
+ y+(int)(h*dh),
+ ((int)((w+1)*dw))-(int)(w*dw),
+ ((int)((h+1)*dh))-(int)(h*dh)
+ );
+ }
+ }
+ }
+ break;
+ case SF_FILLRECT:
+ i=SF_DATA;
+ while (i<fontdata[entry].length) {
+ int xw,xh;
+
+ w=(fontdata[entry][i]&0xF000)>>12;
+ h=(fontdata[entry][i]&0x0F00)>>8;
+ xw = (fontdata[entry][i]&0x00F0)>>4;
+ xh = (fontdata[entry][i]&0x000F);
+ g.fillRect(
+ x+(int)(w*dw),
+ y+(int)(h*dh),
+ ((int)((w+xw)*dw))-(int)(w*dw),
+ ((int)((h+xh)*dh))-(int)(h*dh)
+ );
+ i++;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
blob - /dev/null
blob + baa659369be0ad30a2f8ead65ac57ea3071b7cbb (mode 644)
--- /dev/null
+++ de/mud/terminal/VDU.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.terminal;
+
+import java.awt.Graphics;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Point;
+import java.awt.Insets;
+import java.awt.Event;
+import java.awt.Label;
+import java.awt.Frame;
+import java.awt.Rectangle;
+
+import java.awt.AWTEvent;
+
+/**
+ * Video Display Unit emulation. This class implements all necessary
+ * features of a character display unit, but not the actual terminal emulation.
+ * It can be used as the base for terminal emulations of any kind.
+ * <P>
+ * <B>Maintainer:</B> Matthias L. Jugel
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public class VDU extends Canvas {
+ /** The current version id tag */
+ public final static String ID = "$Id$";
+
+ /** Enable debug messages. */
+ public final static int debug = 0;
+
+ private Dimension size; /* rows and columns */
+ private Insets insets; /* size of the border */
+ private boolean raised; /* indicator if the border is raised */
+
+ private char charArray[][]; /* contains the characters */
+ private int charAttributes[][]; /* contains character attrs */
+ private int bufSize, maxBufSize; /* buffer sizes */
+
+ private int windowBase; /* where the start displaying */
+ private int screenBase; /* the actual screen start */
+ private int topMargin; /* top scroll margin */
+ private int bottomMargin; /* bottom scroll margin */
+
+ private Font normalFont; /* normal font */
+ private FontMetrics fm; /* current font metrics */
+ private int charWidth; /* current width of a char */
+ private int charHeight; /* current height of a char */
+ private int charDescent; /* base line descent */
+ private int resizeStrategy; /* current resizing strategy */
+
+ private int cursorX, cursorY; /* current cursor position */
+ private Point selectBegin, selectEnd; /* selection coordinates */
+
+ private SoftFont sf = new SoftFont();
+
+ private boolean screenLocked = false; /* screen needs to be locked */
+ /* because of paint requests */
+ /* during other operations */
+ private boolean update[]; /* contains the lines that need update */
+
+ /**
+ * Create a color representation that is brighter than the standard
+ * color but not what we would like to use for bold characters.
+ * @param clr the standard color
+ * @return the new brighter color
+ */
+ private Color brighten(Color clr) {
+ return new Color(Math.max((int) (clr.getRed() *.85), 0),
+ Math.max((int) (clr.getGreen() * .85), 0),
+ Math.max((int) (clr.getBlue() * .85), 0));
+ }
+
+ /** A list of colors used for representation of the display */
+ private Color color[] = { brighten(Color.black),
+ brighten(Color.red),
+ brighten(Color.green),
+ brighten(Color.yellow),
+ brighten(Color.blue),
+ brighten(Color.magenta),
+ brighten(Color.cyan),
+ brighten(Color.white),
+ };
+
+ public final static int COLOR_0 = 0;
+ public final static int COLOR_1 = 1;
+ public final static int COLOR_2 = 2;
+ public final static int COLOR_3 = 3;
+ public final static int COLOR_4 = 4;
+ public final static int COLOR_5 = 5;
+ public final static int COLOR_6 = 6;
+ public final static int COLOR_7 = 7;
+
+ /* definitions of standards for the display unit */
+ private static int COLOR_FG_STD = 7;
+ private static int COLOR_FG_BOLD = 3;
+ private static int COLOR_BG_STD = 0;
+ private final static int COLOR = 0x7f8;
+ private final static int COLOR_FG = 0x78;
+ private final static int COLOR_BG = 0x780;
+
+ /** Scroll up when inserting a line. */
+ public final static boolean SCROLL_UP = false;
+ /** Scroll down when inserting a line. */
+ public final static boolean SCROLL_DOWN = true;
+
+ /** Do nothing when the component is resized. */
+ public final static int RESIZE_NONE = 0;
+ /** Resize the width and height of the character screen. */
+ public final static int RESIZE_SCREEN = 1;
+ /** Resize the font to the new screen size. */
+ public final static int RESIZE_FONT = 2;
+
+ /** Make character normal. */
+ public final static int NORMAL = 0x00;
+ /** Make character bold. */
+ public final static int BOLD = 0x01;
+ /** Underline character. */
+ public final static int UNDERLINE = 0x02;
+ /** Invert character. */
+ public final static int INVERT = 0x04;
+
+ /**
+ * Create a new video display unit with the passed width and height in
+ * characters using a special font and font size. These features can
+ * be set independently using the appropriate properties.
+ * @param width the length of the character lines
+ * @param height the amount of lines on the screen
+ * @param font the font to be used (usually Monospaced)
+ */
+ public VDU(int width, int height, Font font) {
+ // set the normal font to use
+ setFont(font);
+ // set the standard resize strategy
+ setResizeStrategy(RESIZE_FONT);
+ // set the display screen size
+ setScreenSize(width, height);
+
+ selectBegin = new Point(0,0);
+ selectEnd = new Point(0,0);
+ }
+
+ /**
+ * Create a display unit with specific size, Font is "Monospaced", size 12.
+ * @param width the length of the character lines
+ * @param height the amount of lines on the screen
+ */
+ public VDU(int width, int height) {
+ this(width, height, new Font("Monospaced", Font.PLAIN, 12));
+ }
+
+ /**
+ * Create a display with the font passed and size 80x24.
+ * @param font the font to be used (usually Monospaced)
+ */
+ public VDU(Font font) {
+ this(80, 24, font);
+ }
+
+ /**
+ * Create a display unit with size 80x24 and Font "Monospaced", size 12.
+ */
+ public VDU() {
+ this(80, 24, new Font("Monospaced", Font.PLAIN, 12));
+ }
+
+ public void setColorSet(Color[] colorset) {
+ System.arraycopy(colorset, 0, color, 0, 8);
+ }
+
+ public Color[] getColorSet() {
+ return color;
+ }
+
+ /**
+ * Put a character on the screen with normal font and outline.
+ * The character previously on that position will be overwritten.
+ * You need to call redraw() to update the screen.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @param ch the character to show on the screen
+ * @see #insertChar
+ * @see #deleteChar
+ * @see #redraw
+ */
+ public void putChar(int c, int l, char ch) {
+ putChar(c, l, ch, NORMAL);
+ }
+
+ /**
+ * Put a character on the screen with specific font and outline.
+ * The character previously on that position will be overwritten.
+ * You need to call redraw() to update the screen.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @param ch the character to show on the screen
+ * @param attributes the character attributes
+ * @see #BOLD
+ * @see #UNDERLINE
+ * @see #INVERT
+ * @see #NORMAL
+ * @see #insertChar
+ * @see #deleteChar
+ * @see #redraw
+ */
+
+ public void putChar(int c, int l, char ch, int attributes) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+ charArray[screenBase + l][c] = ch;
+ charAttributes[screenBase + l][c] = attributes;
+ markLine(l, 1);
+ }
+
+ /**
+ * Get the character at the specified position.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @see #putChar
+ */
+ public char getChar(int c, int l) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+ return charArray[l][c];
+ }
+
+ /**
+ * Get the attributes for the specified position.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @see #putChar
+ */
+ public int getAttributes(int c, int l) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+ return charAttributes[l][c];
+ }
+
+ /**
+ * Insert a character at a specific position on the screen.
+ * All character right to from this position will be moved one to the right.
+ * You need to call redraw() to update the screen.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @param ch the character to insert
+ * @param attributes the character attributes
+ * @see #BOLD
+ * @see #UNDERLINE
+ * @see #INVERT
+ * @see #NORMAL
+ * @see #putChar
+ * @see #deleteChar
+ * @see #redraw
+ */
+ public void insertChar(int c, int l, char ch, int attributes) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+ System.arraycopy(charArray[screenBase + l], c,
+ charArray[screenBase + l], c + 1, size.width - c - 1);
+ System.arraycopy(charAttributes[screenBase + l], c,
+ charAttributes[screenBase + l], c + 1, size.width - c - 1);
+ putChar(c, l, ch, attributes);
+ }
+
+ /**
+ * Delete a character at a given position on the screen.
+ * All characters right to the position will be moved one to the left.
+ * You need to call redraw() to update the screen.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @see #putChar
+ * @see #insertChar
+ * @see #redraw
+ */
+ public void deleteChar(int c, int l) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+ if(c < size.width - 1) {
+ System.arraycopy(charArray[screenBase + l], c + 1,
+ charArray[screenBase + l], c, size.width - c - 1);
+ System.arraycopy(charAttributes[screenBase + l], c + 1,
+ charAttributes[screenBase + l], c, size.width - c - 1);
+ }
+ putChar(size.width - 1, l, (char)0);
+ }
+
+ /**
+ * Put a String at a specific position. Any characters previously on that
+ * position will be overwritten. You need to call redraw() for screen update.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @param s the string to be shown on the screen
+ * @see #BOLD
+ * @see #UNDERLINE
+ * @see #INVERT
+ * @see #NORMAL
+ * @see #putChar
+ * @see #insertLine
+ * @see #deleteLine
+ * @see #redraw
+ */
+ public void putString(int c, int l, String s) {
+ putString(c, l, s, NORMAL);
+ }
+
+ /**
+ * Put a String at a specific position giving all characters the same
+ * attributes. Any characters previously on that position will be
+ * overwritten. You need to call redraw() to update the screen.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (line)
+ * @param s the string to be shown on the screen
+ * @param attributes character attributes
+ * @see #BOLD
+ * @see #UNDERLINE
+ * @see #INVERT
+ * @see #NORMAL
+ * @see #putChar
+ * @see #insertLine
+ * @see #deleteLine
+ * @see #redraw
+ */
+ public void putString(int c, int l, String s, int attributes) {
+ for(int i = 0; i < s.length() && c + i < size.width; i++)
+ putChar(c + i, l, s.charAt(i), attributes);
+ }
+
+ /**
+ * Insert a blank line at a specific position.
+ * The current line and all previous lines are scrolled one line up. The
+ * top line is lost. You need to call redraw() to update the screen.
+ * @param l the y-coordinate to insert the line
+ * @see #deleteLine
+ * @see #redraw
+ */
+ public void insertLine(int l) {
+ insertLine(l, 1, SCROLL_UP);
+ }
+
+ /**
+ * Insert blank lines at a specific position.
+ * You need to call redraw() to update the screen
+ * @param l the y-coordinate to insert the line
+ * @param n amount of lines to be inserted
+ * @see #deleteLine
+ * @see #redraw
+ */
+ public void insertLine(int l, int n) {
+ insertLine(l, n, SCROLL_UP);
+ }
+
+ /**
+ * Insert a blank line at a specific position. Scroll text according to
+ * the argument.
+ * You need to call redraw() to update the screen
+ * @param l the y-coordinate to insert the line
+ * @param scrollDown scroll down
+ * @see #deleteLine
+ * @see #SCROLL_UP
+ * @see #SCROLL_DOWN
+ * @see #redraw
+ */
+ public void insertLine(int l, boolean scrollDown) {
+ insertLine(l, 1, scrollDown);
+ }
+
+ /**
+ * Insert blank lines at a specific position.
+ * The current line and all previous lines are scrolled one line up. The
+ * top line is lost. You need to call redraw() to update the screen.
+ * @param l the y-coordinate to insert the line
+ * @param n number of lines to be inserted
+ * @param scrollDown scroll down
+ * @see #deleteLine
+ * @see #SCROLL_UP
+ * @see #SCROLL_DOWN
+ * @see #redraw
+ */
+ public synchronized void insertLine(int l, int n, boolean scrollDown) {
+ screenLocked = true;
+
+ l = checkBounds(l, 0, size.height - 1);
+
+ char cbuf[][] = null;
+ int abuf[][] = null;
+ int offset = 0;
+ int oldBase = screenBase;
+ int top = (l < topMargin ?
+ 0 : (l > bottomMargin ?
+ (bottomMargin + 1 < size.height ?
+ bottomMargin + 1 : size.height - 1) : topMargin));
+ int bottom = (l > bottomMargin ?
+ size.height - 1 : (l < topMargin ?
+ (topMargin > 0 ?
+ topMargin - 1 : 0) : bottomMargin));
+
+
+ if(scrollDown) {
+ if(n > (bottom - top)) n = (bottom - top);
+ cbuf = new char[bottom - l - (n - 1)][size.width];
+ abuf = new int[bottom - l - (n - 1)][size.width];
+
+ System.arraycopy(charArray, oldBase + l, cbuf, 0, bottom - l - (n - 1));
+ System.arraycopy(charAttributes, oldBase + l,
+ abuf, 0, bottom - l - (n - 1));
+ System.arraycopy(cbuf, 0, charArray, oldBase + l + n,
+ bottom - l - (n - 1));
+ System.arraycopy(abuf, 0, charAttributes, oldBase + l + n,
+ bottom - l - (n - 1));
+ cbuf = charArray;
+ abuf = charAttributes;
+ } else try {
+ if(n > (bottom - top) + 1) n = (bottom - top) + 1;
+ if(bufSize < maxBufSize) {
+ if(bufSize + n > maxBufSize) {
+ offset = n - (maxBufSize - bufSize);
+ bufSize = maxBufSize;
+ screenBase = maxBufSize - size.height - 1;
+ windowBase = screenBase;
+ } else {
+ screenBase += n;
+ windowBase += n;
+ bufSize += n;
+ }
+ cbuf = new char[bufSize][size.width];
+ abuf = new int[bufSize][size.width];
+ } else {
+ offset = n;
+ cbuf = charArray;
+ abuf = charAttributes;
+ }
+ // copy anything from the top of the buffer (+offset) to the new top
+ // up to the screenBase.
+ if(oldBase > 0) {
+ System.arraycopy(charArray, offset,
+ cbuf, 0,
+ oldBase - offset);
+ System.arraycopy(charAttributes, offset,
+ abuf, 0,
+ oldBase - offset);
+ }
+ // copy anything from the top of the screen (screenBase) up to the
+ // topMargin to the new screen
+ if(top > 0) {
+ System.arraycopy(charArray, oldBase,
+ cbuf, screenBase,
+ top);
+ System.arraycopy(charAttributes, oldBase,
+ abuf, screenBase,
+ top);
+ }
+ // copy anything from the topMargin up to the amount of lines inserted
+ // to the gap left over between scrollback buffer and screenBase
+ if(oldBase > 0) {
+ System.arraycopy(charArray, oldBase + top,
+ cbuf, oldBase - offset,
+ n);
+ System.arraycopy(charAttributes, oldBase + top,
+ abuf, oldBase - offset,
+ n);
+ }
+ // copy anything from topMargin + n up to the line linserted to the
+ // topMargin
+ System.arraycopy(charArray, oldBase + top + n,
+ cbuf, screenBase + top,
+ l - top - (n - 1));
+ System.arraycopy(charAttributes, oldBase + top + n,
+ abuf, screenBase + top,
+ l - top - (n - 1));
+ //
+ // copy the all lines next to the inserted to the new buffer
+ if(l < size.height - 1) {
+ System.arraycopy(charArray, oldBase + l + 1,
+ cbuf, screenBase + l + 1,
+ (size.height - 1) - l);
+ System.arraycopy(charAttributes, oldBase + l + 1,
+ abuf, screenBase + l + 1,
+ (size.height - 1) - l);
+ }
+ } catch(ArrayIndexOutOfBoundsException e) {
+ // this should not happen anymore, but I will leave the code
+ // here in case something happens anyway. That code above is
+ // so complex I always have a hard time understanding what
+ // I did, even though there are comments
+ System.err.println("*** Error while scrolling up:");
+ System.err.println("--- BEGIN STACK TRACE ---");
+ e.printStackTrace();
+ System.err.println("--- END STACK TRACE ---");
+ System.err.println("bufSize="+bufSize+", maxBufSize="+maxBufSize);
+ System.err.println("top="+top+", bottom="+bottom);
+ System.err.println("n="+n+", l="+l);
+ System.err.println("screenBase="+screenBase+", windowBase="+windowBase);
+ System.err.println("oldBase="+oldBase);
+ System.err.println("size.width="+size.width+", size.height="+size.height);
+ System.err.println("abuf.length="+abuf.length+", cbuf.length="+cbuf.length);
+ System.err.println("*** done dumping debug information");
+ }
+
+ for(int i = 0; i < n; i++) {
+ cbuf[(screenBase + l) + (scrollDown ? i : -i) ] = new char[size.width];
+ abuf[(screenBase + l) + (scrollDown ? i : -i) ] = new int[size.width];
+ }
+
+ charArray = cbuf;
+ charAttributes = abuf;
+
+ if(scrollDown)
+ markLine(l, bottom - l + 1);
+ else
+ markLine(top, l - top + 1);
+
+ screenLocked = false;
+ }
+
+ /**
+ * Delete a line at a specific position. Subsequent lines will be scrolled
+ * up to fill the space and a blank line is inserted at the end of the
+ * screen.
+ * @param l the y-coordinate to insert the line
+ * @see #deleteLine
+ */
+ public void deleteLine(int l) {
+ l = checkBounds(l, 0, size.height - 1);
+
+ int bottom = (l>bottomMargin?size.height-1:
+ (l<topMargin?topMargin:bottomMargin+1));
+ System.arraycopy(charArray, screenBase + l + 1,
+ charArray, screenBase + l, bottom - l -1 );
+ System.arraycopy(charAttributes, screenBase + l + 1,
+ charAttributes, screenBase + l, bottom - l -1);
+ charArray[screenBase + bottom - 1] = new char[size.width];
+ charAttributes[screenBase + bottom - 1] = new int[size.width];
+ markLine(l, bottom - l);
+ }
+
+
+ /**
+ * Delete a rectangular portion of the screen.
+ * You need to call redraw() to update the screen.
+ * @param c x-coordinate (column)
+ * @param l y-coordinate (row)
+ * @param w with of the area in characters
+ * @param h height of the area in characters
+ * @see #deleteChar
+ * @see #deleteLine
+ * @see redraw
+ */
+ public void deleteArea(int c, int l, int w, int h) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+
+ char cbuf[] = new char[w];
+ int abuf[] = new int[w];
+
+ for(int i = 0; i < h && l + i < size.height; i++)
+ {
+ System.arraycopy(cbuf, 0, charArray[screenBase + l + i], c, w);
+ System.arraycopy(abuf, 0, charAttributes[screenBase + l + i], c, w);
+ }
+ markLine(l, h);
+ }
+
+ /**
+ * Puts the cursor at the specified position.
+ * @param c column
+ * @param l line
+ */
+ public void setCursorPosition(int c, int l) {
+ c = checkBounds(c, 0, size.width - 1);
+ l = checkBounds(l, 0, size.height - 1);
+ markLine(cursorY, 1);
+ cursorX = (c < size.width ? c : size.width);
+ cursorY = (l < size.height ? l : size.height);
+ markLine(l, 1);
+ }
+
+ /**
+ * Get the current cursor position.
+ * @see java.awt.Dimension
+ */
+ public Dimension getCursorPosition() {
+ return new Dimension(cursorX, cursorY);
+ }
+
+ /**
+ * Set the top scroll margin for the screen. If the current bottom margin
+ * is smaller it will become the top margin and the line will become the
+ * bottom margin.
+ * @param l line that is the margin
+ */
+ public void setTopMargin(int l) {
+ if(l > bottomMargin) {
+ topMargin = bottomMargin;
+ bottomMargin = l;
+ }
+ else
+ topMargin = l;
+ if(topMargin < 0) topMargin = 0;
+ if(bottomMargin > size.height - 1) bottomMargin = size.height - 1;
+ }
+
+ /**
+ * Get the top scroll margin.
+ */
+ public int getTopMargin() {
+ return topMargin;
+ }
+
+ /**
+ * Set the bottom scroll margin for the screen. If the current top margin
+ * is bigger it will become the bottom margin and the line will become the
+ * top margin.
+ * @param l line that is the margin
+ */
+ public void setBottomMargin(int l) {
+ if(l < topMargin) {
+ bottomMargin = topMargin;
+ topMargin = l;
+ }
+ else
+ bottomMargin = l;
+ if(topMargin < 0) topMargin = 0;
+ if(bottomMargin > size.height - 1) bottomMargin = size.height - 1;
+ }
+
+ /**
+ * Get the bottom scroll margin.
+ */
+ public int getBottomMargin() {
+ return bottomMargin;
+ }
+
+ /**
+ * Set scrollback buffer size.
+ * @param amount new size of the buffer
+ */
+ public void setBufferSize(int amount) {
+ screenLocked = true;
+
+ if(amount < size.height) amount = size.height;
+ if(amount < maxBufSize) {
+ char cbuf[][] = new char[amount][size.width];
+ int abuf[][] = new int[amount][size.width];
+ if(charArray != null)
+ System.arraycopy(charArray, bufSize - amount, cbuf, 0, amount);
+ if(charAttributes != null)
+ System.arraycopy(charAttributes, bufSize - amount, abuf, 0, amount);
+ charArray = cbuf;
+ charAttributes = abuf;
+ }
+ maxBufSize = amount;
+
+ screenLocked = false;
+
+ repaint();
+ }
+
+ /**
+ * Retrieve current scrollback buffer size.
+ * @see #setBufferSize
+ */
+ public int getBufferSize() {
+ return bufSize;
+ }
+
+ /**
+ * Retrieve maximum buffer Size.
+ * @see #getBufferSize
+ */
+ public int getMaxBufferSize() {
+ return maxBufSize;
+ }
+
+ /**
+ * Set the current window base. This allows to view the scrollback buffer.
+ * @param line the line where the screen window starts
+ * @see setBufferSize
+ * @see getBufferSize
+ */
+ public void setWindowBase(int line) {
+ if(line > screenBase) line = screenBase;
+ else if(line < 0) line = 0;
+ windowBase = line;
+ repaint();
+ }
+
+ /**
+ * Get the current window base.
+ * @see setWindowBase
+ */
+ public int getWindowBase() {
+ return windowBase;
+ }
+
+ /**
+ * Set the font to be used for rendering the characters on screen.
+ * @param font the new font to be used.
+ */
+ public void setFont(Font font) {
+ super.setFont(normalFont = font);
+ fm = getFontMetrics(font);
+ if(fm != null) {
+ charWidth = fm.charWidth('@');
+ charHeight = fm.getHeight();
+ charDescent = fm.getDescent();
+ }
+ }
+
+ /**
+ * Change the size of the screen. This will include adjustment of the
+ * scrollback buffer.
+ * @param columns width of the screen
+ * @param columns height of the screen
+ */
+ public void setScreenSize(int width, int height) {
+ char cbuf[][];
+ int abuf[][];
+ int bsize = bufSize;
+
+ if(width < 1 || height < 1) return;
+
+ if(debug > 0)
+ System.err.println("VDU: screen size ["+width+","+height+"]");
+
+ screenLocked = true;
+
+ // super.update(getGraphics());
+
+ if(height > maxBufSize)
+ maxBufSize = height;
+
+ if(height > bufSize) {
+ bufSize = height;
+ screenBase = 0;
+ windowBase = 0;
+ }
+
+ cbuf = new char[bufSize][width];
+ abuf = new int[bufSize][width];
+
+ if(charArray != null && charAttributes != null)
+ for(int i = 0; i < bsize && i < bufSize; i++) {
+ System.arraycopy(charArray[i], 0, cbuf[i], 0,
+ width < size.width ? width : size.width);
+ System.arraycopy(charAttributes[i], 0, abuf[i], 0,
+ width < size.width ? width : size.width);
+ }
+ charArray = cbuf;
+ charAttributes = abuf;
+ size = new Dimension(width, height);
+ topMargin = 0;
+ bottomMargin = height - 1;
+ update = new boolean[height + 1];
+ for(int i = 0; i <= height; i++) update[i] = true;
+ screenLocked = false;
+ }
+
+ /**
+ * Get the screen size in rows and columns.
+ */
+ public Dimension getScreenSize() {
+ return size;
+ }
+
+ /**
+ * Set the strategy when window is resized.
+ * RESIZE_FONT is default.
+ * @param strategy the strategy
+ * @see #RESIZE_NONE
+ * @see #RESIZE_FONT
+ * @see #RESIZE_SCREEN
+ */
+ public void setResizeStrategy(int strategy) {
+ resizeStrategy = strategy;
+ }
+
+ /**
+ * Get amount of rows on the screen.
+ */
+ public int getRows() { return size.height; }
+
+ /**
+ * Get amount of columns on the screen.
+ */
+ public int getColumns() { return size.width; }
+
+ /**
+ * Set the border thickness and the border type.
+ * @param thickness border thickness in pixels, zero means no border
+ * @param raised a boolean indicating a raised or embossed border
+ */
+ public void setBorder(int thickness, boolean raised) {
+ if(thickness == 0) insets = null;
+ else insets = new Insets(thickness+1, thickness+1,
+ thickness+1, thickness+1);
+ this.raised = raised;
+ }
+
+ /**
+ * Mark lines to be updated with redraw().
+ * @param l starting line
+ * @param n amount of lines to be updated
+ * @see #redraw
+ */
+ public void markLine(int l, int n) {
+ l = checkBounds(l, 0, size.height - 1);
+ for(int i = 0; i < n && l + i < size.height; i++)
+ update[l + i + 1] = true;
+ }
+
+ /**
+ * Redraw marked lines.
+ * @see #markLine
+ */
+ public void redraw() {
+ update[0] = true;
+ repaint();
+ }
+
+ /**
+ * Update the display. to reduce flashing we have overridden this method.
+ */
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ /**
+ * Paint the current screen. All painting is done here. Only lines that have
+ * changed will be redrawn!
+ */
+ public synchronized void paint(Graphics g) {
+ if(screenLocked) return;
+ int xoffset = (super.getSize().width - size.width * charWidth) / 2;
+ int yoffset = (super.getSize().height - size.height * charHeight) / 2;
+
+ Color fg = color[COLOR_FG_STD];
+ Color bg = color[COLOR_BG_STD];
+
+ g.setFont(normalFont);
+
+ for(int l = 0; l < size.height; l++) {
+ if(update[0] && !update[l + 1]) continue;
+ update[l + 1] = false;
+ for(int c = 0; c < size.width; c++) {
+ int addr = 0;
+ int currAttr = charAttributes[windowBase + l][c];
+
+ fg = getForeground();
+ bg = getBackground();
+ // fg = color[COLOR_FG_STD];
+ // bg = color[COLOR_BG_STD];
+
+ // Special handling of BOLD for terminals used on 5ESS
+ if(((currAttr & BOLD) != 0) &&
+ ((currAttr & COLOR_FG) == 0) &&
+ ((currAttr & COLOR_BG) == 0))
+ fg = color[COLOR_FG_BOLD];
+
+ if ((currAttr & COLOR_FG) != 0)
+ fg = color[((currAttr & COLOR_FG) >> 3)-1];
+ if ((currAttr & COLOR_BG) != 0)
+ bg = color[((currAttr & COLOR_BG) >> 7)-1];
+
+ if((currAttr & BOLD) != 0)
+ if(fg.equals(Color.black))
+ fg = Color.gray;
+ else {
+ fg = fg.brighter();
+ bg = bg.brighter();
+ }
+
+ if((currAttr & INVERT) != 0) { Color swapc = bg; bg=fg;fg=swapc; }
+
+ if (sf.inSoftFont(charArray[windowBase + l][c])) {
+ g.setColor(bg);
+ g.fillRect(c * charWidth + xoffset, l * charHeight + yoffset,
+ charWidth, charHeight);
+ g.setColor(fg);
+ sf.drawChar(g,charArray[windowBase + l][c],xoffset+c*charWidth,
+ l*charHeight+yoffset, charWidth, charHeight);
+ if((currAttr & UNDERLINE) != 0)
+ g.drawLine(c * charWidth + xoffset,
+ (l+1) * charHeight - charDescent / 2 + yoffset,
+ c * charWidth + charWidth + xoffset,
+ (l+1) * charHeight - charDescent / 2 + yoffset);
+ continue;
+ }
+
+ // determine the maximum of characters we can print in one go
+ while(c + addr < size.width &&
+ charAttributes[windowBase + l][c + addr] == currAttr &&
+ !sf.inSoftFont(charArray[windowBase + l ][c+addr])
+ ) {
+ if(charArray[windowBase + l][c + addr] < ' ')
+ charArray[windowBase + l][c + addr] = ' ';
+ addr++;
+ }
+
+ // clear the part of the screen we want to change (fill rectangle)
+ g.setColor(bg);
+ g.fillRect(c * charWidth + xoffset, l * charHeight + yoffset,
+ addr * charWidth, charHeight);
+
+ g.setColor(fg);
+
+ // draw the characters
+ g.drawChars(charArray[windowBase + l], c, addr,
+ c * charWidth + xoffset,
+ (l+1) * charHeight - charDescent + yoffset);
+
+ if((currAttr & UNDERLINE) != 0)
+ g.drawLine(c * charWidth + xoffset,
+ (l+1) * charHeight - charDescent / 2 + yoffset,
+ c * charWidth + addr * charWidth + xoffset,
+ (l+1) * charHeight - charDescent / 2 + yoffset);
+
+ c += addr - 1;
+ }
+ }
+
+ // draw cursor
+ if(screenBase + cursorY >= windowBase &&
+ screenBase + cursorY < windowBase + size.height) {
+ g.setColor(color[COLOR_FG_STD]);
+ g.setXORMode(color[COLOR_BG_STD]);
+ g.fillRect( cursorX * charWidth + xoffset,
+ (cursorY + screenBase - windowBase) * charHeight + yoffset,
+ charWidth, charHeight);
+ g.setPaintMode();
+ }
+
+ if(windowBase <= selectBegin.y || windowBase <= selectEnd.y) {
+ int beginLine = selectBegin.y - windowBase;
+ int endLine = selectEnd.y - selectBegin.y;
+ if(beginLine < 0) {
+ endLine += beginLine;
+ beginLine = 0;
+ }
+ if(endLine > size.height) endLine = size.height - beginLine;
+
+ g.setXORMode(color[COLOR_BG_STD]);
+ g.fillRect(selectBegin.x * charWidth + xoffset,
+ beginLine * charHeight + yoffset,
+ (endLine == 0 ? (selectEnd.x - selectBegin.x) :
+ (size.width - selectBegin.x))
+ * charWidth,
+ charHeight);
+ if(endLine > 1)
+ g.fillRect(0 + xoffset,
+ (beginLine + 1) * charHeight + yoffset,
+ size.width * charWidth,
+ (endLine - 1) * charHeight);
+ if(endLine > 0)
+ g.fillRect(0 + xoffset,
+ (beginLine + endLine) * charHeight + yoffset,
+ selectEnd.x * charWidth,
+ charHeight);
+ g.setPaintMode();
+ }
+
+ if(insets != null) {
+ g.setColor(getBackground());
+ xoffset--; yoffset--;
+ for(int i = insets.top - 1; i >= 0; i--)
+ g.draw3DRect(xoffset - i, yoffset - i,
+ charWidth * size.width + 1 + i * 2,
+ charHeight * size.height + 1 + i * 2,
+ raised);
+ }
+
+ update[0] = false;
+ }
+
+ private int checkBounds(int value, int lower, int upper) {
+ if(value < lower) return lower;
+ if(value > upper) return upper;
+ return value;
+ }
+
+ /**
+ * Reshape character display according to resize strategy.
+ * @see #setResizeStrategy
+ */
+ public void setBounds(int x, int y, int w, int h) {
+ if(debug > 0)
+ System.err.println("VDU: setBounds("+x+","+y+","+w+","+h+")");
+
+ int xborder = 0, yborder = 0;
+
+ if(insets != null) {
+ w -= (xborder = insets.left + insets.right);
+ h -= (yborder = insets.top + insets.bottom);
+ }
+
+ if(debug > 0)
+ System.err.println("VDU: looking for better match for "+normalFont);
+
+ Font tmpFont = normalFont;
+ String fontName = normalFont.getName();
+ fm = getFontMetrics(normalFont);
+ if(fm != null) {
+ charWidth = fm.charWidth('@');
+ charHeight = fm.getHeight();
+ }
+
+ switch(resizeStrategy) {
+ case RESIZE_SCREEN:
+ setScreenSize(w / charWidth, size.height = h / charHeight);
+ break;
+ case RESIZE_FONT:
+ int height = h / size.height;
+ int width = w / size.width;
+
+ fm = getFontMetrics(normalFont = new Font(fontName, Font.PLAIN,
+ charHeight));
+
+ // adapt current font size (from small up to best fit)
+ if(fm.getHeight() < height || fm.charWidth('@') < width)
+ do {
+ fm = getFontMetrics(normalFont = new Font(fontName, Font.PLAIN,
+ ++charHeight));
+ } while(fm.getHeight() < height || fm.charWidth('@') < width);
+
+ // now check if we got a font that is too large
+ if(fm.getHeight() > height || fm.charWidth('@') > width)
+ do {
+ fm = getFontMetrics(normalFont = new Font(fontName, Font.PLAIN,
+ --charHeight));
+ } while(charHeight > 1 &&
+ (fm.getHeight() > height ||
+ fm.charWidth('@') > width));
+
+ if(charHeight <= 1) {
+ System.err.println("VDU: error during resize, resetting");
+ normalFont = tmpFont;
+ System.err.println("VDU: disabling font/screen resize");
+ resizeStrategy = RESIZE_NONE;
+ }
+
+ setFont(normalFont);
+ fm = getFontMetrics(normalFont);
+ charWidth = fm.charWidth('@');
+ charHeight = fm.getHeight();
+ charDescent = fm.getDescent();
+ break;
+ case RESIZE_NONE:
+ default:
+ break;
+ }
+ if(debug > 0) {
+ System.err.println("VDU: charWidth="+charWidth+", "+
+ "charHeight="+charHeight+", "+
+ "charDescent="+charDescent);
+ }
+
+ // now set the bounds for the whole component accordingly
+ super.setBounds(x, y, w + xborder, h + yborder);
+ }
+
+ /**
+ * Return the real size in points of the character display.
+ * @return Dimension the dimension of the display
+ * @see java.awt.Dimension
+ */
+ public Dimension getSize() {
+ int xborder = 0, yborder = 0;
+ if(insets != null) {
+ xborder = insets.left + insets.right;
+ yborder = insets.top + insets.bottom;
+ }
+ return new Dimension(size.width * charWidth + xborder,
+ size.height * charHeight + yborder);
+ }
+
+ /**
+ * Return the preferred Size of the character display.
+ * This turns out to be the actual size.
+ * @return Dimension dimension of the display
+ * @see size
+ */
+ public Dimension getPreferredSize() {
+ return getSize();
+ }
+
+ /**
+ * The insets of the character display define the border.
+ * @return Insets border thickness in pixels
+ */
+ public Insets getInsets() {
+ return insets;
+ }
+
+ /**
+ * Handle mouse events for copy & paste
+ * @param evt the event that occured
+ * @return boolean true if action was taken
+ * @see java.awt.Event
+ */
+ /*
+ public void mouseDown(MouseEvent evt) {
+ // handle scrollbar events
+ if(evt != null && evt.arg != null) {
+ int val = ((Integer)evt.arg).intValue();
+ setWindowBase(val);
+ return true;
+ }
+
+ if(evt.id == Event.MOUSE_DOWN || evt.id == Event.MOUSE_UP ||
+ evt.id == Event.MOUSE_DRAG) {
+ int xoffset = (super.size().width - size.width * charWidth) / 2;
+ int yoffset = (super.size().height - size.height * charHeight) / 2;
+ switch(evt.id) {
+ case Event.MOUSE_DOWN:
+ selectBegin.x = (evt.x - xoffset) / charWidth;
+ selectBegin.y = (evt.y - yoffset) / charHeight + windowBase;
+ selectEnd.x = selectBegin.x;
+ selectEnd.y = selectBegin.y;
+ break;
+ case Event.MOUSE_UP:
+ case Event.MOUSE_DRAG:
+ int x = (evt.x - xoffset) / charWidth;
+ int y = (evt.y - yoffset) / charHeight + windowBase;
+ int oldx = selectEnd.x, oldy = selectEnd.y;
+
+ if((x < selectBegin.x && y < selectBegin.y) &&
+ (x < selectEnd.x && y < selectEnd.y)) {
+ selectBegin.x = x;
+ selectBegin.y = y;
+ } else {
+ selectEnd.x = x;
+ selectEnd.y = y;
+ }
+
+ if(evt.id == Event.MOUSE_UP) {
+ if(selectBegin.x == selectEnd.x &&
+ selectBegin.y == selectEnd.y) {
+ repaint();
+ return true;
+ }
+ String tmp = "";
+ // fix end.x and end.y, they can get over the border
+ if (selectEnd.x < 0) selectEnd.x = 0;
+ if (selectEnd.y < 0) selectEnd.y = 0;
+ if (selectEnd.y >= charArray.length) {
+ selectEnd.y = charArray.length-1;
+ }
+ if (selectEnd.x >= charArray[0].length) {
+ selectEnd.x = charArray[0].length-1;
+ }
+ for(int l = selectBegin.y; l <= selectEnd.y; l++)
+ if(l == selectBegin.y)
+ tmp = (new String(charArray[l])).substring(selectBegin.x) + "\n";
+ else if(l == selectEnd.y)
+ tmp += (new String(charArray[l])).substring(0, selectEnd.x);
+ else tmp += new String(charArray[l]) + "\n";
+
+ // for jdk-1.1
+ // String s=(String) ((StringSelection)this.getToolkit().
+ // getSystemClipboard().
+ // getContents(this)).
+ // getTransferData(DataFlavor.stringFlavor);
+ // System.out.println(s);
+ //
+ repaint();
+ } else
+ if(oldx != x || oldy != y) repaint();
+ break;
+ }
+ return true;
+ }
+ return false;
+ }
+ */
+}
blob - /dev/null
blob + 86d5f70125316fb6b421c8f612f3dc58a74b1ade (mode 644)
--- /dev/null
+++ de/mud/terminal/vt320.java
+/*
+ * This file is part of "The Java Telnet Application".
+ *
+ * This 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 2, or (at your option)
+ * any later version.
+ *
+ * "The Java Telnet Application" 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 software; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package de.mud.terminal;
+
+import java.awt.Font;
+import java.awt.Dimension;
+import java.awt.Event;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import java.util.Properties;
+
+/**
+ * Implementation of a VT terminal emulation plus ANSI compatible.
+ * <P>
+ * <B>Maintainer:</B> Marcus Meißner
+ *
+ * @version $Id$
+ * @author Matthias L. Jugel, Marcus Meißner
+ */
+public abstract class vt320 extends VDU implements KeyListener {
+ /** The current version id tag.<P>
+ * $Id$
+ */
+ public final static String ID = "$Id$";
+
+ /** the debug level */
+ private final static int debug = 0;
+
+ /**
+ * Write an answer back to the remote host. This is needed to be able to
+ * send terminal answers requests like status and type information.
+ * @param b the array of bytes to be sent
+ */
+ protected abstract void write(byte[] b);
+
+ /**
+ * Put string at current cursor position. Moves cursor
+ * according to the String. Does NOT wrap.
+ * @param s the string
+ */
+ public void putString(String s) {
+ int i,len=s.length();
+
+ markLine(R,1);
+ for (i=0;i<len;i++)
+ putChar(s.charAt(i),false);
+ setCursorPosition(C, R);
+ redraw();
+ }
+
+ /**
+ * Create a new vt320 terminal and intialize it with useful settings.
+ * @param width the width of the character screen
+ * @param height the amount of rows on screen
+ * @param font the font to be used for rendering characters
+ */
+ public vt320(int width, int height, Font font) {
+ super(width, height, font);
+
+ setVMS(false);
+ setIBMCharset(false);
+ setTerminalID("vt320");
+ setBufferSize(100);
+ setBorder(2, false);
+
+ int nw = getColumns();
+ if (nw<132) nw=132; //catch possible later 132/80 resizes
+ Tabs = new byte[nw];
+ for (int i=0;i<nw;i+=8) {
+ Tabs[i]=1;
+ }
+
+ /* top row of numpad */
+ PF1 = "\u001bOP";
+ PF2 = "\u001bOQ";
+ PF3 = "\u001bOR";
+ PF4 = "\u001bOS";
+
+ /* the 3x2 keyblock on PC keyboards */
+ Insert = new String[4];
+ Remove = new String[4];
+ KeyHome = new String[4];
+ KeyEnd = new String[4];
+ NextScn = new String[4];
+ PrevScn = new String[4];
+ Insert[0] = Insert[1] = Insert[2] = Insert[3] = "\u001b[2~";
+ Remove[0] = Remove[1] = Remove[2] = Remove[3] = "\u001b[3~";
+ PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[5~";
+ NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[6~";
+ KeyHome[0] = KeyHome[1] = KeyHome[2] = KeyHome[3] = "\u001bOH";
+ KeyEnd[0] = KeyEnd[1] = KeyEnd[2] = KeyEnd[3] = "\u001bOF";
+
+ /* some more VT100 keys */
+ Find = "\u001b[1~";
+ Select = "\u001b[4~";
+ Help = "\u001b[28~";
+ Do = "\u001b[29~";
+
+ FunctionKey = new String[21];
+ FunctionKey[0]= "";
+ FunctionKey[1]= PF1;
+ FunctionKey[2]= PF2;
+ FunctionKey[3]= PF3;
+ FunctionKey[4]= PF4;
+ /* following are defined differently for vt220 / vt132 ... */
+ FunctionKey[5]= "\u001b[15~";
+ FunctionKey[6]= "\u001b[17~";
+ FunctionKey[7]= "\u001b[18~";
+ FunctionKey[8]= "\u001b[19~";
+ FunctionKey[9]= "\u001b[20~";
+ FunctionKey[10]= "\u001b[21~";
+ FunctionKey[11]= "\u001b[23~";
+ FunctionKey[12]= "\u001b[24~";
+ FunctionKey[13]= "\u001b[25~";
+ FunctionKey[14]= "\u001b[26~";
+ FunctionKey[15]= Help;
+ FunctionKey[16]= Do;
+ FunctionKey[17]= "\u001b[31~";
+ FunctionKey[18]= "\u001b[32~";
+ FunctionKey[19]= "\u001b[33~";
+ FunctionKey[20]= "\u001b[34~";
+
+ FunctionKeyShift = new String[21];
+ FunctionKeyAlt = new String[21];
+ FunctionKeyCtrl = new String[21];
+
+ for (int i=0;i<20;i++) {
+ FunctionKeyShift[i]="";
+ FunctionKeyAlt[i]="";
+ FunctionKeyCtrl[i]="";
+ }
+ FunctionKeyShift[15] = Find;
+ FunctionKeyShift[16] = Select;
+
+
+ KeyTab = "\u0009";
+ KeyBacktab = "\u001bOP\u0009";
+ KeyUp = "\u001b[A";
+ KeyDown = "\u001b[B";
+ KeyRight = "\u001b[C";
+ KeyLeft = "\u001b[D";
+ KP0 = "\u001bOp";
+ KP1 = "\u001bOq";
+ KP2 = "\u001bOr";
+ KP3 = "\u001bOs";
+ KP4 = "\u001bOt";
+ KP5 = "\u001bOu";
+ KP6 = "\u001bOv";
+ KP7 = "\u001bOw";
+ KP8 = "\u001bOx";
+ KP9 = "\u001bOy";
+ KPMinus = "\u001bOm";
+ KPComma = "\u001bOl";
+ KPPeriod = "\u001bOn";
+ KPEnter = "\u001bOM";
+
+ /* ... */
+
+ addKeyListener(this);
+ addMouseListener(new MouseAdapter() {
+ public void mouseEntered(MouseEvent evt) {
+ requestFocus();
+ }
+ });
+
+ }
+
+ /**
+ * Create a new terminal emulation with specific width and height.
+ * @param width the width of the character screen
+ * @param height the amount of rows on screen
+ */
+ public vt320(int width, int height) {
+ this(width, height, new Font("Monospaced", Font.PLAIN, 10));
+ }
+
+ /**
+ * Create a new terminal emulation with a specific font.
+ * @param font the font to be used for rendering characters
+ */
+ public vt320(Font font) {
+ this(80, 24, font);
+ }
+
+ /**
+ * Create a new terminal emulation with a specific font.
+ */
+ public vt320() {
+ this(80, 24, new Font("Monospaced", Font.PLAIN, 10));
+ }
+
+ private boolean localecho = false;
+
+ /**
+ * Enable or disable the local echo property of the terminal.
+ * @param echo true if the terminal should echo locally
+ */
+ public void setLocalEcho(boolean echo) {
+ localecho = echo;
+ }
+
+ /**
+ * Enable the VMS mode of the terminal to handle some things differently
+ * for VMS hosts.
+ * @param vms true for vms mode, false for normal mode
+ */
+ public void setVMS(boolean vms) {
+ this.vms = vms;
+ }
+
+ /**
+ * Enable the usage of the IBM character set used by some BBS's. Special
+ * graphical character are available in this mode.
+ * @param ibm true to use the ibm character set
+ */
+ public void setIBMCharset(boolean ibm) {
+ useibmcharset = ibm;
+ }
+
+ /**
+ * Override the standard key codes used by the terminal emulation.
+ * @param codes a properties object containing key code definitions
+ */
+ public void setKeyCodes(Properties codes) {
+ String res, prefixes[] = {"","S","C","A"};
+ for (int i=1;i<20;i++) {
+ for (int j=0;j<4;j++) {
+ res= codes.getProperty(prefixes[j]+"F"+i);
+ if (res!=null) FunctionKey[i] = unEscape(res);
+ }
+ }
+ for (int i=0;i<4;i++) {
+ res = codes.getProperty(prefixes[i]+"PGUP");
+ if (res!=null) PrevScn[i]=unEscape(res);
+ res = codes.getProperty(prefixes[i]+"PGDOWN");
+ if (res!=null) NextScn[i]=unEscape(res);
+ res = codes.getProperty(prefixes[i]+"END");
+ if (res!=null) KeyEnd[i]=unEscape(res);
+ res = codes.getProperty(prefixes[i]+"HOME");
+ if (res!=null) KeyHome[i]=unEscape(res);
+ res = codes.getProperty(prefixes[i]+"INSERT");
+ if (res!=null) Insert[i]=unEscape(res);
+ res = codes.getProperty(prefixes[i]+"REMOVE");
+ if (res!=null) Remove[i]=unEscape(res);
+ }
+ res = codes.getProperty("UP");if (res!=null) KeyUp=unEscape(res);
+ res = codes.getProperty("DOWN");if (res!=null) KeyDown=unEscape(res);
+ res = codes.getProperty("LEFT");if (res!=null) KeyLeft=unEscape(res);
+ res = codes.getProperty("RIGHT");if (res!=null) KeyRight=unEscape(res);
+
+ }
+
+ /**
+ * Set the terminal id used to identify this terminal.
+ * @param terminalID the id string
+ */
+ public void setTerminalID(String terminaID) {
+ this.terminalID = terminalID;
+ }
+
+ /**
+ * Get the terminal id used to identify this terminal.
+ * @param terminalID the id string
+ */
+ public String getTerminalID() {
+ return terminalID;
+ }
+
+ /**
+ * A small conveniance method thar converts the string to a byte array
+ * for sending.
+ * @param s the string to be sent
+ */
+ private boolean write(String s) {
+ write(s.getBytes());
+ return true;
+ }
+
+
+ // ===================================================================
+ // the actual terminal emulation code comes here:
+ // ===================================================================
+
+ // due to a bug with Windows we need a keypress cache
+ private int pressedKey = ' ';
+ private long pressedWhen = ' ';
+
+ private String terminalID = "vt320";
+
+ // X - COLUMNS, Y - ROWS
+ int R,C;
+ int Sc,Sr,Sa;
+ int attributes = 0;
+ int insertmode = 0;
+ int statusmode = 0;
+ int vt52mode = 0;
+ int normalcursor = 0;
+ boolean moveoutsidemargins = true;
+ boolean sendcrlf = false;
+ boolean capslock = false;
+ boolean numlock = false;
+
+ private boolean useibmcharset = false;
+
+ private static int lastwaslf = 0;
+ private static int i;
+ private final static char ESC = 27;
+ private final static char IND = 132;
+ private final static char NEL = 133;
+ private final static char RI = 141;
+ private final static char HTS = 136;
+ private final static char DCS = 144;
+ private final static char CSI = 155;
+ private final static char OSC = 157;
+ private final static int TSTATE_DATA = 0;
+ private final static int TSTATE_ESC = 1; /* ESC */
+ private final static int TSTATE_CSI = 2; /* ESC [ */
+ private final static int TSTATE_DCS = 3; /* ESC P */
+ private final static int TSTATE_DCEQ = 4; /* ESC [? */
+ private final static int TSTATE_ESCSQUARE= 5; /* ESC # */
+ private final static int TSTATE_OSC= 6; /* ESC ] */
+ private final static int TSTATE_SETG0= 7; /* ESC (? */
+ private final static int TSTATE_SETG1= 8; /* ESC )? */
+ private final static int TSTATE_SETG2= 9; /* ESC *? */
+ private final static int TSTATE_SETG3= 10; /* ESC +? */
+ private final static int TSTATE_CSI_DOLLAR = 11; /* ESC [ Pn $ */
+
+ /* The graphics charsets
+ * B - default ASCII
+ * A - default UK
+ * 0 - DEC SPECIAL
+ * < - User defined
+ * ....
+ */
+ private static char gx[] = {
+ 'B', // g0
+ '0', // g1
+ 'A', // g2
+ '<', // g3
+ };
+ private static char gr = 1; // default GR to G1
+ private static char gl = 0; // default GL to G0
+
+ // array to store DEC Special -> Unicode mapping
+ // Unicode DEC Unicode name (DEC name)
+ private static char DECSPECIAL[] = {
+ '\u0040', //5f blank
+ '\u2666', //60 black diamond
+ '\u2592', //61 grey square
+ '\u2409', //62 Horizontal tab (ht) pict. for control
+ '\u240c', //63 Form Feed (ff) pict. for control
+ '\u240d', //64 Carriage Return (cr) pict. for control
+ '\u240a', //65 Line Feed (lf) pict. for control
+ '\u00ba', //66 Masculine ordinal indicator
+ '\u00b1', //67 Plus or minus sign
+ '\u2424', //68 New Line (nl) pict. for control
+ '\u240b', //69 Vertical Tab (vt) pict. for control
+ '\u2518', //6a Forms light up and left
+ '\u2510', //6b Forms light down and left
+ '\u250c', //6c Forms light down and right
+ '\u2514', //6d Forms light up and right
+ '\u253c', //6e Forms light vertical and horizontal
+ '\u2594', //6f Upper 1/8 block (Scan 1)
+ '\u2580', //70 Upper 1/2 block (Scan 3)
+ '\u2500', //71 Forms light horizontal or ?em dash? (Scan 5)
+ '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7)
+ '\u005f', //73 \u005f underscore or \u2581 lower 1/8 (Scan 9)
+ '\u251c', //74 Forms light vertical and right
+ '\u2524', //75 Forms light vertical and left
+ '\u2534', //76 Forms light up and horizontal
+ '\u252c', //77 Forms light down and horizontal
+ '\u2502', //78 vertical bar
+ '\u2264', //79 less than or equal
+ '\u2265', //7a greater than or equal
+ '\u00b6', //7b paragraph
+ '\u2260', //7c not equal
+ '\u00a3', //7d Pound Sign (british)
+ '\u00b7' //7e Middle Dot
+ };
+
+ /** Strings to send on function key pressing */
+ private String FunctionKey[];
+ private String FunctionKeyShift[];
+ private String FunctionKeyCtrl[];
+ private String FunctionKeyAlt[];
+ private String KeyUp,KeyDown,KeyLeft,KeyRight,KeyTab,KeyBacktab;
+
+ private String KP0, KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9;
+ private String KPMinus, KPComma, KPPeriod,KPEnter;
+ private String PF1, PF2, PF3, PF4;
+ private String Help, Do, Find, Select;
+
+ private String KeyHome[], KeyEnd[], Insert[], Remove[], PrevScn[], NextScn[];
+
+ private String osc,dcs; /* to memorize OSC & DCS control sequence */
+
+ private int term_state = TSTATE_DATA;
+ private boolean vms = false;
+ private byte[] Tabs;
+ private int[] DCEvars = new int [10];
+ private int DCEvar;
+
+ /**
+ * Replace escape code characters (backslash + identifier) with their
+ * respective codes.
+ * @param tmp the string to be parsed
+ * @return a unescaped string
+ */
+ static String unEscape(String tmp) {
+ int idx = 0, oldidx = 0;
+ String cmd;
+
+ cmd = "";
+ while((idx = tmp.indexOf('\\', oldidx)) >= 0 &&
+ ++idx <= tmp.length()) {
+ cmd += tmp.substring(oldidx, idx-1);
+ if(idx == tmp.length()) return cmd;
+ switch(tmp.charAt(idx)) {
+ case 'b': cmd += "\b"; break;
+ case 'e': cmd += "\u001b"; break;
+ case 'n': cmd += "\n"; break;
+ case 'r': cmd += "\r"; break;
+ case 't': cmd += "\t"; break;
+ case 'v': cmd += "\u000b"; break;
+ case 'a': cmd += "\u0012"; break;
+ default :
+ if ( (tmp.charAt(idx)>='0') && (tmp.charAt(idx)<='9')) {
+ for (i = idx;i<tmp.length();i++)
+ if ( (tmp.charAt(i)<'0') || (tmp.charAt(i)>'9'))
+ break;
+ cmd += (char)Integer.parseInt(tmp.substring(idx, i));
+ idx = i-1;
+ } else
+ cmd += tmp.substring(idx, ++idx);break;
+ }
+ oldidx = ++idx;
+ }
+ if(oldidx <= tmp.length()) cmd += tmp.substring(oldidx);
+ return cmd;
+ }
+
+ /**
+ * Not used.
+ */
+ public void keyTyped(KeyEvent evt) {
+ // nothing to to, however maybe we should use it?
+ }
+
+ /**
+ * Not used.
+ */
+ public void keyReleased(KeyEvent evt) {
+ // nothing to to, however maybe we should use it?
+ }
+
+ /**
+ * Handle events for the terminal. Only accept events for the scroll
+ * bar. Any other events have to be propagated to the parent.
+ * @param evt the event
+ */
+ public void keyPressed(KeyEvent evt) {
+ boolean control = evt.isControlDown();
+ boolean shift = evt.isShiftDown();
+ boolean alt = evt.isAltDown();
+
+ int keyCode = evt.getKeyCode();
+ char keyChar = evt.getKeyChar();
+
+ if(pressedKey == KeyEvent.VK_ENTER &&
+ (keyCode == KeyEvent.VK_ENTER || keyChar == 10)
+ && evt.getWhen() - pressedWhen < 50)
+ // Ray: Elliminate stuttering enter/return
+ return;
+
+ pressedWhen = evt.getWhen();
+
+ if(keyCode == KeyEvent.VK_ENTER && !control) {
+ if(sendcrlf)
+ write("\r\n"); /* YES, see RFC 854 */
+ else
+ write("\r"); /* YES, see RFC 854 */
+ }
+
+ // FIXME: on german PC keyboards you have to use Alt-Ctrl-q to get an @,
+ // so we can't just use it here... will probably break some other VMS
+ // codes. -Marcus
+ // if(((!vms && keyChar == '2') || keyChar == '@' || keyChar == ' ')
+ // && control)
+ if (((!vms && keyChar == '2') || keyChar == ' ') && control)
+ write("" + (char)0);
+
+ if(vms) {
+ if (keyChar == 8) {
+ if(shift && !control)
+ write("" + (char)10); // VMS shift deletes word back
+ else if(control && !shift)
+ write("" + (char)24); // VMS control deletes line back
+ else
+ write("" + (char)127); // VMS other is delete
+ } else if(keyChar == 127 && !control) {
+ if (shift)
+ write(Insert[0]); // VMS shift delete = insert
+ else
+ write(Remove[0]); // VMS delete = remove
+ } else if(control)
+ switch(keyChar) {
+ case '0':
+ write(KP0); return;
+ case '1':
+ write(KP1); return;
+ case '2':
+ write(KP2); return;
+ case '3':
+ write(KP3); return;
+ case '4':
+ write(KP4); return;
+ case '5':
+ write(KP5); return;
+ case '6':
+ write(KP6); return;
+ case '7':
+ write(KP7); return;
+ case '8':
+ write(KP8); return;
+ case '9':
+ write(KP9); return;
+ case '.':
+ write(KPPeriod); return;
+ case '-':
+ case 31:
+ write(KPMinus); return;
+ case '+':
+ write(KPComma); return;
+ case 10:
+ write(KPEnter); return;
+ case '/':
+ write(PF2); return;
+ case '*':
+ write(PF3); return;
+ }
+ if (shift && keyChar < 32)
+ write(PF1+(char)(keyChar + 64));
+ return;
+ }
+
+ String fmap[];
+ int xind;
+ xind = 0;
+ fmap = FunctionKey;
+ if(shift) { fmap = FunctionKeyShift; xind=1; }
+ if(control) { fmap = FunctionKeyCtrl; xind=2; }
+ if(alt) { fmap = FunctionKeyAlt; xind=3; }
+
+ switch (keyCode) {
+ case KeyEvent.VK_F1:
+ write(fmap[1]); return;
+ case KeyEvent.VK_F2:
+ write(fmap[2]); return;
+ case KeyEvent.VK_F3:
+ write(fmap[3]); return;
+ case KeyEvent.VK_F4:
+ write(fmap[4]); return;
+ case KeyEvent.VK_F5:
+ write(fmap[5]); return;
+ case KeyEvent.VK_F6:
+ write(fmap[6]); return;
+ case KeyEvent.VK_F7:
+ write(fmap[7]); return;
+ case KeyEvent.VK_F8:
+ write(fmap[8]); return;
+ case KeyEvent.VK_F9:
+ write(fmap[9]); return;
+ case KeyEvent.VK_F10:
+ write(fmap[10]); return;
+ case KeyEvent.VK_F11:
+ write(fmap[11]); return;
+ case KeyEvent.VK_F12:
+ write(fmap[12]); return;
+ case KeyEvent.VK_UP:
+ write(KeyUp); return;
+ case KeyEvent.VK_DOWN:
+ write(KeyDown); return;
+ case KeyEvent.VK_LEFT:
+ write(KeyLeft); return;
+ case KeyEvent.VK_RIGHT:
+ write(KeyRight); return;
+ case KeyEvent.VK_PAGE_DOWN:
+ write(NextScn[xind]); return;
+ case KeyEvent.VK_PAGE_UP:
+ write(PrevScn[xind]); return;
+ case KeyEvent.VK_INSERT:
+ write(Insert[xind]); return;
+ case KeyEvent.VK_HOME:
+ if(vms)
+ write("" + (char)8);
+ else
+ write(KeyHome[xind]);
+ return;
+ case KeyEvent.VK_END:
+ if(vms)
+ write("" + (char)5);
+ else
+ write(KeyEnd[xind]);
+ return;
+ case KeyEvent.VK_NUM_LOCK:
+ if(vms && control)
+ if(pressedKey != keyCode) {
+ pressedKey = keyCode;
+ write(PF1);
+ } else
+ // Here, we eat a second numlock since that returns numlock state
+ pressedKey = ' ';
+ if(!control)
+ numlock = !numlock;
+ return;
+ case KeyEvent.VK_CAPS_LOCK:
+ capslock = !capslock;
+ return;
+ default:
+ if(debug > 0)
+ System.out.println("vt320: unknown event: "+evt);
+ }
+
+ // Hmmm. Outside the VMS case?
+ if(shift && (keyChar == '\t'))
+ write(KeyBacktab);
+ else if (alt)
+ write(""+((char)(keyChar|0x80)));
+ else if(capslock)
+ write((""+keyChar).toUpperCase());
+ else
+ write(""+keyChar);
+ }
+
+ private void handle_dcs(String dcs) {
+ System.out.println("DCS: "+dcs);
+ }
+ private void handle_osc(String osc) {
+ System.out.println("OSC: "+osc);
+ }
+
+ private final static char unimap[] = {
+ //#
+ //# Name: cp437_DOSLatinUS to Unicode table
+ //# Unicode version: 1.1
+ //# Table version: 1.1
+ //# Table format: Format A
+ //# Date: 03/31/95
+ //# Authors: Michel Suignard <michelsu@microsoft.com>
+ //# Lori Hoerth <lorih@microsoft.com>
+ //# General notes: none
+ //#
+ //# Format: Three tab-separated columns
+ //# Column #1 is the cp1255_WinHebrew code (in hex)
+ //# Column #2 is the Unicode (in hex as 0xXXXX)
+ //# Column #3 is the Unicode name (follows a comment sign, '#')
+ //#
+ //# The entries are in cp437_DOSLatinUS order
+ //#
+
+ 0x0000,// #NULL
+ 0x0001,// #START OF HEADING
+ 0x0002,// #START OF TEXT
+ 0x0003,// #END OF TEXT
+ 0x0004,// #END OF TRANSMISSION
+ 0x0005,// #ENQUIRY
+ 0x0006,// #ACKNOWLEDGE
+ 0x0007,// #BELL
+ 0x0008,// #BACKSPACE
+ 0x0009,// #HORIZONTAL TABULATION
+ 0x000a,// #LINE FEED
+ 0x000b,// #VERTICAL TABULATION
+ 0x000c,// #FORM FEED
+ 0x000d,// #CARRIAGE RETURN
+ 0x000e,// #SHIFT OUT
+ 0x000f,// #SHIFT IN
+ 0x0010,// #DATA LINK ESCAPE
+ 0x0011,// #DEVICE CONTROL ONE
+ 0x0012,// #DEVICE CONTROL TWO
+ 0x0013,// #DEVICE CONTROL THREE
+ 0x0014,// #DEVICE CONTROL FOUR
+ 0x0015,// #NEGATIVE ACKNOWLEDGE
+ 0x0016,// #SYNCHRONOUS IDLE
+ 0x0017,// #END OF TRANSMISSION BLOCK
+ 0x0018,// #CANCEL
+ 0x0019,// #END OF MEDIUM
+ 0x001a,// #SUBSTITUTE
+ 0x001b,// #ESCAPE
+ 0x001c,// #FILE SEPARATOR
+ 0x001d,// #GROUP SEPARATOR
+ 0x001e,// #RECORD SEPARATOR
+ 0x001f,// #UNIT SEPARATOR
+ 0x0020,// #SPACE
+ 0x0021,// #EXCLAMATION MARK
+ 0x0022,// #QUOTATION MARK
+ 0x0023,// #NUMBER SIGN
+ 0x0024,// #DOLLAR SIGN
+ 0x0025,// #PERCENT SIGN
+ 0x0026,// #AMPERSAND
+ 0x0027,// #APOSTROPHE
+ 0x0028,// #LEFT PARENTHESIS
+ 0x0029,// #RIGHT PARENTHESIS
+ 0x002a,// #ASTERISK
+ 0x002b,// #PLUS SIGN
+ 0x002c,// #COMMA
+ 0x002d,// #HYPHEN-MINUS
+ 0x002e,// #FULL STOP
+ 0x002f,// #SOLIDUS
+ 0x0030,// #DIGIT ZERO
+ 0x0031,// #DIGIT ONE
+ 0x0032,// #DIGIT TWO
+ 0x0033,// #DIGIT THREE
+ 0x0034,// #DIGIT FOUR
+ 0x0035,// #DIGIT FIVE
+ 0x0036,// #DIGIT SIX
+ 0x0037,// #DIGIT SEVEN
+ 0x0038,// #DIGIT EIGHT
+ 0x0039,// #DIGIT NINE
+ 0x003a,// #COLON
+ 0x003b,// #SEMICOLON
+ 0x003c,// #LESS-THAN SIGN
+ 0x003d,// #EQUALS SIGN
+ 0x003e,// #GREATER-THAN SIGN
+ 0x003f,// #QUESTION MARK
+ 0x0040,// #COMMERCIAL AT
+ 0x0041,// #LATIN CAPITAL LETTER A
+ 0x0042,// #LATIN CAPITAL LETTER B
+ 0x0043,// #LATIN CAPITAL LETTER C
+ 0x0044,// #LATIN CAPITAL LETTER D
+ 0x0045,// #LATIN CAPITAL LETTER E
+ 0x0046,// #LATIN CAPITAL LETTER F
+ 0x0047,// #LATIN CAPITAL LETTER G
+ 0x0048,// #LATIN CAPITAL LETTER H
+ 0x0049,// #LATIN CAPITAL LETTER I
+ 0x004a,// #LATIN CAPITAL LETTER J
+ 0x004b,// #LATIN CAPITAL LETTER K
+ 0x004c,// #LATIN CAPITAL LETTER L
+ 0x004d,// #LATIN CAPITAL LETTER M
+ 0x004e,// #LATIN CAPITAL LETTER N
+ 0x004f,// #LATIN CAPITAL LETTER O
+ 0x0050,// #LATIN CAPITAL LETTER P
+ 0x0051,// #LATIN CAPITAL LETTER Q
+ 0x0052,// #LATIN CAPITAL LETTER R
+ 0x0053,// #LATIN CAPITAL LETTER S
+ 0x0054,// #LATIN CAPITAL LETTER T
+ 0x0055,// #LATIN CAPITAL LETTER U
+ 0x0056,// #LATIN CAPITAL LETTER V
+ 0x0057,// #LATIN CAPITAL LETTER W
+ 0x0058,// #LATIN CAPITAL LETTER X
+ 0x0059,// #LATIN CAPITAL LETTER Y
+ 0x005a,// #LATIN CAPITAL LETTER Z
+ 0x005b,// #LEFT SQUARE BRACKET
+ 0x005c,// #REVERSE SOLIDUS
+ 0x005d,// #RIGHT SQUARE BRACKET
+ 0x005e,// #CIRCUMFLEX ACCENT
+ 0x005f,// #LOW LINE
+ 0x0060,// #GRAVE ACCENT
+ 0x0061,// #LATIN SMALL LETTER A
+ 0x0062,// #LATIN SMALL LETTER B
+ 0x0063,// #LATIN SMALL LETTER C
+ 0x0064,// #LATIN SMALL LETTER D
+ 0x0065,// #LATIN SMALL LETTER E
+ 0x0066,// #LATIN SMALL LETTER F
+ 0x0067,// #LATIN SMALL LETTER G
+ 0x0068,// #LATIN SMALL LETTER H
+ 0x0069,// #LATIN SMALL LETTER I
+ 0x006a,// #LATIN SMALL LETTER J
+ 0x006b,// #LATIN SMALL LETTER K
+ 0x006c,// #LATIN SMALL LETTER L
+ 0x006d,// #LATIN SMALL LETTER M
+ 0x006e,// #LATIN SMALL LETTER N
+ 0x006f,// #LATIN SMALL LETTER O
+ 0x0070,// #LATIN SMALL LETTER P
+ 0x0071,// #LATIN SMALL LETTER Q
+ 0x0072,// #LATIN SMALL LETTER R
+ 0x0073,// #LATIN SMALL LETTER S
+ 0x0074,// #LATIN SMALL LETTER T
+ 0x0075,// #LATIN SMALL LETTER U
+ 0x0076,// #LATIN SMALL LETTER V
+ 0x0077,// #LATIN SMALL LETTER W
+ 0x0078,// #LATIN SMALL LETTER X
+ 0x0079,// #LATIN SMALL LETTER Y
+ 0x007a,// #LATIN SMALL LETTER Z
+ 0x007b,// #LEFT CURLY BRACKET
+ 0x007c,// #VERTICAL LINE
+ 0x007d,// #RIGHT CURLY BRACKET
+ 0x007e,// #TILDE
+ 0x007f,// #DELETE
+ 0x00c7,// #LATIN CAPITAL LETTER C WITH CEDILLA
+ 0x00fc,// #LATIN SMALL LETTER U WITH DIAERESIS
+ 0x00e9,// #LATIN SMALL LETTER E WITH ACUTE
+ 0x00e2,// #LATIN SMALL LETTER A WITH CIRCUMFLEX
+ 0x00e4,// #LATIN SMALL LETTER A WITH DIAERESIS
+ 0x00e0,// #LATIN SMALL LETTER A WITH GRAVE
+ 0x00e5,// #LATIN SMALL LETTER A WITH RING ABOVE
+ 0x00e7,// #LATIN SMALL LETTER C WITH CEDILLA
+ 0x00ea,// #LATIN SMALL LETTER E WITH CIRCUMFLEX
+ 0x00eb,// #LATIN SMALL LETTER E WITH DIAERESIS
+ 0x00e8,// #LATIN SMALL LETTER E WITH GRAVE
+ 0x00ef,// #LATIN SMALL LETTER I WITH DIAERESIS
+ 0x00ee,// #LATIN SMALL LETTER I WITH CIRCUMFLEX
+ 0x00ec,// #LATIN SMALL LETTER I WITH GRAVE
+ 0x00c4,// #LATIN CAPITAL LETTER A WITH DIAERESIS
+ 0x00c5,// #LATIN CAPITAL LETTER A WITH RING ABOVE
+ 0x00c9,// #LATIN CAPITAL LETTER E WITH ACUTE
+ 0x00e6,// #LATIN SMALL LIGATURE AE
+ 0x00c6,// #LATIN CAPITAL LIGATURE AE
+ 0x00f4,// #LATIN SMALL LETTER O WITH CIRCUMFLEX
+ 0x00f6,// #LATIN SMALL LETTER O WITH DIAERESIS
+ 0x00f2,// #LATIN SMALL LETTER O WITH GRAVE
+ 0x00fb,// #LATIN SMALL LETTER U WITH CIRCUMFLEX
+ 0x00f9,// #LATIN SMALL LETTER U WITH GRAVE
+ 0x00ff,// #LATIN SMALL LETTER Y WITH DIAERESIS
+ 0x00d6,// #LATIN CAPITAL LETTER O WITH DIAERESIS
+ 0x00dc,// #LATIN CAPITAL LETTER U WITH DIAERESIS
+ 0x00a2,// #CENT SIGN
+ 0x00a3,// #POUND SIGN
+ 0x00a5,// #YEN SIGN
+ 0x20a7,// #PESETA SIGN
+ 0x0192,// #LATIN SMALL LETTER F WITH HOOK
+ 0x00e1,// #LATIN SMALL LETTER A WITH ACUTE
+ 0x00ed,// #LATIN SMALL LETTER I WITH ACUTE
+ 0x00f3,// #LATIN SMALL LETTER O WITH ACUTE
+ 0x00fa,// #LATIN SMALL LETTER U WITH ACUTE
+ 0x00f1,// #LATIN SMALL LETTER N WITH TILDE
+ 0x00d1,// #LATIN CAPITAL LETTER N WITH TILDE
+ 0x00aa,// #FEMININE ORDINAL INDICATOR
+ 0x00ba,// #MASCULINE ORDINAL INDICATOR
+ 0x00bf,// #INVERTED QUESTION MARK
+ 0x2310,// #REVERSED NOT SIGN
+ 0x00ac,// #NOT SIGN
+ 0x00bd,// #VULGAR FRACTION ONE HALF
+ 0x00bc,// #VULGAR FRACTION ONE QUARTER
+ 0x00a1,// #INVERTED EXCLAMATION MARK
+ 0x00ab,// #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ 0x00bb,// #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ 0x2591,// #LIGHT SHADE
+ 0x2592,// #MEDIUM SHADE
+ 0x2593,// #DARK SHADE
+ 0x2502,// #BOX DRAWINGS LIGHT VERTICAL
+ 0x2524,// #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+ 0x2561,// #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+ 0x2562,// #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+ 0x2556,// #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+ 0x2555,// #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+ 0x2563,// #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+ 0x2551,// #BOX DRAWINGS DOUBLE VERTICAL
+ 0x2557,// #BOX DRAWINGS DOUBLE DOWN AND LEFT
+ 0x255d,// #BOX DRAWINGS DOUBLE UP AND LEFT
+ 0x255c,// #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+ 0x255b,// #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+ 0x2510,// #BOX DRAWINGS LIGHT DOWN AND LEFT
+ 0x2514,// #BOX DRAWINGS LIGHT UP AND RIGHT
+ 0x2534,// #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+ 0x252c,// #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+ 0x251c,// #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+ 0x2500,// #BOX DRAWINGS LIGHT HORIZONTAL
+ 0x253c,// #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+ 0x255e,// #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+ 0x255f,// #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+ 0x255a,// #BOX DRAWINGS DOUBLE UP AND RIGHT
+ 0x2554,// #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+ 0x2569,// #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+ 0x2566,// #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+ 0x2560,// #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+ 0x2550,// #BOX DRAWINGS DOUBLE HORIZONTAL
+ 0x256c,// #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+ 0x2567,// #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+ 0x2568,// #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+ 0x2564,// #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+ 0x2565,// #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+ 0x2559,// #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+ 0x2558,// #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+ 0x2552,// #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+ 0x2553,// #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+ 0x256b,// #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+ 0x256a,// #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+ 0x2518,// #BOX DRAWINGS LIGHT UP AND LEFT
+ 0x250c,// #BOX DRAWINGS LIGHT DOWN AND RIGHT
+ 0x2588,// #FULL BLOCK
+ 0x2584,// #LOWER HALF BLOCK
+ 0x258c,// #LEFT HALF BLOCK
+ 0x2590,// #RIGHT HALF BLOCK
+ 0x2580,// #UPPER HALF BLOCK
+ 0x03b1,// #GREEK SMALL LETTER ALPHA
+ 0x00df,// #LATIN SMALL LETTER SHARP S
+ 0x0393,// #GREEK CAPITAL LETTER GAMMA
+ 0x03c0,// #GREEK SMALL LETTER PI
+ 0x03a3,// #GREEK CAPITAL LETTER SIGMA
+ 0x03c3,// #GREEK SMALL LETTER SIGMA
+ 0x00b5,// #MICRO SIGN
+ 0x03c4,// #GREEK SMALL LETTER TAU
+ 0x03a6,// #GREEK CAPITAL LETTER PHI
+ 0x0398,// #GREEK CAPITAL LETTER THETA
+ 0x03a9,// #GREEK CAPITAL LETTER OMEGA
+ 0x03b4,// #GREEK SMALL LETTER DELTA
+ 0x221e,// #INFINITY
+ 0x03c6,// #GREEK SMALL LETTER PHI
+ 0x03b5,// #GREEK SMALL LETTER EPSILON
+ 0x2229,// #INTERSECTION
+ 0x2261,// #IDENTICAL TO
+ 0x00b1,// #PLUS-MINUS SIGN
+ 0x2265,// #GREATER-THAN OR EQUAL TO
+ 0x2264,// #LESS-THAN OR EQUAL TO
+ 0x2320,// #TOP HALF INTEGRAL
+ 0x2321,// #BOTTOM HALF INTEGRAL
+ 0x00f7,// #DIVISION SIGN
+ 0x2248,// #ALMOST EQUAL TO
+ 0x00b0,// #DEGREE SIGN
+ 0x2219,// #BULLET OPERATOR
+ 0x00b7,// #MIDDLE DOT
+ 0x221a,// #SQUARE ROOT
+ 0x207f,// #SUPERSCRIPT LATIN SMALL LETTER N
+ 0x00b2,// #SUPERSCRIPT TWO
+ 0x25a0,// #BLACK SQUARE
+ 0x00a0,// #NO-BREAK SPACE
+ };
+
+ public char map_cp850_unicode(char x) {
+ if (x>=0x100)
+ return x;
+ return unimap[x];
+ }
+
+ private void _SetCursor(int row,int col) {
+ int maxr = getRows();
+ int tm = getTopMargin();
+
+ R = (row<0)?0:row;
+ C = (col<0)?0:col;
+
+ if (!moveoutsidemargins) {
+ R += getTopMargin();
+ maxr = getBottomMargin();
+ }
+ if (R>maxr) R = maxr;
+ }
+
+ private void putChar(char c, boolean doshowcursor) {
+ Dimension size;
+ int rows = getRows(); //statusline
+ int columns = getColumns();
+ int tm = getTopMargin();
+ int bm = getBottomMargin();
+ String tosend;
+ byte msg[];
+
+ if (debug>4) System.out.println("putChar("+c+" ["+((int)c)+"]) at R="+R+" , C="+C+", columns="+columns+", rows="+rows);
+ markLine(R,1);
+ if (c>255) {
+ if (debug>0)
+ System.out.println("char > 255:"+((int)c));
+ return;
+ }
+ switch (term_state) {
+ case TSTATE_DATA:
+ /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset.
+ * probably... but some BBS do anyway...
+ */
+ if (!useibmcharset) {
+ boolean doneflag = true;
+ switch (c) {
+ case OSC:
+ osc="";
+ term_state = TSTATE_OSC;
+ break;
+ case RI:
+ if (R>tm)
+ R--;
+ else
+ insertLine(R,1,SCROLL_DOWN);
+ if (debug>1)
+ System.out.println("RI");
+ break;
+ case IND:
+ if (R == tm - 1 || R == bm || R == rows - 1) // Ray: not bottom margin - 1
+ insertLine(R,1,SCROLL_UP);
+ else
+ R++;
+ if (debug>1)
+ System.out.println("IND (at "+R+" )");
+ break;
+ case NEL:
+ if (R == tm - 1 || R == bm || R == rows - 1) // Ray: not bottom margin - 1
+ insertLine(R,1,SCROLL_UP);
+ else
+ R++;
+ C=0;
+ if (debug>1)
+ System.out.println("NEL (at "+R+" )");
+ break;
+ case HTS:
+ Tabs[C] = 1;
+ if (debug>1)
+ System.out.println("HTS");
+ break;
+ case DCS:
+ dcs="";
+ term_state = TSTATE_DCS;
+ break;
+ default:
+ doneflag = false;
+ break;
+ }
+ if (doneflag) break;
+ }
+ switch (c) {
+ case CSI: // should be in the 8bit section, but some BBS use this
+ term_state = TSTATE_DCEQ;
+ break;
+ case ESC:
+ term_state = TSTATE_ESC;
+ lastwaslf=0;
+ break;
+ case '\b':
+ C--;
+ if (C<0)
+ C=0;
+ lastwaslf = 0;
+ break;
+ case '\t':
+ if (insertmode == 1) {
+ int nr,newc;
+
+ newc = C;
+ do {
+ insertChar(C,R,' ',attributes);
+ newc++;
+ } while (newc<columns && Tabs[newc]==0);
+ } else {
+ do {
+ putChar(C++,R,' ',attributes);
+ } while (C<columns && (Tabs[C]==0));
+ }
+ lastwaslf = 0;
+ break;
+ case '\r':
+ C=0;
+ break;
+ case '\n':
+ if (debug>3)
+ System.out.println("R= "+R+", bm "+bm+", tm="+tm+", rows="+rows);
+ if (!vms)
+ {
+ if (lastwaslf!=0 && lastwaslf!=c) // Ray: I do not understand this logic.
+ break;
+ lastwaslf=c;
+ /*C = 0;*/
+ }
+ // note: we do not scroll at the topmargin! only at the bottommargin
+ // of the scrollregion and at the bottom.
+ if ( R == bm || R >= rows - 1)
+ insertLine(R,1);
+ else
+ R++;
+ break;
+ case '\016':
+ /* ^N, Shift out - Put G1 into GL */
+ gl = 1;
+ break;
+ case '\017':
+ /* ^O, Shift in - Put G0 into GL */
+ gl = 0;
+ break;
+ default:
+ lastwaslf=0;
+ if (c<32) {
+ if (c!=0)
+ if (debug>0)
+ System.out.println("TSTATE_DATA char: "+((int)c));
+ break;
+ }
+ if(C >= columns) {
+ if(R < rows - 1)
+ R++;
+ else
+ insertLine(R,SCROLL_UP);
+ C = 0;
+ }
+
+ // Mapping if DEC Special is chosen charset
+ if ( gx[gl] == '0' ) {
+ if ( c >= '\u005f' && c <= '\u007e' ) {
+ if (debug>3)
+ System.out.print("Mapping "+c+" (index "+((short)c-0x5f)+" to ");
+ c = DECSPECIAL[(short)c - 0x5f];
+ if (debug>3)
+ System.out.println(c+" ("+(int)c+")");
+ }
+ }
+ /*
+ if ( gx[gr] == '0' ) {
+ if ( c >= '\u00bf' && c <= '\u00fe' ) {
+ if (debug>2)
+ System.out.print("Mapping "+c);
+ c = DECSPECIAL[(short)c - 0xbf];
+ if (debug>2)
+ System.out.println("to "+c);
+ }
+ }
+ */
+ if (useibmcharset)
+ c = map_cp850_unicode(c);
+
+ /*if(true || (statusmode == 0)) { */
+ if (debug>4) System.out.println("output "+c+" at "+C+","+R);
+ if (insertmode==1) {
+ insertChar(C, R, c, attributes);
+ } else {
+ putChar(C, R, c, attributes);
+ }
+ /*
+ } else {
+ if (insertmode==1) {
+ insertChar(C, rows, c, attributes);
+ } else {
+ putChar(C, rows, c, attributes);
+ }
+ }
+ */
+ C++;
+ break;
+ } /* switch(c) */
+ break;
+ case TSTATE_OSC:
+ if ((c<0x20) && (c!=ESC)) {// NP - No printing character
+ handle_osc(osc);
+ term_state = TSTATE_DATA;
+ break;
+ }
+ //but check for vt102 ESC \
+ if (c=='\\' && osc.charAt(osc.length()-1)==ESC) {
+ handle_osc(osc);
+ term_state = TSTATE_DATA;
+ break;
+ }
+ osc = osc + c;
+ break;
+ case TSTATE_ESC:
+ switch (c) {
+ case '#':
+ term_state = TSTATE_ESCSQUARE;
+ break;
+ case 'c':
+ /* Hard terminal reset */
+ /*FIXME:*/
+ term_state = TSTATE_DATA;
+ break;
+ case '[':
+ term_state = TSTATE_CSI;
+ DCEvar = 0;
+ DCEvars[0] = 0;
+ DCEvars[1] = 0;
+ DCEvars[2] = 0;
+ DCEvars[3] = 0;
+ break;
+ case ']':
+ osc="";
+ term_state = TSTATE_OSC;
+ break;
+ case 'P':
+ dcs="";
+ term_state = TSTATE_DCS;
+ break;
+ case 'E':
+ if (R == tm - 1 || R == bm || R == rows - 1) // Ray: not bottom margin - 1
+ insertLine(R,1,SCROLL_UP);
+ else
+ R++;
+ C=0;
+ if (debug>1)
+ System.out.println("ESC E (at "+R+")");
+ term_state = TSTATE_DATA;
+ break;
+ case 'D':
+ if (R == tm - 1 || R == bm || R == rows - 1)
+ insertLine(R,1,SCROLL_UP);
+ else
+ R++;
+ if (debug>1)
+ System.out.println("ESC D (at "+R+" )");
+ term_state = TSTATE_DATA;
+ break;
+ case 'M': // IL
+ if ((R>=tm) && (R<=bm)) // in scrolregion
+ insertLine(R,1,SCROLL_DOWN);
+ /* else do nothing ; */
+ if (debug>1)
+ System.out.println("ESC M ");
+ term_state = TSTATE_DATA;
+ break;
+ case 'H':
+ if (debug>1)
+ System.out.println("ESC H at "+C);
+ /* right border probably ...*/
+ if (C>=columns)
+ C=columns-1;
+ Tabs[C] = 1;
+ term_state = TSTATE_DATA;
+ break;
+ case '=':
+ /*application keypad*/
+ if (debug>0)
+ System.out.println("ESC =");
+ term_state = TSTATE_DATA;
+ break;
+ case '>':
+ /*normal keypad*/
+ if (debug>0)
+ System.out.println("ESC >");
+ term_state = TSTATE_DATA;
+ break;
+ case '7':
+ /*save cursor */
+ Sc = C;
+ Sr = R;
+ Sa = attributes;
+ if (debug>1)
+ System.out.println("ESC 7");
+ term_state = TSTATE_DATA;
+ break;
+ case '8':
+ /*restore cursor */
+ C = Sc;
+ R = Sr;
+ attributes = Sa;
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC 7");
+ break;
+ case '(':
+ /* Designate G0 Character set (ISO 2022) */
+ term_state = TSTATE_SETG0;
+ break;
+ case ')':
+ /* Designate G0 character set (ISO 2022) */
+ term_state = TSTATE_SETG1;
+ break;
+ case '*':
+ /* Designate G1 Character set (ISO 2022) */
+ term_state = TSTATE_SETG2;
+ break;
+ case '+':
+ /* Designate G1 Character set (ISO 2022) */
+ term_state = TSTATE_SETG3;
+ break;
+ case '~':
+ /* Locking Shift 1, right */
+ term_state = TSTATE_DATA;
+ gr = 1;
+ break;
+ case 'n':
+ /* Locking Shift 2 */
+ term_state = TSTATE_DATA;
+ gl = 2;
+ break;
+ case '}':
+ /* Locking Shift 2, right */
+ term_state = TSTATE_DATA;
+ gr = 2;
+ break;
+ case 'o':
+ /* Locking Shift 3 */
+ term_state = TSTATE_DATA;
+ gl = 3;
+ break;
+ case '|':
+ /* Locking Shift 3, right */
+ term_state = TSTATE_DATA;
+ gr = 3;
+ break;
+ default:
+ System.out.println("ESC unknown letter: ("+((int)c)+")");
+ term_state = TSTATE_DATA;
+ break;
+ }
+ break;
+ case TSTATE_SETG0:
+ if(c!='0' && c!='A' && c!='B')
+ System.out.println("ESC ( : G0 char set? ("+((int)c)+")");
+ else {
+ if (debug>2) System.out.println("ESC ( : G0 char set ("+c+" "+((int)c)+")");
+ gx[0] = c;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case TSTATE_SETG1:
+ if(c!='0' && c!='A' && c!='B')
+ System.out.println("ESC ) :G1 char set? ("+((int)c)+")");
+ else {
+ if (debug>2) System.out.println("ESC ) :G1 char set ("+c+" "+((int)c)+")");
+ gx[1] = c;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case TSTATE_SETG2:
+ if(c!='0' && c!='A' && c!='B')
+ System.out.println("ESC*:G2 char set? ("+((int)c)+")");
+ else {
+ if (debug>2) System.out.println("ESC*:G2 char set ("+c+" "+((int)c)+")");
+ gx[2] = c;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case TSTATE_SETG3:
+ if(c!='0' && c!='A' && c!='B')
+ System.out.println("ESC+:G3 char set? ("+((int)c)+")");
+ else {
+ if (debug>2) System.out.println("ESC+:G3 char set ("+c+" "+((int)c)+")");
+ gx[3] = c;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case TSTATE_ESCSQUARE:
+ switch (c) {
+ case '8':
+ for (int i=0;i<columns;i++)
+ for (int j=0;j<rows;j++)
+ putChar(i,j,'E',0);
+ break;
+ default:
+ System.out.println("ESC # "+c+" not supported.");
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case TSTATE_DCS:
+ if (c=='\\' && dcs.charAt(dcs.length()-1)==ESC) {
+ handle_dcs(dcs);
+ term_state = TSTATE_DATA;
+ break;
+ }
+ dcs = dcs + c;
+ break;
+ case TSTATE_DCEQ:
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ DCEvars[DCEvar]=DCEvars[DCEvar]*10+((int)c)-48;
+ break;
+ case 'r': // XTERM_RESTORE
+ if (true || debug>1)
+ System.out.println("ESC [ ? "+DCEvars[0]+" r");
+ /* DEC Mode reset */
+ switch (DCEvars[0]){
+ case 3: /* 80 columns*/
+ size = getSize();
+ setScreenSize(80,rows);
+ break;
+ case 4: /* scrolling mode, smooth */
+ break;
+ case 5: /* light background */
+ break;
+ case 6: /* move inside margins ? */
+ moveoutsidemargins = true;
+ break;
+ case 12:/* local echo off */
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case 'h': // DECSET
+ if (debug>0)
+ System.out.println("ESC [ ? "+DCEvars[0]+" h");
+ /* DEC Mode set */
+ switch (DCEvars[0]){
+ case 1: /* Application cursor keys */
+ KeyUp = "\u001bOA";
+ KeyDown = "\u001bOB";
+ KeyRight= "\u001bOC";
+ KeyLeft = "\u001bOD";
+ break;
+ case 3: /* 132 columns*/
+ size = getSize();
+ setScreenSize(132,rows);
+ break;
+ case 4: /* scrolling mode, smooth */
+ break;
+ case 5: /* light background */
+ break;
+ case 6: /* move inside margins ? */
+ moveoutsidemargins = false;
+ break;
+ case 12:/* local echo off */
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case 'l': //DECRST
+ /* DEC Mode reset */
+ if (debug>0)
+ System.out.println("ESC [ ? "+DCEvars[0]+" l");
+ switch (DCEvars[0]){
+ case 1: /* Application cursor keys */
+ KeyUp = "\u001b[A";
+ KeyDown = "\u001b[B";
+ KeyRight= "\u001b[C";
+ KeyLeft = "\u001b[D";
+ break;
+ case 3: /* 80 columns*/
+ size = getSize();
+ setScreenSize(80,rows);
+ break;
+ case 4: /* scrolling mode, jump */
+ break;
+ case 5: /* dark background */
+ break;
+ case 6: /* move outside margins ? */
+ moveoutsidemargins = true;
+ break;
+ case 12:/* local echo on */
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case ';':
+ DCEvar++;
+ DCEvars[DCEvar] = 0;
+ break;
+ case 'n':
+ if (debug>0)
+ System.out.println("ESC [ ? "+DCEvars[0]+" n");
+ switch (DCEvars[0]) {
+ case 15:
+ /* printer? no printer. */
+ write(((char)ESC)+"[?13n");
+ System.out.println("ESC[5n");
+ break;
+ default:break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ default:
+ if (debug>0)
+ System.out.println("ESC [ ? "+DCEvars[0]+" "+c);
+ term_state = TSTATE_DATA;
+ break;
+ }
+ break;
+ case TSTATE_CSI_DOLLAR:
+ switch (c) {
+ case '}':
+ System.out.println("Active Status Display now "+DCEvars[0]);
+ statusmode = DCEvars[0];
+ break;
+ /* bad documentation?
+ case '-':
+ System.out.println("Set Status Display now "+DCEvars[0]);
+ break;
+ */
+ case '~':
+ System.out.println("Status Line mode now "+DCEvars[0]);
+ break;
+ default:
+ System.out.println("UNKNOWN Status Display code "+c+", with Pn="+DCEvars[0]);
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case TSTATE_CSI:
+ switch (c) {
+ case '$':
+ term_state=TSTATE_CSI_DOLLAR;
+ break;
+ case '?':
+ DCEvar=0;
+ DCEvars[0]=0;
+ term_state=TSTATE_DCEQ;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ DCEvars[DCEvar]=DCEvars[DCEvar]*10+((int)c)-48;
+ break;
+ case ';':
+ DCEvar++;
+ DCEvars[DCEvar] = 0;
+ break;
+ case 'c':/* send primary device attributes */
+ /* send (ESC[?61c) */
+ write(((char)ESC)+"[?1;2c");
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" c");
+ break;
+ case 'q':
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" q");
+ term_state = TSTATE_DATA;
+ break;
+ case 'g':
+ /* used for tabsets */
+ switch (DCEvars[0]){
+ case 3:/* clear them */
+ int nw = getColumns();
+ Tabs = new byte[nw];
+ break;
+ case 0:
+ Tabs[C] = 0;
+ break;
+ }
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" g");
+ term_state = TSTATE_DATA;
+ break;
+ case 'h':
+ switch (DCEvars[0]) {
+ case 4:
+ insertmode = 1;
+ break;
+ case 20:
+ sendcrlf = true;
+ break;
+ default:
+ System.out.println("unsupported: ESC [ "+DCEvars[0]+" h");
+ break;
+ }
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" h");
+ break;
+ case 'l':
+ switch (DCEvars[0]) {
+ case 4:
+ insertmode = 0;
+ break;
+ case 20:
+ sendcrlf = false;
+ break;
+ }
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" l");
+ break;
+ case 'A': // CUU
+ {
+ int limit;
+ /* FIXME: xterm only cares about 0 and topmargin */
+ if (R > bm)
+ limit = bm+1;
+ else if (R >= tm) {
+ limit = tm;
+ } else
+ limit = 0;
+ if (DCEvars[0]==0)
+ R--;
+ else
+ R-=DCEvars[0];
+ if (R < limit)
+ R = limit;
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" A");
+ break;
+ }
+ case 'B': // CUD
+ /* cursor down n (1) times */
+ {
+ int limit;
+ if (R < tm)
+ limit = tm-1;
+ else if (R <= bm) {
+ limit = bm;
+ } else
+ limit = rows - 1;
+ if (DCEvars[0]==0)
+ R++;
+ else
+ R+=DCEvars[0];
+ if (R > limit)
+ R = limit;
+ else {
+ if (debug>2) System.out.println("Not limited.");
+ }
+ if (debug>2) System.out.println("to: " + R);
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" B (at C="+C+")");
+ break;
+ }
+ case 'C':
+ if (DCEvars[0]==0)
+ C++;
+ else
+ C+=DCEvars[0];
+ if (C>columns-1)
+ C=columns-1;
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" C");
+ break;
+ case 'd': // CVA
+ R = DCEvars[0];
+ System.out.println("ESC [ "+DCEvars[0]+" d");
+ term_state = TSTATE_DATA;
+ break;
+ case 'D':
+ if (DCEvars[0]==0)
+ C--;
+ else
+ C-=DCEvars[0];
+ if (C<0) C=0;
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" D");
+ break;
+ case 'r': // DECSTBM
+ if (DCEvar>0) // Ray: Any argument is optional
+ {
+ R = DCEvars[1]-1;
+ if (R < 0)
+ R = rows-1;
+ else if (R >= rows) {
+ R = rows - 1;
+ }
+ } else
+ R = rows - 1;
+ setBottomMargin(DCEvars[1]-1);
+ if (R >= DCEvars[0])
+ {
+ R = DCEvars[0]-1;
+ if (R < 0)
+ R = 0;
+ }
+ setTopMargin(DCEvars[0]-1);
+ _SetCursor(0,0);
+ if (debug>1)
+ System.out.println("ESC ["+DCEvars[0]+" ; "+DCEvars[1]+" r");
+ term_state = TSTATE_DATA;
+ break;
+ case 'G': /* CUP / cursor absolute column */
+ C = DCEvars[0];
+ System.out.println("ESC [ "+DCEvars[0]+" G");
+ term_state = TSTATE_DATA;
+ break;
+ case 'H': /* CUP / cursor position */
+ /* gets 2 arguments */
+ _SetCursor(DCEvars[0]-1,DCEvars[1]-1);
+ term_state = TSTATE_DATA;
+ if (debug>2) {
+ System.out.println("ESC [ "+DCEvars[0]+";"+DCEvars[1]+" H, moveoutsidemargins "+moveoutsidemargins);
+ System.out.println(" -> R now "+R+", C now "+C);
+ }
+ break;
+ case 'f': /* move cursor 2 */
+ /* gets 2 arguments */
+ R = DCEvars[0]-1;
+ C = DCEvars[1]-1;
+ if (C<0) C=0;
+ if (R<0) R=0;
+ term_state = TSTATE_DATA;
+ if (debug>2)
+ System.out.println("ESC [ "+DCEvars[0]+";"+DCEvars[1]+" f");
+ break;
+ case 'L':
+ /* insert n lines */
+ if (DCEvars[0]==0)
+ insertLine(R,SCROLL_DOWN);
+ else
+ insertLine(R,DCEvars[0],SCROLL_DOWN);
+ term_state = TSTATE_DATA;
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" L (at R "+R+")");
+ break;
+ case 'M':
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+"M at R="+R);
+ if (DCEvars[0]==0)
+ deleteLine(R);
+ else
+ for (int i=0;i<DCEvars[0];i++)
+ deleteLine(R);
+ term_state = TSTATE_DATA;
+ break;
+ case 'K':
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" K");
+ /* clear in line */
+ switch (DCEvars[0]) {
+ case 0:/*clear to right*/
+ if (C<columns-1)
+ deleteArea(C,R,columns-C,1);
+ break;
+ case 1:/*clear to the left*/
+ if (C>0)
+ deleteArea(0,R,C,1); // Ray: Should at least include character before this one, not C-1
+ break;
+ case 2:/*clear whole line */
+ deleteArea(0,R,columns,1);
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case 'J':
+ /* clear below current line */
+ switch (DCEvars[0]) {
+ case 0:
+ if (R<rows-1)
+ deleteArea(0,R + 1,columns,rows-R-1);
+ if (C<columns-1)
+ deleteArea(C,R,columns-C,1);
+ break;
+ case 1:
+ if (R>0)
+ deleteArea(0,0,columns,R-1);
+ if (C>0)
+ deleteArea(0,R,C,1); // Ray: Should at least include character before this one, not C-1
+ break;
+ case 2:
+ deleteArea(0,0,columns,rows);
+ break;
+ }
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" J");
+ term_state = TSTATE_DATA;
+ break;
+ case '@':
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" @");
+ for (int i=0;i<DCEvars[0];i++)
+ insertChar(C,R,' ',attributes);
+ term_state = TSTATE_DATA;
+ break;
+ case 'P':
+ if (debug>1)
+ System.out.println("ESC [ "+DCEvars[0]+" P, C="+C+",R="+R);
+ if (DCEvars[0]==0) DCEvars[0]=1;
+ for (int i=0;i<DCEvars[0];i++)
+ deleteChar(C,R);
+ term_state = TSTATE_DATA;
+ break;
+ case 'n':
+ switch (DCEvars[0]){
+ case 5: /* malfunction? No malfunction. */
+ write(((char)ESC)+"[0n");
+ if(debug > 1)
+ System.out.println("ESC[5n");
+ break;
+ case 6:
+ write(((char)ESC)+"["+R+";"+C+"R");
+ if(debug > 1)
+ System.out.println("ESC[6n");
+ break;
+ default:
+ if (debug>0)
+ System.out.println("ESC [ "+DCEvars[0]+" n??");
+ break;
+ }
+ term_state = TSTATE_DATA;
+ break;
+ case 'm': /* attributes as color, bold , blink,*/
+ if (debug>3)
+ System.out.print("ESC [ ");
+ if (DCEvar == 0 && DCEvars[0] == 0)
+ attributes = 0;
+ for (i=0;i<=DCEvar;i++) {
+ switch (DCEvars[i]) {
+ case 0:
+ if (DCEvar>0)
+ attributes =0;
+ break;
+ case 4:
+ attributes |= UNDERLINE;
+ break;
+ case 1:
+ attributes |= BOLD;
+ break;
+ case 7:
+ attributes |= INVERT;
+ break;
+ case 5: /* blink on */
+ break;
+ case 25: /* blinking off */
+ break;
+ case 27:
+ attributes &= ~INVERT;
+ break;
+ case 24:
+ attributes &= ~UNDERLINE;
+ break;
+ case 22:
+ attributes &= ~BOLD;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ attributes &= ~(0xf<<3);
+ attributes |= ((DCEvars[i]-30)+1)<<3;
+ break;
+ case 39:
+ attributes &= ~(0xf<<3);
+ break;
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ attributes &= ~(0xf<<7);
+ attributes |= ((DCEvars[i]-40)+1)<<7;
+ break;
+ case 49:
+ attributes &= ~(0xf<<7);
+ break;
+
+ default:
+ System.out.println("ESC [ "+DCEvars[i]+" m unknown...");
+ break;
+ }
+ if (debug>3)
+ System.out.print(""+DCEvars[i]+";");
+ }
+ if (debug>3)
+ System.out.print(" (attributes = "+attributes+")m \n");
+ term_state = TSTATE_DATA;
+ break;
+ default:
+ if (debug>0)
+ System.out.println("ESC [ unknown letter:"+c+" ("+((int)c)+")");
+ term_state = TSTATE_DATA;
+ break;
+ }
+ break;
+ default:
+ term_state = TSTATE_DATA;
+ break;
+ }
+ if (C > columns) C = columns;
+ if (R > rows) R = rows;
+ if (C < 0) C = 0;
+ if (R < 0) R = 0;
+ if (doshowcursor)
+ setCursorPosition(C, R);
+ markLine(R,1);
+ }
+}