Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / corlib / System / Console.cs
1 //
2 // System.Console.cs
3 //
4 // Author:
5 //      Dietmar Maurer (dietmar@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (C) Ximian, Inc.  http://www.ximian.com
9 // (C) 2004,2005 Novell, Inc. (http://www.novell.com)
10 //
11
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:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
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.
30 //
31
32 using System.Diagnostics;
33 using System.IO;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Security;
37 using System.Security.Permissions;
38 using System.Text;
39
40 namespace System
41 {
42         public static class Console
43         {
44 #if !NET_2_1
45                 private class WindowsConsole
46                 {
47                         public static bool ctrlHandlerAdded = false;
48                         private delegate bool WindowsCancelHandler (int keyCode);
49                         private static WindowsCancelHandler cancelHandler = new WindowsCancelHandler (DoWindowsConsoleCancelEvent);
50
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 ();
55
56                         [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
57                         private static extern bool SetConsoleCtrlHandler (WindowsCancelHandler handler, bool addHandler);
58
59                         // Only call the event handler if Control-C was pressed (code == 0), nothing else
60                         private static bool DoWindowsConsoleCancelEvent (int keyCode)
61                         {
62                                 if (keyCode == 0)
63                                         DoConsoleCancelEvent ();
64                                 return keyCode == 0;
65                         }
66
67                         [MethodImpl (MethodImplOptions.NoInlining)]
68                         public static int GetInputCodePage ()
69                         {
70                                 return GetConsoleCP ();
71                         }
72
73                         [MethodImpl (MethodImplOptions.NoInlining)]
74                         public static int GetOutputCodePage ()
75                         {
76                                 return GetConsoleOutputCP ();
77                         }
78
79                         public static void AddCtrlHandler ()
80                         {
81                                 SetConsoleCtrlHandler (cancelHandler, true);
82                                 ctrlHandlerAdded = true;
83                         }
84                         
85                         public static void RemoveCtrlHandler ()
86                         {
87                                 SetConsoleCtrlHandler (cancelHandler, false);
88                                 ctrlHandlerAdded = false;
89                         }
90                 }
91 #endif
92
93                 internal static TextWriter stdout;
94                 private static TextWriter stderr;
95                 private static TextReader stdin;
96
97 #if NET_4_5
98                 static TextWriter console_stdout;
99                 static TextWriter console_stderr;
100                 static TextReader console_stdin;
101 #endif
102
103                 static Console ()
104                 {
105 #if NET_2_1
106                         Encoding inputEncoding;
107                         Encoding outputEncoding;
108 #endif
109
110                         if (Environment.IsRunningOnWindows) {
111                                 //
112                                 // On Windows, follow the Windows tradition
113                                 //
114 #if NET_2_1
115                                 // should never happen since Moonlight does not run on windows
116                                 inputEncoding = outputEncoding = Encoding.Default;
117 #else                   
118                                 try {
119                                         inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
120                                         outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
121                                         // ArgumentException and NotSupportedException can be thrown as well
122                                 } catch {
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;
126                                 }
127 #endif
128                         } else {
129                                 //
130                                 // On Unix systems (128), do not output the
131                                 // UTF-8 ZWNBSP (zero-width non-breaking space).
132                                 //
133                                 int code_page = 0;
134                                 Encoding.InternalCodePage (ref code_page);
135
136                                 if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
137                                         || ((code_page & 0x10000000) != 0)))
138                                         inputEncoding = outputEncoding = Encoding.UTF8Unmarked;
139                                 else
140                                         inputEncoding = outputEncoding = Encoding.Default;
141                         }
142
143                         SetupStreams (inputEncoding, outputEncoding);
144                 }
145
146                 static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding)
147                 {
148 #if !NET_2_1
149                         if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
150                                 StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
151                                 w.AutoFlush = true;
152                                 stdout = TextWriter.Synchronized (w, true);
153
154                                 w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
155                                 w.AutoFlush = true;
156                                 stderr = TextWriter.Synchronized (w, true);
157                                 
158                                 stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
159                         } else {
160 #endif
161 #if FULL_AOT_RUNTIME
162                                 Type nslogwriter = Type.GetType ("MonoTouch.Foundation.NSLogWriter, monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
163                                 stdout = (TextWriter) Activator.CreateInstance (nslogwriter);
164 #else
165                                 stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
166                                 ((StreamWriter)stdout).AutoFlush = true;
167 #endif
168                                 stdout = TextWriter.Synchronized (stdout, true);
169
170 #if FULL_AOT_RUNTIME
171                                 stderr = (TextWriter) Activator.CreateInstance (nslogwriter);
172 #else
173                                 stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding); 
174                                 ((StreamWriter)stderr).AutoFlush = true;
175 #endif
176                                 stderr = TextWriter.Synchronized (stderr, true);
177
178                                 stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
179                                 stdin = TextReader.Synchronized (stdin);
180 #if !NET_2_1
181                         }
182 #endif
183
184 #if NET_4_5
185                         console_stderr = stderr;
186                         console_stdout = stdout;
187                         console_stdin = stdin;
188 #endif
189
190 #if MONODROID
191                         if (LogcatTextWriter.IsRunningOnAndroid ()) {
192                                 stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout));
193                                 stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr));
194                         }
195 #endif  // MONODROID
196
197                         GC.SuppressFinalize (stdout);
198                         GC.SuppressFinalize (stderr);
199                         GC.SuppressFinalize (stdin);
200                 }
201
202                 public static TextWriter Error {
203                         get {
204                                 return stderr;
205                         }
206                 }
207
208                 public static TextWriter Out {
209                         get {
210                                 return stdout;
211                         }
212                 }
213
214                 public static TextReader In {
215                         get {
216                                 return stdin;
217                         }
218                 }
219
220 #if NET_4_5
221                 public static bool IsErrorRedirected {
222                         get {
223                                 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
224                         }
225                 }
226
227                 public static bool IsOutputRedirected {
228                         get {
229                                 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
230                         }
231                 }
232
233                 public static bool IsInputRedirected {
234                         get {
235                                 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
236                         }
237                 }
238 #endif
239
240                 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
241                 {
242 #if MOONLIGHT
243                         if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
244                                 return new NullStream ();
245 #endif
246                         try {
247                                 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
248                         } catch (IOException) {
249                                 return new NullStream ();
250                         }
251                 }
252
253                 public static Stream OpenStandardError ()
254                 {
255                         return OpenStandardError (0);
256                 }
257
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)
264                 {
265                         return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
266                 }
267
268                 public static Stream OpenStandardInput ()
269                 {
270                         return OpenStandardInput (0);
271                 }
272
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)
279                 {
280                         return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
281                 }
282
283                 public static Stream OpenStandardOutput ()
284                 {
285                         return OpenStandardOutput (0);
286                 }
287
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)
294                 {
295                         return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
296                 }
297
298                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
299                 public static void SetError (TextWriter newError)
300                 {
301                         if (newError == null)
302                                 throw new ArgumentNullException ("newError");
303
304                         stderr = newError;
305                 }
306
307                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
308                 public static void SetIn (TextReader newIn)
309                 {
310                         if (newIn == null)
311                                 throw new ArgumentNullException ("newIn");
312
313                         stdin = newIn;
314                 }
315
316                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
317                 public static void SetOut (TextWriter newOut)
318                 {
319                         if (newOut == null)
320                                 throw new ArgumentNullException ("newOut");
321
322                         stdout = newOut;
323                 }
324
325                 public static void Write (bool value)
326                 {
327                         stdout.Write (value);
328                 }
329
330                 public static void Write (char value)
331                 {
332                         stdout.Write (value);
333                 }
334
335                 public static void Write (char[] buffer)
336                 {
337                         stdout.Write (buffer);
338                 }
339
340                 public static void Write (decimal value)
341                 {
342                         stdout.Write (value);
343                 }
344                 
345                 public static void Write (double value)
346                 {
347                         stdout.Write (value);
348                 }
349
350                 public static void Write (int value)
351                 {
352                         stdout.Write (value);
353                 }
354
355                 public static void Write (long value)
356                 {
357                         stdout.Write (value);
358                 }
359
360                 public static void Write (object value)
361                 {
362                         stdout.Write (value);
363                 }
364
365                 public static void Write (float value)
366                 {
367                         stdout.Write (value);
368                 }
369
370                 public static void Write (string value)
371                 {
372                         stdout.Write (value);
373                 }
374
375                 [CLSCompliant (false)]
376                 public static void Write (uint value)
377                 {
378                         stdout.Write (value);
379                 }
380
381                 [CLSCompliant (false)]
382                 public static void Write (ulong value)
383                 {
384                         stdout.Write (value);
385                 }
386
387                 public static void Write (string format, object arg0)
388                 {
389                         stdout.Write (format, arg0);
390                 }
391
392                 public static void Write (string format, params object[] arg)
393                 {
394                         if (arg == null)
395                                 stdout.Write (format);
396                         else
397                                 stdout.Write (format, arg);
398                 }
399
400                 public static void Write (char[] buffer, int index, int count)
401                 {
402                         stdout.Write (buffer, index, count);
403                 }
404
405                 public static void Write (string format, object arg0, object arg1)
406                 {
407                         stdout.Write (format, arg0, arg1);
408                 }
409
410                 public static void Write (string format, object arg0, object arg1, object arg2 )
411                 {
412                         stdout.Write (format, arg0, arg1, arg2);
413                 }
414
415                 [CLSCompliant (false)]
416                 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
417                 {
418                         ArgIterator iter = new ArgIterator (__arglist);
419                         int argCount = iter.GetRemainingCount();
420
421                         object[] args = new object [argCount + 4];
422                         args [0] = arg0;
423                         args [1] = arg1;
424                         args [2] = arg2;
425                         args [3] = arg3;
426                         for (int i = 0; i < argCount; i++) {
427                                 TypedReference typedRef = iter.GetNextArg ();
428                                 args [i + 4] = TypedReference.ToObject (typedRef);
429                         }
430
431                         stdout.Write (String.Format (format, args));
432                 }
433
434                 public static void WriteLine ()
435                 {
436                         stdout.WriteLine ();
437                 }
438
439                 public static void WriteLine (bool value)
440                 {
441                         stdout.WriteLine (value);
442                 }
443
444                 public static void WriteLine (char value)
445                 {
446                         stdout.WriteLine (value);
447                 }
448
449                 public static void WriteLine (char[] buffer)
450                 {
451                         stdout.WriteLine (buffer);
452                 }
453
454                 public static void WriteLine (decimal value)
455                 {
456                         stdout.WriteLine (value);
457                 }
458
459                 public static void WriteLine (double value)
460                 {
461                         stdout.WriteLine (value);
462                 }
463
464                 public static void WriteLine (int value)
465                 {
466                         stdout.WriteLine (value);
467                 }
468
469                 public static void WriteLine (long value)
470                 {
471                         stdout.WriteLine (value);
472                 }
473
474                 public static void WriteLine (object value)
475                 {
476                         stdout.WriteLine (value);
477                 }
478
479                 public static void WriteLine (float value)
480                 {
481                         stdout.WriteLine (value);
482                 }
483
484                 public static void WriteLine (string value)
485                 {
486                         stdout.WriteLine (value);
487                 }
488
489                 [CLSCompliant (false)]
490                 public static void WriteLine (uint value)
491                 {
492                         stdout.WriteLine (value);
493                 }
494
495                 [CLSCompliant (false)]
496                 public static void WriteLine (ulong value)
497                 {
498                         stdout.WriteLine (value);
499                 }
500
501                 public static void WriteLine (string format, object arg0)
502                 {
503                         stdout.WriteLine (format, arg0);
504                 }
505
506                 public static void WriteLine (string format, params object[] arg)
507                 {
508                         if (arg == null)
509                                 stdout.WriteLine (format);
510                         else
511                                 stdout.WriteLine (format, arg);
512                 }
513
514                 public static void WriteLine (char[] buffer, int index, int count)
515                 {
516                         stdout.WriteLine (buffer, index, count);
517                 }
518
519                 public static void WriteLine (string format, object arg0, object arg1)
520                 {
521                         stdout.WriteLine (format, arg0, arg1);
522                 }
523
524                 public static void WriteLine (string format, object arg0, object arg1, object arg2)
525                 {
526                         stdout.WriteLine (format, arg0, arg1, arg2);
527                 }
528
529                 [CLSCompliant (false)]
530                 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
531                 {
532                         ArgIterator iter = new ArgIterator (__arglist);
533                         int argCount = iter.GetRemainingCount();
534
535                         object[] args = new object [argCount + 4];
536                         args [0] = arg0;
537                         args [1] = arg1;
538                         args [2] = arg2;
539                         args [3] = arg3;
540                         for (int i = 0; i < argCount; i++) {
541                                 TypedReference typedRef = iter.GetNextArg ();
542                                 args [i + 4] = TypedReference.ToObject (typedRef);
543                         }
544
545                         stdout.WriteLine (String.Format (format, args));
546                 }
547
548 #if !NET_2_1
549                 public static int Read ()
550                 {
551                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
552                                 return ConsoleDriver.Read ();
553                         } else {
554                                 return stdin.Read ();
555                         }
556                 }
557
558                 public static string ReadLine ()
559                 {
560                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
561                                 return ConsoleDriver.ReadLine ();
562                         } else {
563                                 return stdin.ReadLine ();
564                         }
565                 }
566 #else
567                 public static int Read ()
568                 {
569                         return stdin.Read ();
570                 }
571
572                 public static string ReadLine ()
573                 {
574                         return stdin.ReadLine ();
575                 }
576
577 #endif
578
579 #if !NET_2_1
580                 // FIXME: Console should use these encodings when changed
581                 static Encoding inputEncoding;
582                 static Encoding outputEncoding;
583
584                 public static Encoding InputEncoding {
585                         get { return inputEncoding; }
586                         set {
587                                 inputEncoding = value;
588                                 SetupStreams (inputEncoding, outputEncoding);
589                         }
590                 }
591
592                 public static Encoding OutputEncoding {
593                         get { return outputEncoding; }
594                         set {
595                                 outputEncoding = value;
596                                 SetupStreams (inputEncoding, outputEncoding);
597                         }
598                 }
599
600                 public static ConsoleColor BackgroundColor {
601                         get { return ConsoleDriver.BackgroundColor; }
602                         set { ConsoleDriver.BackgroundColor = value; }
603                 }
604
605                 public static int BufferHeight {
606                         get { return ConsoleDriver.BufferHeight; }
607                         [MonoLimitation ("Implemented only on Windows")]
608                         set { ConsoleDriver.BufferHeight = value; }
609                 }
610
611                 public static int BufferWidth {
612                         get { return ConsoleDriver.BufferWidth; }
613                         [MonoLimitation ("Implemented only on Windows")]
614                         set { ConsoleDriver.BufferWidth = value; }
615                 }
616
617                 [MonoLimitation ("Implemented only on Windows")]
618                 public static bool CapsLock {
619                         get { return ConsoleDriver.CapsLock; }
620                 }
621
622                 public static int CursorLeft {
623                         get { return ConsoleDriver.CursorLeft; }
624                         set { ConsoleDriver.CursorLeft = value; }
625                 }
626
627                 public static int CursorTop {
628                         get { return ConsoleDriver.CursorTop; }
629                         set { ConsoleDriver.CursorTop = value; }
630                 }
631
632                 public static int CursorSize {
633                         get { return ConsoleDriver.CursorSize; }
634                         set { ConsoleDriver.CursorSize = value; }
635                 }
636
637                 public static bool CursorVisible {
638                         get { return ConsoleDriver.CursorVisible; }
639                         set { ConsoleDriver.CursorVisible = value; }
640                 }
641
642                 public static ConsoleColor ForegroundColor {
643                         get { return ConsoleDriver.ForegroundColor; }
644                         set { ConsoleDriver.ForegroundColor = value; }
645                 }
646
647                 public static bool KeyAvailable {
648                         get { return ConsoleDriver.KeyAvailable; }
649                 }
650
651                 public static int LargestWindowHeight {
652                         get { return ConsoleDriver.LargestWindowHeight; }
653                 }
654
655                 public static int LargestWindowWidth {
656                         get { return ConsoleDriver.LargestWindowWidth; }
657                 }
658
659                 [MonoLimitation ("Only works on windows")]
660                 public static bool NumberLock {
661                         get { return ConsoleDriver.NumberLock; }
662                 }
663
664                 public static string Title {
665                         get { return ConsoleDriver.Title; }
666                         set { ConsoleDriver.Title = value; }
667                 }
668
669                 public static bool TreatControlCAsInput {
670                         get { return ConsoleDriver.TreatControlCAsInput; }
671                         set { ConsoleDriver.TreatControlCAsInput = value; }
672                 }
673
674                 [MonoLimitation ("Only works on windows")]
675                 public static int WindowHeight {
676                         get { return ConsoleDriver.WindowHeight; }
677                         set { ConsoleDriver.WindowHeight = value; }
678                 }
679
680                 [MonoLimitation ("Only works on windows")]
681                 public static int WindowLeft {
682                         get { return ConsoleDriver.WindowLeft; }
683                         set { ConsoleDriver.WindowLeft = value; }
684                 }
685
686                 [MonoLimitation ("Only works on windows")]
687                 public static int WindowTop {
688                         get { return ConsoleDriver.WindowTop; }
689                         set { ConsoleDriver.WindowTop = value; }
690                 }
691
692                 [MonoLimitation ("Only works on windows")]
693                 public static int WindowWidth {
694                         get { return ConsoleDriver.WindowWidth; }
695                         set { ConsoleDriver.WindowWidth = value; }
696                 }
697
698                 public static void Beep ()
699                 {
700                         Beep (1000, 500);
701                 }
702
703                 public static void Beep (int frequency, int duration)
704                 {
705                         if (frequency < 37 || frequency > 32767)
706                                 throw new ArgumentOutOfRangeException ("frequency");
707
708                         if (duration <= 0)
709                                 throw new ArgumentOutOfRangeException ("duration");
710
711                         ConsoleDriver.Beep (frequency, duration);
712                 }
713
714                 public static void Clear ()
715                 {
716                         ConsoleDriver.Clear ();
717                 }
718
719                 [MonoLimitation ("Implemented only on Windows")]
720                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
721                                                 int targetLeft, int targetTop)
722                 {
723                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
724                 }
725
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)
730                 {
731                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
732                                                         sourceChar, sourceForeColor, sourceBackColor);
733                 }
734
735                 public static ConsoleKeyInfo ReadKey ()
736                 {
737                         return ReadKey (false);
738                 }
739
740                 public static ConsoleKeyInfo ReadKey (bool intercept)
741                 {
742                         return ConsoleDriver.ReadKey (intercept);
743                 }
744
745                 public static void ResetColor ()
746                 {
747                         ConsoleDriver.ResetColor ();
748                 }
749
750                 [MonoLimitation ("Only works on windows")]
751                 public static void SetBufferSize (int width, int height)
752                 {
753                         ConsoleDriver.SetBufferSize (width, height);
754                 }
755
756                 public static void SetCursorPosition (int left, int top)
757                 {
758                         ConsoleDriver.SetCursorPosition (left, top);
759                 }
760
761                 public static void SetWindowPosition (int left, int top)
762                 {
763                         ConsoleDriver.SetWindowPosition (left, top);
764                 }
765
766                 public static void SetWindowSize (int width, int height)
767                 {
768                         ConsoleDriver.SetWindowSize (width, height);
769                 }
770
771                 static ConsoleCancelEventHandler cancel_event;
772                 public static event ConsoleCancelEventHandler CancelKeyPress {
773                         add {
774                                 if (ConsoleDriver.Initialized == false)
775                                         ConsoleDriver.Init ();
776
777                                 cancel_event += value;
778
779                                 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
780                                         WindowsConsole.AddCtrlHandler();
781                         }
782                         remove {
783                                 if (ConsoleDriver.Initialized == false)
784                                         ConsoleDriver.Init ();
785
786                                 cancel_event -= value;
787
788                                 if (cancel_event == null && Environment.IsRunningOnWindows)
789                                 {
790                                         // Need to remove our hook if there's nothing left in the event
791                                         if (WindowsConsole.ctrlHandlerAdded)
792                                                 WindowsConsole.RemoveCtrlHandler();
793                                 }
794                         }
795                 }
796
797                 delegate void InternalCancelHandler ();
798                 
799 #pragma warning disable 414
800                 //
801                 // Used by console-io.c
802                 //
803                 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
804 #pragma warning restore 414             
805
806                 internal static void DoConsoleCancelEvent ()
807                 {
808                         bool exit = true;
809                         if (cancel_event != null) {
810                                 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
811                                 Delegate [] delegates = cancel_event.GetInvocationList ();
812                                 foreach (ConsoleCancelEventHandler d in delegates){
813                                         try {
814                                                 // Sender is always null here.
815                                                 d (null, args);
816                                         } catch {} // Ignore any exception.
817                                 }
818                                 exit = !args.Cancel;
819                         }
820
821                         if (exit)
822                                 Environment.Exit (58);
823                 }
824 #endif
825         }
826 }
827