Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[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                 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
221                 {
222 #if MOONLIGHT
223                         if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
224                                 return new NullStream ();
225 #endif
226                         try {
227                                 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
228                         } catch (IOException) {
229                                 return new NullStream ();
230                         }
231                 }
232
233                 public static Stream OpenStandardError ()
234                 {
235                         return OpenStandardError (0);
236                 }
237
238                 // calling any FileStream constructor with a handle normally
239                 // requires permissions UnmanagedCode permissions. In this 
240                 // case we assert this permission so the console can be used
241                 // in partial trust (i.e. without having UnmanagedCode).
242                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
243                 public static Stream OpenStandardError (int bufferSize)
244                 {
245                         return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
246                 }
247
248                 public static Stream OpenStandardInput ()
249                 {
250                         return OpenStandardInput (0);
251                 }
252
253                 // calling any FileStream constructor with a handle normally
254                 // requires permissions UnmanagedCode permissions. In this 
255                 // case we assert this permission so the console can be used
256                 // in partial trust (i.e. without having UnmanagedCode).
257                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
258                 public static Stream OpenStandardInput (int bufferSize)
259                 {
260                         return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
261                 }
262
263                 public static Stream OpenStandardOutput ()
264                 {
265                         return OpenStandardOutput (0);
266                 }
267
268                 // calling any FileStream constructor with a handle normally
269                 // requires permissions UnmanagedCode permissions. In this 
270                 // case we assert this permission so the console can be used
271                 // in partial trust (i.e. without having UnmanagedCode).
272                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
273                 public static Stream OpenStandardOutput (int bufferSize)
274                 {
275                         return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
276                 }
277
278                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
279                 public static void SetError (TextWriter newError)
280                 {
281                         if (newError == null)
282                                 throw new ArgumentNullException ("newError");
283
284                         stderr = newError;
285                 }
286
287                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
288                 public static void SetIn (TextReader newIn)
289                 {
290                         if (newIn == null)
291                                 throw new ArgumentNullException ("newIn");
292
293                         stdin = newIn;
294                 }
295
296                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
297                 public static void SetOut (TextWriter newOut)
298                 {
299                         if (newOut == null)
300                                 throw new ArgumentNullException ("newOut");
301
302                         stdout = newOut;
303                 }
304
305                 public static void Write (bool value)
306                 {
307                         stdout.Write (value);
308                 }
309
310                 public static void Write (char value)
311                 {
312                         stdout.Write (value);
313                 }
314
315                 public static void Write (char[] buffer)
316                 {
317                         stdout.Write (buffer);
318                 }
319
320                 public static void Write (decimal value)
321                 {
322                         stdout.Write (value);
323                 }
324                 
325                 public static void Write (double value)
326                 {
327                         stdout.Write (value);
328                 }
329
330                 public static void Write (int value)
331                 {
332                         stdout.Write (value);
333                 }
334
335                 public static void Write (long value)
336                 {
337                         stdout.Write (value);
338                 }
339
340                 public static void Write (object value)
341                 {
342                         stdout.Write (value);
343                 }
344
345                 public static void Write (float value)
346                 {
347                         stdout.Write (value);
348                 }
349
350                 public static void Write (string value)
351                 {
352                         stdout.Write (value);
353                 }
354
355                 [CLSCompliant (false)]
356                 public static void Write (uint value)
357                 {
358                         stdout.Write (value);
359                 }
360
361                 [CLSCompliant (false)]
362                 public static void Write (ulong value)
363                 {
364                         stdout.Write (value);
365                 }
366
367                 public static void Write (string format, object arg0)
368                 {
369                         stdout.Write (format, arg0);
370                 }
371
372                 public static void Write (string format, params object[] arg)
373                 {
374                         if (arg == null)
375                                 stdout.Write (format);
376                         else
377                                 stdout.Write (format, arg);
378                 }
379
380                 public static void Write (char[] buffer, int index, int count)
381                 {
382                         stdout.Write (buffer, index, count);
383                 }
384
385                 public static void Write (string format, object arg0, object arg1)
386                 {
387                         stdout.Write (format, arg0, arg1);
388                 }
389
390                 public static void Write (string format, object arg0, object arg1, object arg2 )
391                 {
392                         stdout.Write (format, arg0, arg1, arg2);
393                 }
394
395                 [CLSCompliant (false)]
396                 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
397                 {
398                         ArgIterator iter = new ArgIterator (__arglist);
399                         int argCount = iter.GetRemainingCount();
400
401                         object[] args = new object [argCount + 4];
402                         args [0] = arg0;
403                         args [1] = arg1;
404                         args [2] = arg2;
405                         args [3] = arg3;
406                         for (int i = 0; i < argCount; i++) {
407                                 TypedReference typedRef = iter.GetNextArg ();
408                                 args [i + 4] = TypedReference.ToObject (typedRef);
409                         }
410
411                         stdout.Write (String.Format (format, args));
412                 }
413
414                 public static void WriteLine ()
415                 {
416                         stdout.WriteLine ();
417                 }
418
419                 public static void WriteLine (bool value)
420                 {
421                         stdout.WriteLine (value);
422                 }
423
424                 public static void WriteLine (char value)
425                 {
426                         stdout.WriteLine (value);
427                 }
428
429                 public static void WriteLine (char[] buffer)
430                 {
431                         stdout.WriteLine (buffer);
432                 }
433
434                 public static void WriteLine (decimal value)
435                 {
436                         stdout.WriteLine (value);
437                 }
438
439                 public static void WriteLine (double value)
440                 {
441                         stdout.WriteLine (value);
442                 }
443
444                 public static void WriteLine (int value)
445                 {
446                         stdout.WriteLine (value);
447                 }
448
449                 public static void WriteLine (long value)
450                 {
451                         stdout.WriteLine (value);
452                 }
453
454                 public static void WriteLine (object value)
455                 {
456                         stdout.WriteLine (value);
457                 }
458
459                 public static void WriteLine (float value)
460                 {
461                         stdout.WriteLine (value);
462                 }
463
464                 public static void WriteLine (string value)
465                 {
466                         stdout.WriteLine (value);
467                 }
468
469                 [CLSCompliant (false)]
470                 public static void WriteLine (uint value)
471                 {
472                         stdout.WriteLine (value);
473                 }
474
475                 [CLSCompliant (false)]
476                 public static void WriteLine (ulong value)
477                 {
478                         stdout.WriteLine (value);
479                 }
480
481                 public static void WriteLine (string format, object arg0)
482                 {
483                         stdout.WriteLine (format, arg0);
484                 }
485
486                 public static void WriteLine (string format, params object[] arg)
487                 {
488                         if (arg == null)
489                                 stdout.WriteLine (format);
490                         else
491                                 stdout.WriteLine (format, arg);
492                 }
493
494                 public static void WriteLine (char[] buffer, int index, int count)
495                 {
496                         stdout.WriteLine (buffer, index, count);
497                 }
498
499                 public static void WriteLine (string format, object arg0, object arg1)
500                 {
501                         stdout.WriteLine (format, arg0, arg1);
502                 }
503
504                 public static void WriteLine (string format, object arg0, object arg1, object arg2)
505                 {
506                         stdout.WriteLine (format, arg0, arg1, arg2);
507                 }
508
509                 [CLSCompliant (false)]
510                 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
511                 {
512                         ArgIterator iter = new ArgIterator (__arglist);
513                         int argCount = iter.GetRemainingCount();
514
515                         object[] args = new object [argCount + 4];
516                         args [0] = arg0;
517                         args [1] = arg1;
518                         args [2] = arg2;
519                         args [3] = arg3;
520                         for (int i = 0; i < argCount; i++) {
521                                 TypedReference typedRef = iter.GetNextArg ();
522                                 args [i + 4] = TypedReference.ToObject (typedRef);
523                         }
524
525                         stdout.WriteLine (String.Format (format, args));
526                 }
527
528 #if !NET_2_1
529                 public static int Read ()
530                 {
531                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
532                                 return ConsoleDriver.Read ();
533                         } else {
534                                 return stdin.Read ();
535                         }
536                 }
537
538                 public static string ReadLine ()
539                 {
540                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
541                                 return ConsoleDriver.ReadLine ();
542                         } else {
543                                 return stdin.ReadLine ();
544                         }
545                 }
546 #else
547                 public static int Read ()
548                 {
549                         return stdin.Read ();
550                 }
551
552                 public static string ReadLine ()
553                 {
554                         return stdin.ReadLine ();
555                 }
556
557 #endif
558
559 #if !NET_2_1
560                 // FIXME: Console should use these encodings when changed
561                 static Encoding inputEncoding;
562                 static Encoding outputEncoding;
563
564                 public static Encoding InputEncoding {
565                         get { return inputEncoding; }
566                         set {
567                                 inputEncoding = value;
568                                 SetupStreams (inputEncoding, outputEncoding);
569                         }
570                 }
571
572                 public static Encoding OutputEncoding {
573                         get { return outputEncoding; }
574                         set {
575                                 outputEncoding = value;
576                                 SetupStreams (inputEncoding, outputEncoding);
577                         }
578                 }
579
580                 public static ConsoleColor BackgroundColor {
581                         get { return ConsoleDriver.BackgroundColor; }
582                         set { ConsoleDriver.BackgroundColor = value; }
583                 }
584
585                 public static int BufferHeight {
586                         get { return ConsoleDriver.BufferHeight; }
587                         [MonoLimitation ("Implemented only on Windows")]
588                         set { ConsoleDriver.BufferHeight = value; }
589                 }
590
591                 public static int BufferWidth {
592                         get { return ConsoleDriver.BufferWidth; }
593                         [MonoLimitation ("Implemented only on Windows")]
594                         set { ConsoleDriver.BufferWidth = value; }
595                 }
596
597                 [MonoLimitation ("Implemented only on Windows")]
598                 public static bool CapsLock {
599                         get { return ConsoleDriver.CapsLock; }
600                 }
601
602                 public static int CursorLeft {
603                         get { return ConsoleDriver.CursorLeft; }
604                         set { ConsoleDriver.CursorLeft = value; }
605                 }
606
607                 public static int CursorTop {
608                         get { return ConsoleDriver.CursorTop; }
609                         set { ConsoleDriver.CursorTop = value; }
610                 }
611
612                 public static int CursorSize {
613                         get { return ConsoleDriver.CursorSize; }
614                         set { ConsoleDriver.CursorSize = value; }
615                 }
616
617                 public static bool CursorVisible {
618                         get { return ConsoleDriver.CursorVisible; }
619                         set { ConsoleDriver.CursorVisible = value; }
620                 }
621
622                 public static ConsoleColor ForegroundColor {
623                         get { return ConsoleDriver.ForegroundColor; }
624                         set { ConsoleDriver.ForegroundColor = value; }
625                 }
626
627                 public static bool KeyAvailable {
628                         get { return ConsoleDriver.KeyAvailable; }
629                 }
630
631                 public static int LargestWindowHeight {
632                         get { return ConsoleDriver.LargestWindowHeight; }
633                 }
634
635                 public static int LargestWindowWidth {
636                         get { return ConsoleDriver.LargestWindowWidth; }
637                 }
638
639                 [MonoLimitation ("Only works on windows")]
640                 public static bool NumberLock {
641                         get { return ConsoleDriver.NumberLock; }
642                 }
643
644                 public static string Title {
645                         get { return ConsoleDriver.Title; }
646                         set { ConsoleDriver.Title = value; }
647                 }
648
649                 public static bool TreatControlCAsInput {
650                         get { return ConsoleDriver.TreatControlCAsInput; }
651                         set { ConsoleDriver.TreatControlCAsInput = value; }
652                 }
653
654                 [MonoLimitation ("Only works on windows")]
655                 public static int WindowHeight {
656                         get { return ConsoleDriver.WindowHeight; }
657                         set { ConsoleDriver.WindowHeight = value; }
658                 }
659
660                 [MonoLimitation ("Only works on windows")]
661                 public static int WindowLeft {
662                         get { return ConsoleDriver.WindowLeft; }
663                         set { ConsoleDriver.WindowLeft = value; }
664                 }
665
666                 [MonoLimitation ("Only works on windows")]
667                 public static int WindowTop {
668                         get { return ConsoleDriver.WindowTop; }
669                         set { ConsoleDriver.WindowTop = value; }
670                 }
671
672                 [MonoLimitation ("Only works on windows")]
673                 public static int WindowWidth {
674                         get { return ConsoleDriver.WindowWidth; }
675                         set { ConsoleDriver.WindowWidth = value; }
676                 }
677
678 #if NET_4_5
679                 public static bool IsErrorRedirected {
680                         get {
681                                 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
682                         }
683                 }
684
685                 public static bool IsOutputRedirected {
686                         get {
687                                 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
688                         }
689                 }
690
691                 public static bool IsInputRedirected {
692                         get {
693                                 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
694                         }
695                 }
696 #endif
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