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)
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 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;
97 #if NET_4_5 && !MOBILE
98 static TextWriter console_stdout;
99 static TextWriter console_stderr;
100 static TextReader console_stdin;
106 Encoding inputEncoding;
107 Encoding outputEncoding;
110 if (Environment.IsRunningOnWindows) {
112 // On Windows, follow the Windows tradition
115 // should never happen since Moonlight does not run on windows
116 inputEncoding = outputEncoding = Encoding.Default;
119 inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
120 outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
121 // ArgumentException and NotSupportedException can be thrown as well
123 // FIXME: I18N assemblies are not available when compiling mcs
124 // Use Latin 1 as it is fast and UTF-8 is never used as console code page
125 inputEncoding = outputEncoding = Encoding.Default;
130 // On Unix systems (128), do not output the
131 // UTF-8 ZWNBSP (zero-width non-breaking space).
134 Encoding.InternalCodePage (ref code_page);
136 if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
137 || ((code_page & 0x10000000) != 0)))
138 inputEncoding = outputEncoding = Encoding.UTF8Unmarked;
140 inputEncoding = outputEncoding = Encoding.Default;
143 SetupStreams (inputEncoding, outputEncoding);
146 static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding)
149 if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
150 StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
152 stdout = TextWriter.Synchronized (w, true);
154 w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
156 stderr = TextWriter.Synchronized (w, true);
158 stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
162 Type nslogwriter = Type.GetType ("MonoTouch.Foundation.NSLogWriter, monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
163 stdout = (TextWriter) Activator.CreateInstance (nslogwriter);
165 stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
166 ((StreamWriter)stdout).AutoFlush = true;
168 stdout = TextWriter.Synchronized (stdout, true);
171 stderr = (TextWriter) Activator.CreateInstance (nslogwriter);
173 stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
174 ((StreamWriter)stderr).AutoFlush = true;
176 stderr = TextWriter.Synchronized (stderr, true);
178 stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
179 stdin = TextReader.Synchronized (stdin);
184 #if NET_4_5 && !MOBILE
185 console_stderr = stderr;
186 console_stdout = stdout;
187 console_stdin = stdin;
191 if (LogcatTextWriter.IsRunningOnAndroid ()) {
192 stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout));
193 stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr));
197 GC.SuppressFinalize (stdout);
198 GC.SuppressFinalize (stderr);
199 GC.SuppressFinalize (stdin);
202 public static TextWriter Error {
208 public static TextWriter Out {
214 public static TextReader In {
220 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
223 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
224 } catch (IOException) {
225 return new NullStream ();
229 public static Stream OpenStandardError ()
231 return OpenStandardError (0);
234 // calling any FileStream constructor with a handle normally
235 // requires permissions UnmanagedCode permissions. In this
236 // case we assert this permission so the console can be used
237 // in partial trust (i.e. without having UnmanagedCode).
238 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
239 public static Stream OpenStandardError (int bufferSize)
241 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
244 public static Stream OpenStandardInput ()
246 return OpenStandardInput (0);
249 // calling any FileStream constructor with a handle normally
250 // requires permissions UnmanagedCode permissions. In this
251 // case we assert this permission so the console can be used
252 // in partial trust (i.e. without having UnmanagedCode).
253 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
254 public static Stream OpenStandardInput (int bufferSize)
256 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
259 public static Stream OpenStandardOutput ()
261 return OpenStandardOutput (0);
264 // calling any FileStream constructor with a handle normally
265 // requires permissions UnmanagedCode permissions. In this
266 // case we assert this permission so the console can be used
267 // in partial trust (i.e. without having UnmanagedCode).
268 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
269 public static Stream OpenStandardOutput (int bufferSize)
271 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
274 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
275 public static void SetError (TextWriter newError)
277 if (newError == null)
278 throw new ArgumentNullException ("newError");
283 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
284 public static void SetIn (TextReader newIn)
287 throw new ArgumentNullException ("newIn");
292 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
293 public static void SetOut (TextWriter newOut)
296 throw new ArgumentNullException ("newOut");
301 public static void Write (bool value)
303 stdout.Write (value);
306 public static void Write (char value)
308 stdout.Write (value);
311 public static void Write (char[] buffer)
313 stdout.Write (buffer);
316 public static void Write (decimal value)
318 stdout.Write (value);
321 public static void Write (double value)
323 stdout.Write (value);
326 public static void Write (int value)
328 stdout.Write (value);
331 public static void Write (long value)
333 stdout.Write (value);
336 public static void Write (object value)
338 stdout.Write (value);
341 public static void Write (float value)
343 stdout.Write (value);
346 public static void Write (string value)
348 stdout.Write (value);
351 [CLSCompliant (false)]
352 public static void Write (uint value)
354 stdout.Write (value);
357 [CLSCompliant (false)]
358 public static void Write (ulong value)
360 stdout.Write (value);
363 public static void Write (string format, object arg0)
365 stdout.Write (format, arg0);
368 public static void Write (string format, params object[] arg)
371 stdout.Write (format);
373 stdout.Write (format, arg);
376 public static void Write (char[] buffer, int index, int count)
378 stdout.Write (buffer, index, count);
381 public static void Write (string format, object arg0, object arg1)
383 stdout.Write (format, arg0, arg1);
386 public static void Write (string format, object arg0, object arg1, object arg2 )
388 stdout.Write (format, arg0, arg1, arg2);
391 [CLSCompliant (false)]
392 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
394 ArgIterator iter = new ArgIterator (__arglist);
395 int argCount = iter.GetRemainingCount();
397 object[] args = new object [argCount + 4];
402 for (int i = 0; i < argCount; i++) {
403 TypedReference typedRef = iter.GetNextArg ();
404 args [i + 4] = TypedReference.ToObject (typedRef);
407 stdout.Write (String.Format (format, args));
410 public static void WriteLine ()
415 public static void WriteLine (bool value)
417 stdout.WriteLine (value);
420 public static void WriteLine (char value)
422 stdout.WriteLine (value);
425 public static void WriteLine (char[] buffer)
427 stdout.WriteLine (buffer);
430 public static void WriteLine (decimal value)
432 stdout.WriteLine (value);
435 public static void WriteLine (double value)
437 stdout.WriteLine (value);
440 public static void WriteLine (int value)
442 stdout.WriteLine (value);
445 public static void WriteLine (long value)
447 stdout.WriteLine (value);
450 public static void WriteLine (object value)
452 stdout.WriteLine (value);
455 public static void WriteLine (float value)
457 stdout.WriteLine (value);
460 public static void WriteLine (string value)
462 stdout.WriteLine (value);
465 [CLSCompliant (false)]
466 public static void WriteLine (uint value)
468 stdout.WriteLine (value);
471 [CLSCompliant (false)]
472 public static void WriteLine (ulong value)
474 stdout.WriteLine (value);
477 public static void WriteLine (string format, object arg0)
479 stdout.WriteLine (format, arg0);
482 public static void WriteLine (string format, params object[] arg)
485 stdout.WriteLine (format);
487 stdout.WriteLine (format, arg);
490 public static void WriteLine (char[] buffer, int index, int count)
492 stdout.WriteLine (buffer, index, count);
495 public static void WriteLine (string format, object arg0, object arg1)
497 stdout.WriteLine (format, arg0, arg1);
500 public static void WriteLine (string format, object arg0, object arg1, object arg2)
502 stdout.WriteLine (format, arg0, arg1, arg2);
505 [CLSCompliant (false)]
506 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
508 ArgIterator iter = new ArgIterator (__arglist);
509 int argCount = iter.GetRemainingCount();
511 object[] args = new object [argCount + 4];
516 for (int i = 0; i < argCount; i++) {
517 TypedReference typedRef = iter.GetNextArg ();
518 args [i + 4] = TypedReference.ToObject (typedRef);
521 stdout.WriteLine (String.Format (format, args));
525 public static int Read ()
527 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
528 return ConsoleDriver.Read ();
530 return stdin.Read ();
534 public static string ReadLine ()
536 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
537 return ConsoleDriver.ReadLine ();
539 return stdin.ReadLine ();
543 public static int Read ()
545 return stdin.Read ();
548 public static string ReadLine ()
550 return stdin.ReadLine ();
556 // FIXME: Console should use these encodings when changed
557 static Encoding inputEncoding;
558 static Encoding outputEncoding;
560 public static Encoding InputEncoding {
561 get { return inputEncoding; }
563 inputEncoding = value;
564 SetupStreams (inputEncoding, outputEncoding);
568 public static Encoding OutputEncoding {
569 get { return outputEncoding; }
571 outputEncoding = value;
572 SetupStreams (inputEncoding, outputEncoding);
576 public static ConsoleColor BackgroundColor {
577 get { return ConsoleDriver.BackgroundColor; }
578 set { ConsoleDriver.BackgroundColor = value; }
581 public static int BufferHeight {
582 get { return ConsoleDriver.BufferHeight; }
583 [MonoLimitation ("Implemented only on Windows")]
584 set { ConsoleDriver.BufferHeight = value; }
587 public static int BufferWidth {
588 get { return ConsoleDriver.BufferWidth; }
589 [MonoLimitation ("Implemented only on Windows")]
590 set { ConsoleDriver.BufferWidth = value; }
593 [MonoLimitation ("Implemented only on Windows")]
594 public static bool CapsLock {
595 get { return ConsoleDriver.CapsLock; }
598 public static int CursorLeft {
599 get { return ConsoleDriver.CursorLeft; }
600 set { ConsoleDriver.CursorLeft = value; }
603 public static int CursorTop {
604 get { return ConsoleDriver.CursorTop; }
605 set { ConsoleDriver.CursorTop = value; }
608 public static int CursorSize {
609 get { return ConsoleDriver.CursorSize; }
610 set { ConsoleDriver.CursorSize = value; }
613 public static bool CursorVisible {
614 get { return ConsoleDriver.CursorVisible; }
615 set { ConsoleDriver.CursorVisible = value; }
618 public static ConsoleColor ForegroundColor {
619 get { return ConsoleDriver.ForegroundColor; }
620 set { ConsoleDriver.ForegroundColor = value; }
623 public static bool KeyAvailable {
624 get { return ConsoleDriver.KeyAvailable; }
627 public static int LargestWindowHeight {
628 get { return ConsoleDriver.LargestWindowHeight; }
631 public static int LargestWindowWidth {
632 get { return ConsoleDriver.LargestWindowWidth; }
635 [MonoLimitation ("Only works on windows")]
636 public static bool NumberLock {
637 get { return ConsoleDriver.NumberLock; }
640 public static string Title {
641 get { return ConsoleDriver.Title; }
642 set { ConsoleDriver.Title = value; }
645 public static bool TreatControlCAsInput {
646 get { return ConsoleDriver.TreatControlCAsInput; }
647 set { ConsoleDriver.TreatControlCAsInput = value; }
650 [MonoLimitation ("Only works on windows")]
651 public static int WindowHeight {
652 get { return ConsoleDriver.WindowHeight; }
653 set { ConsoleDriver.WindowHeight = value; }
656 [MonoLimitation ("Only works on windows")]
657 public static int WindowLeft {
658 get { return ConsoleDriver.WindowLeft; }
659 set { ConsoleDriver.WindowLeft = value; }
662 [MonoLimitation ("Only works on windows")]
663 public static int WindowTop {
664 get { return ConsoleDriver.WindowTop; }
665 set { ConsoleDriver.WindowTop = value; }
668 [MonoLimitation ("Only works on windows")]
669 public static int WindowWidth {
670 get { return ConsoleDriver.WindowWidth; }
671 set { ConsoleDriver.WindowWidth = value; }
675 public static bool IsErrorRedirected {
677 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
681 public static bool IsOutputRedirected {
683 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
687 public static bool IsInputRedirected {
689 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
694 public static void Beep ()
699 public static void Beep (int frequency, int duration)
701 if (frequency < 37 || frequency > 32767)
702 throw new ArgumentOutOfRangeException ("frequency");
705 throw new ArgumentOutOfRangeException ("duration");
707 ConsoleDriver.Beep (frequency, duration);
710 public static void Clear ()
712 ConsoleDriver.Clear ();
715 [MonoLimitation ("Implemented only on Windows")]
716 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
717 int targetLeft, int targetTop)
719 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
722 [MonoLimitation ("Implemented only on Windows")]
723 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
724 int targetLeft, int targetTop, Char sourceChar,
725 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
727 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
728 sourceChar, sourceForeColor, sourceBackColor);
731 public static ConsoleKeyInfo ReadKey ()
733 return ReadKey (false);
736 public static ConsoleKeyInfo ReadKey (bool intercept)
738 return ConsoleDriver.ReadKey (intercept);
741 public static void ResetColor ()
743 ConsoleDriver.ResetColor ();
746 [MonoLimitation ("Only works on windows")]
747 public static void SetBufferSize (int width, int height)
749 ConsoleDriver.SetBufferSize (width, height);
752 public static void SetCursorPosition (int left, int top)
754 ConsoleDriver.SetCursorPosition (left, top);
757 public static void SetWindowPosition (int left, int top)
759 ConsoleDriver.SetWindowPosition (left, top);
762 public static void SetWindowSize (int width, int height)
764 ConsoleDriver.SetWindowSize (width, height);
767 static ConsoleCancelEventHandler cancel_event;
768 public static event ConsoleCancelEventHandler CancelKeyPress {
770 if (ConsoleDriver.Initialized == false)
771 ConsoleDriver.Init ();
773 cancel_event += value;
775 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
776 WindowsConsole.AddCtrlHandler();
779 if (ConsoleDriver.Initialized == false)
780 ConsoleDriver.Init ();
782 cancel_event -= value;
784 if (cancel_event == null && Environment.IsRunningOnWindows)
786 // Need to remove our hook if there's nothing left in the event
787 if (WindowsConsole.ctrlHandlerAdded)
788 WindowsConsole.RemoveCtrlHandler();
793 delegate void InternalCancelHandler ();
795 #pragma warning disable 414
797 // Used by console-io.c
799 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
800 #pragma warning restore 414
802 internal static void DoConsoleCancelEvent ()
805 if (cancel_event != null) {
806 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
807 Delegate [] delegates = cancel_event.GetInvocationList ();
808 foreach (ConsoleCancelEventHandler d in delegates){
810 // Sender is always null here.
812 } catch {} // Ignore any exception.
818 Environment.Exit (58);