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;
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);
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 if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
224 return new NullStream ();
227 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
228 } catch (IOException) {
229 return new NullStream ();
233 public static Stream OpenStandardError ()
235 return OpenStandardError (0);
238 // calling any FileStream constructor with a handle normally
239 // requires permissions UnmanagedCode permissions. In this
240 // case we assert this permission so the console can be used
241 // in partial trust (i.e. without having UnmanagedCode).
242 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
243 public static Stream OpenStandardError (int bufferSize)
245 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
248 public static Stream OpenStandardInput ()
250 return OpenStandardInput (0);
253 // calling any FileStream constructor with a handle normally
254 // requires permissions UnmanagedCode permissions. In this
255 // case we assert this permission so the console can be used
256 // in partial trust (i.e. without having UnmanagedCode).
257 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
258 public static Stream OpenStandardInput (int bufferSize)
260 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
263 public static Stream OpenStandardOutput ()
265 return OpenStandardOutput (0);
268 // calling any FileStream constructor with a handle normally
269 // requires permissions UnmanagedCode permissions. In this
270 // case we assert this permission so the console can be used
271 // in partial trust (i.e. without having UnmanagedCode).
272 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
273 public static Stream OpenStandardOutput (int bufferSize)
275 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
278 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
279 public static void SetError (TextWriter newError)
281 if (newError == null)
282 throw new ArgumentNullException ("newError");
287 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
288 public static void SetIn (TextReader newIn)
291 throw new ArgumentNullException ("newIn");
296 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
297 public static void SetOut (TextWriter newOut)
300 throw new ArgumentNullException ("newOut");
305 public static void Write (bool value)
307 stdout.Write (value);
310 public static void Write (char value)
312 stdout.Write (value);
315 public static void Write (char[] buffer)
317 stdout.Write (buffer);
320 public static void Write (decimal value)
322 stdout.Write (value);
325 public static void Write (double value)
327 stdout.Write (value);
330 public static void Write (int value)
332 stdout.Write (value);
335 public static void Write (long value)
337 stdout.Write (value);
340 public static void Write (object value)
342 stdout.Write (value);
345 public static void Write (float value)
347 stdout.Write (value);
350 public static void Write (string value)
352 stdout.Write (value);
355 [CLSCompliant (false)]
356 public static void Write (uint value)
358 stdout.Write (value);
361 [CLSCompliant (false)]
362 public static void Write (ulong value)
364 stdout.Write (value);
367 public static void Write (string format, object arg0)
369 stdout.Write (format, arg0);
372 public static void Write (string format, params object[] arg)
375 stdout.Write (format);
377 stdout.Write (format, arg);
380 public static void Write (char[] buffer, int index, int count)
382 stdout.Write (buffer, index, count);
385 public static void Write (string format, object arg0, object arg1)
387 stdout.Write (format, arg0, arg1);
390 public static void Write (string format, object arg0, object arg1, object arg2 )
392 stdout.Write (format, arg0, arg1, arg2);
395 [CLSCompliant (false)]
396 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
398 ArgIterator iter = new ArgIterator (__arglist);
399 int argCount = iter.GetRemainingCount();
401 object[] args = new object [argCount + 4];
406 for (int i = 0; i < argCount; i++) {
407 TypedReference typedRef = iter.GetNextArg ();
408 args [i + 4] = TypedReference.ToObject (typedRef);
411 stdout.Write (String.Format (format, args));
414 public static void WriteLine ()
419 public static void WriteLine (bool value)
421 stdout.WriteLine (value);
424 public static void WriteLine (char value)
426 stdout.WriteLine (value);
429 public static void WriteLine (char[] buffer)
431 stdout.WriteLine (buffer);
434 public static void WriteLine (decimal value)
436 stdout.WriteLine (value);
439 public static void WriteLine (double value)
441 stdout.WriteLine (value);
444 public static void WriteLine (int value)
446 stdout.WriteLine (value);
449 public static void WriteLine (long value)
451 stdout.WriteLine (value);
454 public static void WriteLine (object value)
456 stdout.WriteLine (value);
459 public static void WriteLine (float value)
461 stdout.WriteLine (value);
464 public static void WriteLine (string value)
466 stdout.WriteLine (value);
469 [CLSCompliant (false)]
470 public static void WriteLine (uint value)
472 stdout.WriteLine (value);
475 [CLSCompliant (false)]
476 public static void WriteLine (ulong value)
478 stdout.WriteLine (value);
481 public static void WriteLine (string format, object arg0)
483 stdout.WriteLine (format, arg0);
486 public static void WriteLine (string format, params object[] arg)
489 stdout.WriteLine (format);
491 stdout.WriteLine (format, arg);
494 public static void WriteLine (char[] buffer, int index, int count)
496 stdout.WriteLine (buffer, index, count);
499 public static void WriteLine (string format, object arg0, object arg1)
501 stdout.WriteLine (format, arg0, arg1);
504 public static void WriteLine (string format, object arg0, object arg1, object arg2)
506 stdout.WriteLine (format, arg0, arg1, arg2);
509 [CLSCompliant (false)]
510 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
512 ArgIterator iter = new ArgIterator (__arglist);
513 int argCount = iter.GetRemainingCount();
515 object[] args = new object [argCount + 4];
520 for (int i = 0; i < argCount; i++) {
521 TypedReference typedRef = iter.GetNextArg ();
522 args [i + 4] = TypedReference.ToObject (typedRef);
525 stdout.WriteLine (String.Format (format, args));
529 public static int Read ()
531 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
532 return ConsoleDriver.Read ();
534 return stdin.Read ();
538 public static string ReadLine ()
540 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
541 return ConsoleDriver.ReadLine ();
543 return stdin.ReadLine ();
547 public static int Read ()
549 return stdin.Read ();
552 public static string ReadLine ()
554 return stdin.ReadLine ();
560 // FIXME: Console should use these encodings when changed
561 static Encoding inputEncoding;
562 static Encoding outputEncoding;
564 public static Encoding InputEncoding {
565 get { return inputEncoding; }
567 inputEncoding = value;
568 SetupStreams (inputEncoding, outputEncoding);
572 public static Encoding OutputEncoding {
573 get { return outputEncoding; }
575 outputEncoding = value;
576 SetupStreams (inputEncoding, outputEncoding);
580 public static ConsoleColor BackgroundColor {
581 get { return ConsoleDriver.BackgroundColor; }
582 set { ConsoleDriver.BackgroundColor = value; }
585 public static int BufferHeight {
586 get { return ConsoleDriver.BufferHeight; }
587 [MonoLimitation ("Implemented only on Windows")]
588 set { ConsoleDriver.BufferHeight = value; }
591 public static int BufferWidth {
592 get { return ConsoleDriver.BufferWidth; }
593 [MonoLimitation ("Implemented only on Windows")]
594 set { ConsoleDriver.BufferWidth = value; }
597 [MonoLimitation ("Implemented only on Windows")]
598 public static bool CapsLock {
599 get { return ConsoleDriver.CapsLock; }
602 public static int CursorLeft {
603 get { return ConsoleDriver.CursorLeft; }
604 set { ConsoleDriver.CursorLeft = value; }
607 public static int CursorTop {
608 get { return ConsoleDriver.CursorTop; }
609 set { ConsoleDriver.CursorTop = value; }
612 public static int CursorSize {
613 get { return ConsoleDriver.CursorSize; }
614 set { ConsoleDriver.CursorSize = value; }
617 public static bool CursorVisible {
618 get { return ConsoleDriver.CursorVisible; }
619 set { ConsoleDriver.CursorVisible = value; }
622 public static ConsoleColor ForegroundColor {
623 get { return ConsoleDriver.ForegroundColor; }
624 set { ConsoleDriver.ForegroundColor = value; }
627 public static bool KeyAvailable {
628 get { return ConsoleDriver.KeyAvailable; }
631 public static int LargestWindowHeight {
632 get { return ConsoleDriver.LargestWindowHeight; }
635 public static int LargestWindowWidth {
636 get { return ConsoleDriver.LargestWindowWidth; }
639 [MonoLimitation ("Only works on windows")]
640 public static bool NumberLock {
641 get { return ConsoleDriver.NumberLock; }
644 public static string Title {
645 get { return ConsoleDriver.Title; }
646 set { ConsoleDriver.Title = value; }
649 public static bool TreatControlCAsInput {
650 get { return ConsoleDriver.TreatControlCAsInput; }
651 set { ConsoleDriver.TreatControlCAsInput = value; }
654 [MonoLimitation ("Only works on windows")]
655 public static int WindowHeight {
656 get { return ConsoleDriver.WindowHeight; }
657 set { ConsoleDriver.WindowHeight = value; }
660 [MonoLimitation ("Only works on windows")]
661 public static int WindowLeft {
662 get { return ConsoleDriver.WindowLeft; }
663 set { ConsoleDriver.WindowLeft = value; }
666 [MonoLimitation ("Only works on windows")]
667 public static int WindowTop {
668 get { return ConsoleDriver.WindowTop; }
669 set { ConsoleDriver.WindowTop = value; }
672 [MonoLimitation ("Only works on windows")]
673 public static int WindowWidth {
674 get { return ConsoleDriver.WindowWidth; }
675 set { ConsoleDriver.WindowWidth = value; }
679 public static bool IsErrorRedirected {
681 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
685 public static bool IsOutputRedirected {
687 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
691 public static bool IsInputRedirected {
693 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
698 public static void Beep ()
703 public static void Beep (int frequency, int duration)
705 if (frequency < 37 || frequency > 32767)
706 throw new ArgumentOutOfRangeException ("frequency");
709 throw new ArgumentOutOfRangeException ("duration");
711 ConsoleDriver.Beep (frequency, duration);
714 public static void Clear ()
716 ConsoleDriver.Clear ();
719 [MonoLimitation ("Implemented only on Windows")]
720 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
721 int targetLeft, int targetTop)
723 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
726 [MonoLimitation ("Implemented only on Windows")]
727 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
728 int targetLeft, int targetTop, Char sourceChar,
729 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
731 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
732 sourceChar, sourceForeColor, sourceBackColor);
735 public static ConsoleKeyInfo ReadKey ()
737 return ReadKey (false);
740 public static ConsoleKeyInfo ReadKey (bool intercept)
742 return ConsoleDriver.ReadKey (intercept);
745 public static void ResetColor ()
747 ConsoleDriver.ResetColor ();
750 [MonoLimitation ("Only works on windows")]
751 public static void SetBufferSize (int width, int height)
753 ConsoleDriver.SetBufferSize (width, height);
756 public static void SetCursorPosition (int left, int top)
758 ConsoleDriver.SetCursorPosition (left, top);
761 public static void SetWindowPosition (int left, int top)
763 ConsoleDriver.SetWindowPosition (left, top);
766 public static void SetWindowSize (int width, int height)
768 ConsoleDriver.SetWindowSize (width, height);
771 static ConsoleCancelEventHandler cancel_event;
772 public static event ConsoleCancelEventHandler CancelKeyPress {
774 if (ConsoleDriver.Initialized == false)
775 ConsoleDriver.Init ();
777 cancel_event += value;
779 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
780 WindowsConsole.AddCtrlHandler();
783 if (ConsoleDriver.Initialized == false)
784 ConsoleDriver.Init ();
786 cancel_event -= value;
788 if (cancel_event == null && Environment.IsRunningOnWindows)
790 // Need to remove our hook if there's nothing left in the event
791 if (WindowsConsole.ctrlHandlerAdded)
792 WindowsConsole.RemoveCtrlHandler();
797 delegate void InternalCancelHandler ();
799 #pragma warning disable 414
801 // Used by console-io.c
803 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
804 #pragma warning restore 414
806 internal static void DoConsoleCancelEvent ()
809 if (cancel_event != null) {
810 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
811 Delegate [] delegates = cancel_event.GetInvocationList ();
812 foreach (ConsoleCancelEventHandler d in delegates){
814 // Sender is always null here.
816 } catch {} // Ignore any exception.
822 Environment.Exit (58);