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;
92 internal static TextWriter stdout;
93 private static TextWriter stderr;
94 private static TextReader stdin;
99 Encoding inputEncoding;
100 Encoding outputEncoding;
103 if (Environment.IsRunningOnWindows) {
105 // On Windows, follow the Windows tradition
108 // should never happen since Moonlight does not run on windows
109 inputEncoding = outputEncoding = Encoding.Default;
112 inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
113 outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
114 // ArgumentException and NotSupportedException can be thrown as well
116 // FIXME: I18N assemblies are not available when compiling mcs
117 // Use Latin 1 as it is fast and UTF-8 is never used as console code page
118 inputEncoding = outputEncoding = Encoding.Default;
123 // On Unix systems (128), do not output the
124 // UTF-8 ZWNBSP (zero-width non-breaking space).
127 Encoding.InternalCodePage (ref code_page);
129 if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
130 || ((code_page & 0x10000000) != 0)))
131 inputEncoding = outputEncoding = Encoding.UTF8Unmarked;
133 inputEncoding = outputEncoding = Encoding.Default;
136 SetupStreams (inputEncoding, outputEncoding);
139 static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding)
141 stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
142 ((StreamWriter)stderr).AutoFlush = true;
143 stderr = TextWriter.Synchronized (stderr, true);
146 if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
147 StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
149 stdout = TextWriter.Synchronized (w, true);
150 stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
153 stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
154 ((StreamWriter)stdout).AutoFlush = true;
155 stdout = TextWriter.Synchronized (stdout, true);
156 stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
157 stdin = TextReader.Synchronized (stdin);
162 GC.SuppressFinalize (stdout);
163 GC.SuppressFinalize (stderr);
164 GC.SuppressFinalize (stdin);
167 public static TextWriter Error {
173 public static TextWriter Out {
179 public static TextReader In {
185 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
188 if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
189 return new NullStream ();
192 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
193 } catch (IOException) {
194 return new NullStream ();
198 public static Stream OpenStandardError ()
200 return OpenStandardError (0);
203 // calling any FileStream constructor with a handle normally
204 // requires permissions UnmanagedCode permissions. In this
205 // case we assert this permission so the console can be used
206 // in partial trust (i.e. without having UnmanagedCode).
207 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
208 public static Stream OpenStandardError (int bufferSize)
210 return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
213 public static Stream OpenStandardInput ()
215 return OpenStandardInput (0);
218 // calling any FileStream constructor with a handle normally
219 // requires permissions UnmanagedCode permissions. In this
220 // case we assert this permission so the console can be used
221 // in partial trust (i.e. without having UnmanagedCode).
222 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
223 public static Stream OpenStandardInput (int bufferSize)
225 return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
228 public static Stream OpenStandardOutput ()
230 return OpenStandardOutput (0);
233 // calling any FileStream constructor with a handle normally
234 // requires permissions UnmanagedCode permissions. In this
235 // case we assert this permission so the console can be used
236 // in partial trust (i.e. without having UnmanagedCode).
237 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
238 public static Stream OpenStandardOutput (int bufferSize)
240 return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
243 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
244 public static void SetError (TextWriter newError)
246 if (newError == null)
247 throw new ArgumentNullException ("newError");
252 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
253 public static void SetIn (TextReader newIn)
256 throw new ArgumentNullException ("newIn");
261 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
262 public static void SetOut (TextWriter newOut)
265 throw new ArgumentNullException ("newOut");
270 public static void Write (bool value)
272 stdout.Write (value);
275 public static void Write (char value)
277 stdout.Write (value);
280 public static void Write (char[] buffer)
282 stdout.Write (buffer);
285 public static void Write (decimal value)
287 stdout.Write (value);
290 public static void Write (double value)
292 stdout.Write (value);
295 public static void Write (int value)
297 stdout.Write (value);
300 public static void Write (long value)
302 stdout.Write (value);
305 public static void Write (object value)
307 stdout.Write (value);
310 public static void Write (float value)
312 stdout.Write (value);
315 public static void Write (string value)
317 stdout.Write (value);
320 [CLSCompliant (false)]
321 public static void Write (uint value)
323 stdout.Write (value);
326 [CLSCompliant (false)]
327 public static void Write (ulong value)
329 stdout.Write (value);
332 public static void Write (string format, object arg0)
334 stdout.Write (format, arg0);
337 public static void Write (string format, params object[] arg)
340 stdout.Write (format);
342 stdout.Write (format, arg);
345 public static void Write (char[] buffer, int index, int count)
347 stdout.Write (buffer, index, count);
350 public static void Write (string format, object arg0, object arg1)
352 stdout.Write (format, arg0, arg1);
355 public static void Write (string format, object arg0, object arg1, object arg2 )
357 stdout.Write (format, arg0, arg1, arg2);
360 [CLSCompliant (false)]
361 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
363 ArgIterator iter = new ArgIterator (__arglist);
364 int argCount = iter.GetRemainingCount();
366 object[] args = new object [argCount + 4];
371 for (int i = 0; i < argCount; i++) {
372 TypedReference typedRef = iter.GetNextArg ();
373 args [i + 4] = TypedReference.ToObject (typedRef);
376 stdout.Write (String.Format (format, args));
379 public static void WriteLine ()
384 public static void WriteLine (bool value)
386 stdout.WriteLine (value);
389 public static void WriteLine (char value)
391 stdout.WriteLine (value);
394 public static void WriteLine (char[] buffer)
396 stdout.WriteLine (buffer);
399 public static void WriteLine (decimal value)
401 stdout.WriteLine (value);
404 public static void WriteLine (double value)
406 stdout.WriteLine (value);
409 public static void WriteLine (int value)
411 stdout.WriteLine (value);
414 public static void WriteLine (long value)
416 stdout.WriteLine (value);
419 public static void WriteLine (object value)
421 stdout.WriteLine (value);
424 public static void WriteLine (float value)
426 stdout.WriteLine (value);
429 public static void WriteLine (string value)
431 stdout.WriteLine (value);
434 [CLSCompliant (false)]
435 public static void WriteLine (uint value)
437 stdout.WriteLine (value);
440 [CLSCompliant (false)]
441 public static void WriteLine (ulong value)
443 stdout.WriteLine (value);
446 public static void WriteLine (string format, object arg0)
448 stdout.WriteLine (format, arg0);
451 public static void WriteLine (string format, params object[] arg)
454 stdout.WriteLine (format);
456 stdout.WriteLine (format, arg);
459 public static void WriteLine (char[] buffer, int index, int count)
461 stdout.WriteLine (buffer, index, count);
464 public static void WriteLine (string format, object arg0, object arg1)
466 stdout.WriteLine (format, arg0, arg1);
469 public static void WriteLine (string format, object arg0, object arg1, object arg2)
471 stdout.WriteLine (format, arg0, arg1, arg2);
474 [CLSCompliant (false)]
475 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
477 ArgIterator iter = new ArgIterator (__arglist);
478 int argCount = iter.GetRemainingCount();
480 object[] args = new object [argCount + 4];
485 for (int i = 0; i < argCount; i++) {
486 TypedReference typedRef = iter.GetNextArg ();
487 args [i + 4] = TypedReference.ToObject (typedRef);
490 stdout.WriteLine (String.Format (format, args));
494 public static int Read ()
496 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
497 return ConsoleDriver.Read ();
499 return stdin.Read ();
503 public static string ReadLine ()
505 if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
506 return ConsoleDriver.ReadLine ();
508 return stdin.ReadLine ();
512 public static int Read ()
514 return stdin.Read ();
517 public static string ReadLine ()
519 return stdin.ReadLine ();
525 // FIXME: Console should use these encodings when changed
526 static Encoding inputEncoding;
527 static Encoding outputEncoding;
529 public static Encoding InputEncoding {
530 get { return inputEncoding; }
532 inputEncoding = value;
533 SetupStreams (inputEncoding, outputEncoding);
537 public static Encoding OutputEncoding {
538 get { return outputEncoding; }
540 outputEncoding = value;
541 SetupStreams (inputEncoding, outputEncoding);
545 public static ConsoleColor BackgroundColor {
546 get { return ConsoleDriver.BackgroundColor; }
547 set { ConsoleDriver.BackgroundColor = value; }
550 public static int BufferHeight {
551 get { return ConsoleDriver.BufferHeight; }
552 [MonoLimitation ("Implemented only on Windows")]
553 set { ConsoleDriver.BufferHeight = value; }
556 public static int BufferWidth {
557 get { return ConsoleDriver.BufferWidth; }
558 [MonoLimitation ("Implemented only on Windows")]
559 set { ConsoleDriver.BufferWidth = value; }
562 [MonoLimitation ("Implemented only on Windows")]
563 public static bool CapsLock {
564 get { return ConsoleDriver.CapsLock; }
567 public static int CursorLeft {
568 get { return ConsoleDriver.CursorLeft; }
569 set { ConsoleDriver.CursorLeft = value; }
572 public static int CursorTop {
573 get { return ConsoleDriver.CursorTop; }
574 set { ConsoleDriver.CursorTop = value; }
577 public static int CursorSize {
578 get { return ConsoleDriver.CursorSize; }
579 set { ConsoleDriver.CursorSize = value; }
582 public static bool CursorVisible {
583 get { return ConsoleDriver.CursorVisible; }
584 set { ConsoleDriver.CursorVisible = value; }
587 public static ConsoleColor ForegroundColor {
588 get { return ConsoleDriver.ForegroundColor; }
589 set { ConsoleDriver.ForegroundColor = value; }
592 public static bool KeyAvailable {
593 get { return ConsoleDriver.KeyAvailable; }
596 public static int LargestWindowHeight {
597 get { return ConsoleDriver.LargestWindowHeight; }
600 public static int LargestWindowWidth {
601 get { return ConsoleDriver.LargestWindowWidth; }
604 [MonoLimitation ("Only works on windows")]
605 public static bool NumberLock {
606 get { return ConsoleDriver.NumberLock; }
609 public static string Title {
610 get { return ConsoleDriver.Title; }
611 set { ConsoleDriver.Title = value; }
614 public static bool TreatControlCAsInput {
615 get { return ConsoleDriver.TreatControlCAsInput; }
616 set { ConsoleDriver.TreatControlCAsInput = value; }
619 [MonoLimitation ("Only works on windows")]
620 public static int WindowHeight {
621 get { return ConsoleDriver.WindowHeight; }
622 set { ConsoleDriver.WindowHeight = value; }
625 [MonoLimitation ("Only works on windows")]
626 public static int WindowLeft {
627 get { return ConsoleDriver.WindowLeft; }
628 set { ConsoleDriver.WindowLeft = value; }
631 [MonoLimitation ("Only works on windows")]
632 public static int WindowTop {
633 get { return ConsoleDriver.WindowTop; }
634 set { ConsoleDriver.WindowTop = value; }
637 [MonoLimitation ("Only works on windows")]
638 public static int WindowWidth {
639 get { return ConsoleDriver.WindowWidth; }
640 set { ConsoleDriver.WindowWidth = value; }
643 public static void Beep ()
648 public static void Beep (int frequency, int duration)
650 if (frequency < 37 || frequency > 32767)
651 throw new ArgumentOutOfRangeException ("frequency");
654 throw new ArgumentOutOfRangeException ("duration");
656 ConsoleDriver.Beep (frequency, duration);
659 public static void Clear ()
661 ConsoleDriver.Clear ();
664 [MonoLimitation ("Implemented only on Windows")]
665 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
666 int targetLeft, int targetTop)
668 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
671 [MonoLimitation ("Implemented only on Windows")]
672 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
673 int targetLeft, int targetTop, Char sourceChar,
674 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
676 ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
677 sourceChar, sourceForeColor, sourceBackColor);
680 public static ConsoleKeyInfo ReadKey ()
682 return ReadKey (false);
685 public static ConsoleKeyInfo ReadKey (bool intercept)
687 return ConsoleDriver.ReadKey (intercept);
690 public static void ResetColor ()
692 ConsoleDriver.ResetColor ();
695 [MonoLimitation ("Only works on windows")]
696 public static void SetBufferSize (int width, int height)
698 ConsoleDriver.SetBufferSize (width, height);
701 public static void SetCursorPosition (int left, int top)
703 ConsoleDriver.SetCursorPosition (left, top);
706 public static void SetWindowPosition (int left, int top)
708 ConsoleDriver.SetWindowPosition (left, top);
711 public static void SetWindowSize (int width, int height)
713 ConsoleDriver.SetWindowSize (width, height);
716 static ConsoleCancelEventHandler cancel_event;
717 public static event ConsoleCancelEventHandler CancelKeyPress {
719 if (ConsoleDriver.Initialized == false)
720 ConsoleDriver.Init ();
722 cancel_event += value;
724 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
725 WindowsConsole.AddCtrlHandler();
728 if (ConsoleDriver.Initialized == false)
729 ConsoleDriver.Init ();
731 cancel_event -= value;
733 if (cancel_event == null && Environment.IsRunningOnWindows)
735 // Need to remove our hook if there's nothing left in the event
736 if (WindowsConsole.ctrlHandlerAdded)
737 WindowsConsole.RemoveCtrlHandler();
742 delegate void InternalCancelHandler ();
744 #pragma warning disable 414
746 // Used by console-io.c
748 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
749 #pragma warning restore 414
751 internal static void DoConsoleCancelEvent ()
754 if (cancel_event != null) {
755 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
756 Delegate [] delegates = cancel_event.GetInvocationList ();
757 foreach (ConsoleCancelEventHandler d in delegates){
759 // Sender is always null here.
761 } catch {} // Ignore any exception.
767 Environment.Exit (58);