|
From: <ls...@us...> - 2007-08-02 18:15:29
|
Revision: 3374
http://jnode.svn.sourceforge.net/jnode/?rev=3374&view=rev
Author: lsantha
Date: 2007-08-02 11:15:27 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
Keyboard input patch by Stephen Crawley. This patch enables line editting in programs like js and bsh.
Modified Paths:
--------------
trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java
trunk/core/src/core/org/jnode/util/SystemInputStream.java
trunk/core/src/driver/org/jnode/driver/console/ConsoleManager.java
trunk/core/src/driver/org/jnode/driver/console/TextConsole.java
trunk/core/src/driver/org/jnode/driver/console/spi/AbstractConsoleManager.java
trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java
trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsoleManager.java
trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsolePlugin.java
trunk/core/src/driver/org/jnode/driver/input/AbstractKeyboardDriver.java
trunk/core/src/driver/org/jnode/driver/input/Key.java
trunk/core/src/driver/org/jnode/driver/input/KeyboardInterpreter.java
trunk/distr/src/apps/org/jnode/apps/console/SwingConsole.java
trunk/distr/src/apps/org/jnode/apps/editor/TextEditor.java
trunk/distr/src/emu/org/jnode/emu/EditEmu.java
trunk/distr/src/emu/org/jnode/emu/ShellEmu.java
trunk/fs/src/fs/org/jnode/fs/command/CatCommand.java
trunk/gui/src/test/org/jnode/test/gui/ConsoleTest2.java
trunk/gui/src/test/org/jnode/test/gui/FBConsole.java
trunk/shell/descriptors/org.jnode.shell.xml
trunk/shell/src/shell/org/jnode/shell/CommandShell.java
trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java
trunk/shell/src/shell/org/jnode/shell/Shell.java
trunk/shell/src/shell/org/jnode/shell/ThreadCommandInvoker.java
trunk/shell/src/shell/org/jnode/shell/command/HistoryCommand.java
trunk/shell/src/shell/org/jnode/shell/command/driver/console/ConsoleCommand.java
trunk/textui/src/textui/charva/awt/Toolkit.java
Added Paths:
-----------
trunk/core/src/driver/org/jnode/driver/console/CommandHistory.java
trunk/core/src/driver/org/jnode/driver/console/CompletionInfo.java
trunk/core/src/driver/org/jnode/driver/console/InputCompleter.java
trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java
trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java
Removed Paths:
-------------
trunk/core/src/driver/org/jnode/driver/input/KeyboardInputStream.java
trunk/shell/src/shell/org/jnode/shell/CommandHistory.java
trunk/shell/src/shell/org/jnode/shell/CompletionInfo.java
trunk/shell/src/shell/org/jnode/shell/Line.java
Modified: trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java
===================================================================
--- trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -62,7 +62,13 @@
try {
// Create the appenders
final ConsoleManager conMgr = InitialNaming.lookup(ConsoleManager.NAME);
- final TextConsole console = (TextConsole)conMgr.createConsole("Log4j", ConsoleManager.CreateOptions.TEXT | ConsoleManager.CreateOptions.SCROLLABLE | ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR_IN);
+ final TextConsole console =
+ (TextConsole)conMgr.createConsole(
+ "Log4j",
+ (ConsoleManager.CreateOptions.TEXT |
+ ConsoleManager.CreateOptions.SCROLLABLE |
+ ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR |
+ ConsoleManager.CreateOptions.NO_LINE_EDITTING));
conMgr.registerConsole(console);
console.setAcceleratorKeyCode(KeyEvent.VK_F7);
Modified: trunk/core/src/core/org/jnode/util/SystemInputStream.java
===================================================================
--- trunk/core/src/core/org/jnode/util/SystemInputStream.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/core/org/jnode/util/SystemInputStream.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -61,7 +61,9 @@
final public void setIn(InputStream in)
{
- localeIn.set(in);
+ if (in != this) {
+ localeIn.set(in);
+ }
}
/**
@@ -101,7 +103,7 @@
*/
public void initialize(InputStream systemIn)
{
- if(this.systemIn == EMPTY) // register only the first keyboard
+ if (this.systemIn == EMPTY && systemIn != this) // register only the first keyboard
{
this.systemIn = systemIn;
}
Added: trunk/core/src/driver/org/jnode/driver/console/CommandHistory.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/CommandHistory.java (rev 0)
+++ trunk/core/src/driver/org/jnode/driver/console/CommandHistory.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -0,0 +1,94 @@
+/*
+ * $Id: CommandHistory.java 2224 2006-01-01 12:49:03Z epr $
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.driver.console;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Used to keep an archive of commands.
+ * @author Matt Paine
+ */
+public class CommandHistory {
+
+ /** Holds the commands. **/
+ private final List<String> history = new ArrayList<String>();
+
+ /** Constructs a CommandHistory object. **/
+ public CommandHistory() {
+ }
+
+ /** Adds a command to the archive.
+ * @param line The CommandLine to add to the archive.
+ **/
+ public void addCommand(String line) {
+ if( history.contains(line) )
+ history.remove(line);
+ history.add(line);
+ }
+
+ /** Returns the number of commands held in the archive.
+ * @return the number of commands held in the archive.
+ **/
+ public int size() {
+ return history.size();
+ }
+
+ /** Gets a command at a given index.
+ * TODO: make exception more specific
+ * @param index The index (starting at zero) of the command to return.
+ * @return The command at the index given or null if no command found
+ * (out of bounds index).
+ **/
+ public String getCommand(int index) {
+ String retCommand = null;
+ try {
+ retCommand = (String)history.get(index);
+ } catch (Exception ex) {
+ }
+ return retCommand;
+ }
+
+ /** Searches for the most recent command types starting with the specified
+ * string.
+ * @param start The string to search for.
+ * @return The most recent command matching the search string.
+ **/
+ public String getCommand(String start) {
+ return getCommand(findCommand(start));
+ }
+
+ /** Searches the collection for the most recent command starting with the
+ * specified string.
+ * @param start the string to search for.
+ * @return the index number of the specified string (or -1 if not found).
+ **/
+ private int findCommand(String start) {
+ for (int x = 0; x < history.size(); x++) {
+ String cmdLine = (String)history.get(x);
+ if (cmdLine != null)
+ if (cmdLine.startsWith(start))
+ return x;
+ }
+ return -1;
+ }
+
+}
Added: trunk/core/src/driver/org/jnode/driver/console/CompletionInfo.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/CompletionInfo.java (rev 0)
+++ trunk/core/src/driver/org/jnode/driver/console/CompletionInfo.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -0,0 +1,94 @@
+/*
+ * $Id: CompletionInfo.java 2224 2006-01-01 12:49:03Z epr $
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.driver.console;
+
+/**
+ * @author Ewout Prangsma (ep...@us...)
+ */
+public class CompletionInfo {
+ private String[] items = null;
+
+ private String completed = null;
+
+ private boolean newPrompt = false;
+
+ /**
+ * @return Returns the completed.
+ */
+ public String getCompleted() {
+ return completed;
+ }
+
+ /**
+ * @param completed
+ * The completed to set.
+ */
+ public void setCompleted(String completed) {
+ this.completed = completed;
+ }
+
+ /**
+ * get the possible completions
+ *
+ * @return Returns the items.
+ */
+ public String[] getItems() {
+ return items;
+ }
+
+ /**
+ * Specify the possible completions
+ *
+ * @param items
+ * The items to set.
+ */
+ public void setItems(String[] items) {
+ this.items = items;
+ this.completed = null;
+ this.newPrompt = true;
+ }
+
+ /**
+ * Do we have more than one possible completion ?
+ *
+ * @return
+ */
+ public boolean hasItems() {
+ return items != null;
+ }
+
+ /**
+ * Specify if we need a new prompt or not
+ *
+ * @param newPrompt
+ */
+ public void setNewPrompt(boolean newPrompt) {
+ this.newPrompt = newPrompt;
+ }
+
+ /**
+ * @return true if we need to display a new prompt
+ */
+ public boolean needNewPrompt() {
+ return newPrompt;
+ }
+}
Modified: trunk/core/src/driver/org/jnode/driver/console/ConsoleManager.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/ConsoleManager.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/console/ConsoleManager.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -22,6 +22,7 @@
package org.jnode.driver.console;
import java.util.Set;
+import java.io.InputStream;
import java.io.PrintStream;
import org.jnode.driver.input.KeyboardListener;
@@ -112,11 +113,15 @@
/** Create a scrollable console. */
public static final int SCROLLABLE = 0x02;
- /** Do not claim System.out, err, in when focused. */
- public static final int NO_SYSTEM_OUT_ERR_IN = 0x04;
+ /** Do not claim System.out, err when focused. */
+ public static final int NO_SYSTEM_OUT_ERR = 0x04;
/** Stack console on the current screen */
public static final int STACKED = 0x08;
+
+ /** Do not create a line-editting input stream for the console.
+ * The console's input will be whatever System.in currently is. */
+ public static final int NO_LINE_EDITTING = 0x10;
}
/**
Added: trunk/core/src/driver/org/jnode/driver/console/InputCompleter.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/InputCompleter.java (rev 0)
+++ trunk/core/src/driver/org/jnode/driver/console/InputCompleter.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -0,0 +1,8 @@
+package org.jnode.driver.console;
+
+
+public interface InputCompleter {
+ CompletionInfo complete(String partial);
+
+ CommandHistory getCommandHistory();
+}
Modified: trunk/core/src/driver/org/jnode/driver/console/TextConsole.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/TextConsole.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/console/TextConsole.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -21,6 +21,7 @@
package org.jnode.driver.console;
+import java.io.InputStream;
import java.io.PrintStream;
/**
@@ -155,6 +156,12 @@
*/
public void ensureVisible(int row);
+ /**
+ * Gets the input stream of this console.
+ * @return
+ */
+ public InputStream getIn();
+
/**
* Gets the error stream of this console.
* @return
@@ -177,4 +184,17 @@
* @param visible
*/
public void setCursorVisible(boolean visible);
+
+
+ /**
+ * Get the console's input completer
+ * @return The completer or <code>null</code>.
+ */
+ public InputCompleter getCompleter();
+
+ /**
+ * Ges the console's input completer
+ * @param The new completer or <code>null</code>.
+ */
+ public void setCompleter(InputCompleter completer);
}
Modified: trunk/core/src/driver/org/jnode/driver/console/spi/AbstractConsoleManager.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/spi/AbstractConsoleManager.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/console/spi/AbstractConsoleManager.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -98,6 +98,10 @@
}
}
+ protected KeyboardAPI getKeyboardApi() {
+ return kbApi;
+ }
+
/**
* Add a pointer device
*
Added: trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java (rev 0)
+++ trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -0,0 +1,444 @@
+package org.jnode.driver.console.textscreen;
+
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import javax.naming.NameNotFoundException;
+
+import org.jnode.driver.ApiNotFoundException;
+import org.jnode.driver.Device;
+import org.jnode.driver.DeviceListener;
+import org.jnode.driver.DeviceManager;
+import org.jnode.driver.console.CompletionInfo;
+import org.jnode.driver.console.InputCompleter;
+import org.jnode.driver.console.TextConsole;
+import org.jnode.driver.input.KeyboardAPI;
+import org.jnode.driver.input.KeyboardEvent;
+import org.jnode.driver.input.KeyboardListener;
+import org.jnode.naming.InitialNaming;
+import org.jnode.system.BootLog;
+import org.jnode.system.event.FocusEvent;
+import org.jnode.system.event.FocusListener;
+import org.jnode.util.Queue;
+
+
+/**
+ * KeyInputStream maps keyboard events into a stream of characters. Current functionality includes:
+ * <ul>
+ * <li>line buffering and line editing, using a text console,
+ * <li>integrated input history and completion,
+ * <li>CTRL-D is interpretted as a 'soft' EOF mark,KeyboardInputStream
+ * <li>listens to keyboard focus events.
+ * </ul>
+ *
+ * Future enhancements include:
+ * <ul>
+ * <li>a "raw" mode in which characters and other keyboard events are delivered without line editing,
+ * <li>a "no echo" mode in which line editting occurs without echoing of input characters,
+ * <li>making the active characters and keycodes "soft",
+ * <li>making completion and history context sensitive; e.g. when switching between a shell and
+ * an application, and
+ * <li>code refactoring to support classical terminal devices and remote consoles.
+ * </ul>
+ *
+ * Bugs:
+ * <ul>
+ * <li>The current method of echoing the input is suboptimal, and is broken in the case where an
+ * application outputs a prompt string to stdout or stderr.
+ * </ul>
+ *
+ * @author cr...@jn...
+ *
+ */
+public class KeyboardInputStream extends InputStream
+implements KeyboardListener, FocusListener, DeviceListener {
+
+ public static final byte CTRL_L = 12;
+ public static final byte CTRL_D = 4;
+
+ private boolean eof;
+
+ private byte[] buffer;
+ private int pos;
+ private int lim;
+
+ private static final char NO_CHAR = 0;
+
+ private KeyboardAPI api;
+ private DeviceManager devMan;
+
+ /** The queue of keyboard events */
+ private final Queue<KeyboardEvent> queue = new Queue<KeyboardEvent>();
+
+ private final Line currentLine;
+ private final TextConsole console;
+ private InputCompleter completer;
+ private final PrintStream out;
+ private boolean hasFocus;
+
+ private String currentPrompt;
+
+ /**
+ * Contains an index to the current history line, counting from zero. The value
+ * -1 denotes the current line.
+ */
+ private int historyIndex = -1;
+
+ /**
+ * Contains the current line; i.e. the text being entered by the user.
+ */
+ private String newestLine = "";
+
+ public KeyboardInputStream(KeyboardAPI api, TextConsole console) {
+ if (api != null) {
+ this.api = api;
+ this.api.addKeyboardListener(this);
+ }
+ else {
+ try {
+ this.devMan = InitialNaming.lookup(DeviceManager.NAME);
+ this.devMan.addListener(this);
+ }
+ catch (NameNotFoundException ex) {
+ BootLog.error("DeviceManager not found", ex);
+ }
+ }
+ this.console = console;
+ this.out = console.getOut();
+ this.currentLine = new Line(console);
+ this.pos = this.lim = 0;
+ }
+
+ private void registerKeyboardApi(Device device) {
+ if (this.api == null) {
+ try {
+ this.api = device.getAPI(KeyboardAPI.class);
+ this.api.addKeyboardListener(this);
+ }
+ catch (ApiNotFoundException ex) {
+ BootLog.error("KeyboardAPI not found", ex);
+ }
+ this.devMan.removeListener(this);
+ }
+ }
+
+ public boolean isSoftEOF() {
+ return eof;
+ }
+
+ public void clearSoftEOF() {
+ eof = false;
+ }
+
+ @Override
+ public int available() throws IOException {
+ if (eof) {
+ return 0; /* per the JDK 1.6 API docs */
+ }
+ else {
+ // FIXME - what about the case where the line buffer is empty
+ // and there are unconsumed input events in the queue?
+ return currentLine.getLineLength();
+ }
+ }
+
+ /**
+ * @see org.jnode.driver.input.KeyboardListener#keyPressed(org.jnode.driver.input.KeyboardEvent)
+ */
+ public void keyPressed(KeyboardEvent event) {
+ if (hasFocus) {
+ queue.add(event);
+ }
+ }
+
+ /**
+ * @see org.jnode.driver.input.KeyboardListener#keyReleased(org.jnode.driver.input.KeyboardEvent)
+ */
+ public void keyReleased(KeyboardEvent event) {
+ }
+
+ /**
+ * @see java.io.InputStream#close()
+ */
+ public void close() throws IOException {
+ if (api != null) {
+ api.removeKeyboardListener(this);
+ }
+ super.close();
+ }
+
+ /**
+ * Pull a keyboard event from the queue and process it.
+ */
+ private boolean processEvent() {
+ KeyboardEvent event = queue.get();
+ if (!event.isConsumed()) {
+ char ch = event.getKeyChar();
+ if (ch != NO_CHAR) {
+ event.consume();
+ return !processChar(ch);
+ }
+ else {
+ int kc = event.getKeyCode();
+ int mods = event.getModifiers();
+ if (processVirtualKeystroke(kc, mods)) {
+ event.consume();
+ }
+ return true;
+ }
+ }
+ else {
+ return true;
+ }
+ }
+
+ /**
+ * Process a keystroke interpretted as a character.
+ *
+ * @param ch
+ * @return <code>true</code> if the character should cause the current line
+ * buffer contents to be returned to the user.
+ */
+ private boolean processChar(char ch) {
+ boolean breakChar = false;
+ switch (ch) {
+ // if its a backspace we want to remove one from the end of our current
+ // line
+ case KeyEvent.VK_BACK_SPACE:
+ if (currentLine.backspace()) {
+ refreshCurrentLine();
+ }
+ break;
+ // if its a delete we want to remove one under the cursor
+ case KeyEvent.VK_DELETE:
+ currentLine.delete();
+ refreshCurrentLine();
+ break;
+ // if its an enter key we want to process the command, and then resume
+ // the thread
+ case '\n':
+ currentLine.moveEnd();
+ refreshCurrentLine();
+ out.println();
+ currentLine.appendChar(ch);
+ breakChar = true;
+ break;
+ // if it's the tab key, we want to trigger command line completion
+ case '\t':
+ if (completer != null) {
+ CompletionInfo completion = currentLine.complete(currentPrompt);
+ if (completion.needNewPrompt()) {
+ currentLine.start(true);
+ }
+ refreshCurrentLine();
+ }
+ break;
+ case CTRL_D:
+ currentLine.moveEnd();
+ refreshCurrentLine();
+ out.println();
+ eof = true;
+ breakChar = true;
+ break;
+ case CTRL_L:
+ this.console.clear();
+ this.console.setCursor(0, 0);
+ out.print(currentPrompt);
+ currentLine.start();
+ refreshCurrentLine();
+ break;
+ default:
+ // otherwise add it to our current line
+ currentLine.appendChar(ch);
+ refreshCurrentLine();
+ }
+ return breakChar;
+ }
+
+ /**
+ * Process a keystroke that doesn't have an associated char value.
+ * @param code
+ * @param modifiers
+ * @return <code>true</code> if the keystroke has been recognized and
+ * acted on, <code>false</code> otherwise.
+ */
+ private boolean processVirtualKeystroke(int code, int modifiers) {
+ if (modifiers != 0) {
+ return false;
+ }
+ switch (code) {
+ case KeyEvent.VK_UP:
+ // Previous history item
+ if (completer != null) {
+ if (historyIndex == -1) {
+ newestLine = currentLine.getContent();
+ historyIndex = completer.getCommandHistory().size();
+ }
+ historyIndex--;
+ redisplay();
+ }
+ break;
+ case KeyEvent.VK_DOWN:
+ // Next history item
+ if (completer != null) {
+ if (historyIndex == completer.getCommandHistory().size() - 1)
+ historyIndex = -2;
+ else if (historyIndex == -1)
+ newestLine = currentLine.getContent();
+ historyIndex++;
+ redisplay();
+ }
+ break;
+ case KeyEvent.VK_LEFT:
+ // Left the cursor goes left
+ if (currentLine.moveLeft()) {
+ refreshCurrentLine();
+ }
+ break;
+ case KeyEvent.VK_RIGHT:
+ // Right the cursor goes right
+ if (currentLine.moveRight()) {
+ refreshCurrentLine();
+ }
+ break;
+ case KeyEvent.VK_HOME:
+ // The cursor goes at the start
+ currentLine.moveBegin();
+ refreshCurrentLine();
+ break;
+ case KeyEvent.VK_END:
+ // the cursor goes at the end of line
+ currentLine.moveEnd();
+ refreshCurrentLine();
+ break;
+ default:
+ // ignore other virtual keys.
+ return false;
+ }
+ return true;
+ }
+
+ private void refreshCurrentLine() {
+ currentLine.refreshCurrentLine(currentPrompt);
+ }
+
+ private void redisplay() {
+ if (historyIndex == -1) {
+ currentLine.setContent(newestLine);
+ }
+ else {
+ currentLine.setContent(completer.getCommandHistory().getCommand(historyIndex));
+ }
+ refreshCurrentLine();
+ currentLine.moveEnd();
+ }
+
+ private boolean fillBuffer() throws IOException {
+ int x = console.getCursorX();
+ int y = console.getCursorY();
+ StringBuffer sb = new StringBuffer(x);
+ for (int i = 0; i < x; i++) {
+ sb.append(console.getChar(i, y));
+ }
+ currentPrompt = sb.toString();
+
+ currentLine.start();
+ while (processEvent()) { /* */ }
+ buffer = currentLine.consumeBytes();
+ lim = buffer.length;
+ pos = 0;
+ return pos < lim;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (pos >= lim) {
+ if (eof || !fillBuffer()) {
+ return -1;
+ }
+ }
+ return buffer[pos++];
+ }
+
+ @Override
+ public int read(byte[] buff, int off, int len) throws IOException {
+ int nosRead = 0;
+ if (pos >= lim) {
+ if (eof || !fillBuffer()) {
+ return -1;
+ }
+ }
+ while (nosRead < len && pos < lim) {
+ buff[nosRead + off] = buffer[pos];
+ nosRead++;
+ pos++;
+ }
+ return nosRead;
+ }
+
+ @Override
+ public int read(byte[] buff) throws IOException {
+ return read(buff, 0, buff.length);
+ }
+
+ @Override
+ public void mark(int readLimit) {
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public void reset() throws IOException {
+ throw new UnsupportedOperationException("Mark/reset not supported");
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ // I don't expect this method will be used much.
+ for (long i = 0; i < n; i++) {
+ if (read() == -1) {
+ return i;
+ }
+ }
+ return n;
+ }
+
+ public InputCompleter getCompleter() {
+ return completer;
+ }
+
+ public void setCompleter(InputCompleter completer) {
+ this.completer = completer;
+ }
+
+ public void focusGained(FocusEvent event) {
+ hasFocus = true;
+ }
+
+ public void focusLost(FocusEvent event) {
+ hasFocus = false;
+ }
+
+ /**
+ * @param device
+ * @see org.jnode.driver.DeviceListener#deviceStarted(org.jnode.driver.Device)
+ */
+ public void deviceStarted(Device device) {
+ if (device.implementsAPI(KeyboardAPI.class)) {
+ registerKeyboardApi(device);
+ }
+ }
+
+ /**
+ * @param device
+ * @see org.jnode.driver.DeviceListener#deviceStop(org.jnode.driver.Device)
+ */
+ public void deviceStop(Device device) {
+ /* Do nothing */
+ }
+}
Added: trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java (rev 0)
+++ trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -0,0 +1,323 @@
+/*
+ * $Id: Line.java 3119 2007-02-11 22:25:20Z fduminy $
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.driver.console.textscreen;
+
+import java.io.PrintStream;
+
+import org.jnode.driver.console.CompletionInfo;
+import org.jnode.driver.console.InputCompleter;
+import org.jnode.driver.console.TextConsole;
+
+
+/**
+ * A class that handles the content of the current command line in the shell.
+ * That can be : - a new command that the user is beeing editing - an existing
+ * command (from the command history)
+ *
+ * This class also handles the current cursor position in the command line and
+ * keep trace of the position (consoleX, consoleY) of the first character of the
+ * command line (to handle commands that are multilines).
+ *
+ * @author Ewout Prangsma (ep...@us...)
+ * @author Fabien DUMINY (fd...@jn...)
+ */
+class Line {
+ //TODO get the real screen width (in columns)
+ final static private int SCREEN_WIDTH = 80;
+
+ private int consoleX;
+
+ private int consoleY;
+
+ /**
+ * Contains the current position of the cursor on the currentLine
+ */
+ private int posOnCurrentLine = 0;
+
+ /** Contains the current line * */
+ private StringBuffer currentLine = new StringBuffer(80);
+
+ private boolean shortened = true;
+
+ private int oldLength = 0;
+
+ private int maxLength = 0;
+
+ private final TextConsole console;
+
+ private PrintStream out;
+
+ public Line(TextConsole console) {
+ this.console = console;
+ this.out = console.getOut();
+ }
+
+ public void start() {
+ start(false);
+ }
+
+ public boolean isEmpty() {
+ return currentLine.toString().trim().length() == 0;
+ }
+
+ public void start(boolean keepContent) {
+ if (keepContent) {
+ // we stay at the same position in X coordinate
+ // only Y may have changed
+ consoleY = console.getCursorY();
+ } else {
+ consoleX = console.getCursorX();
+ consoleY = console.getCursorY();
+
+ setContent("");
+ console.setCursor( consoleX,consoleY);//move the cursor to the start of the line.
+ }
+ }
+
+ public String getContent() {
+ return currentLine.toString();
+ }
+
+ public byte[] getBytes() {
+ return currentLine.toString().getBytes();
+ }
+
+ public byte[] consumeBytes() {
+ byte[] res = getBytes();
+ currentLine.setLength(0);
+ return res;
+ }
+
+ public void setContent(String content) {
+ startModif();
+ currentLine.setLength(0);
+ currentLine.append(content);
+ moveEnd();
+ endModif();
+ }
+
+ public boolean moveLeft() {
+ if (posOnCurrentLine > 0) {
+ posOnCurrentLine--;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean moveRight() {
+ if (posOnCurrentLine < currentLine.length()) {
+ posOnCurrentLine++;
+ return true;
+ }
+ return false;
+ }
+
+ public void moveEnd() {
+ posOnCurrentLine = currentLine.length();
+ }
+
+ public void moveBegin() {
+ posOnCurrentLine = 0;
+ }
+
+ public boolean backspace() {
+ if (posOnCurrentLine > 0) {
+ moveLeft();
+ delete();
+ return true;
+ }
+ return false;
+ }
+
+ public void delete() {
+ if ((posOnCurrentLine >= 0)
+ && (posOnCurrentLine < currentLine.length())) {
+ startModif();
+ currentLine.deleteCharAt(posOnCurrentLine);
+ endModif();
+ }
+ }
+
+ public CompletionInfo complete(String currentPrompt) {
+ CompletionInfo info = null;
+ InputCompleter completer = console.getCompleter();
+ if (posOnCurrentLine != currentLine.length()) {
+ String ending = currentLine.substring(posOnCurrentLine);
+ info = completer.complete(currentLine.substring(0, posOnCurrentLine));
+ printList(info, currentPrompt);
+ if (info.getCompleted() != null) {
+ setContent(info.getCompleted() + ending);
+ posOnCurrentLine = currentLine.length() - ending.length();
+ }
+ } else {
+ info = completer.complete(currentLine.toString());
+ printList(info, currentPrompt);
+ if (info.getCompleted() != null) {
+ setContent(info.getCompleted());
+ posOnCurrentLine = currentLine.length();
+ }
+ }
+
+ return info;
+ }
+
+ protected void printList(CompletionInfo info, String currentPrompt) {
+ if ((info != null) && info.hasItems()) {
+ int oldPosOnCurrentLine = posOnCurrentLine;
+ moveEnd();
+ refreshCurrentLine(currentPrompt);
+
+ out.println();
+ String[] list = info.getItems();
+
+ final int minItemsToSplit = 5;
+ if(list.length > minItemsToSplit)
+ {
+ list = splitInColumns(list);
+ }
+
+ // display items column (may be single or multiple columns)
+ for (String item : list)
+ {
+ // item may actually be a single item or in fact multiple items
+ if((item.length() % SCREEN_WIDTH) == 0)
+ {
+ // we are already at the first column of the next line
+ out.print(item);
+ }
+ else
+ {
+ // we aren't at the first column of the next line
+ out.println(item);
+ }
+ }
+
+ posOnCurrentLine = oldPosOnCurrentLine;
+ }
+ }
+
+ protected String[] splitInColumns(String[] items)
+ {
+ final int separatorWidth = 3;
+
+ // compute the maximum width of items
+ int maxWidth = 0;
+ for(String item : items)
+ {
+ if(item.length() > maxWidth)
+ {
+ maxWidth = item.length();
+ }
+ }
+
+ final int columnWidth = Math.min(SCREEN_WIDTH, maxWidth + separatorWidth);
+ final int nbColumns = SCREEN_WIDTH / columnWidth;
+ final boolean lastLineIsFull = ((items.length % nbColumns) == 0);
+ final int nbLines = (items.length / nbColumns) + (lastLineIsFull ? 0 : 1);
+
+ String[] lines = new String[nbLines];
+ StringBuilder line = new StringBuilder(SCREEN_WIDTH);
+ int lineNum = 0;
+ for(int itemNum = 0 ; itemNum < items.length ; )
+ {
+ for(int c = 0 ; c < nbColumns ; c++)
+ {
+ final String item = items[itemNum++];
+ line.append(item);
+
+ // add some blanks
+ final int nbBlanks = columnWidth - item.length();
+ for(int i = 0 ; i < nbBlanks ; i++)
+ {
+ line.append(' ');
+ }
+
+ if(itemNum >= items.length) break;
+ }
+
+ lines[lineNum++] = line.toString();
+ line.setLength(0); // clear the buffer
+ }
+
+ return lines;
+ }
+
+ public void appendChar(char c) {
+ startModif();
+ if (posOnCurrentLine == currentLine.length()) {
+ currentLine.append(c);
+ } else {
+ currentLine.insert(posOnCurrentLine, c);
+ }
+ posOnCurrentLine++;
+ endModif();
+ }
+
+ protected void startModif() {
+ shortened = false;
+ oldLength = currentLine.length();
+ }
+
+ protected void endModif() {
+ maxLength = Math.max(oldLength, currentLine.length());
+ shortened = oldLength > currentLine.length();
+ oldLength = 0;
+ }
+
+ public void refreshCurrentLine(String currentPrompt) {
+ try {
+ int x = consoleX;
+ int width = console.getWidth();
+ int nbLines = ((x + maxLength) / width);
+
+ if (((x + maxLength) % width) != 0)
+ nbLines++;
+
+ // if the line has not been shortened (delete, backspace...)
+ if (!shortened)
+ // scroll up the buffer if necessary, and get the new y
+ console.ensureVisible(consoleY + nbLines - 1);
+
+ for (int i = 0; i < nbLines; i++) {
+ console.clearRow(consoleY + i);
+ }
+
+ // print the input line
+ console.setCursor(0, consoleY);
+ out.print(currentPrompt + currentLine);
+
+ int posCurX = x + posOnCurrentLine;
+ int posCurY = consoleY;
+ if (posCurX >= width) {
+ posCurY += posCurX / width;
+ posCurX = (posCurX % width);
+ }
+ console.setCursor(posCurX, posCurY);
+ } catch (Exception e) {
+ //todo: why is it ignored?
+ }
+ }
+
+ public int getLineLength() {
+ return currentLine.length();
+ }
+}
Modified: trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -21,16 +21,19 @@
package org.jnode.driver.console.textscreen;
+import java.io.InputStream;
import java.io.PrintStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.jnode.driver.console.ConsoleManager;
+import org.jnode.driver.console.InputCompleter;
import org.jnode.driver.console.TextConsole;
import org.jnode.driver.console.spi.AbstractConsole;
import org.jnode.driver.console.spi.ConsoleOutputStream;
import org.jnode.driver.textscreen.TextScreen;
import org.jnode.system.event.FocusEvent;
+import org.jnode.system.event.FocusListener;
import org.jnode.vm.isolate.VmIsolate;
/**
@@ -56,10 +59,14 @@
/** Current Y position */
private int curY;
+
+ private InputStream in;
private final PrintStream out;
private final PrintStream err;
+
+ private InputStream savedIn;
private PrintStream savedOut;
@@ -67,7 +74,7 @@
private boolean cursorVisible = true;
- private final boolean claimSystemOutErrIn;
+ private final boolean claimSystemOutErr;
private VmIsolate myIsolate;
@@ -86,7 +93,7 @@
this, 0x07));
this.savedErr = this.err = new PrintStream(new ConsoleOutputStream(
this, 0x04));
- this.claimSystemOutErrIn = ((options & ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR_IN) == 0);
+ this.claimSystemOutErr = ((options & ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR) == 0);
this.myIsolate = VmIsolate.currentIsolate();
}
@@ -285,7 +292,33 @@
syncScreen();
}
+ public InputCompleter getCompleter() {
+ if (in instanceof KeyboardInputStream) {
+ return ((KeyboardInputStream) in).getCompleter();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public void setCompleter(InputCompleter completer) {
+ if (in instanceof KeyboardInputStream) {
+ ((KeyboardInputStream) in).setCompleter(completer);
+ }
+ }
+
/**
+ * @see org.jnode.driver.console.TextConsole#getIn()
+ */
+ public InputStream getIn() {
+ return in;
+ }
+
+ void setIn(InputStream in) {
+ this.savedIn = this.in = in;
+ }
+
+ /**
* @see org.jnode.driver.console.TextConsole#getErr()
*/
public PrintStream getErr() {
@@ -323,7 +356,10 @@
public void focusGained(FocusEvent event) {
super.focusGained(event);
syncScreen();
- if (claimSystemOutErrIn) {
+ if (in instanceof FocusListener) {
+ ((FocusListener) in).focusGained(event);
+ }
+ if (claimSystemOutErr) {
myIsolate.invokeAndWait(new Runnable() {
public void run() {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@@ -342,7 +378,10 @@
* @see org.jnode.system.event.FocusListener#focusLost(org.jnode.system.event.FocusEvent)
*/
public void focusLost(FocusEvent event) {
- if (claimSystemOutErrIn) {
+ if (in instanceof FocusListener) {
+ ((FocusListener) in).focusLost(event);
+ }
+ if (claimSystemOutErr) {
myIsolate.invokeAndWait(new Runnable() {
public void run() {
savedOut = System.out;
Modified: trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsoleManager.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsoleManager.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsoleManager.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -21,11 +21,10 @@
package org.jnode.driver.console.textscreen;
-import java.awt.event.KeyEvent;
+import java.io.InputStream;
import javax.naming.NameNotFoundException;
-import org.jnode.driver.console.Console;
import org.jnode.driver.console.ConsoleException;
import org.jnode.driver.console.spi.AbstractConsoleManager;
import org.jnode.driver.textscreen.ScrollableTextScreen;
@@ -53,7 +52,7 @@
* @see org.jnode.driver.console.ConsoleManager#createConsole(String, int)
*/
public TextScreenConsole createConsole(String name, int options) {
- if ((options & CreateOptions.TEXT) != 0) {
+ if ((options & CreateOptions.TEXT) != 0) {
final TextScreenManager tsm;
tsm = getTextScreenManager();
final TextScreenConsole console;
@@ -69,6 +68,11 @@
screen = tsm.getSystemScreen().createCompatibleBufferScreen();
console = new TextScreenConsole(this, name, screen, options);
}
+ InputStream in = System.in;
+ if ((options & CreateOptions.NO_LINE_EDITTING) == 0) {
+ in = new KeyboardInputStream(getKeyboardApi(), console);
+ }
+ console.setIn(in);
if ((options & CreateOptions.STACKED) != 0){
stackConsole(console);
} else {
@@ -81,7 +85,7 @@
throw new IllegalArgumentException("Unknown option " + options);
}
}
-
+
protected TextScreenManager getTextScreenManager() {
TextScreenManager tsm;
try {
Modified: trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsolePlugin.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsolePlugin.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsolePlugin.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -55,7 +55,10 @@
InitialNaming.bind(ConsoleManager.NAME, mgr);
// Create the first console
- final TextConsole first = (TextConsole)mgr.createConsole(null, ConsoleManager.CreateOptions.TEXT | ConsoleManager.CreateOptions.SCROLLABLE);
+ final TextConsole first = (TextConsole) mgr.createConsole(
+ null,
+ (ConsoleManager.CreateOptions.TEXT |
+ ConsoleManager.CreateOptions.SCROLLABLE));
mgr.focus(first);
System.setOut(first.getOut());
System.setErr(first.getErr());
Modified: trunk/core/src/driver/org/jnode/driver/input/AbstractKeyboardDriver.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/input/AbstractKeyboardDriver.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/input/AbstractKeyboardDriver.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -31,8 +31,6 @@
import org.jnode.driver.Device;
import org.jnode.driver.DriverException;
-import org.jnode.system.BootLog;
-import org.jnode.util.EmptyInputStream;
import org.jnode.util.SystemInputStream;
/**
@@ -105,18 +103,18 @@
dev.registerAPI(KeyboardAPI.class, this);
dev.registerAPI(SystemTriggerAPI.class, this);
- // If no inputstream has been defined, create and set one.
- kis = null;
- if (channel != null) {
- kis = new KeyboardInputStream(this);
- }
- final InputStream systemIn = kis;
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- SystemInputStream.getInstance().initialize(systemIn);
- return null;
- }
- });
+// // If no inputstream has been defined, create and set one.
+// kis = null;
+// if (channel != null) {
+// kis = new KeyboardInputStream(this);
+// }
+// final InputStream systemIn = kis;
+// AccessController.doPrivileged(new PrivilegedAction() {
+// public Object run() {
+// SystemInputStream.getInstance().initialize(systemIn);
+// return null;
+// }
+// });
}
/**
Modified: trunk/core/src/driver/org/jnode/driver/input/Key.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/input/Key.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/input/Key.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -125,6 +125,11 @@
{
this.upperChar = upperChar;
}
+
+ public char getControlChar()
+ {
+ return (char) (upperChar & 0x1f);
+ }
public char getAltGrChar()
{
Deleted: trunk/core/src/driver/org/jnode/driver/input/KeyboardInputStream.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/input/KeyboardInputStream.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/input/KeyboardInputStream.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -1,153 +0,0 @@
-/*
- * $Id$
- *
- * JNode.org
- * Copyright (C) 2003-2006 JNode.org
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; If not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-package org.jnode.driver.input;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.jnode.util.Queue;
-
-/**
- * @author epr
- */
-public class KeyboardInputStream extends InputStream implements KeyboardListener {
-
- private final KeyboardAPI api;
- /** The queue of keyboard events */
- private final Queue<KeyboardEvent> queue = new Queue<KeyboardEvent>();
- /** Should we echo keys on the System.out? */
- private boolean echo = true;
-
- /**
- * Create a new instance
- * @param api the keyboard API
- */
- public KeyboardInputStream(KeyboardAPI api) {
- this.api = api;
- api.addKeyboardListener(this);
- }
-
- /**
- * @see java.io.InputStream#available()
- */
- public int available() throws IOException {
- return 0;
- }
-
- /*
- Doesn't block after the first blocking read.
- public int read(byte[] b, int off, int len) throws IOException {
- if (off < 0 || len < 0 || b.length - off < len)
- throw new IndexOutOfBoundsException();
-
- long time = System.currentTimeMillis();
-
- int i = 0;
- int ch = read(time);
-
- for(;;) {
- b[off + i ++] = (byte) ch;
-
- if(i < len && queue.size() > 0)
- ch = read(time);
- else
- break;
- }
-
- return i;
- }
- */
-
- public int read(byte[] b, int off, int len) throws IOException {
- if (off < 0 || len < 0 || b.length - off < len)
- throw new IndexOutOfBoundsException();
-
- long time = System.currentTimeMillis();
-
- int i = 0;
- int ch = read(time);
-
- for(;;) {
- b[off + i ++] = (byte) ch;
-
- if(i < len && ch != '\n')
- ch = read(time);
- else
- break;
- }
-
- return i;
- }
-
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- long time = System.currentTimeMillis();
- return read(time);
- }
-
- private int read(long time){
- while (true) {
- KeyboardEvent event = queue.get();
- int c = event2char(event, time);
- if(c > 0)
- return c;
- }
- }
-
- private int event2char(KeyboardEvent event, long time) {
- if (!event.isConsumed() && event.getTime() - time > -10000) {
- event.consume();
- char ch = event.getKeyChar();
- if (ch != 0) {
- if (echo) {
- System.out.print(ch);
- }
- return ch;
- }
- }
- return -1;
- }
-
- /**
- * @see org.jnode.driver.input.KeyboardListener#keyPressed(org.jnode.driver.input.KeyboardEvent)
- */
- public void keyPressed(KeyboardEvent event) {
- queue.add(event);
- }
-
- /**
- * @see org.jnode.driver.input.KeyboardListener#keyReleased(org.jnode.driver.input.KeyboardEvent)
- */
- public void keyReleased(KeyboardEvent event) {
- }
-
- /**
- * @see java.io.InputStream#close()
- */
- public void close() throws IOException {
- api.removeKeyboardListener(this);
- super.close();
- }
-
-}
Modified: trunk/core/src/driver/org/jnode/driver/input/KeyboardInterpreter.java
===================================================================
--- trunk/core/src/driver/org/jnode/driver/input/KeyboardInterpreter.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/core/src/driver/org/jnode/driver/input/KeyboardInterpreter.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -32,6 +32,10 @@
*/
public abstract class KeyboardInterpreter
{
+ // FIXME We are currently using the character zero (0x0000) to indicate that no
+ // (Unicode) character corresponds to a keycode. This means that we cannot represent
+ // the NUL control character. Instead we should really be using 0xffff which Unicode
+ // defines to be a non-character.
private int flags;
@@ -110,8 +114,13 @@
catch (UnsupportedKeyException e)
{
final char ch;
- if ((flags & InputEvent.SHIFT_DOWN_MASK) != 0)
+
+ if ((flags & InputEvent.CTRL_DOWN_MASK) != 0)
{
+ ch = keys.getKey(scancode).getControlChar();
+ }
+ else if ((flags & InputEvent.SHIFT_DOWN_MASK) != 0)
+ {
ch = keys.getKey(scancode).getUpperChar();
if (!extendedMode)
Modified: trunk/distr/src/apps/org/jnode/apps/console/SwingConsole.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/console/SwingConsole.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/distr/src/apps/org/jnode/apps/console/SwingConsole.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -28,9 +28,11 @@
TextScreenConsoleManager manager = (TextScreenConsoleManager) sm.getCurrentShell().getConsole().getManager();
SwingTextScreenConsoleManager cm = new SwingTextScreenConsoleManager();
cm.setParent(manager);
- new Thread(new CommandShell((TextConsole) cm.createConsole(null,
- ConsoleManager.CreateOptions.TEXT | ConsoleManager.CreateOptions.SCROLLABLE)), "SwingConsoleCommandShell").
- start();
+ TextConsole console = cm.createConsole(
+ null,
+ (ConsoleManager.CreateOptions.TEXT |
+ ConsoleManager.CreateOptions.SCROLLABLE));
+ new Thread(new CommandShell(console), "SwingConsoleCommandShell").start();
synchronized(SwingConsole.class){
frame = cm.getFrame();
Modified: trunk/distr/src/apps/org/jnode/apps/editor/TextEditor.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/editor/TextEditor.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/distr/src/apps/org/jnode/apps/editor/TextEditor.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -36,10 +36,12 @@
ShellManager sm = InitialNaming.lookup(ShellManager.NAME);
TextScreenConsoleManager manager = (TextScreenConsoleManager) sm.getCurrentShell().getConsole().getManager();
- TextConsole console = manager.createConsole("editor",
- ConsoleManager.CreateOptions.TEXT |
- ConsoleManager.CreateOptions.STACKED |
- ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR_IN);
+ TextConsole console = manager.createConsole(
+ "editor",
+ (ConsoleManager.CreateOptions.TEXT |
+ ConsoleManager.CreateOptions.STACKED |
+ ConsoleManager.CreateOptions.NO_LINE_EDITTING |
+ ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR));
manager.focus(console);
TextEditor te = new TextEditor(console);
Modified: trunk/distr/src/emu/org/jnode/emu/EditEmu.java
===================================================================
--- trunk/distr/src/emu/org/jnode/emu/EditEmu.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/distr/src/emu/org/jnode/emu/EditEmu.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -21,8 +21,11 @@
}
SwingTextScreenConsoleManager cm = new SwingTextScreenConsoleManager();
- final TextScreenConsole console = cm.createConsole(null,
- ConsoleManager.CreateOptions.TEXT | ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR_IN);
+ final TextScreenConsole console = cm.createConsole(
+ null,
+ (ConsoleManager.CreateOptions.TEXT |
+ ConsoleManager.CreateOptions.NO_SYSTEM_OUT_ERR |
+ ConsoleManager.CreateOptions.NO_LINE_EDITTING));
TextEditor te = new TextEditor(console);
File f = new File(argv[0]);
Modified: trunk/distr/src/emu/org/jnode/emu/ShellEmu.java
===================================================================
--- trunk/distr/src/emu/org/jnode/emu/ShellEmu.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/distr/src/emu/org/jnode/emu/ShellEmu.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -12,8 +12,9 @@
public static void main(String[] argv) throws Exception {
initEnv();
SwingTextScreenConsoleManager cm = new SwingTextScreenConsoleManager();
- new Thread(new CommandShell(cm.createConsole("Console 1",
- ConsoleManager.CreateOptions.TEXT | ConsoleManager.CreateOptions.SCROLLABLE))).
- start();
+ new Thread(new CommandShell(cm.createConsole(
+ "Console 1",
+ (ConsoleManager.CreateOptions.TEXT |
+ ConsoleManager.CreateOptions.SCROLLABLE)))).start();
}
}
Modified: trunk/fs/src/fs/org/jnode/fs/command/CatCommand.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/command/CatCommand.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/fs/src/fs/org/jnode/fs/command/CatCommand.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -22,6 +22,7 @@
package org.jnode.fs.command;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
@@ -38,6 +39,7 @@
/**
* @author epr
* @author Andreas H\u00e4nel
+ * @author Stephen Crawley
*/
public class CatCommand implements Command{
@@ -45,8 +47,10 @@
"the file (or URL) to print out");
public static Help.Info HELP_INFO = new Help.Info("cat",
- "Print the contents of the given file (or URL)",
- new Parameter[] { new Parameter(ARG_FILE, Parameter.MANDATORY)});
+ "Print the contents of the given file (or URL). " +
+ "If the file is omitted, standard input is read until EOF is reached; " +
+ "e.g. ^D when reading keyboard input.",
+ new Parameter[] { new Parameter(ARG_FILE, Parameter.OPTIONAL)});
public static void main(String[] args) throws Exception {
new CatCommand().execute(new CommandLine(args), System.in, System.out, System.err);
@@ -54,20 +58,40 @@
public void execute(CommandLine commandLine, InputStream in, PrintStream out, PrintStream err) throws Exception {
ParsedArguments cmdLine = HELP_INFO.parse(commandLine.toStringArray());
- URL url = openURL(ARG_FILE.getValue(cmdLine));
- InputStream is = url.openStream();
- if (is == null) {
- err.println("Not found " + ARG_FILE.getValue(cmdLine));
- } else {
- int len;
- final byte[] buf = new byte[ 1024];
- while ((len = is.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- out.println();
- out.flush();
- is.close();
- }
+ String fileName = ARG_FILE.getValue(cmdLine);
+ InputStream is = null;
+ try {
+ if (fileName == null) {
+ is = in;
+ }
+ else {
+ URL url = openURL(fileName);
+ try {
+ is = url.openStream();
+ }
+ catch (IOException ex) {
+ /* drop through ... */
+ }
+ if (is == null) {
+ err.println("Not found " + ARG_FILE.getValue(cmdLine));
+ // FIXME ... System.exit(1);
+ return;
+ }
+ }
+ int len;
+ final byte[] buf = new byte[ 1024];
+ while ((len = is.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ // FIXME ... Why are we adding an extra newline???
+ out.println();
+ out.flush();
+ }
+ finally {
+ if (is != null && fileName != null) {
+ is.close();
+ }
+ }
}
private URL openURL(String fname) throws MalformedURLException {
Modified: trunk/gui/src/test/org/jnode/test/gui/ConsoleTest2.java
===================================================================
--- trunk/gui/src/test/org/jnode/test/gui/ConsoleTest2.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/gui/src/test/org/jnode/test/gui/ConsoleTest2.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -62,7 +62,8 @@
screen = new JTextAreaTextScreen(80,24);
manager = new TextScreenConsoleManager();
- console = new TextScreenConsole(manager, "test", screen, ConsoleManager.CreateOptions.TEXT);
+ console = new TextScreenConsole(
+ manager, "test", screen, ConsoleManager.CreateOptions.TEXT);
manager.focus(console);
CommandShell commandShell = new CommandShell(console);
Modified: trunk/gui/src/test/org/jnode/test/gui/FBConsole.java
===================================================================
--- trunk/gui/src/test/org/jnode/test/gui/FBConsole.java 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/gui/src/test/org/jnode/test/gui/FBConsole.java 2007-08-02 18:15:27 UTC (rev 3374)
@@ -58,7 +58,8 @@
ScrollableTextScreen ts = new FBConsole.FBPcTextScreen(g).createCompatibleScrollableBufferScreen(500);
- ScrollableTextScreenConsole first = new ScrollableTextScreenConsole(mgr, "console", ts,
+ ScrollableTextScreenConsole first =
+ new ScrollableTextScreenConsole(mgr, "console", ts,
ConsoleManager.CreateOptions.TEXT |
ConsoleManager.CreateOptions.SCROLLABLE);
Modified: trunk/shell/descriptors/org.jnode.shell.xml
===================================================================
--- trunk/shell/descriptors/org.jnode.shell.xml 2007-07-31 18:23:49 UTC (rev 3373)
+++ trunk/shell/descriptors/org.jnode.shell.xml 2007-08-02 18:15:27 UTC (rev 3374)
@@ -32,6 +32,7 @@
<permission class="java.io.FilePermission" name="<<ALL FILES>>" actions="read,write"/>
<permission class="java.lang.RuntimePermission" name="modifyThreadGroup"/>
<permission class="java.lang.RuntimePermission" name="modifyThread"/>
+ <permission class="java.lang.RuntimePermission" name="setIO"/>
<permission class="java.net.SocketPermission" name="*" actions="resolve,listen,connect"/>
<permission class="java.net.SocketPermission" name="*:0-" actions="connect,reso...
[truncated message content] |