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)
148 stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
149 ((StreamWriter)stderr).AutoFlush = true;
150 stderr = TextWriter.Synchronized (stderr, true);
153 if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
154 StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
156 stdout = TextWriter.Synchronized (w, true);
157 stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
160 stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
161 ((StreamWriter)stdout).AutoFlush = true;
162 stdout = TextWriter.Synchronized (stdout, true);
163 stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
164 stdin = TextReader.Synchronized (stdin);
170 console_stderr = stderr;
171 console_stdout = stdout;
172 console_stdin = stdin;
175 GC.SuppressFinalize (stdout);
176 GC.SuppressFinalize (stderr);
177 GC.SuppressFinalize (stdin);
180 public static TextWriter Error {
186 public static TextWriter Out {
192 public static TextReader In {
199 public static bool IsErrorRedirected {
201 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
205 public static bool IsOutputRedirected {
207 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
211 public static bool IsInputRedirected {
213 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
218 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
221 if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
222 return new NullStream ();
225 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
226 } catch (IOException) {
227 return new NullStream ();
231 public static Stream OpenStandardError ()
233 return OpenStandardError (0);
236 // calling any FileStream constructor with a handle normally
237 // requires permissions UnmanagedCode permissions. In this
238 // case we assert this permission so the console can be used
239 // in partial trust (i.e. without having UnmanagedCode).
240 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
241 public static Stream OpenStandardError (int bufferSize)
243 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
246 public static Stream OpenStandardInput ()
248 return OpenStandardInput (0);
251 // calling any FileStream constructor with a handle normally
252 // requires permissions UnmanagedCode permissions. In this
253 // case we assert this permission so the console can be used
254 // in partial trust (i.e. without having UnmanagedCode).
255 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
256 public static Stream OpenStandardInput (int bufferSize)
258 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
261 public static Stream OpenStandardOutput ()
263 return OpenStandardOutput (0);
266 // calling any FileStream constructor with a handle normally
267 // requires permissions UnmanagedCode permissions. In this
268 // case we assert this permission so the console can be used
269 // in partial trust (i.e. without having UnmanagedCode).
270 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
271 public static Stream OpenStandardOutput (int bufferSize)
273 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
276 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
277 public static void SetError (TextWriter newError)
279 if (newError == null)
280 throw new ArgumentNullException ("newError");
285 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
286 public static void SetIn (TextReader newIn)
289 throw new ArgumentNullException ("newIn");
294 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
295 public static void SetOut (TextWriter newOut)
298 throw new ArgumentNullException ("newOut");
303 public static void Write (bool value)
305 stdout.Write (value);
308 public static void Write (char value)
310 stdout.Write (value);
313 public static void Write (char[] buffer)
315 stdout.Write (buffer);
318 public static void Write (decimal value)
320 stdout.Write (value);
323 public static void Write (double value)
325 stdout.Write (value);
328 public static void Write (int value)
330 stdout.Write (value);
333 public static void Write (long value)
335 stdout.Write (value);
338 public static void Write (object value)
340 stdout.Write (value);
343 public static void Write (float value)
345 stdout.Write (value);
348 public static void Write (string value)
350 stdout.Write (value);
353 [CLSCompliant (false)]
354 public static void Write (uint value)
356 stdout.Write (value);
359 [CLSCompliant (false)]
360 public static void Write (ulong value)
362 stdout.Write (value);
365 public static void Write (string format, object arg0)
367 stdout.Write (format, arg0);
370 public static void Write (string format, params object[] arg)
373 stdout.Write (format);
375 stdout.Write (format, arg);
378 public static void Write (char[] buffer, int index, int count)
380 stdout.Write (buffer, index, count);
383 public static void Write (string format, object arg0, object arg1)
385 stdout.Write (format, arg0, arg1);
388 public static void Write (string format, object arg0, object arg1, object arg2 )
390 stdout.Write (format, arg0, arg1, arg2);
393 [CLSCompliant (false)]
394 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
396 ArgIterator iter = new ArgIterator (__arglist);
397 int argCount = iter.GetRemainingCount();
399 object[] args = new object [argCount + 4];
404 for (int i = 0; i < argCount; i++) {
405 TypedReference typedRef = iter.GetNextArg ();
406 args [i + 4] = TypedReference.ToObject (typedRef);
409 stdout.Write (String.Format (format, args));
412 public static void WriteLine ()
417 public static void WriteLine (bool value)
419 stdout.WriteLine (value);
422 public static void WriteLine (char value)
424 stdout.WriteLine (value);
427 public static void WriteLine (char[] buffer)
429 stdout.WriteLine (buffer);
432 public static void WriteLine (decimal value)
434 stdout.WriteLine (value);
437 public static void WriteLine (double value)
439 stdout.WriteLine (value);
442 public static void WriteLine (int value)
444 stdout.WriteLine (value);
447 public static void WriteLine (long value)
449 stdout.WriteLine (value);
452 public static void WriteLine (object value)
454 stdout.WriteLine (value);
457 public static void WriteLine (float value)
459 stdout.WriteLine (value);
462 public static void WriteLine (string value)
464 stdout.WriteLine (value);
467 [CLSCompliant (false)]
468 public static void WriteLine (uint value)
470 stdout.WriteLine (value);
473 [CLSCompliant (false)]
474 public static void WriteLine (ulong value)
476 stdout.WriteLine (value);
479 public static void WriteLine (string format, object arg0)
481 stdout.WriteLine (format, arg0);
484 public static void WriteLine (string format, params object[] arg)
487 stdout.WriteLine (format);
489 stdout.WriteLine (format, arg);
492 public static void WriteLine (char[] buffer, int index, int count)
494 stdout.WriteLine (buffer, index, count);
497 public static void WriteLine (string format, object arg0, object arg1)
499 stdout.WriteLine (format, arg0, arg1);
502 public static void WriteLine (string format, object arg0, object arg1, object arg2)
504 stdout.WriteLine (format, arg0, arg1, arg2);
507 [CLSCompliant (false)]
508 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
510 ArgIterator iter = new ArgIterator (__arglist);
511 int argCount = iter.GetRemainingCount();
513 object[] args = new object [argCount + 4];
518 for (int i = 0; i < argCount; i++) {
519 TypedReference typedRef = iter.GetNextArg ();
520 args [i + 4] = TypedReference.ToObject (typedRef);
523 stdout.WriteLine (String.Format (format, args));
527 public static int Read ()
529 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
530 return ConsoleDriver.Read ();
532 return stdin.Read ();
536 public static string ReadLine ()
538 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
539 return ConsoleDriver.ReadLine ();
541 return stdin.ReadLine ();
545 public static int Read ()
547 return stdin.Read ();
550 public static string ReadLine ()
552 return stdin.ReadLine ();
558 // FIXME: Console should use these encodings when changed
559 static Encoding inputEncoding;
560 static Encoding outputEncoding;
562 public static Encoding InputEncoding {
563 get { return inputEncoding; }
565 inputEncoding = value;
566 SetupStreams (inputEncoding, outputEncoding);
570 public static Encoding OutputEncoding {
571 get { return outputEncoding; }
573 outputEncoding = value;
574 SetupStreams (inputEncoding, outputEncoding);
578 public static ConsoleColor BackgroundColor {
579 get { return ConsoleDriver.BackgroundColor; }
580 set { ConsoleDriver.BackgroundColor = value; }
583 public static int BufferHeight {
584 get { return ConsoleDriver.BufferHeight; }
585 [MonoLimitation ("Implemented only on Windows")]
586 set { ConsoleDriver.BufferHeight = value; }
589 public static int BufferWidth {
590 get { return ConsoleDriver.BufferWidth; }
591 [MonoLimitation ("Implemented only on Windows")]
592 set { ConsoleDriver.BufferWidth = value; }
595 [MonoLimitation ("Implemented only on Windows")]
596 public static bool CapsLock {
597 get { return ConsoleDriver.CapsLock; }
600 public static int CursorLeft {
601 get { return ConsoleDriver.CursorLeft; }
602 set { ConsoleDriver.CursorLeft = value; }
605 public static int CursorTop {
606 get { return ConsoleDriver.CursorTop; }
607 set { ConsoleDriver.CursorTop = value; }
610 public static int CursorSize {
611 get { return ConsoleDriver.CursorSize; }
612 set { ConsoleDriver.CursorSize = value; }
615 public static bool CursorVisible {
616 get { return ConsoleDriver.CursorVisible; }
617 set { ConsoleDriver.CursorVisible = value; }
620 public static ConsoleColor ForegroundColor {
621 get { return ConsoleDriver.ForegroundColor; }
622 set { ConsoleDriver.ForegroundColor = value; }
625 public static bool KeyAvailable {
626 get { return ConsoleDriver.KeyAvailable; }
629 public static int LargestWindowHeight {
630 get { return ConsoleDriver.LargestWindowHeight; }
633 public static int LargestWindowWidth {
634 get { return ConsoleDriver.LargestWindowWidth; }
637 [MonoLimitation ("Only works on windows")]
638 public static bool NumberLock {
639 get { return ConsoleDriver.NumberLock; }
642 public static string Title {
643 get { return ConsoleDriver.Title; }
644 set { ConsoleDriver.Title = value; }
647 public static bool TreatControlCAsInput {
648 get { return ConsoleDriver.TreatControlCAsInput; }
649 set { ConsoleDriver.TreatControlCAsInput = value; }
652 [MonoLimitation ("Only works on windows")]
653 public static int WindowHeight {
654 get { return ConsoleDriver.WindowHeight; }
655 set { ConsoleDriver.WindowHeight = value; }
658 [MonoLimitation ("Only works on windows")]
659 public static int WindowLeft {
660 get { return ConsoleDriver.WindowLeft; }
661 set { ConsoleDriver.WindowLeft = value; }
664 [MonoLimitation ("Only works on windows")]
665 public static int WindowTop {
666 get { return ConsoleDriver.WindowTop; }
667 set { ConsoleDriver.WindowTop = value; }
670 [MonoLimitation ("Only works on windows")]
671 public static int WindowWidth {
672 get { return ConsoleDriver.WindowWidth; }
673 set { ConsoleDriver.WindowWidth = value; }
676 public static void Beep ()
681 public static void Beep (int frequency, int duration)
683 if (frequency < 37 || frequency > 32767)
684 throw new ArgumentOutOfRangeException ("frequency");
687 throw new ArgumentOutOfRangeException ("duration");
689 ConsoleDriver.Beep (frequency, duration);
692 public static void Clear ()
694 ConsoleDriver.Clear ();
697 [MonoLimitation ("Implemented only on Windows")]
698 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
699 int targetLeft, int targetTop)
701 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
704 [MonoLimitation ("Implemented only on Windows")]
705 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
706 int targetLeft, int targetTop, Char sourceChar,
707 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
709 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
710 sourceChar, sourceForeColor, sourceBackColor);
713 public static ConsoleKeyInfo ReadKey ()
715 return ReadKey (false);
718 public static ConsoleKeyInfo ReadKey (bool intercept)
720 return ConsoleDriver.ReadKey (intercept);
723 public static void ResetColor ()
725 ConsoleDriver.ResetColor ();
728 [MonoLimitation ("Only works on windows")]
729 public static void SetBufferSize (int width, int height)
731 ConsoleDriver.SetBufferSize (width, height);
734 public static void SetCursorPosition (int left, int top)
736 ConsoleDriver.SetCursorPosition (left, top);
739 public static void SetWindowPosition (int left, int top)
741 ConsoleDriver.SetWindowPosition (left, top);
744 public static void SetWindowSize (int width, int height)
746 ConsoleDriver.SetWindowSize (width, height);
749 static ConsoleCancelEventHandler cancel_event;
750 public static event ConsoleCancelEventHandler CancelKeyPress {
752 if (ConsoleDriver.Initialized == false)
753 ConsoleDriver.Init ();
755 cancel_event += value;
757 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
758 WindowsConsole.AddCtrlHandler();
761 if (ConsoleDriver.Initialized == false)
762 ConsoleDriver.Init ();
764 cancel_event -= value;
766 if (cancel_event == null && Environment.IsRunningOnWindows)
768 // Need to remove our hook if there's nothing left in the event
769 if (WindowsConsole.ctrlHandlerAdded)
770 WindowsConsole.RemoveCtrlHandler();
775 delegate void InternalCancelHandler ();
777 #pragma warning disable 414
779 // Used by console-io.c
781 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
782 #pragma warning restore 414
784 internal static void DoConsoleCancelEvent ()
787 if (cancel_event != null) {
788 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
789 Delegate [] delegates = cancel_event.GetInvocationList ();
790 foreach (ConsoleCancelEventHandler d in delegates){
792 // Sender is always null here.
794 } catch {} // Ignore any exception.
800 Environment.Exit (58);