2006-09-19 Gonzalo Paniagua Javier <gonzalo@ximian.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Tue, 19 Sep 2006 18:29:25 +0000 (18:29 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Tue, 19 Sep 2006 18:29:25 +0000 (18:29 -0000)
* ConsoleDriver.cs:
* TermInfoDriver.cs:
* IConsoleDriver.cs:
* Console.cs:
* WindowsConsoleDriver.cs: don't switch to the alternate window.
Trigger the cancel event. Retrieve the cursor position at the
beginning, as we're going to keep track of it instead of querying it
all the time.

svn path=/trunk/mcs/; revision=65680

mcs/class/corlib/System/ChangeLog
mcs/class/corlib/System/Console.cs
mcs/class/corlib/System/ConsoleDriver.cs
mcs/class/corlib/System/IConsoleDriver.cs
mcs/class/corlib/System/TermInfoDriver.cs
mcs/class/corlib/System/WindowsConsoleDriver.cs

index 25aa5f1b1d4e5bf845708b27cba7619fdd72f6b7..71e1f63d650f0914301b2d1262143784d9e6eb3e 100644 (file)
@@ -1,3 +1,14 @@
+2006-09-19 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * ConsoleDriver.cs:
+       * TermInfoDriver.cs:
+       * IConsoleDriver.cs:
+       * Console.cs:
+       * WindowsConsoleDriver.cs: don't switch to the alternate window.
+       Trigger the cancel event. Retrieve the cursor position at the
+       beginning, as we're going to keep track of it instead of querying it
+       all the time.
+
 2006-09-14  Jonathan Chambers  <joncham@gmail.com>
 
        * Environment.cs (ProcessorCount): Implement as icall.
index c963158ce6109dae73bca6591df708a2e60ad61b..bed36804a4877993b9540f602143d248c1b8056d 100644 (file)
@@ -104,13 +104,29 @@ namespace System
                                        inputEncoding = outputEncoding = Encoding.Default;
                        }
 
-                       stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding); 
-                       ((StreamWriter)stderr).AutoFlush = true;
-                       stderr = TextWriter.Synchronized (stderr, true);
+#if NET_2_0
+/*
+                       if (ConsoleDriver.IsConsole) {
+                               CStreamWriter w = new CStreamWriter (OpenStandardError (0), outputEncoding); 
+                               w.AutoFlush = true;
+                               stderr = TextWriter.Synchronized (w, true);
+
+                               w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
+                               w.AutoFlush = true;
+                               stdout = TextWriter.Synchronized (w, true);
+                       } else {
+                       */
+#endif
+                               stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding); 
+                               ((StreamWriter)stderr).AutoFlush = true;
+                               stderr = TextWriter.Synchronized (stderr, true);
 
-                       stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
-                       ((StreamWriter)stdout).AutoFlush = true;
-                       stdout = TextWriter.Synchronized (stdout, true);
+                               stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
+                               ((StreamWriter)stdout).AutoFlush = true;
+                               stdout = TextWriter.Synchronized (stdout, true);
+#if NET_2_0
+                       //}
+#endif
 
                        stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
                        stdin = TextReader.Synchronized (stdin);
@@ -148,7 +164,7 @@ namespace System
                        return OpenStandardError (0);
                }
 
-               // calling any FileStream constructor with an handle normally
+               // calling any FileStream constructor with a handle normally
                // requires permissions UnmanagedCode permissions. In this 
                // case we assert this permission so the console can be used
                // in partial trust (i.e. without having UnmanagedCode).
@@ -167,7 +183,7 @@ namespace System
                        return OpenStandardInput (0);
                }
 
-               // calling any FileStream constructor with an handle normally
+               // calling any FileStream constructor with a handle normally
                // requires permissions UnmanagedCode permissions. In this 
                // case we assert this permission so the console can be used
                // in partial trust (i.e. without having UnmanagedCode).
@@ -186,7 +202,7 @@ namespace System
                        return OpenStandardOutput (0);
                }
 
-               // calling any FileStream constructor with an handle normally
+               // calling any FileStream constructor with a handle normally
                // requires permissions UnmanagedCode permissions. In this 
                // case we assert this permission so the console can be used
                // in partial trust (i.e. without having UnmanagedCode).
@@ -448,27 +464,30 @@ namespace System
                }
 #endif
 
+#if NET_2_0
                public static int Read ()
                {
-                       return stdin.Read ();
+                       if (ConsoleDriver.IsConsole) {
+                               return ConsoleDriver.Read ();
+                       } else {
+                               return stdin.Read ();
+                       }
                }
 
-#if NET_2_0
                public static string ReadLine ()
                {
-                       bool prevEcho = false;
-                       if (ConsoleDriver.Initialized) {
-                               prevEcho = ConsoleDriver.Echo;
-                               ConsoleDriver.Echo = true;
+                       if (ConsoleDriver.IsConsole) {
+                               return ConsoleDriver.ReadLine ();
+                       } else {
+                               return stdin.ReadLine ();
                        }
-
-                       string ret = stdin.ReadLine ();
-                       if (ConsoleDriver.Initialized)
-                               ConsoleDriver.Echo = prevEcho;
-
-                       return ret;
                }
 #else
+               public static int Read ()
+               {
+                       return stdin.Read ();
+               }
+
                public static string ReadLine ()
                {
                        return stdin.ReadLine ();
@@ -631,8 +650,30 @@ namespace System
                        ConsoleDriver.SetWindowSize (width, height);
                }
 
-               [MonoTODO ("Implement add/remove hooks")]
                public static event ConsoleCancelEventHandler CancelKeyPress;
+
+               delegate void InternalCancelHandler ();
+               static InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
+
+               internal static void DoConsoleCancelEvent ()
+               {
+                       bool exit = true;
+                       if (CancelKeyPress != null) {
+                               ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
+                               Delegate [] delegates = CancelKeyPress.GetInvocationList ();
+                               foreach (ConsoleCancelEventHandler d in delegates){
+                                       try {
+                                               // Sender is always null here.
+                                               d (null, args);
+                                       } catch {} // Ignore any exception.
+                               }
+                               exit = !args.Cancel;
+                       }
+
+                       if (exit)
+                               Environment.Exit (58);
+               }
 #endif
        }
 }
+
index 44b21638d6fb0e49a69ce5dc152127f954b55eb7..d2b552d84119aa1d737ebc6fa44052c89e342ca4 100644 (file)
@@ -34,6 +34,8 @@ using System.Runtime.CompilerServices;
 namespace System {
        class ConsoleDriver {
                static IConsoleDriver driver;
+               static bool is_console;
+               static bool called_isatty;
 
                static ConsoleDriver ()
                {
@@ -178,6 +180,16 @@ namespace System {
                                        targetLeft, targetTop, sourceChar, sourceForeColor, sourceBackColor);
                }
 
+               public static int Read ()
+               {
+                       return ReadKey (false).KeyChar;
+               }
+
+               public static string ReadLine ()
+               {
+                       return driver.ReadLine ();
+               }
+
                public static ConsoleKeyInfo ReadKey (bool intercept)
                {
                        return driver.ReadKey (intercept);
@@ -208,14 +220,25 @@ namespace System {
                        driver.SetWindowSize (width, height);
                }
 
+               public static bool IsConsole {
+                       get {
+                               if (called_isatty)
+                                       return is_console;
+
+                               is_console = (Isatty (MonoIO.ConsoleOutput) && Isatty (MonoIO.ConsoleInput));
+                               called_isatty = true;
+                               return is_console;
+                       }
+               }
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal static extern bool Isatty (IntPtr handle);
+               static extern bool Isatty (IntPtr handle);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern int InternalKeyAvailable (int ms_timeout);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal static extern bool TtySetup (string teardown);
+               internal static extern bool TtySetup (string teardown, out byte verase, out byte vsusp, out byte intr);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern bool SetEcho (bool wantEcho);
@@ -225,6 +248,9 @@ namespace System {
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern bool GetTtySize (IntPtr handle, out int width, out int height);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal static extern void Suspend ();
        }
 }
 #endif
index 422fe71a7401147f23b29a22fb97d745a8e24582..2c6bde30bfbe812be9ff073757d2a26f4c973b38 100644 (file)
@@ -63,6 +63,7 @@ namespace System {
                void SetCursorPosition (int left, int top);
                void SetWindowPosition (int left, int top);
                void SetWindowSize (int width, int height);
+               string ReadLine ();
        }
 }
 #endif
index d6bfe6b16bebd7ed59264039a50de727255616d9..c0c13d474fd0bbc1319087d9e32edee41a9342bb 100644 (file)
@@ -4,7 +4,7 @@
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2005 Novell, Inc (http://www.novell.com)
+// (C) 2005,2006 Novell, Inc (http://www.novell.com)
 //
 
 //
@@ -30,6 +30,7 @@
 #if NET_2_0
 using System.Collections;
 using System.IO;
+using System.Text;
 namespace System {
        class TermInfoDriver : IConsoleDriver {
                static string [] locations = { "/etc/terminfo", "/usr/share/terminfo", "/usr/lib/terminfo" };
@@ -47,6 +48,9 @@ namespace System {
                string term;
                Stream stdout;
                Stream stdin;
+               byte verase;
+               byte vsusp;
+               byte intr;
 
                int windowWidth;
                int windowHeight;
@@ -58,7 +62,6 @@ namespace System {
                byte [] buffer;
                int readpos;
                int writepos;
-               string enterCA, exitCA;
                string keypadXmit, keypadLocal;
                bool controlCAsInput;
                bool inited;
@@ -132,6 +135,8 @@ namespace System {
 
                        if (reader == null)
                                reader = new TermInfoReader (term, KnownTerminals.ansi);
+
+                       Init ();
                }
 
                public bool Initialized {
@@ -142,25 +147,22 @@ namespace System {
                {
                        if (inited)
                                return;
+                       
+                       /* This should not happen any more, since it is checked for in Console */
+                       if (!ConsoleDriver.IsConsole)
+                               throw new IOException ("Not a tty.");
 
                        inited = true;
-                       enterCA = reader.Get (TermInfoStrings.EnterCaMode);
-                       exitCA = reader.Get (TermInfoStrings.ExitCaMode);
+                       ConsoleDriver.SetEcho (false);
                        string endString = null;
-                       if (enterCA != null && exitCA != null)
-                               endString = exitCA;
-
                        keypadXmit = reader.Get (TermInfoStrings.KeypadXmit);
                        keypadLocal = reader.Get (TermInfoStrings.KeypadLocal);
                        if (keypadXmit != null) {
-                               WriteConsole (keypadXmit);
+                               WriteConsole (keypadXmit); // Needed to get the arrows working
                                if (keypadLocal != null)
                                        endString += keypadLocal;
                        }
 
-                       if (!ConsoleDriver.Isatty (MonoIO.ConsoleOutput) || !ConsoleDriver.Isatty (MonoIO.ConsoleInput))
-                               throw new IOException ("Not a tty.");
-
                        origPair = reader.Get (TermInfoStrings.OrigPair);
                        origColors = reader.Get (TermInfoStrings.OrigColors);
                        setafcolor = MangleParameters (reader.Get (TermInfoStrings.SetAForeground));
@@ -169,12 +171,9 @@ namespace System {
                        if (resetColors != null)
                                endString += resetColors;
 
-                       if (!ConsoleDriver.TtySetup (endString))
+                       if (!ConsoleDriver.TtySetup (endString, out verase, out vsusp, out intr))
                                throw new IOException ("Error initializing terminal.");
 
-                       if (enterCA != null && exitCA != null)
-                               WriteConsole (enterCA);
-
                        stdout = Console.OpenStandardOutput (0);
                        stdin = Console.OpenStandardInput (0);
                        clear = reader.Get (TermInfoStrings.ClearScreen);
@@ -204,6 +203,13 @@ namespace System {
                                home_1_1 = (cursorAddress != result);
                                cursorAddress = MangleParameters (result);
                        }
+
+                       GetCursorPosition ();
+                       if (noGetPosition) {
+                               WriteConsole (clear);
+                               cursorLeft = 0;
+                               cursorTop = 0;
+                       }
                }
 
                static string MangleParameters (string str)
@@ -252,7 +258,6 @@ namespace System {
                public ConsoleColor BackgroundColor {
                        get { return bgcolor; }
                        set {
-                               Init ();
                                bgcolor = value;
                                WriteConsole (String.Format (setabcolor, TranslateColor (value)));
                        }
@@ -261,17 +266,14 @@ namespace System {
                public ConsoleColor ForegroundColor {
                        get { return fgcolor; }
                        set {
-                               Init ();
                                fgcolor = value;
                                WriteConsole (String.Format (setafcolor, TranslateColor (value)));
                        }
                }
 
+               // Only used once.
                void GetCursorPosition ()
                {
-                       if (noGetPosition)
-                               return;
-
                        int row = 0, col = 0;
                        bool prevEcho = Echo;
                        Echo = false;
@@ -330,7 +332,6 @@ namespace System {
 
                public int BufferHeight {
                        get {
-                               GetWindowDimensions ();
                                return bufferHeight;
                        }
                        set {
@@ -340,7 +341,6 @@ namespace System {
 
                public int BufferWidth {
                        get {
-                               GetWindowDimensions ();
                                return bufferWidth;
                        }
                        set {
@@ -354,12 +354,10 @@ namespace System {
 
                public int CursorLeft {
                        get {
-                               Init ();
                                GetCursorPosition ();
                                return cursorLeft;
                        }
                        set {
-                               Init ();
                                SetCursorPosition (value, CursorTop);
                                cursorLeft = value;
                        }
@@ -367,12 +365,10 @@ namespace System {
 
                public int CursorTop {
                        get {
-                               Init ();
                                GetCursorPosition ();
                                return cursorTop;
                        }
                        set {
-                               Init ();
                                SetCursorPosition (CursorLeft, value);
                                cursorTop = value;
                        }
@@ -380,11 +376,9 @@ namespace System {
 
                public bool CursorVisible {
                        get {
-                               Init ();
                                return cursorVisible;
                        }
                        set {
-                               Init ();
                                cursorVisible = value;
                                WriteConsole ((value ? csrVisible : csrInvisible));
                        }
@@ -410,7 +404,6 @@ namespace System {
 
                public bool KeyAvailable {
                        get {
-                               Init ();
                                return (writepos > readpos || ConsoleDriver.InternalKeyAvailable (0) > 0);
                        }
                }
@@ -432,7 +425,6 @@ namespace System {
                        get { return title; }
                        
                        set {
-                               Init ();
                                title = value;
                                WriteConsole (String.Format (titleFormat, value));
                        }
@@ -444,16 +436,14 @@ namespace System {
                                if (controlCAsInput == value)
                                        return;
 
-                               Init ();
                                ConsoleDriver.SetBreak (value);
                                controlCAsInput = value;
                        }
                }
 
+               // TODO: use this at the beginning and on every SIGWINCH
                void GetWindowDimensions ()
                {
-                       //TODO: Handle SIGWINCH
-
                        /* Try the ioctl first */
                        if (!ConsoleDriver.GetTtySize (MonoIO.ConsoleOutput, out windowWidth, out windowHeight)) {
                                windowWidth = reader.Get (TermInfoNumbers.Columns);
@@ -475,8 +465,6 @@ namespace System {
                                }
                        }
 
-                       //windowTop = 0;
-                       //windowLeft = 0;
                        bufferHeight = windowHeight;
                        bufferWidth = windowWidth;
                }
@@ -523,13 +511,11 @@ namespace System {
 
                public void Clear ()
                {
-                       Init ();
                        WriteConsole (clear);
                }
 
                public void Beep (int frequency, int duration)
                {
-                       Init ();
                        WriteConsole (bell);
                }
 
@@ -633,7 +619,6 @@ namespace System {
 
                public ConsoleKeyInfo ReadKey (bool intercept)
                {
-                       Init ();
                        bool prevEcho = Echo;
                        if (prevEcho == intercept)
                                Echo  = !intercept;
@@ -645,9 +630,28 @@ namespace System {
                        return key;
                }
 
+               public string ReadLine ()
+               {
+                       bool prevEcho = Echo;
+                       if (prevEcho == false)
+                               Echo  = true;
+                       StringBuilder builder = new StringBuilder ();
+                       bool exit = false;
+                       do {
+                               ConsoleKeyInfo key = ReadKeyInternal ();
+                               char c = key.KeyChar;
+                               exit = (c == '\n');
+                               if (!exit)
+                                       builder.Append (c);
+                               stdout.WriteByte ((byte) c);
+                       } while (!exit);
+                       if (prevEcho == false)
+                               Echo = prevEcho;
+                       return builder.ToString ();
+               }
+
                public void ResetColor ()
                {
-                       Init ();
                        string str = (origPair != null) ? origPair : origColors;
                        WriteConsole (str);
                }
@@ -668,8 +672,6 @@ namespace System {
                        if (top < 0 || top >= bufferHeight)
                                throw new ArgumentOutOfRangeException ("top", "Value must be positive and below the buffer height.");
 
-                       Init ();
-
                        // Either CursorAddress or nothing.
                        // We might want to play with up/down/left/right/home when ca is not available.
                        if (cursorAddress == null)
index f0d7d0a540e4321a815f2e9ea8425311745953e3..b9592116785b45f20882e45a2639f4dc883b4597 100644 (file)
@@ -456,6 +456,20 @@ namespace System {
                                throw new ArgumentException (String.Empty, "Cannot write to the specified coordinates.");
                }
 
+               public string ReadLine ()
+               {
+                       StringBuilder builder = new StringBuilder ();
+                       bool exit = false;
+                       do {
+                               ConsoleKeyInfo key = ReadKey (false);
+                               char c = key.KeyChar;
+                               exit = (c == '\n');
+                               if (!exit)
+                                       builder.Append (key.KeyChar);
+                       } while (!exit);
+                       return builder.ToString ();
+               }
+
                public ConsoleKeyInfo ReadKey (bool intercept)
                {
                        int eventsRead;