2007-04-18 Jeffrey Stedfast <fejj@novell.com>
authorJeffrey Stedfast <fejj@novell.com>
Thu, 19 Apr 2007 15:28:39 +0000 (15:28 -0000)
committerJeffrey Stedfast <fejj@novell.com>
Thu, 19 Apr 2007 15:28:39 +0000 (15:28 -0000)
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
mcs/class/corlib/System/ChangeLog
mcs/class/corlib/System/TermInfoDriver.cs

index 37e15a21e2991576cbf5105999b67e7a71b77fa6..420554f4a67f32b51928b954d14e183eb64710b6 100644 (file)
@@ -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) {
                        }
 
index 29886ac51ad78e412ee3bfea3c5e484d851154a7..eae3f10abf46121be2ec8686aca11fe58fd13319 100644 (file)
@@ -1,3 +1,18 @@
+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
index 98f2833d42a2dea53bb8bf6e1e5cb557237fc45d..583722b3cb45248a823fbaa3d7518cb5bbaf5697 100644 (file)
@@ -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 ();
                }