namespace System.IO {
class CStreamReader : StreamReader {
+ TermInfoDriver driver;
+
public CStreamReader(Stream stream, Encoding encoding)
: base (stream, encoding)
{
+ driver = (TermInfoDriver) ConsoleDriver.driver;
}
public override int Peek ()
if (index > dest.Length - count)
throw new ArgumentException ("index + count > dest.Length");
- int nread = 0;
- int c;
-
- while (count > 0) {
- if ((c = Read ()) == -1)
- break;
-
- nread++;
- count--;
-
- dest[index++] = (char) c;
+ try {
+ return driver.Read (dest, index, count);
+ } catch (IOException) {
}
- return nread;
+ return 0;
}
public override string ReadLine ()
{
try {
- return ConsoleDriver.driver.ReadLine ();
+ return driver.ReadLine ();
} catch (IOException) {
}
+2007-04-18 Jeffrey Stedfast <fejj@novell.com>
+
+ Fixes bug #81159: behave the same as mscorlib
+
+ * TermInfoDriver.cs (ReadKeyInternal): Now has an 'out bool fresh'
+ argument which is used to tell our caller if the key was freshly
+ read from the console or pre-buffered.
+ (Read): New implementation of Console.In.Read(char[], int, int)
+ that behaves exactly like mscorlib's implementation.
+ (ReadKey): Updated for the ReadKeyInternal() API change - only
+ echo if the key was fresh.
+ (ReadLine): Same.
+
+ * CStreamReader.cs (Read): Call the new TermInfoDriver.Read()
+
2007-04-17 Jeffrey Stedfast <fejj@novell.com>
* CStreamWriter.cs (Write): Optimized this some more, we don't
return key;
}
- ConsoleKeyInfo ReadKeyInternal ()
+ ConsoleKeyInfo ReadKeyInternal (out bool fresh)
{
- if (!inited) {
+ if (!inited)
Init ();
- }
InitKeys ();
- object o = null;
- while (o == null) {
- o = GetKeyFromBuffer (true);
- if (o == null) {
+
+ object o;
+
+ if ((o = GetKeyFromBuffer (true)) == null) {
+ do {
if (ConsoleDriver.InternalKeyAvailable (150) > 0) {
do {
AddToBuffer (stdin.ReadByte ());
} while (ConsoleDriver.InternalKeyAvailable (0) > 0);
} else {
- o = GetKeyFromBuffer (false);
- if (o == null)
- AddToBuffer (stdin.ReadByte ());
+ if ((o = GetKeyFromBuffer (false)) != null)
+ break;
+
+ AddToBuffer (stdin.ReadByte ());
}
- }
+
+ o = GetKeyFromBuffer (true);
+ } while (o == null);
+
+ // freshly read character
+ fresh = true;
+ } else {
+ // this char was pre-buffered (e.g. not fresh)
+ fresh = false;
}
return (ConsoleKeyInfo) o;
}
+ public int Read ([In, Out] char [] dest, int index, int count)
+ {
+ CStreamWriter writer = Console.stdout as CStreamWriter;
+ StringBuilder sbuf;
+ ConsoleKeyInfo key;
+ int BoL = 0; // Beginning-of-Line marker (can't backspace beyond this)
+ bool fresh;
+ object o;
+ char c;
+
+ sbuf = new StringBuilder ();
+
+ // consume buffered keys first (do not echo, these have already been echo'd)
+ while (true) {
+ if ((o = GetKeyFromBuffer (true)) == null)
+ break;
+
+ key = (ConsoleKeyInfo) o;
+ c = key.KeyChar;
+
+ if (key.Key != ConsoleKey.Backspace) {
+ if (key.Key == ConsoleKey.Enter)
+ BoL = sbuf.Length;
+
+ sbuf.Append (c);
+ } else if (sbuf.Length > BoL) {
+ sbuf.Length--;
+ }
+ }
+
+ // continue reading until Enter is hit
+ rl_startx = cursorLeft;
+ rl_starty = cursorTop;
+
+ do {
+ key = ReadKeyInternal (out fresh);
+ c = key.KeyChar;
+
+ if (key.Key != ConsoleKey.Backspace) {
+ if (key.Key == ConsoleKey.Enter)
+ BoL = sbuf.Length;
+
+ sbuf.Append (c);
+ } else if (sbuf.Length > BoL) {
+ sbuf.Length--;
+ } else {
+ continue;
+ }
+
+ if (fresh) {
+ // echo fresh keys back to the console
+ if (writer != null)
+ writer.WriteKey (key);
+ else
+ Console.stdout.Write (c);
+ }
+ } while (key.Key != ConsoleKey.Enter);
+
+ rl_startx = -1;
+ rl_starty = -1;
+
+ // copy up to count chars into dest
+ int nread = 0;
+ while (count > 0 && nread < sbuf.Length) {
+ dest[index + nread] = sbuf[nread];
+ nread++;
+ count--;
+ }
+
+ // put the rest back into our key buffer
+ for (int i = nread; i < sbuf.Length; i++)
+ AddToBuffer (sbuf[i]);
+
+ return nread;
+ }
+
public ConsoleKeyInfo ReadKey (bool intercept)
{
- if (!inited)
- Init ();
-
- ConsoleKeyInfo key = ReadKeyInternal ();
-
- if (!intercept) {
- // echo the key back to the console
+ bool fresh;
+
+ ConsoleKeyInfo key = ReadKeyInternal (out fresh);
+
+ if (!intercept && fresh) {
+ // echo the fresh key back to the console
CStreamWriter writer = Console.stdout as CStreamWriter;
if (writer != null)
else
Console.stdout.Write (key.KeyChar);
}
-
+
return key;
}
// cursor state normally).
GetCursorPosition ();
- StringBuilder builder = new StringBuilder ();
- bool exit = false;
CStreamWriter writer = Console.stdout as CStreamWriter;
+ StringBuilder builder = new StringBuilder ();
+ ConsoleKeyInfo key;
+ bool fresh;
+ char c;
+
rl_startx = cursorLeft;
rl_starty = cursorTop;
+
do {
- ConsoleKeyInfo key = ReadKeyInternal ();
- char c = key.KeyChar;
- exit = (c == '\n');
- if (!exit) {
+ key = ReadKeyInternal (out fresh);
+ c = key.KeyChar;
+ if (key.Key != ConsoleKey.Enter) {
if (key.Key != ConsoleKey.Backspace)
builder.Append (c);
else if (builder.Length > 0)
continue;
}
}
-
- // echo the key back to the console
- if (writer != null)
- writer.WriteKey (key);
- else
- Console.stdout.Write (c);
- } while (!exit);
-
+
+ if (fresh) {
+ // echo fresh keys back to the console
+ if (writer != null)
+ writer.WriteKey (key);
+ else
+ Console.stdout.Write (c);
+ }
+ } while (key.Key != ConsoleKey.Enter);
+
rl_startx = -1;
rl_starty = -1;
+
return builder.ToString ();
}