From 160431bcbc0a88b10b86315a2fbffd32fc272d88 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Thu, 19 Apr 2007 15:28:39 +0000 Subject: [PATCH] 2007-04-18 Jeffrey Stedfast 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() svn path=/trunk/mcs/; revision=75958 --- mcs/class/corlib/System/CStreamReader.cs | 21 ++- mcs/class/corlib/System/ChangeLog | 15 +++ mcs/class/corlib/System/TermInfoDriver.cs | 156 +++++++++++++++++----- 3 files changed, 146 insertions(+), 46 deletions(-) diff --git a/mcs/class/corlib/System/CStreamReader.cs b/mcs/class/corlib/System/CStreamReader.cs index 37e15a21e29..420554f4a67 100644 --- a/mcs/class/corlib/System/CStreamReader.cs +++ b/mcs/class/corlib/System/CStreamReader.cs @@ -35,9 +35,12 @@ using System.Runtime.InteropServices; 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 () @@ -73,26 +76,18 @@ namespace System.IO { 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) { } diff --git a/mcs/class/corlib/System/ChangeLog b/mcs/class/corlib/System/ChangeLog index 29886ac51ad..eae3f10abf4 100644 --- a/mcs/class/corlib/System/ChangeLog +++ b/mcs/class/corlib/System/ChangeLog @@ -1,3 +1,18 @@ +2007-04-18 Jeffrey Stedfast + + 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 * CStreamWriter.cs (Write): Optimized this some more, we don't diff --git a/mcs/class/corlib/System/TermInfoDriver.cs b/mcs/class/corlib/System/TermInfoDriver.cs index 98f2833d42a..583722b3cb4 100644 --- a/mcs/class/corlib/System/TermInfoDriver.cs +++ b/mcs/class/corlib/System/TermInfoDriver.cs @@ -843,41 +843,125 @@ namespace System { 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) @@ -885,7 +969,7 @@ namespace System { else Console.stdout.Write (key.KeyChar); } - + return key; } @@ -899,16 +983,19 @@ namespace System { // 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) @@ -918,16 +1005,19 @@ namespace System { 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 (); } -- 2.25.1