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);
161 stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
162 ((StreamWriter)stdout).AutoFlush = true;
163 stdout = TextWriter.Synchronized (stdout, true);
165 stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
166 ((StreamWriter)stderr).AutoFlush = true;
167 stderr = TextWriter.Synchronized (stderr, true);
169 stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
170 stdin = TextReader.Synchronized (stdin);
176 console_stderr = stderr;
177 console_stdout = stdout;
178 console_stdin = stdin;
182 if (LogcatTextWriter.IsRunningOnAndroid ()) {
183 stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout));
184 stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr));
188 GC.SuppressFinalize (stdout);
189 GC.SuppressFinalize (stderr);
190 GC.SuppressFinalize (stdin);
193 public static TextWriter Error {
199 public static TextWriter Out {
205 public static TextReader In {
212 public static bool IsErrorRedirected {
214 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
218 public static bool IsOutputRedirected {
220 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
224 public static bool IsInputRedirected {
226 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
231 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
234 if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
235 return new NullStream ();
238 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
239 } catch (IOException) {
240 return new NullStream ();
244 public static Stream OpenStandardError ()
246 return OpenStandardError (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 OpenStandardError (int bufferSize)
256 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
259 public static Stream OpenStandardInput ()
261 return OpenStandardInput (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 OpenStandardInput (int bufferSize)
271 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
274 public static Stream OpenStandardOutput ()
276 return OpenStandardOutput (0);
279 // calling any FileStream constructor with a handle normally
280 // requires permissions UnmanagedCode permissions. In this
281 // case we assert this permission so the console can be used
282 // in partial trust (i.e. without having UnmanagedCode).
283 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
284 public static Stream OpenStandardOutput (int bufferSize)
286 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
289 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
290 public static void SetError (TextWriter newError)
292 if (newError == null)
293 throw new ArgumentNullException ("newError");
298 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
299 public static void SetIn (TextReader newIn)
302 throw new ArgumentNullException ("newIn");
307 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
308 public static void SetOut (TextWriter newOut)
311 throw new ArgumentNullException ("newOut");
316 public static void Write (bool value)
318 stdout.Write (value);
321 public static void Write (char value)
323 stdout.Write (value);
326 public static void Write (char[] buffer)
328 stdout.Write (buffer);
331 public static void Write (decimal value)
333 stdout.Write (value);
336 public static void Write (double value)
338 stdout.Write (value);
341 public static void Write (int value)
343 stdout.Write (value);
346 public static void Write (long value)
348 stdout.Write (value);
351 public static void Write (object value)
353 stdout.Write (value);
356 public static void Write (float value)
358 stdout.Write (value);
361 public static void Write (string value)
363 stdout.Write (value);
366 [CLSCompliant (false)]
367 public static void Write (uint value)
369 stdout.Write (value);
372 [CLSCompliant (false)]
373 public static void Write (ulong value)
375 stdout.Write (value);
378 public static void Write (string format, object arg0)
380 stdout.Write (format, arg0);
383 public static void Write (string format, params object[] arg)
386 stdout.Write (format);
388 stdout.Write (format, arg);
391 public static void Write (char[] buffer, int index, int count)
393 stdout.Write (buffer, index, count);
396 public static void Write (string format, object arg0, object arg1)
398 stdout.Write (format, arg0, arg1);
401 public static void Write (string format, object arg0, object arg1, object arg2 )
403 stdout.Write (format, arg0, arg1, arg2);
406 [CLSCompliant (false)]
407 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
409 ArgIterator iter = new ArgIterator (__arglist);
410 int argCount = iter.GetRemainingCount();
412 object[] args = new object [argCount + 4];
417 for (int i = 0; i < argCount; i++) {
418 TypedReference typedRef = iter.GetNextArg ();
419 args [i + 4] = TypedReference.ToObject (typedRef);
422 stdout.Write (String.Format (format, args));
425 public static void WriteLine ()
430 public static void WriteLine (bool value)
432 stdout.WriteLine (value);
435 public static void WriteLine (char value)
437 stdout.WriteLine (value);
440 public static void WriteLine (char[] buffer)
442 stdout.WriteLine (buffer);
445 public static void WriteLine (decimal value)
447 stdout.WriteLine (value);
450 public static void WriteLine (double value)
452 stdout.WriteLine (value);
455 public static void WriteLine (int value)
457 stdout.WriteLine (value);
460 public static void WriteLine (long value)
462 stdout.WriteLine (value);
465 public static void WriteLine (object value)
467 stdout.WriteLine (value);
470 public static void WriteLine (float value)
472 stdout.WriteLine (value);
475 public static void WriteLine (string value)
477 stdout.WriteLine (value);
480 [CLSCompliant (false)]
481 public static void WriteLine (uint value)
483 stdout.WriteLine (value);
486 [CLSCompliant (false)]
487 public static void WriteLine (ulong value)
489 stdout.WriteLine (value);
492 public static void WriteLine (string format, object arg0)
494 stdout.WriteLine (format, arg0);
497 public static void WriteLine (string format, params object[] arg)
500 stdout.WriteLine (format);
502 stdout.WriteLine (format, arg);
505 public static void WriteLine (char[] buffer, int index, int count)
507 stdout.WriteLine (buffer, index, count);
510 public static void WriteLine (string format, object arg0, object arg1)
512 stdout.WriteLine (format, arg0, arg1);
515 public static void WriteLine (string format, object arg0, object arg1, object arg2)
517 stdout.WriteLine (format, arg0, arg1, arg2);
520 [CLSCompliant (false)]
521 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
523 ArgIterator iter = new ArgIterator (__arglist);
524 int argCount = iter.GetRemainingCount();
526 object[] args = new object [argCount + 4];
531 for (int i = 0; i < argCount; i++) {
532 TypedReference typedRef = iter.GetNextArg ();
533 args [i + 4] = TypedReference.ToObject (typedRef);
536 stdout.WriteLine (String.Format (format, args));
540 public static int Read ()
542 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
543 return ConsoleDriver.Read ();
545 return stdin.Read ();
549 public static string ReadLine ()
551 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
552 return ConsoleDriver.ReadLine ();
554 return stdin.ReadLine ();
558 public static int Read ()
560 return stdin.Read ();
563 public static string ReadLine ()
565 return stdin.ReadLine ();
571 // FIXME: Console should use these encodings when changed
572 static Encoding inputEncoding;
573 static Encoding outputEncoding;
575 public static Encoding InputEncoding {
576 get { return inputEncoding; }
578 inputEncoding = value;
579 SetupStreams (inputEncoding, outputEncoding);
583 public static Encoding OutputEncoding {
584 get { return outputEncoding; }
586 outputEncoding = value;
587 SetupStreams (inputEncoding, outputEncoding);
591 public static ConsoleColor BackgroundColor {
592 get { return ConsoleDriver.BackgroundColor; }
593 set { ConsoleDriver.BackgroundColor = value; }
596 public static int BufferHeight {
597 get { return ConsoleDriver.BufferHeight; }
598 [MonoLimitation ("Implemented only on Windows")]
599 set { ConsoleDriver.BufferHeight = value; }
602 public static int BufferWidth {
603 get { return ConsoleDriver.BufferWidth; }
604 [MonoLimitation ("Implemented only on Windows")]
605 set { ConsoleDriver.BufferWidth = value; }
608 [MonoLimitation ("Implemented only on Windows")]
609 public static bool CapsLock {
610 get { return ConsoleDriver.CapsLock; }
613 public static int CursorLeft {
614 get { return ConsoleDriver.CursorLeft; }
615 set { ConsoleDriver.CursorLeft = value; }
618 public static int CursorTop {
619 get { return ConsoleDriver.CursorTop; }
620 set { ConsoleDriver.CursorTop = value; }
623 public static int CursorSize {
624 get { return ConsoleDriver.CursorSize; }
625 set { ConsoleDriver.CursorSize = value; }
628 public static bool CursorVisible {
629 get { return ConsoleDriver.CursorVisible; }
630 set { ConsoleDriver.CursorVisible = value; }
633 public static ConsoleColor ForegroundColor {
634 get { return ConsoleDriver.ForegroundColor; }
635 set { ConsoleDriver.ForegroundColor = value; }
638 public static bool KeyAvailable {
639 get { return ConsoleDriver.KeyAvailable; }
642 public static int LargestWindowHeight {
643 get { return ConsoleDriver.LargestWindowHeight; }
646 public static int LargestWindowWidth {
647 get { return ConsoleDriver.LargestWindowWidth; }
650 [MonoLimitation ("Only works on windows")]
651 public static bool NumberLock {
652 get { return ConsoleDriver.NumberLock; }
655 public static string Title {
656 get { return ConsoleDriver.Title; }
657 set { ConsoleDriver.Title = value; }
660 public static bool TreatControlCAsInput {
661 get { return ConsoleDriver.TreatControlCAsInput; }
662 set { ConsoleDriver.TreatControlCAsInput = value; }
665 [MonoLimitation ("Only works on windows")]
666 public static int WindowHeight {
667 get { return ConsoleDriver.WindowHeight; }
668 set { ConsoleDriver.WindowHeight = value; }
671 [MonoLimitation ("Only works on windows")]
672 public static int WindowLeft {
673 get { return ConsoleDriver.WindowLeft; }
674 set { ConsoleDriver.WindowLeft = value; }
677 [MonoLimitation ("Only works on windows")]
678 public static int WindowTop {
679 get { return ConsoleDriver.WindowTop; }
680 set { ConsoleDriver.WindowTop = value; }
683 [MonoLimitation ("Only works on windows")]
684 public static int WindowWidth {
685 get { return ConsoleDriver.WindowWidth; }
686 set { ConsoleDriver.WindowWidth = value; }
689 public static void Beep ()
694 public static void Beep (int frequency, int duration)
696 if (frequency < 37 || frequency > 32767)
697 throw new ArgumentOutOfRangeException ("frequency");
700 throw new ArgumentOutOfRangeException ("duration");
702 ConsoleDriver.Beep (frequency, duration);
705 public static void Clear ()
707 ConsoleDriver.Clear ();
710 [MonoLimitation ("Implemented only on Windows")]
711 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
712 int targetLeft, int targetTop)
714 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
717 [MonoLimitation ("Implemented only on Windows")]
718 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
719 int targetLeft, int targetTop, Char sourceChar,
720 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
722 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
723 sourceChar, sourceForeColor, sourceBackColor);
726 public static ConsoleKeyInfo ReadKey ()
728 return ReadKey (false);
731 public static ConsoleKeyInfo ReadKey (bool intercept)
733 return ConsoleDriver.ReadKey (intercept);
736 public static void ResetColor ()
738 ConsoleDriver.ResetColor ();
741 [MonoLimitation ("Only works on windows")]
742 public static void SetBufferSize (int width, int height)
744 ConsoleDriver.SetBufferSize (width, height);
747 public static void SetCursorPosition (int left, int top)
749 ConsoleDriver.SetCursorPosition (left, top);
752 public static void SetWindowPosition (int left, int top)
754 ConsoleDriver.SetWindowPosition (left, top);
757 public static void SetWindowSize (int width, int height)
759 ConsoleDriver.SetWindowSize (width, height);
762 static ConsoleCancelEventHandler cancel_event;
763 public static event ConsoleCancelEventHandler CancelKeyPress {
765 if (ConsoleDriver.Initialized == false)
766 ConsoleDriver.Init ();
768 cancel_event += value;
770 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
771 WindowsConsole.AddCtrlHandler();
774 if (ConsoleDriver.Initialized == false)
775 ConsoleDriver.Init ();
777 cancel_event -= value;
779 if (cancel_event == null && Environment.IsRunningOnWindows)
781 // Need to remove our hook if there's nothing left in the event
782 if (WindowsConsole.ctrlHandlerAdded)
783 WindowsConsole.RemoveCtrlHandler();
788 delegate void InternalCancelHandler ();
790 #pragma warning disable 414
792 // Used by console-io.c
794 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
795 #pragma warning restore 414
797 internal static void DoConsoleCancelEvent ()
800 if (cancel_event != null) {
801 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
802 Delegate [] delegates = cancel_event.GetInvocationList ();
803 foreach (ConsoleCancelEventHandler d in delegates){
805 // Sender is always null here.
807 } catch {} // Ignore any exception.
813 Environment.Exit (58);