From: <cr...@us...> - 2008-09-13 08:02:26
|
Revision: 4556 http://jnode.svn.sourceforge.net/jnode/?rev=4556&view=rev Author: crawley Date: 2008-09-13 08:02:20 +0000 (Sat, 13 Sep 2008) Log Message: ----------- Converted the console subsystem to be natively character (Reader/Writer) based rather than byte (Stream) based, and propagated the API changes throughout the system. Modified Paths: -------------- trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java trunk/core/src/core/org/jnode/log4j/config/VirtualConsoleAppender.java trunk/core/src/core/org/jnode/util/Queue.java trunk/core/src/driver/org/jnode/driver/console/TextConsole.java trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.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/KeyboardEvent.java trunk/distr/src/apps/org/jnode/apps/telnetd/RemoteConsoleManager.java trunk/shell/src/shell/org/jnode/shell/AsyncCommandInvoker.java trunk/shell/src/shell/org/jnode/shell/CommandLine.java trunk/shell/src/shell/org/jnode/shell/CommandRunner.java 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/PathnamePattern.java trunk/shell/src/shell/org/jnode/shell/Shell.java trunk/shell/src/shell/org/jnode/shell/command/HelpCommand.java trunk/shell/src/shell/org/jnode/shell/command/JavaCommand.java trunk/shell/src/shell/org/jnode/shell/command/SyntaxCommand.java trunk/shell/src/shell/org/jnode/shell/command/debug/RemoteOutputCommand.java trunk/shell/src/shell/org/jnode/shell/command/driver/console/ConsoleCommand.java trunk/shell/src/shell/org/jnode/shell/help/Argument.java trunk/shell/src/shell/org/jnode/shell/help/CommandLineElement.java trunk/shell/src/shell/org/jnode/shell/help/Help.java trunk/shell/src/shell/org/jnode/shell/help/Parameter.java trunk/shell/src/shell/org/jnode/shell/help/argument/EnumOptionArgument.java trunk/shell/src/shell/org/jnode/shell/help/argument/OptionArgument.java trunk/shell/src/shell/org/jnode/shell/help/def/DefaultHelp.java trunk/shell/src/shell/org/jnode/shell/io/BaseCommandIO.java trunk/shell/src/shell/org/jnode/shell/io/CommandIO.java trunk/shell/src/shell/org/jnode/shell/io/CommandIOMarker.java trunk/shell/src/shell/org/jnode/shell/io/CommandInput.java trunk/shell/src/shell/org/jnode/shell/io/CommandInputOutput.java trunk/shell/src/shell/org/jnode/shell/io/CommandOutput.java trunk/shell/src/shell/org/jnode/shell/syntax/Log4jLoggerArgument.java trunk/shell/src/shell/org/jnode/shell/syntax/OptionSetSyntax.java trunk/shell/src/test/org/jnode/test/shell/help/DefaultHelpTest.java trunk/shell/src/test/org/jnode/test/shell/io/ReaderInputStreamTest.java trunk/shell/src/test/org/jnode/test/shell/io/WriterOutputStreamTest.java Added Paths: ----------- trunk/core/src/core/org/jnode/log4j/config/JNodeConsoleAppender.java trunk/core/src/core/org/jnode/util/ReaderInputStream.java trunk/core/src/core/org/jnode/util/WriterOutputStream.java trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleWriter.java trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardReader.java trunk/shell/src/shell/org/jnode/shell/io/FanoutWriter.java Removed Paths: ------------- trunk/core/src/driver/org/jnode/driver/console/ConsoleInputStream.java trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleOutputStream.java trunk/core/src/driver/org/jnode/driver/console/spi/ConsolePrintStream.java trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java trunk/shell/src/shell/org/jnode/shell/io/FanoutOutputStream.java trunk/shell/src/shell/org/jnode/shell/io/ReaderInputStream.java trunk/shell/src/shell/org/jnode/shell/io/WriterOutputStream.java Added: trunk/core/src/core/org/jnode/log4j/config/JNodeConsoleAppender.java =================================================================== --- trunk/core/src/core/org/jnode/log4j/config/JNodeConsoleAppender.java (rev 0) +++ trunk/core/src/core/org/jnode/log4j/config/JNodeConsoleAppender.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -0,0 +1,74 @@ +/* + * $Id: Log4jConfigurePlugin.java 4387 2008-08-03 07:55:38Z 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.log4j.config; + +import java.io.Writer; + +import org.apache.log4j.Layout; +import org.apache.log4j.WriterAppender; +import org.jnode.driver.console.TextConsole; + +/** + * Custom Log4j appender class for appending to JNode consoles. This appender + * avoids the unnecessary Writer to Stream to Writer wrappering that goes on + * if we use the standard Log4j ConsoleAppender. (JNode's consoles are natively + * character oriented rather than byte oriented.) + * + * @author cr...@jn... + */ +public class JNodeConsoleAppender extends WriterAppender { + + private Writer writer; + + /** + * Create an appender for a given JNode console. + * @param layout the appender's initial log message layout. + * @param console the target console. + * @param toErr if <code>true</code> output to the console's 'err' stream, + * otherwise to it's 'out' stream. + */ + public JNodeConsoleAppender(Layout layout, TextConsole console, boolean toErr) { + super(); + this.layout = layout; + this.immediateFlush = true; + this.writer = toErr ? console.getErr() : console.getOut(); + super.setWriter(this.writer); + } + + @Override + protected void closeWriter() { + // Ignore the close request. We don't own the writer. + } + + @Override + public void activateOptions() { + super.setWriter(writer); + } + + @Override + public synchronized void setWriter(Writer writer) { + if (writer != this.writer) { + throw new IllegalArgumentException("cannot change the writer"); + } + super.setWriter(writer); + } + +} Modified: trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java =================================================================== --- trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/core/org/jnode/log4j/config/Log4jConfigurePlugin.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -32,6 +32,7 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; +import org.apache.log4j.WriterAppender; import org.jnode.driver.console.ConsoleManager; import org.jnode.driver.console.TextConsole; import org.jnode.naming.InitialNaming; @@ -39,6 +40,7 @@ import org.jnode.plugin.PluginDescriptor; import org.jnode.plugin.PluginException; import org.jnode.system.BootLog; +import org.jnode.util.WriterOutputStream; /** * @author Ewout Prangsma (ep...@us...) @@ -58,6 +60,7 @@ * @see org.jnode.plugin.Plugin#startPlugin() */ protected void startPlugin() throws PluginException { + System.err.println("Running in Log4jConfigurePlugin.startPlugin"); final Logger root = Logger.getRootLogger(); try { // Create the appenders @@ -72,12 +75,23 @@ conMgr.registerConsole(console); console.setAcceleratorKeyCode(KeyEvent.VK_F7); - final VirtualConsoleAppender debugApp = new VirtualConsoleAppender(console, new PatternLayout(LAYOUT)); + final VirtualConsoleAppender debugApp = + new VirtualConsoleAppender(console, new PatternLayout(LAYOUT)); debugApp.setThreshold(Level.DEBUG); - BootLog.setDebugOut(new PrintStream(console.getOut())); + BootLog.setDebugOut(new PrintStream(new WriterOutputStream(console.getOut()), true)); - final ConsoleAppender infoApp = new ConsoleAppender(new PatternLayout(LAYOUT)); + // This doesn't work yet. It sends to the F7 console, whereas we really want to send + // the log messages to the current active console. +// final WriterAppender infoApp = +// new JNodeConsoleAppender(new PatternLayout(LAYOUT), console, false); + + // This kind of works. It sends to whatever System.out currently is at the point + // that the appender is created. But if this plugin is started too late, this will + // could be almost anything. + final WriterAppender infoApp = + new ConsoleAppender(new PatternLayout(LAYOUT)); infoApp.setThreshold(Level.INFO); + infoApp.setImmediateFlush(true); // Add the new appenders root.addAppender(debugApp); @@ -86,10 +100,12 @@ // Remove the existing appenders. for (Enumeration<?> appEnum = root.getAllAppenders(); appEnum.hasMoreElements();) { final Appender appender = (Appender) appEnum.nextElement(); - if ((appender != debugApp) && (appender != infoApp)) { + if (appender != debugApp && appender != infoApp) { root.removeAppender(appender); } } + System.err.println("Sending a test log message"); + root.error("Test log message"); } catch (NameNotFoundException ex) { root.error("ConsoleManager not found", ex); } Modified: trunk/core/src/core/org/jnode/log4j/config/VirtualConsoleAppender.java =================================================================== --- trunk/core/src/core/org/jnode/log4j/config/VirtualConsoleAppender.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/core/org/jnode/log4j/config/VirtualConsoleAppender.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -21,7 +21,6 @@ package org.jnode.log4j.config; -import java.io.OutputStreamWriter; import org.apache.log4j.Layout; import org.apache.log4j.WriterAppender; import org.jnode.driver.console.TextConsole; @@ -38,6 +37,6 @@ */ public VirtualConsoleAppender(TextConsole console, Layout layout) { setLayout(layout); - setWriter(new OutputStreamWriter(console.getOut())); + setWriter(console.getOut()); } } Modified: trunk/core/src/core/org/jnode/util/Queue.java =================================================================== --- trunk/core/src/core/org/jnode/util/Queue.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/core/org/jnode/util/Queue.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -27,6 +27,8 @@ * @author epr */ public class Queue<T> { + + public static final int NO_WAIT = -1; /** * The actual queue @@ -47,7 +49,7 @@ */ public synchronized T get(boolean ignoreInteruptions, long timeout) { while (queue.isEmpty()) { - if (closed) { + if (closed || timeout == NO_WAIT) { return null; } try { @@ -62,7 +64,6 @@ return null; } } - //T result = queue.get(0); return queue.remove(0); } Added: trunk/core/src/core/org/jnode/util/ReaderInputStream.java =================================================================== --- trunk/core/src/core/org/jnode/util/ReaderInputStream.java (rev 0) +++ trunk/core/src/core/org/jnode/util/ReaderInputStream.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -0,0 +1,147 @@ +/* + * $Id: ThreadCommandInvoker.java 3374 2007-08-02 18:15:27Z lsantha $ + * + * JNode.org + * Copyright (C) 2007 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.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; + +/** + * This class wraps a Reader with the InputStream API. It is used internally + * by the JNode shell, and is not recommended for general use. + * + * @author cr...@jn... + */ +public class ReaderInputStream extends InputStream { + private final Reader reader; + + private CharBuffer chars = CharBuffer.allocate(1024); + private ByteBuffer bytes = ByteBuffer.allocate(2048); + + private CharsetEncoder encoder; + + public ReaderInputStream(Reader reader) { + this(reader, Charset.defaultCharset().name()); + } + + public ReaderInputStream(Reader reader, String encoding) { + this.reader = reader; + this.encoder = Charset.forName(encoding).newEncoder(); + this.bytes.position(bytes.limit()); + this.chars.position(chars.limit()); + } + + @Override + public synchronized int read() throws IOException { + if (bytes.remaining() == 0) { + if (fillBuffer(true) == -1) { + return -1; + } + } + return bytes.get(); + } + + @Override + public synchronized int read(byte[] b, int off, int len) throws IOException { + if (off < 0 || off > b.length || len < 0 || off + len > b.length || off + len < 0) { + throw new IndexOutOfBoundsException(); + } + // This implementation is simple-minded. I'm sure we could recode it to avoid + // the 'bytes.get' copying step if we thought about it. + int count = 0; + do { + if (bytes.remaining() == 0) { + int nosRead = fillBuffer(count == 0); + if (nosRead <= 0) { + return count > 0 ? count : -1; + } + } + int toCopy = Math.min(bytes.remaining(), len); + bytes.get(b, off, toCopy); + count += toCopy; + len -= toCopy; + off += toCopy; + } while (count < len); + return count; + } + + @Override + public int read(byte[] b) throws IOException { + return this.read(b, 0, b.length); + } + + /** + * This method puts bytes into the (empty) 'bytes' buffer. It returns + * <code>false</code> if no bytes were copied either because the reader + * would have blocked or because it returned <code>-1</code>. + * + * @param wait if <code>true</code> allow the reader to block. + * @return the number of bytes added; <code>-1</code> if none were added + * and the reader is at the EOF. + * @throws IOException + */ + private int fillBuffer(boolean wait) throws IOException { + bytes.clear(); + // The loop is necessary because of the way that an encoder has to deal + // with UTF-16 surrogate pairs. + CoderResult cr = null; + int count; + do { + if (chars.remaining() == 0 || cr == CoderResult.UNDERFLOW) { + if (chars.remaining() == 0) { + if (!reader.ready() && !wait) { + bytes.flip(); + return 0; + } + chars.clear(); + } else { + char[] tmp = new char[chars.remaining()]; + chars.get(tmp); + chars.clear(); + chars.put(tmp); + } + if (reader.read(chars) == -1) { + chars.flip(); + cr = encoder.encode(chars, bytes, true); + if (cr.isError()) { + cr.throwException(); + } + count = bytes.position(); + bytes.flip(); + return count > 0 ? count : -1; + } + chars.flip(); + } + cr = encoder.encode(chars, bytes, false); + if (cr.isError()) { + cr.throwException(); + } + count = bytes.position(); + } while (wait && count == 0); + bytes.flip(); + return count; + } +} Added: trunk/core/src/core/org/jnode/util/WriterOutputStream.java =================================================================== --- trunk/core/src/core/org/jnode/util/WriterOutputStream.java (rev 0) +++ trunk/core/src/core/org/jnode/util/WriterOutputStream.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -0,0 +1,124 @@ +/* + * $Id: ShellManager.java 3571 2007-10-26 21:30:12Z lsantha $ + * + * 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.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; + +/** + * This class wraps a Writer with the OutputStream API. It is used internally + * by the JNode shell, and is not recommended for general use. + * + * @author cr...@jn... + */ +public class WriterOutputStream extends OutputStream { + + private ByteBuffer bytes = ByteBuffer.allocate(2048); + private CharBuffer chars = CharBuffer.allocate(2048); + + private Writer writer; + private CharsetDecoder decoder; + + public WriterOutputStream(Writer writer) { + this(writer, Charset.defaultCharset().name()); + } + + public WriterOutputStream(Writer writer, String encoding) { + this.writer = writer; + this.decoder = Charset.forName(encoding).newDecoder(); + bytes.clear(); + chars.clear(); + } + + @Override + public synchronized void write(int b) throws IOException { + bytes.put((byte) b); + if (bytes.remaining() == 0) { + flush(false); + } + } + + @Override + public void flush() throws IOException { + flush(false); + writer.flush(); + } + + @Override + public void close() throws IOException { + flush(true); + writer.close(); + } + + private synchronized int flush(boolean all) throws IOException { + if (bytes.position() > 0) { + bytes.flip(); + chars.clear(); + CoderResult cr = decoder.decode(bytes, chars, all); + int count = chars.position(); + if (count > 0) { + int pos = chars.arrayOffset(); + writer.write(chars.array(), pos, count); + } + if (cr.isError() || (all && cr == CoderResult.UNDERFLOW)) { + cr.throwException(); + } + if (bytes.remaining() > 0) { + byte[] tmp = new byte[bytes.remaining()]; + bytes.get(tmp); + bytes.clear(); + bytes.put(tmp); + } else { + bytes.clear(); + } + return count; + } else { + return 0; + } + } + + @Override + public synchronized void write(byte[] b, int off, int len) throws IOException { + if (off < 0 || off > b.length || len < 0 || off + len > b.length || off + len < 0) { + throw new IndexOutOfBoundsException(); + } + while (len > 0) { + int toWrite = Math.min(len, bytes.remaining()); + bytes.put(b, off, toWrite); + off += toWrite; + len -= toWrite; + if (bytes.remaining() == 0) { + flush(false); + } + } + } + + @Override + public void write(byte[] b) throws IOException { + this.write(b, 0, b.length); + } +} Deleted: trunk/core/src/driver/org/jnode/driver/console/ConsoleInputStream.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/ConsoleInputStream.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/driver/org/jnode/driver/console/ConsoleInputStream.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -1,87 +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.console; - -import java.io.IOException; -import java.io.InputStream; -import org.jnode.driver.input.KeyboardEvent; -import org.jnode.driver.input.KeyboardListener; -import org.jnode.util.Queue; - -/** - * @author epr - */ -public class ConsoleInputStream extends InputStream implements KeyboardListener { - - private final Queue<KeyboardEvent> queue = new Queue<KeyboardEvent>(); - private boolean echo = false; - - public ConsoleInputStream(Console console) { - console.addKeyboardListener(this); - } - - /** - * @return Available bytes - * @throws IOException - * @see java.io.InputStream#available() - */ - public int available() throws IOException { - return queue.size(); - } - - /** - * @return int - * @throws IOException - * @see java.io.InputStream#read() - */ - public int read() throws IOException { - while (true) { - KeyboardEvent event = (KeyboardEvent) queue.get(); - if (!event.isConsumed()) { - event.consume(); - char ch = event.getKeyChar(); - if (ch != 0) { - if (echo) { - System.out.print(ch); - } - return ch; - } - } - } - } - - /** - * @param event - * @see org.jnode.driver.input.KeyboardListener#keyPressed(org.jnode.driver.input.KeyboardEvent) - */ - public void keyPressed(KeyboardEvent event) { - //log.debug("got event(" + event + ")"); - queue.add(event); - } - - /** - * @param event - * @see org.jnode.driver.input.KeyboardListener#keyReleased(org.jnode.driver.input.KeyboardEvent) - */ - public void keyReleased(KeyboardEvent event) { - } -} Modified: trunk/core/src/driver/org/jnode/driver/console/TextConsole.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/TextConsole.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/driver/org/jnode/driver/console/TextConsole.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -21,8 +21,8 @@ package org.jnode.driver.console; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; /** * @author Ewout Prangsma (ep...@us...) @@ -155,25 +155,27 @@ public void setTabSize(int tabSize); /** - * Gets the input stream of this console. + * Gets the Reader that delivers input characters from this console. These + * characters are the result of processing keyboard events, performing line + * editing and completion. * * @return */ - public InputStream getIn(); + public Reader getIn(); /** - * Gets the error stream of this console. + * Gets the Writer that receives 'error' output for this console. * * @return */ - public OutputStream getErr(); + public Writer getErr(); /** - * Gets the output stream of this console. + * Gets the Writer that receives 'normal' output for this console. * * @return */ - public OutputStream getOut(); + public Writer getOut(); /** * Is the cursor visible. @@ -196,7 +198,7 @@ public InputCompleter getCompleter(); /** - * Ges the console's input completer + * Set the console's input completer * * @param The new completer or <code>null</code>. */ Deleted: trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleOutputStream.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleOutputStream.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleOutputStream.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -1,94 +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.console.spi; - -import java.io.IOException; -import java.io.OutputStream; -import org.jnode.driver.console.TextConsole; - -/** - * @author epr - * @author Levente S\u00e1ntha (ls...@us...) - */ -public class ConsoleOutputStream extends OutputStream { - - private static final int BUFFER_SIZE = 160; - private final char[] buffer = new char[BUFFER_SIZE]; - private TextConsole console; - private int fgColor; - - - /** - * Create a new instance - * - * @param console - * @param fgColor - */ - public ConsoleOutputStream(TextConsole console, int fgColor) { - this.console = console; - this.fgColor = fgColor; - } - - /** - * @param b - * @throws IOException - * @see java.io.OutputStream#write(int) - */ - public void write(int b) throws IOException { - console.putChar((char) b, fgColor); - } - - public void write(byte[] b, int off, int len) - throws IOException, NullPointerException, IndexOutOfBoundsException { - if (off < 0 || len < 0 || off + len > b.length) - throw new ArrayIndexOutOfBoundsException(); - - int bi = 0; - for (int i = 0; i < len; ++i) { - if (bi >= BUFFER_SIZE) { - console.putChar(buffer, 0, BUFFER_SIZE, fgColor); - bi = 0; - } - buffer[bi++] = (char) b[off + i]; - } - - console.putChar(buffer, 0, bi, fgColor); - } - - - /** - * @return int - */ - public int getFgColor() { - return fgColor; - } - - /** - * Sets the fgColor. - * - * @param fgColor The fgColor to set - */ - public void setFgColor(int fgColor) { - this.fgColor = fgColor; - } - -} Deleted: trunk/core/src/driver/org/jnode/driver/console/spi/ConsolePrintStream.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/spi/ConsolePrintStream.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/driver/org/jnode/driver/console/spi/ConsolePrintStream.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -1,17 +0,0 @@ -package org.jnode.driver.console.spi; - -import java.io.PrintStream; - -public class ConsolePrintStream extends PrintStream { - public ConsolePrintStream(ConsoleOutputStream out) { - super(out); - } - - public int getFgColor() { - return ((ConsoleOutputStream) out).getFgColor(); - } - - public void setFgColor(int color) { - ((ConsoleOutputStream) out).setFgColor(color); - } -} Added: trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleWriter.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleWriter.java (rev 0) +++ trunk/core/src/driver/org/jnode/driver/console/spi/ConsoleWriter.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -0,0 +1,98 @@ +/* + * $Id: ConsoleOutputStream.java 4153 2008-05-30 12:20:45Z lsantha $ + * + * 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.spi; + +import java.io.IOException; +import java.io.Writer; +import org.jnode.driver.console.TextConsole; + +/** + * @author epr + * @author Levente S\u00e1ntha (ls...@us...) + */ +public class ConsoleWriter extends Writer { + + private static final int BUFFER_SIZE = 160; + private final char[] buffer = new char[BUFFER_SIZE]; + private TextConsole console; + private int fgColor; + + + /** + * Create a new instance + * + * @param console + * @param fgColor + */ + public ConsoleWriter(TextConsole console, int fgColor) { + this.console = console; + this.fgColor = fgColor; + } + + @Override + public void write(int b) throws IOException { + console.putChar((char) b, fgColor); + } + + public void write(char[] cbuf, int off, int len) + throws IOException, NullPointerException, IndexOutOfBoundsException { + if (off < 0 || len < 0 || off + len > cbuf.length) + throw new ArrayIndexOutOfBoundsException(); + + int bi = 0; + for (int i = 0; i < len; ++i) { + if (bi >= BUFFER_SIZE) { + console.putChar(buffer, 0, BUFFER_SIZE, fgColor); + bi = 0; + } + buffer[bi++] = (char) cbuf[off + i]; + } + + console.putChar(buffer, 0, bi, fgColor); + } + + + @Override + public void close() throws IOException { + } + + @Override + public void flush() throws IOException { + } + + /** + * @return int + */ + public int getFgColor() { + return fgColor; + } + + /** + * Sets the fgColor. + * + * @param fgColor The fgColor to set + */ + public void setFgColor(int fgColor) { + this.fgColor = fgColor; + } + +} Deleted: trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardInputStream.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -1,390 +0,0 @@ -package org.jnode.driver.console.textscreen; - -import java.awt.event.KeyEvent; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; - -import org.jnode.driver.console.InputCompleter; -import org.jnode.driver.console.TextConsole; -import org.jnode.driver.input.KeyboardEvent; -import org.jnode.system.event.FocusEvent; -import org.jnode.system.event.FocusListener; - - -/** - * 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> - * <p/> - * 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> - * <p/> - * 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 FocusListener { - - 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 final Line currentLine; - private final TextConsole console; - private InputCompleter completer; - private final PrintStream out; - - 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 savedCurrentLine; - - private final KeyboardHandler keyboardHandler; - private final FocusListener focusListener; - - public KeyboardInputStream(KeyboardHandler kbHandler, TextConsole console) { - this.keyboardHandler = kbHandler; - this.console = console; - this.out = new PrintStream(console.getOut()); - this.currentLine = new Line(console); - this.pos = this.lim = 0; - - if (keyboardHandler instanceof FocusListener) { - this.focusListener = (FocusListener) keyboardHandler; - } else { - this.focusListener = null; - } - } - - 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 java.io.InputStream#close() - */ - public void close() throws IOException { - keyboardHandler.close(); - super.close(); - } - - /** - * Pull a keyboard event from the queue and process it. - * - * @return true if the event was processed - */ - private boolean processEvent() { - KeyboardEvent event = keyboardHandler.getEvent(); - 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 the character to process - * @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 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; - historyIndex = -1; - break; - // if it's the tab key, we want to trigger command line completion - case '\t': - if (completer != null) { - if (currentLine.complete()) { - currentLine.start(true); - } - out.print(currentPrompt); - refreshCurrentLine(); - } - break; - // interpret ^D as a soft EOF - // FIXME - behavior correct? cf bash's treatment of ^D - case CTRL_D: - currentLine.moveEnd(); - refreshCurrentLine(); - out.println(); - eof = true; - breakChar = true; - break; - // ^L means kill current line and redraw screen. - // FIXME - is this behavior useful? - 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(); - historyIndex = -1; - } - return breakChar; - } - - /** - * Process a keystroke that doesn't have an associated char value. - * - * @param code key code - * @param modifiers key 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) { - historyIndex = completer.getInputHistory().size(); - savedCurrentLine = currentLine.getContent(); - } - historyIndex--; - - updateCurrentLine(); - } - break; - case KeyEvent.VK_DOWN: - // Next history item - if (completer != null) { - if (historyIndex == -1) - savedCurrentLine = currentLine.getContent(); - - if (historyIndex == completer.getInputHistory().size() - 1) - historyIndex = -2; - - historyIndex++; - - updateCurrentLine(); - - } - 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; - // if its a delete we want to remove one under the cursor - case KeyEvent.VK_DELETE: - currentLine.delete(); - refreshCurrentLine(); - break; - default: - // ignore other virtual keys. - return false; - } - return true; - } - - private void updateCurrentLine() { - if (historyIndex > -1) { - currentLine.setContent(completer.getInputHistory().getLineAt(historyIndex)); - } else { - currentLine.setContent(savedCurrentLine); - } - refreshCurrentLine(); - currentLine.moveEnd(); - } - - private void refreshCurrentLine() { - currentLine.refreshCurrentLine(); - } - - 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) { - if (focusListener != null) { - focusListener.focusGained(event); - } - } - - public void focusLost(FocusEvent event) { - if (focusListener != null) { - focusListener.focusLost(event); - } - } -} Added: trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardReader.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardReader.java (rev 0) +++ trunk/core/src/driver/org/jnode/driver/console/textscreen/KeyboardReader.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -0,0 +1,385 @@ +package org.jnode.driver.console.textscreen; + +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.io.Reader; +import java.io.PrintStream; +import java.io.Writer; + +import org.jnode.driver.console.InputCompleter; +import org.jnode.driver.console.TextConsole; +import org.jnode.driver.input.KeyboardEvent; +import org.jnode.system.event.FocusEvent; +import org.jnode.system.event.FocusListener; + + +/** + * KeyboardInputStream 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 interpreted as a 'soft' EOF mark,KeyboardInputStream + * <li>listens to keyboard focus events. + * </ul> + * <p/> + * 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 editing 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> + * <p/> + * 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 KeyboardReader extends Reader + implements FocusListener { + + public static final byte CTRL_L = 12; + public static final byte CTRL_D = 4; + + private boolean eof; + + private char[] buffer; + private int pos; + private int lim; + + private static final char NO_CHAR = 0; + + private final Line currentLine; + private final TextConsole console; + private InputCompleter completer; + private final Writer out; + + 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 savedCurrentLine; + + private final KeyboardHandler keyboardHandler; + private final FocusListener focusListener; + + public KeyboardReader(KeyboardHandler kbHandler, TextConsole console) { + this.keyboardHandler = kbHandler; + this.console = console; + this.out = console.getOut(); + this.currentLine = new Line(console); + this.pos = this.lim = 0; + + if (keyboardHandler instanceof FocusListener) { + this.focusListener = (FocusListener) keyboardHandler; + } else { + this.focusListener = null; + } + } + + public boolean isSoftEOF() { + return eof; + } + + public void clearSoftEOF() { + eof = false; + } + + @Override + public boolean ready() throws IOException { + return eof || currentLine.getLineLength() > 0; + } + + /** + * @see java.io.Reader#close() + */ + public void close() throws IOException { + keyboardHandler.close(); + } + + /** + * Pull a keyboard event from the queue and process it. + * + * @return true if the event was processed + */ + private boolean processEvent() throws IOException { + KeyboardEvent event = keyboardHandler.getEvent(); + 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 interpreted as a character. + * + * @param ch the character to process + * @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) throws IOException { + 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 an enter key we want to process the command, and then + // resume + // the thread + case '\n': + currentLine.moveEnd(); + refreshCurrentLine(); + out.write('\n'); + currentLine.appendChar(ch); + breakChar = true; + historyIndex = -1; + break; + // if it's the tab key, we want to trigger command line completion + case '\t': + if (completer != null) { + if (currentLine.complete()) { + currentLine.start(true); + } + out.write(currentPrompt); + refreshCurrentLine(); + } + break; + // interpret ^D as a soft EOF + // FIXME - behavior correct? cf bash's treatment of ^D + case CTRL_D: + currentLine.moveEnd(); + refreshCurrentLine(); + out.write('\n'); + eof = true; + breakChar = true; + break; + // ^L means kill current line and redraw screen. + // FIXME - is this behavior useful? + case CTRL_L: + this.console.clear(); + this.console.setCursor(0, 0); + out.write(currentPrompt); + currentLine.start(); + refreshCurrentLine(); + break; + default: + // otherwise add it to our current line + currentLine.appendChar(ch); + refreshCurrentLine(); + historyIndex = -1; + } + return breakChar; + } + + /** + * Process a keystroke that doesn't have an associated char value. + * + * @param code key code + * @param modifiers key modifiers + * @return <code>true</code> if the keystroke has been recognized and + * acted on, <code>false</code> otherwise. + * @throws IOException + */ + private boolean processVirtualKeystroke(int code, int modifiers) throws IOException { + if (modifiers != 0) { + return false; + } + switch (code) { + case KeyEvent.VK_UP: + // Previous history item + if (completer != null) { + if (historyIndex == -1) { + historyIndex = completer.getInputHistory().size(); + savedCurrentLine = currentLine.getContent(); + } + historyIndex--; + + updateCurrentLine(); + } + break; + case KeyEvent.VK_DOWN: + // Next history item + if (completer != null) { + if (historyIndex == -1) + savedCurrentLine = currentLine.getContent(); + + if (historyIndex == completer.getInputHistory().size() - 1) + historyIndex = -2; + + historyIndex++; + + updateCurrentLine(); + + } + 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; + // if its a delete we want to remove one under the cursor + case KeyEvent.VK_DELETE: + currentLine.delete(); + refreshCurrentLine(); + break; + default: + // ignore other virtual keys. + return false; + } + return true; + } + + private void updateCurrentLine() throws IOException { + if (historyIndex > -1) { + currentLine.setContent(completer.getInputHistory().getLineAt(historyIndex)); + } else { + currentLine.setContent(savedCurrentLine); + } + refreshCurrentLine(); + currentLine.moveEnd(); + } + + private void refreshCurrentLine() throws IOException { + currentLine.refreshCurrentLine(); + } + + 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.consumeChars(); + 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(char[] 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(char[] 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) { + if (focusListener != null) { + focusListener.focusGained(event); + } + } + + public void focusLost(FocusEvent event) { + if (focusListener != null) { + focusListener.focusLost(event); + } + } +} Modified: trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java 2008-09-11 18:40:09 UTC (rev 4555) +++ trunk/core/src/driver/org/jnode/driver/console/textscreen/Line.java 2008-09-13 08:02:20 UTC (rev 4556) @@ -21,13 +21,14 @@ package org.jnode.driver.console.textscreen; +import java.io.IOException; import java.util.Arrays; import java.util.SortedSet; import org.jnode.driver.console.CompletionInfo; import org.jnode.driver.console.InputCompleter; import org.jnode.driver.console.ScrollableTextConsole; import org.jnode.driver.console.TextConsole; -import org.jnode.driver.console.spi.ConsolePrintStream; +import org.jnode.driver.console.spi.ConsoleWriter; /** @@ -68,11 +69,11 @@ private final TextConsole console; - private ConsolePrintStream out; + private ConsoleWriter out; public Line(TextConsole console) { this.console = console; - this.out = (ConsolePrintStream) console.getOut(); + this.out = (ConsoleWriter) console.getOut(); } public void start() { @@ -101,12 +102,14 @@ return currentLine.toString(); } - public byte[] getBytes() { - return currentLine.toString().getBytes(); + public char[] getChars() { + char[] res = new char[currentLine.length()]; + currentLine.getChars(0, currentLine.length(), res, 0); + return res; } - public byte[] consumeBytes() { - byte[] res = getBytes(); + public char[] consumeChars() { + char[] res = getChars(); currentLine.setLength(0); return res; } @@ -161,7 +164,7 @@ } } - public boolean complete() { + public boolean complete() throws IOException { CompletionInfo info = null; InputCompleter completer... [truncated message content] |