5 // Dietmar Maurer (dietmar@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (C) Ximian, Inc. http://www.ximian.com
9 // (C) 2004,2005 Novell, Inc. (http://www.novell.com)
10 // Copyright 2013 Xamarin Inc. (http://www.xamarin.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Diagnostics;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Security;
37 using System.Security.Permissions;
42 public static partial class Console
45 private class WindowsConsole
47 public static bool ctrlHandlerAdded = false;
48 private delegate bool WindowsCancelHandler (int keyCode);
49 private static WindowsCancelHandler cancelHandler = new WindowsCancelHandler (DoWindowsConsoleCancelEvent);
51 [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
52 private static extern int GetConsoleCP ();
53 [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
54 private static extern int GetConsoleOutputCP ();
56 [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
57 private static extern bool SetConsoleCtrlHandler (WindowsCancelHandler handler, bool addHandler);
59 // Only call the event handler if Control-C was pressed (code == 0), nothing else
60 private static bool DoWindowsConsoleCancelEvent (int keyCode)
63 DoConsoleCancelEvent ();
67 [MethodImpl (MethodImplOptions.NoInlining)]
68 public static int GetInputCodePage ()
70 return GetConsoleCP ();
73 [MethodImpl (MethodImplOptions.NoInlining)]
74 public static int GetOutputCodePage ()
76 return GetConsoleOutputCP ();
79 public static void AddCtrlHandler ()
81 SetConsoleCtrlHandler (cancelHandler, true);
82 ctrlHandlerAdded = true;
85 public static void RemoveCtrlHandler ()
87 SetConsoleCtrlHandler (cancelHandler, false);
88 ctrlHandlerAdded = false;
93 internal static TextWriter stdout;
94 private static TextWriter stderr;
95 private static TextReader stdin;
100 Encoding inputEncoding;
101 Encoding outputEncoding;
104 if (Environment.IsRunningOnWindows) {
106 // On Windows, follow the Windows tradition
109 // should never happen since Moonlight does not run on windows
110 inputEncoding = outputEncoding = Encoding.Default;
113 inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
114 outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
115 // ArgumentException and NotSupportedException can be thrown as well
117 // FIXME: I18N assemblies are not available when compiling mcs
118 // Use Latin 1 as it is fast and UTF-8 is never used as console code page
119 inputEncoding = outputEncoding = Encoding.Default;
124 // On Unix systems (128), do not output the
125 // UTF-8 ZWNBSP (zero-width non-breaking space).
128 EncodingHelper.InternalCodePage (ref code_page);
130 if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
131 || ((code_page & 0x10000000) != 0)))
132 inputEncoding = outputEncoding = EncodingHelper.UTF8Unmarked;
134 inputEncoding = outputEncoding = Encoding.Default;
137 SetupStreams (inputEncoding, outputEncoding);
140 static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding)
143 if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
144 StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding, true);
146 stdout = TextWriter.Synchronized (w);
148 w = new CStreamWriter (OpenStandardOutput (0), outputEncoding, true);
150 stderr = TextWriter.Synchronized (w);
152 stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
155 // FULL_AOT_RUNTIME is used (instead of MONOTOUCH) since we only want this code when running on
156 // iOS (simulator or devices) and *not* when running tools (e.g. btouch #12179) that needs to use
157 // the mscorlib.dll shipped with Xamarin.iOS
158 #if MONOTOUCH && FULL_AOT_RUNTIME
159 stdout = new NSLogWriter ();
161 stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
162 ((StreamWriter)stdout).AutoFlush = true;
164 stdout = TextWriter.Synchronized (stdout);
166 #if MONOTOUCH && FULL_AOT_RUNTIME
167 stderr = new NSLogWriter ();
169 stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
170 ((StreamWriter)stderr).AutoFlush = true;
172 stderr = TextWriter.Synchronized (stderr);
174 stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
175 stdin = TextReader.Synchronized (stdin);
181 if (LogcatTextWriter.IsRunningOnAndroid ()) {
182 stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout));
183 stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr));
187 GC.SuppressFinalize (stdout);
188 GC.SuppressFinalize (stderr);
189 GC.SuppressFinalize (stdin);
192 public static TextWriter Error {
198 public static TextWriter Out {
204 public static TextReader In {
210 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
213 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
214 } catch (IOException) {
219 public static Stream OpenStandardError ()
221 return OpenStandardError (0);
224 // calling any FileStream constructor with a handle normally
225 // requires permissions UnmanagedCode permissions. In this
226 // case we assert this permission so the console can be used
227 // in partial trust (i.e. without having UnmanagedCode).
228 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
229 public static Stream OpenStandardError (int bufferSize)
231 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
234 public static Stream OpenStandardInput ()
236 return OpenStandardInput (0);
239 // calling any FileStream constructor with a handle normally
240 // requires permissions UnmanagedCode permissions. In this
241 // case we assert this permission so the console can be used
242 // in partial trust (i.e. without having UnmanagedCode).
243 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
244 public static Stream OpenStandardInput (int bufferSize)
246 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
249 public static Stream OpenStandardOutput ()
251 return OpenStandardOutput (0);
254 // calling any FileStream constructor with a handle normally
255 // requires permissions UnmanagedCode permissions. In this
256 // case we assert this permission so the console can be used
257 // in partial trust (i.e. without having UnmanagedCode).
258 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
259 public static Stream OpenStandardOutput (int bufferSize)
261 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
264 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
265 public static void SetError (TextWriter newError)
267 if (newError == null)
268 throw new ArgumentNullException ("newError");
273 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
274 public static void SetIn (TextReader newIn)
277 throw new ArgumentNullException ("newIn");
282 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
283 public static void SetOut (TextWriter newOut)
286 throw new ArgumentNullException ("newOut");
291 public static void Write (bool value)
293 stdout.Write (value);
296 public static void Write (char value)
298 stdout.Write (value);
301 public static void Write (char[] buffer)
303 stdout.Write (buffer);
306 public static void Write (decimal value)
308 stdout.Write (value);
311 public static void Write (double value)
313 stdout.Write (value);
316 public static void Write (int value)
318 stdout.Write (value);
321 public static void Write (long value)
323 stdout.Write (value);
326 public static void Write (object value)
328 stdout.Write (value);
331 public static void Write (float value)
333 stdout.Write (value);
336 public static void Write (string value)
338 stdout.Write (value);
341 [CLSCompliant (false)]
342 public static void Write (uint value)
344 stdout.Write (value);
347 [CLSCompliant (false)]
348 public static void Write (ulong value)
350 stdout.Write (value);
353 public static void Write (string format, object arg0)
355 stdout.Write (format, arg0);
358 public static void Write (string format, params object[] arg)
361 stdout.Write (format);
363 stdout.Write (format, arg);
366 public static void Write (char[] buffer, int index, int count)
368 stdout.Write (buffer, index, count);
371 public static void Write (string format, object arg0, object arg1)
373 stdout.Write (format, arg0, arg1);
376 public static void Write (string format, object arg0, object arg1, object arg2 )
378 stdout.Write (format, arg0, arg1, arg2);
381 [CLSCompliant (false)]
382 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
384 ArgIterator iter = new ArgIterator (__arglist);
385 int argCount = iter.GetRemainingCount();
387 object[] args = new object [argCount + 4];
392 for (int i = 0; i < argCount; i++) {
393 TypedReference typedRef = iter.GetNextArg ();
394 args [i + 4] = TypedReference.ToObject (typedRef);
397 stdout.Write (String.Format (format, args));
400 public static void WriteLine ()
405 public static void WriteLine (bool value)
407 stdout.WriteLine (value);
410 public static void WriteLine (char value)
412 stdout.WriteLine (value);
415 public static void WriteLine (char[] buffer)
417 stdout.WriteLine (buffer);
420 public static void WriteLine (decimal value)
422 stdout.WriteLine (value);
425 public static void WriteLine (double value)
427 stdout.WriteLine (value);
430 public static void WriteLine (int value)
432 stdout.WriteLine (value);
435 public static void WriteLine (long value)
437 stdout.WriteLine (value);
440 public static void WriteLine (object value)
442 stdout.WriteLine (value);
445 public static void WriteLine (float value)
447 stdout.WriteLine (value);
450 public static void WriteLine (string value)
452 stdout.WriteLine (value);
455 [CLSCompliant (false)]
456 public static void WriteLine (uint value)
458 stdout.WriteLine (value);
461 [CLSCompliant (false)]
462 public static void WriteLine (ulong value)
464 stdout.WriteLine (value);
467 public static void WriteLine (string format, object arg0)
469 stdout.WriteLine (format, arg0);
472 public static void WriteLine (string format, params object[] arg)
475 stdout.WriteLine (format);
477 stdout.WriteLine (format, arg);
480 public static void WriteLine (char[] buffer, int index, int count)
482 stdout.WriteLine (buffer, index, count);
485 public static void WriteLine (string format, object arg0, object arg1)
487 stdout.WriteLine (format, arg0, arg1);
490 public static void WriteLine (string format, object arg0, object arg1, object arg2)
492 stdout.WriteLine (format, arg0, arg1, arg2);
495 [CLSCompliant (false)]
496 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
498 ArgIterator iter = new ArgIterator (__arglist);
499 int argCount = iter.GetRemainingCount();
501 object[] args = new object [argCount + 4];
506 for (int i = 0; i < argCount; i++) {
507 TypedReference typedRef = iter.GetNextArg ();
508 args [i + 4] = TypedReference.ToObject (typedRef);
511 stdout.WriteLine (String.Format (format, args));
515 public static int Read ()
517 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
518 return ConsoleDriver.Read ();
520 return stdin.Read ();
524 public static string ReadLine ()
526 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
527 return ConsoleDriver.ReadLine ();
529 return stdin.ReadLine ();
533 public static int Read ()
535 return stdin.Read ();
538 public static string ReadLine ()
540 return stdin.ReadLine ();
546 // FIXME: Console should use these encodings when changed
547 static Encoding inputEncoding;
548 static Encoding outputEncoding;
550 public static Encoding InputEncoding {
551 get { return inputEncoding; }
553 inputEncoding = value;
554 SetupStreams (inputEncoding, outputEncoding);
558 public static Encoding OutputEncoding {
559 get { return outputEncoding; }
561 outputEncoding = value;
562 SetupStreams (inputEncoding, outputEncoding);
566 public static ConsoleColor BackgroundColor {
567 get { return ConsoleDriver.BackgroundColor; }
568 set { ConsoleDriver.BackgroundColor = value; }
571 public static int BufferHeight {
572 get { return ConsoleDriver.BufferHeight; }
573 [MonoLimitation ("Implemented only on Windows")]
574 set { ConsoleDriver.BufferHeight = value; }
577 public static int BufferWidth {
578 get { return ConsoleDriver.BufferWidth; }
579 [MonoLimitation ("Implemented only on Windows")]
580 set { ConsoleDriver.BufferWidth = value; }
583 [MonoLimitation ("Implemented only on Windows")]
584 public static bool CapsLock {
585 get { return ConsoleDriver.CapsLock; }
588 public static int CursorLeft {
589 get { return ConsoleDriver.CursorLeft; }
590 set { ConsoleDriver.CursorLeft = value; }
593 public static int CursorTop {
594 get { return ConsoleDriver.CursorTop; }
595 set { ConsoleDriver.CursorTop = value; }
598 public static int CursorSize {
599 get { return ConsoleDriver.CursorSize; }
600 set { ConsoleDriver.CursorSize = value; }
603 public static bool CursorVisible {
604 get { return ConsoleDriver.CursorVisible; }
605 set { ConsoleDriver.CursorVisible = value; }
608 public static ConsoleColor ForegroundColor {
609 get { return ConsoleDriver.ForegroundColor; }
610 set { ConsoleDriver.ForegroundColor = value; }
613 public static bool KeyAvailable {
614 get { return ConsoleDriver.KeyAvailable; }
617 public static int LargestWindowHeight {
618 get { return ConsoleDriver.LargestWindowHeight; }
621 public static int LargestWindowWidth {
622 get { return ConsoleDriver.LargestWindowWidth; }
625 [MonoLimitation ("Only works on windows")]
626 public static bool NumberLock {
627 get { return ConsoleDriver.NumberLock; }
630 public static string Title {
631 get { return ConsoleDriver.Title; }
632 set { ConsoleDriver.Title = value; }
635 public static bool TreatControlCAsInput {
636 get { return ConsoleDriver.TreatControlCAsInput; }
637 set { ConsoleDriver.TreatControlCAsInput = value; }
640 [MonoLimitation ("Only works on windows")]
641 public static int WindowHeight {
642 get { return ConsoleDriver.WindowHeight; }
643 set { ConsoleDriver.WindowHeight = value; }
646 [MonoLimitation ("Only works on windows")]
647 public static int WindowLeft {
648 get { return ConsoleDriver.WindowLeft; }
649 set { ConsoleDriver.WindowLeft = value; }
652 [MonoLimitation ("Only works on windows")]
653 public static int WindowTop {
654 get { return ConsoleDriver.WindowTop; }
655 set { ConsoleDriver.WindowTop = value; }
658 [MonoLimitation ("Only works on windows")]
659 public static int WindowWidth {
660 get { return ConsoleDriver.WindowWidth; }
661 set { ConsoleDriver.WindowWidth = value; }
664 public static bool IsErrorRedirected {
666 return ConsoleDriver.IsErrorRedirected;
670 public static bool IsOutputRedirected {
672 return ConsoleDriver.IsOutputRedirected;
676 public static bool IsInputRedirected {
678 return ConsoleDriver.IsInputRedirected;
682 public static void Beep ()
687 public static void Beep (int frequency, int duration)
689 if (frequency < 37 || frequency > 32767)
690 throw new ArgumentOutOfRangeException ("frequency");
693 throw new ArgumentOutOfRangeException ("duration");
695 ConsoleDriver.Beep (frequency, duration);
698 public static void Clear ()
700 ConsoleDriver.Clear ();
703 [MonoLimitation ("Implemented only on Windows")]
704 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
705 int targetLeft, int targetTop)
707 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
710 [MonoLimitation ("Implemented only on Windows")]
711 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
712 int targetLeft, int targetTop, Char sourceChar,
713 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
715 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
716 sourceChar, sourceForeColor, sourceBackColor);
719 public static ConsoleKeyInfo ReadKey ()
721 return ReadKey (false);
724 public static ConsoleKeyInfo ReadKey (bool intercept)
726 return ConsoleDriver.ReadKey (intercept);
729 public static void ResetColor ()
731 ConsoleDriver.ResetColor ();
734 [MonoLimitation ("Only works on windows")]
735 public static void SetBufferSize (int width, int height)
737 ConsoleDriver.SetBufferSize (width, height);
740 public static void SetCursorPosition (int left, int top)
742 ConsoleDriver.SetCursorPosition (left, top);
745 public static void SetWindowPosition (int left, int top)
747 ConsoleDriver.SetWindowPosition (left, top);
750 public static void SetWindowSize (int width, int height)
752 ConsoleDriver.SetWindowSize (width, height);
755 static ConsoleCancelEventHandler cancel_event;
756 public static event ConsoleCancelEventHandler CancelKeyPress {
758 if (ConsoleDriver.Initialized == false)
759 ConsoleDriver.Init ();
761 cancel_event += value;
763 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
764 WindowsConsole.AddCtrlHandler();
767 if (ConsoleDriver.Initialized == false)
768 ConsoleDriver.Init ();
770 cancel_event -= value;
772 if (cancel_event == null && Environment.IsRunningOnWindows)
774 // Need to remove our hook if there's nothing left in the event
775 if (WindowsConsole.ctrlHandlerAdded)
776 WindowsConsole.RemoveCtrlHandler();
781 delegate void InternalCancelHandler ();
783 #pragma warning disable 414
785 // Used by console-io.c
787 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
788 #pragma warning restore 414
790 internal static void DoConsoleCancelEvent ()
793 if (cancel_event != null) {
794 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
795 Delegate [] delegates = cancel_event.GetInvocationList ();
796 foreach (ConsoleCancelEventHandler d in delegates){
798 // Sender is always null here.
800 } catch {} // Ignore any exception.
806 Environment.Exit (58);