X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem%2FConsole.cs;h=fe0f229e396b169123983fdb3292b672d18c83d3;hb=e2b2d181084848f3c5dde2788370db1b79893c69;hp=d1ffae3ffccbf0558256f84179ebdf39616445bc;hpb=71c2b176059ebf7ad36870a0049e6f58b2e929b2;p=mono.git diff --git a/mcs/class/corlib/System/Console.cs b/mcs/class/corlib/System/Console.cs index d1ffae3ffcc..fe0f229e396 100644 --- a/mcs/class/corlib/System/Console.cs +++ b/mcs/class/corlib/System/Console.cs @@ -29,29 +29,41 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Security; using System.Security.Permissions; using System.Text; namespace System { - public -#if NET_2_0 - static -#else - sealed -#endif - class Console + public static class Console { +#if !NET_2_1 private class WindowsConsole { + public static bool ctrlHandlerAdded = false; + private delegate bool WindowsCancelHandler (int keyCode); + private static WindowsCancelHandler cancelHandler = new WindowsCancelHandler (DoWindowsConsoleCancelEvent); + [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] private static extern int GetConsoleCP (); [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] private static extern int GetConsoleOutputCP (); + [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] + private static extern bool SetConsoleCtrlHandler (WindowsCancelHandler handler, bool addHandler); + + // Only call the event handler if Control-C was pressed (code == 0), nothing else + private static bool DoWindowsConsoleCancelEvent (int keyCode) + { + if (keyCode == 0) + DoConsoleCancelEvent (); + return keyCode == 0; + } + [MethodImpl (MethodImplOptions.NoInlining)] public static int GetInputCodePage () { @@ -63,15 +75,34 @@ namespace System { return GetConsoleOutputCP (); } + + public static void AddCtrlHandler () + { + SetConsoleCtrlHandler (cancelHandler, true); + ctrlHandlerAdded = true; + } + + public static void RemoveCtrlHandler () + { + SetConsoleCtrlHandler (cancelHandler, false); + ctrlHandlerAdded = false; + } } +#endif internal static TextWriter stdout; private static TextWriter stderr; private static TextReader stdin; +#if NET_4_5 + static TextWriter console_stdout; + static TextWriter console_stderr; + static TextReader console_stdin; +#endif + static Console () { -#if !NET_2_0 +#if NET_2_1 Encoding inputEncoding; Encoding outputEncoding; #endif @@ -80,6 +111,10 @@ namespace System // // On Windows, follow the Windows tradition // +#if NET_2_1 + // should never happen since Moonlight does not run on windows + inputEncoding = outputEncoding = Encoding.Default; +#else try { inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ()); outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ()); @@ -87,8 +122,9 @@ namespace System } catch { // FIXME: I18N assemblies are not available when compiling mcs // Use Latin 1 as it is fast and UTF-8 is never used as console code page - inputEncoding = outputEncoding = Encoding.GetEncoding (28591); + inputEncoding = outputEncoding = Encoding.Default; } +#endif } else { // // On Unix systems (128), do not output the @@ -104,39 +140,65 @@ namespace System inputEncoding = outputEncoding = Encoding.Default; } - stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding); - ((StreamWriter)stderr).AutoFlush = true; - stderr = TextWriter.Synchronized (stderr, true); + SetupStreams (inputEncoding, outputEncoding); + } -#if NET_2_0 - if (ConsoleDriver.IsConsole) { + static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding) + { +#if !NET_2_1 + if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) { StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding); w.AutoFlush = true; - stdout = w; + stdout = TextWriter.Synchronized (w, true); + + w = new CStreamWriter (OpenStandardOutput (0), outputEncoding); + w.AutoFlush = true; + stderr = TextWriter.Synchronized (w, true); + stdin = new CStreamReader (OpenStandardInput (0), inputEncoding); - ConsoleDriver.Init (); } else { #endif +#if FULL_AOT_RUNTIME + Type nslogwriter = Type.GetType ("MonoTouch.Foundation.NSLogWriter, monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); + stdout = (TextWriter) Activator.CreateInstance (nslogwriter); +#else stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding); ((StreamWriter)stdout).AutoFlush = true; +#endif stdout = TextWriter.Synchronized (stdout, true); + +#if FULL_AOT_RUNTIME + stderr = (TextWriter) Activator.CreateInstance (nslogwriter); +#else + stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding); + ((StreamWriter)stderr).AutoFlush = true; +#endif + stderr = TextWriter.Synchronized (stderr, true); + stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding); stdin = TextReader.Synchronized (stdin); -#if NET_2_0 +#if !NET_2_1 } #endif +#if NET_4_5 + console_stderr = stderr; + console_stdout = stdout; + console_stdin = stdin; +#endif + +#if MONODROID + if (LogcatTextWriter.IsRunningOnAndroid ()) { + stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout)); + stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr)); + } +#endif // MONODROID + GC.SuppressFinalize (stdout); GC.SuppressFinalize (stderr); GC.SuppressFinalize (stdin); } -#if !NET_2_0 - private Console () - { - } -#endif - public static TextWriter Error { get { return stderr; @@ -155,6 +217,39 @@ namespace System } } +#if NET_4_5 + public static bool IsErrorRedirected { + get { + return stderr != console_stderr || ConsoleDriver.IsErrorRedirected; + } + } + + public static bool IsOutputRedirected { + get { + return stdout != console_stdout || ConsoleDriver.IsOutputRedirected; + } + } + + public static bool IsInputRedirected { + get { + return stdin != console_stdin || ConsoleDriver.IsInputRedirected; + } + } +#endif + + private static Stream Open (IntPtr handle, FileAccess access, int bufferSize) + { +#if MOONLIGHT + if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null) + return new NullStream (); +#endif + try { + return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0); + } catch (IOException) { + return new NullStream (); + } + } + public static Stream OpenStandardError () { return OpenStandardError (0); @@ -167,11 +262,7 @@ namespace System [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)] public static Stream OpenStandardError (int bufferSize) { - try { - return new FileStream (MonoIO.ConsoleError, FileAccess.Write, false, bufferSize, false, bufferSize == 0); - } catch (IOException) { - return new NullStream (); - } + return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize); } public static Stream OpenStandardInput () @@ -186,11 +277,7 @@ namespace System [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)] public static Stream OpenStandardInput (int bufferSize) { - try { - return new FileStream (MonoIO.ConsoleInput, FileAccess.Read, false, bufferSize, false, bufferSize == 0); - } catch (IOException) { - return new NullStream (); - } + return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize); } public static Stream OpenStandardOutput () @@ -205,11 +292,7 @@ namespace System [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)] public static Stream OpenStandardOutput (int bufferSize) { - try { - return new FileStream (MonoIO.ConsoleOutput, FileAccess.Write, false, bufferSize, false, bufferSize == 0); - } catch (IOException) { - return new NullStream (); - } + return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize); } [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)] @@ -249,9 +332,9 @@ namespace System stdout.Write (value); } - public static void Write (char[] value) + public static void Write (char[] buffer) { - stdout.Write (value); + stdout.Write (buffer); } public static void Write (decimal value) @@ -308,7 +391,10 @@ namespace System public static void Write (string format, params object[] arg) { - stdout.Write (format, arg); + if (arg == null) + stdout.Write (format); + else + stdout.Write (format, arg); } public static void Write (char[] buffer, int index, int count) @@ -326,7 +412,6 @@ namespace System stdout.Write (format, arg0, arg1, arg2); } -#if ! BOOTSTRAP_WITH_OLDLIB [CLSCompliant (false)] public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist) { @@ -345,7 +430,6 @@ namespace System stdout.Write (String.Format (format, args)); } -#endif public static void WriteLine () { @@ -362,9 +446,9 @@ namespace System stdout.WriteLine (value); } - public static void WriteLine (char[] value) + public static void WriteLine (char[] buffer) { - stdout.WriteLine (value); + stdout.WriteLine (buffer); } public static void WriteLine (decimal value) @@ -421,7 +505,10 @@ namespace System public static void WriteLine (string format, params object[] arg) { - stdout.WriteLine (format, arg); + if (arg == null) + stdout.WriteLine (format); + else + stdout.WriteLine (format, arg); } public static void WriteLine (char[] buffer, int index, int count) @@ -439,7 +526,6 @@ namespace System stdout.WriteLine (format, arg0, arg1, arg2); } -#if ! BOOTSTRAP_WITH_OLDLIB [CLSCompliant (false)] public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist) { @@ -458,9 +544,8 @@ namespace System stdout.WriteLine (String.Format (format, args)); } -#endif -#if NET_2_0 +#if !NET_2_1 public static int Read () { if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) { @@ -491,19 +576,25 @@ namespace System #endif -#if NET_2_0 +#if !NET_2_1 // FIXME: Console should use these encodings when changed static Encoding inputEncoding; static Encoding outputEncoding; public static Encoding InputEncoding { get { return inputEncoding; } - set { inputEncoding = value; } + set { + inputEncoding = value; + SetupStreams (inputEncoding, outputEncoding); + } } public static Encoding OutputEncoding { get { return outputEncoding; } - set { outputEncoding = value; } + set { + outputEncoding = value; + SetupStreams (inputEncoding, outputEncoding); + } } public static ConsoleColor BackgroundColor { @@ -513,14 +604,21 @@ namespace System public static int BufferHeight { get { return ConsoleDriver.BufferHeight; } + [MonoLimitation ("Implemented only on Windows")] set { ConsoleDriver.BufferHeight = value; } } public static int BufferWidth { get { return ConsoleDriver.BufferWidth; } + [MonoLimitation ("Implemented only on Windows")] set { ConsoleDriver.BufferWidth = value; } } + [MonoLimitation ("Implemented only on Windows")] + public static bool CapsLock { + get { return ConsoleDriver.CapsLock; } + } + public static int CursorLeft { get { return ConsoleDriver.CursorLeft; } set { ConsoleDriver.CursorLeft = value; } @@ -531,6 +629,11 @@ namespace System set { ConsoleDriver.CursorTop = value; } } + public static int CursorSize { + get { return ConsoleDriver.CursorSize; } + set { ConsoleDriver.CursorSize = value; } + } + public static bool CursorVisible { get { return ConsoleDriver.CursorVisible; } set { ConsoleDriver.CursorVisible = value; } @@ -545,6 +648,19 @@ namespace System get { return ConsoleDriver.KeyAvailable; } } + public static int LargestWindowHeight { + get { return ConsoleDriver.LargestWindowHeight; } + } + + public static int LargestWindowWidth { + get { return ConsoleDriver.LargestWindowWidth; } + } + + [MonoLimitation ("Only works on windows")] + public static bool NumberLock { + get { return ConsoleDriver.NumberLock; } + } + public static string Title { get { return ConsoleDriver.Title; } set { ConsoleDriver.Title = value; } @@ -555,21 +671,25 @@ namespace System set { ConsoleDriver.TreatControlCAsInput = value; } } + [MonoLimitation ("Only works on windows")] public static int WindowHeight { get { return ConsoleDriver.WindowHeight; } set { ConsoleDriver.WindowHeight = value; } } + [MonoLimitation ("Only works on windows")] public static int WindowLeft { get { return ConsoleDriver.WindowLeft; } set { ConsoleDriver.WindowLeft = value; } } + [MonoLimitation ("Only works on windows")] public static int WindowTop { get { return ConsoleDriver.WindowTop; } set { ConsoleDriver.WindowTop = value; } } + [MonoLimitation ("Only works on windows")] public static int WindowWidth { get { return ConsoleDriver.WindowWidth; } set { ConsoleDriver.WindowWidth = value; } @@ -596,19 +716,20 @@ namespace System ConsoleDriver.Clear (); } - [MonoTODO] + [MonoLimitation ("Implemented only on Windows")] public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop) { - throw new NotImplementedException (); + ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop); } - [MonoTODO] + [MonoLimitation ("Implemented only on Windows")] public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop, Char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) { - throw new NotImplementedException (); + ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop, + sourceChar, sourceForeColor, sourceBackColor); } public static ConsoleKeyInfo ReadKey () @@ -626,6 +747,7 @@ namespace System ConsoleDriver.ResetColor (); } + [MonoLimitation ("Only works on windows")] public static void SetBufferSize (int width, int height) { ConsoleDriver.SetBufferSize (width, height); @@ -646,17 +768,47 @@ namespace System ConsoleDriver.SetWindowSize (width, height); } - public static event ConsoleCancelEventHandler CancelKeyPress; + static ConsoleCancelEventHandler cancel_event; + public static event ConsoleCancelEventHandler CancelKeyPress { + add { + if (ConsoleDriver.Initialized == false) + ConsoleDriver.Init (); + + cancel_event += value; + + if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded) + WindowsConsole.AddCtrlHandler(); + } + remove { + if (ConsoleDriver.Initialized == false) + ConsoleDriver.Init (); + + cancel_event -= value; + + if (cancel_event == null && Environment.IsRunningOnWindows) + { + // Need to remove our hook if there's nothing left in the event + if (WindowsConsole.ctrlHandlerAdded) + WindowsConsole.RemoveCtrlHandler(); + } + } + } delegate void InternalCancelHandler (); - static InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent); + +#pragma warning disable 414 + // + // Used by console-io.c + // + static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent); +#pragma warning restore 414 internal static void DoConsoleCancelEvent () { bool exit = true; - if (CancelKeyPress != null) { + if (cancel_event != null) { ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC); - Delegate [] delegates = CancelKeyPress.GetInvocationList (); + Delegate [] delegates = cancel_event.GetInvocationList (); foreach (ConsoleCancelEventHandler d in delegates){ try { // Sender is always null here.