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 {
221 public static bool IsErrorRedirected {
223 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
227 public static bool IsOutputRedirected {
229 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
233 public static bool IsInputRedirected {
235 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
240 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
243 if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
244 return new NullStream ();
247 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
248 } catch (IOException) {
249 return new NullStream ();
253 public static Stream OpenStandardError ()
255 return OpenStandardError (0);
258 // calling any FileStream constructor with a handle normally
259 // requires permissions UnmanagedCode permissions. In this
260 // case we assert this permission so the console can be used
261 // in partial trust (i.e. without having UnmanagedCode).
262 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
263 public static Stream OpenStandardError (int bufferSize)
265 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
268 public static Stream OpenStandardInput ()
270 return OpenStandardInput (0);
273 // calling any FileStream constructor with a handle normally
274 // requires permissions UnmanagedCode permissions. In this
275 // case we assert this permission so the console can be used
276 // in partial trust (i.e. without having UnmanagedCode).
277 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
278 public static Stream OpenStandardInput (int bufferSize)
280 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
283 public static Stream OpenStandardOutput ()
285 return OpenStandardOutput (0);
288 // calling any FileStream constructor with a handle normally
289 // requires permissions UnmanagedCode permissions. In this
290 // case we assert this permission so the console can be used
291 // in partial trust (i.e. without having UnmanagedCode).
292 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
293 public static Stream OpenStandardOutput (int bufferSize)
295 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
298 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
299 public static void SetError (TextWriter newError)
301 if (newError == null)
302 throw new ArgumentNullException ("newError");
307 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
308 public static void SetIn (TextReader newIn)
311 throw new ArgumentNullException ("newIn");
316 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
317 public static void SetOut (TextWriter newOut)
320 throw new ArgumentNullException ("newOut");
325 public static void Write (bool value)
327 stdout.Write (value);
330 public static void Write (char value)
332 stdout.Write (value);
335 public static void Write (char[] buffer)
337 stdout.Write (buffer);
340 public static void Write (decimal value)
342 stdout.Write (value);
345 public static void Write (double value)
347 stdout.Write (value);
350 public static void Write (int value)
352 stdout.Write (value);
355 public static void Write (long value)
357 stdout.Write (value);
360 public static void Write (object value)
362 stdout.Write (value);
365 public static void Write (float value)
367 stdout.Write (value);
370 public static void Write (string value)
372 stdout.Write (value);
375 [CLSCompliant (false)]
376 public static void Write (uint value)
378 stdout.Write (value);
381 [CLSCompliant (false)]
382 public static void Write (ulong value)
384 stdout.Write (value);
387 public static void Write (string format, object arg0)
389 stdout.Write (format, arg0);
392 public static void Write (string format, params object[] arg)
395 stdout.Write (format);
397 stdout.Write (format, arg);
400 public static void Write (char[] buffer, int index, int count)
402 stdout.Write (buffer, index, count);
405 public static void Write (string format, object arg0, object arg1)
407 stdout.Write (format, arg0, arg1);
410 public static void Write (string format, object arg0, object arg1, object arg2 )
412 stdout.Write (format, arg0, arg1, arg2);
415 [CLSCompliant (false)]
416 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
418 ArgIterator iter = new ArgIterator (__arglist);
419 int argCount = iter.GetRemainingCount();
421 object[] args = new object [argCount + 4];
426 for (int i = 0; i < argCount; i++) {
427 TypedReference typedRef = iter.GetNextArg ();
428 args [i + 4] = TypedReference.ToObject (typedRef);
431 stdout.Write (String.Format (format, args));
434 public static void WriteLine ()
439 public static void WriteLine (bool value)
441 stdout.WriteLine (value);
444 public static void WriteLine (char value)
446 stdout.WriteLine (value);
449 public static void WriteLine (char[] buffer)
451 stdout.WriteLine (buffer);
454 public static void WriteLine (decimal value)
456 stdout.WriteLine (value);
459 public static void WriteLine (double value)
461 stdout.WriteLine (value);
464 public static void WriteLine (int value)
466 stdout.WriteLine (value);
469 public static void WriteLine (long value)
471 stdout.WriteLine (value);
474 public static void WriteLine (object value)
476 stdout.WriteLine (value);
479 public static void WriteLine (float value)
481 stdout.WriteLine (value);
484 public static void WriteLine (string value)
486 stdout.WriteLine (value);
489 [CLSCompliant (false)]
490 public static void WriteLine (uint value)
492 stdout.WriteLine (value);
495 [CLSCompliant (false)]
496 public static void WriteLine (ulong value)
498 stdout.WriteLine (value);
501 public static void WriteLine (string format, object arg0)
503 stdout.WriteLine (format, arg0);
506 public static void WriteLine (string format, params object[] arg)
509 stdout.WriteLine (format);
511 stdout.WriteLine (format, arg);
514 public static void WriteLine (char[] buffer, int index, int count)
516 stdout.WriteLine (buffer, index, count);
519 public static void WriteLine (string format, object arg0, object arg1)
521 stdout.WriteLine (format, arg0, arg1);
524 public static void WriteLine (string format, object arg0, object arg1, object arg2)
526 stdout.WriteLine (format, arg0, arg1, arg2);
529 [CLSCompliant (false)]
530 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
532 ArgIterator iter = new ArgIterator (__arglist);
533 int argCount = iter.GetRemainingCount();
535 object[] args = new object [argCount + 4];
540 for (int i = 0; i < argCount; i++) {
541 TypedReference typedRef = iter.GetNextArg ();
542 args [i + 4] = TypedReference.ToObject (typedRef);
545 stdout.WriteLine (String.Format (format, args));
549 public static int Read ()
551 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
552 return ConsoleDriver.Read ();
554 return stdin.Read ();
558 public static string ReadLine ()
560 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
561 return ConsoleDriver.ReadLine ();
563 return stdin.ReadLine ();
567 public static int Read ()
569 return stdin.Read ();
572 public static string ReadLine ()
574 return stdin.ReadLine ();
580 // FIXME: Console should use these encodings when changed
581 static Encoding inputEncoding;
582 static Encoding outputEncoding;
584 public static Encoding InputEncoding {
585 get { return inputEncoding; }
587 inputEncoding = value;
588 SetupStreams (inputEncoding, outputEncoding);
592 public static Encoding OutputEncoding {
593 get { return outputEncoding; }
595 outputEncoding = value;
596 SetupStreams (inputEncoding, outputEncoding);
600 public static ConsoleColor BackgroundColor {
601 get { return ConsoleDriver.BackgroundColor; }
602 set { ConsoleDriver.BackgroundColor = value; }
605 public static int BufferHeight {
606 get { return ConsoleDriver.BufferHeight; }
607 [MonoLimitation ("Implemented only on Windows")]
608 set { ConsoleDriver.BufferHeight = value; }
611 public static int BufferWidth {
612 get { return ConsoleDriver.BufferWidth; }
613 [MonoLimitation ("Implemented only on Windows")]
614 set { ConsoleDriver.BufferWidth = value; }
617 [MonoLimitation ("Implemented only on Windows")]
618 public static bool CapsLock {
619 get { return ConsoleDriver.CapsLock; }
622 public static int CursorLeft {
623 get { return ConsoleDriver.CursorLeft; }
624 set { ConsoleDriver.CursorLeft = value; }
627 public static int CursorTop {
628 get { return ConsoleDriver.CursorTop; }
629 set { ConsoleDriver.CursorTop = value; }
632 public static int CursorSize {
633 get { return ConsoleDriver.CursorSize; }
634 set { ConsoleDriver.CursorSize = value; }
637 public static bool CursorVisible {
638 get { return ConsoleDriver.CursorVisible; }
639 set { ConsoleDriver.CursorVisible = value; }
642 public static ConsoleColor ForegroundColor {
643 get { return ConsoleDriver.ForegroundColor; }
644 set { ConsoleDriver.ForegroundColor = value; }
647 public static bool KeyAvailable {
648 get { return ConsoleDriver.KeyAvailable; }
651 public static int LargestWindowHeight {
652 get { return ConsoleDriver.LargestWindowHeight; }
655 public static int LargestWindowWidth {
656 get { return ConsoleDriver.LargestWindowWidth; }
659 [MonoLimitation ("Only works on windows")]
660 public static bool NumberLock {
661 get { return ConsoleDriver.NumberLock; }
664 public static string Title {
665 get { return ConsoleDriver.Title; }
666 set { ConsoleDriver.Title = value; }
669 public static bool TreatControlCAsInput {
670 get { return ConsoleDriver.TreatControlCAsInput; }
671 set { ConsoleDriver.TreatControlCAsInput = value; }
674 [MonoLimitation ("Only works on windows")]
675 public static int WindowHeight {
676 get { return ConsoleDriver.WindowHeight; }
677 set { ConsoleDriver.WindowHeight = value; }
680 [MonoLimitation ("Only works on windows")]
681 public static int WindowLeft {
682 get { return ConsoleDriver.WindowLeft; }
683 set { ConsoleDriver.WindowLeft = value; }
686 [MonoLimitation ("Only works on windows")]
687 public static int WindowTop {
688 get { return ConsoleDriver.WindowTop; }
689 set { ConsoleDriver.WindowTop = value; }
692 [MonoLimitation ("Only works on windows")]
693 public static int WindowWidth {
694 get { return ConsoleDriver.WindowWidth; }
695 set { ConsoleDriver.WindowWidth = value; }
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);