Handle ENETDOWN error if defined.
[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 && !MOBILE
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 && !MOBILE
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                         try {
223                                 return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
224                         } catch (IOException) {
225                                 return new NullStream ();
226                         }
227                 }
228
229                 public static Stream OpenStandardError ()
230                 {
231                         return OpenStandardError (0);
232                 }
233
234                 // calling any FileStream constructor with a handle normally
235                 // requires permissions UnmanagedCode permissions. In this 
236                 // case we assert this permission so the console can be used
237                 // in partial trust (i.e. without having UnmanagedCode).
238                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
239                 public static Stream OpenStandardError (int bufferSize)
240                 {
241                         return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
242                 }
243
244                 public static Stream OpenStandardInput ()
245                 {
246                         return OpenStandardInput (0);
247                 }
248
249                 // calling any FileStream constructor with a handle normally
250                 // requires permissions UnmanagedCode permissions. In this 
251                 // case we assert this permission so the console can be used
252                 // in partial trust (i.e. without having UnmanagedCode).
253                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
254                 public static Stream OpenStandardInput (int bufferSize)
255                 {
256                         return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
257                 }
258
259                 public static Stream OpenStandardOutput ()
260                 {
261                         return OpenStandardOutput (0);
262                 }
263
264                 // calling any FileStream constructor with a handle normally
265                 // requires permissions UnmanagedCode permissions. In this 
266                 // case we assert this permission so the console can be used
267                 // in partial trust (i.e. without having UnmanagedCode).
268                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
269                 public static Stream OpenStandardOutput (int bufferSize)
270                 {
271                         return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
272                 }
273
274                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
275                 public static void SetError (TextWriter newError)
276                 {
277                         if (newError == null)
278                                 throw new ArgumentNullException ("newError");
279
280                         stderr = newError;
281                 }
282
283                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
284                 public static void SetIn (TextReader newIn)
285                 {
286                         if (newIn == null)
287                                 throw new ArgumentNullException ("newIn");
288
289                         stdin = newIn;
290                 }
291
292                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
293                 public static void SetOut (TextWriter newOut)
294                 {
295                         if (newOut == null)
296                                 throw new ArgumentNullException ("newOut");
297
298                         stdout = newOut;
299                 }
300
301                 public static void Write (bool value)
302                 {
303                         stdout.Write (value);
304                 }
305
306                 public static void Write (char value)
307                 {
308                         stdout.Write (value);
309                 }
310
311                 public static void Write (char[] buffer)
312                 {
313                         stdout.Write (buffer);
314                 }
315
316                 public static void Write (decimal value)
317                 {
318                         stdout.Write (value);
319                 }
320                 
321                 public static void Write (double value)
322                 {
323                         stdout.Write (value);
324                 }
325
326                 public static void Write (int value)
327                 {
328                         stdout.Write (value);
329                 }
330
331                 public static void Write (long value)
332                 {
333                         stdout.Write (value);
334                 }
335
336                 public static void Write (object value)
337                 {
338                         stdout.Write (value);
339                 }
340
341                 public static void Write (float value)
342                 {
343                         stdout.Write (value);
344                 }
345
346                 public static void Write (string value)
347                 {
348                         stdout.Write (value);
349                 }
350
351                 [CLSCompliant (false)]
352                 public static void Write (uint value)
353                 {
354                         stdout.Write (value);
355                 }
356
357                 [CLSCompliant (false)]
358                 public static void Write (ulong value)
359                 {
360                         stdout.Write (value);
361                 }
362
363                 public static void Write (string format, object arg0)
364                 {
365                         stdout.Write (format, arg0);
366                 }
367
368                 public static void Write (string format, params object[] arg)
369                 {
370                         if (arg == null)
371                                 stdout.Write (format);
372                         else
373                                 stdout.Write (format, arg);
374                 }
375
376                 public static void Write (char[] buffer, int index, int count)
377                 {
378                         stdout.Write (buffer, index, count);
379                 }
380
381                 public static void Write (string format, object arg0, object arg1)
382                 {
383                         stdout.Write (format, arg0, arg1);
384                 }
385
386                 public static void Write (string format, object arg0, object arg1, object arg2 )
387                 {
388                         stdout.Write (format, arg0, arg1, arg2);
389                 }
390
391                 [CLSCompliant (false)]
392                 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
393                 {
394                         ArgIterator iter = new ArgIterator (__arglist);
395                         int argCount = iter.GetRemainingCount();
396
397                         object[] args = new object [argCount + 4];
398                         args [0] = arg0;
399                         args [1] = arg1;
400                         args [2] = arg2;
401                         args [3] = arg3;
402                         for (int i = 0; i < argCount; i++) {
403                                 TypedReference typedRef = iter.GetNextArg ();
404                                 args [i + 4] = TypedReference.ToObject (typedRef);
405                         }
406
407                         stdout.Write (String.Format (format, args));
408                 }
409
410                 public static void WriteLine ()
411                 {
412                         stdout.WriteLine ();
413                 }
414
415                 public static void WriteLine (bool value)
416                 {
417                         stdout.WriteLine (value);
418                 }
419
420                 public static void WriteLine (char value)
421                 {
422                         stdout.WriteLine (value);
423                 }
424
425                 public static void WriteLine (char[] buffer)
426                 {
427                         stdout.WriteLine (buffer);
428                 }
429
430                 public static void WriteLine (decimal value)
431                 {
432                         stdout.WriteLine (value);
433                 }
434
435                 public static void WriteLine (double value)
436                 {
437                         stdout.WriteLine (value);
438                 }
439
440                 public static void WriteLine (int value)
441                 {
442                         stdout.WriteLine (value);
443                 }
444
445                 public static void WriteLine (long value)
446                 {
447                         stdout.WriteLine (value);
448                 }
449
450                 public static void WriteLine (object value)
451                 {
452                         stdout.WriteLine (value);
453                 }
454
455                 public static void WriteLine (float value)
456                 {
457                         stdout.WriteLine (value);
458                 }
459
460                 public static void WriteLine (string value)
461                 {
462                         stdout.WriteLine (value);
463                 }
464
465                 [CLSCompliant (false)]
466                 public static void WriteLine (uint value)
467                 {
468                         stdout.WriteLine (value);
469                 }
470
471                 [CLSCompliant (false)]
472                 public static void WriteLine (ulong value)
473                 {
474                         stdout.WriteLine (value);
475                 }
476
477                 public static void WriteLine (string format, object arg0)
478                 {
479                         stdout.WriteLine (format, arg0);
480                 }
481
482                 public static void WriteLine (string format, params object[] arg)
483                 {
484                         if (arg == null)
485                                 stdout.WriteLine (format);
486                         else
487                                 stdout.WriteLine (format, arg);
488                 }
489
490                 public static void WriteLine (char[] buffer, int index, int count)
491                 {
492                         stdout.WriteLine (buffer, index, count);
493                 }
494
495                 public static void WriteLine (string format, object arg0, object arg1)
496                 {
497                         stdout.WriteLine (format, arg0, arg1);
498                 }
499
500                 public static void WriteLine (string format, object arg0, object arg1, object arg2)
501                 {
502                         stdout.WriteLine (format, arg0, arg1, arg2);
503                 }
504
505                 [CLSCompliant (false)]
506                 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
507                 {
508                         ArgIterator iter = new ArgIterator (__arglist);
509                         int argCount = iter.GetRemainingCount();
510
511                         object[] args = new object [argCount + 4];
512                         args [0] = arg0;
513                         args [1] = arg1;
514                         args [2] = arg2;
515                         args [3] = arg3;
516                         for (int i = 0; i < argCount; i++) {
517                                 TypedReference typedRef = iter.GetNextArg ();
518                                 args [i + 4] = TypedReference.ToObject (typedRef);
519                         }
520
521                         stdout.WriteLine (String.Format (format, args));
522                 }
523
524 #if !NET_2_1
525                 public static int Read ()
526                 {
527                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
528                                 return ConsoleDriver.Read ();
529                         } else {
530                                 return stdin.Read ();
531                         }
532                 }
533
534                 public static string ReadLine ()
535                 {
536                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
537                                 return ConsoleDriver.ReadLine ();
538                         } else {
539                                 return stdin.ReadLine ();
540                         }
541                 }
542 #else
543                 public static int Read ()
544                 {
545                         return stdin.Read ();
546                 }
547
548                 public static string ReadLine ()
549                 {
550                         return stdin.ReadLine ();
551                 }
552
553 #endif
554
555 #if !NET_2_1
556                 // FIXME: Console should use these encodings when changed
557                 static Encoding inputEncoding;
558                 static Encoding outputEncoding;
559
560                 public static Encoding InputEncoding {
561                         get { return inputEncoding; }
562                         set {
563                                 inputEncoding = value;
564                                 SetupStreams (inputEncoding, outputEncoding);
565                         }
566                 }
567
568                 public static Encoding OutputEncoding {
569                         get { return outputEncoding; }
570                         set {
571                                 outputEncoding = value;
572                                 SetupStreams (inputEncoding, outputEncoding);
573                         }
574                 }
575
576                 public static ConsoleColor BackgroundColor {
577                         get { return ConsoleDriver.BackgroundColor; }
578                         set { ConsoleDriver.BackgroundColor = value; }
579                 }
580
581                 public static int BufferHeight {
582                         get { return ConsoleDriver.BufferHeight; }
583                         [MonoLimitation ("Implemented only on Windows")]
584                         set { ConsoleDriver.BufferHeight = value; }
585                 }
586
587                 public static int BufferWidth {
588                         get { return ConsoleDriver.BufferWidth; }
589                         [MonoLimitation ("Implemented only on Windows")]
590                         set { ConsoleDriver.BufferWidth = value; }
591                 }
592
593                 [MonoLimitation ("Implemented only on Windows")]
594                 public static bool CapsLock {
595                         get { return ConsoleDriver.CapsLock; }
596                 }
597
598                 public static int CursorLeft {
599                         get { return ConsoleDriver.CursorLeft; }
600                         set { ConsoleDriver.CursorLeft = value; }
601                 }
602
603                 public static int CursorTop {
604                         get { return ConsoleDriver.CursorTop; }
605                         set { ConsoleDriver.CursorTop = value; }
606                 }
607
608                 public static int CursorSize {
609                         get { return ConsoleDriver.CursorSize; }
610                         set { ConsoleDriver.CursorSize = value; }
611                 }
612
613                 public static bool CursorVisible {
614                         get { return ConsoleDriver.CursorVisible; }
615                         set { ConsoleDriver.CursorVisible = value; }
616                 }
617
618                 public static ConsoleColor ForegroundColor {
619                         get { return ConsoleDriver.ForegroundColor; }
620                         set { ConsoleDriver.ForegroundColor = value; }
621                 }
622
623                 public static bool KeyAvailable {
624                         get { return ConsoleDriver.KeyAvailable; }
625                 }
626
627                 public static int LargestWindowHeight {
628                         get { return ConsoleDriver.LargestWindowHeight; }
629                 }
630
631                 public static int LargestWindowWidth {
632                         get { return ConsoleDriver.LargestWindowWidth; }
633                 }
634
635                 [MonoLimitation ("Only works on windows")]
636                 public static bool NumberLock {
637                         get { return ConsoleDriver.NumberLock; }
638                 }
639
640                 public static string Title {
641                         get { return ConsoleDriver.Title; }
642                         set { ConsoleDriver.Title = value; }
643                 }
644
645                 public static bool TreatControlCAsInput {
646                         get { return ConsoleDriver.TreatControlCAsInput; }
647                         set { ConsoleDriver.TreatControlCAsInput = value; }
648                 }
649
650                 [MonoLimitation ("Only works on windows")]
651                 public static int WindowHeight {
652                         get { return ConsoleDriver.WindowHeight; }
653                         set { ConsoleDriver.WindowHeight = value; }
654                 }
655
656                 [MonoLimitation ("Only works on windows")]
657                 public static int WindowLeft {
658                         get { return ConsoleDriver.WindowLeft; }
659                         set { ConsoleDriver.WindowLeft = value; }
660                 }
661
662                 [MonoLimitation ("Only works on windows")]
663                 public static int WindowTop {
664                         get { return ConsoleDriver.WindowTop; }
665                         set { ConsoleDriver.WindowTop = value; }
666                 }
667
668                 [MonoLimitation ("Only works on windows")]
669                 public static int WindowWidth {
670                         get { return ConsoleDriver.WindowWidth; }
671                         set { ConsoleDriver.WindowWidth = value; }
672                 }
673
674 #if NET_4_5
675                 public static bool IsErrorRedirected {
676                         get {
677                                 return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
678                         }
679                 }
680
681                 public static bool IsOutputRedirected {
682                         get {
683                                 return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
684                         }
685                 }
686
687                 public static bool IsInputRedirected {
688                         get {
689                                 return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
690                         }
691                 }
692 #endif
693
694                 public static void Beep ()
695                 {
696                         Beep (1000, 500);
697                 }
698
699                 public static void Beep (int frequency, int duration)
700                 {
701                         if (frequency < 37 || frequency > 32767)
702                                 throw new ArgumentOutOfRangeException ("frequency");
703
704                         if (duration <= 0)
705                                 throw new ArgumentOutOfRangeException ("duration");
706
707                         ConsoleDriver.Beep (frequency, duration);
708                 }
709
710                 public static void Clear ()
711                 {
712                         ConsoleDriver.Clear ();
713                 }
714
715                 [MonoLimitation ("Implemented only on Windows")]
716                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
717                                                 int targetLeft, int targetTop)
718                 {
719                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
720                 }
721
722                 [MonoLimitation ("Implemented only on Windows")]
723                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
724                                                 int targetLeft, int targetTop, Char sourceChar,
725                                                 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
726                 {
727                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
728                                                         sourceChar, sourceForeColor, sourceBackColor);
729                 }
730
731                 public static ConsoleKeyInfo ReadKey ()
732                 {
733                         return ReadKey (false);
734                 }
735
736                 public static ConsoleKeyInfo ReadKey (bool intercept)
737                 {
738                         return ConsoleDriver.ReadKey (intercept);
739                 }
740
741                 public static void ResetColor ()
742                 {
743                         ConsoleDriver.ResetColor ();
744                 }
745
746                 [MonoLimitation ("Only works on windows")]
747                 public static void SetBufferSize (int width, int height)
748                 {
749                         ConsoleDriver.SetBufferSize (width, height);
750                 }
751
752                 public static void SetCursorPosition (int left, int top)
753                 {
754                         ConsoleDriver.SetCursorPosition (left, top);
755                 }
756
757                 public static void SetWindowPosition (int left, int top)
758                 {
759                         ConsoleDriver.SetWindowPosition (left, top);
760                 }
761
762                 public static void SetWindowSize (int width, int height)
763                 {
764                         ConsoleDriver.SetWindowSize (width, height);
765                 }
766
767                 static ConsoleCancelEventHandler cancel_event;
768                 public static event ConsoleCancelEventHandler CancelKeyPress {
769                         add {
770                                 if (ConsoleDriver.Initialized == false)
771                                         ConsoleDriver.Init ();
772
773                                 cancel_event += value;
774
775                                 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
776                                         WindowsConsole.AddCtrlHandler();
777                         }
778                         remove {
779                                 if (ConsoleDriver.Initialized == false)
780                                         ConsoleDriver.Init ();
781
782                                 cancel_event -= value;
783
784                                 if (cancel_event == null && Environment.IsRunningOnWindows)
785                                 {
786                                         // Need to remove our hook if there's nothing left in the event
787                                         if (WindowsConsole.ctrlHandlerAdded)
788                                                 WindowsConsole.RemoveCtrlHandler();
789                                 }
790                         }
791                 }
792
793                 delegate void InternalCancelHandler ();
794                 
795 #pragma warning disable 414
796                 //
797                 // Used by console-io.c
798                 //
799                 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
800 #pragma warning restore 414             
801
802                 internal static void DoConsoleCancelEvent ()
803                 {
804                         bool exit = true;
805                         if (cancel_event != null) {
806                                 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
807                                 Delegate [] delegates = cancel_event.GetInvocationList ();
808                                 foreach (ConsoleCancelEventHandler d in delegates){
809                                         try {
810                                                 // Sender is always null here.
811                                                 d (null, args);
812                                         } catch {} // Ignore any exception.
813                                 }
814                                 exit = !args.Cancel;
815                         }
816
817                         if (exit)
818                                 Environment.Exit (58);
819                 }
820 #endif
821         }
822 }
823