[corlib] Remove local variables inadvertently overriding class variables.
[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 // Copyright 2013 Xamarin Inc. (http://www.xamarin.com)
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 partial 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                 static Console ()
98                 {
99                         if (Environment.IsRunningOnWindows) {
100                                 //
101                                 // On Windows, follow the Windows tradition
102                                 //
103 #if NET_2_1
104                                 // should never happen since Moonlight does not run on windows
105                                 inputEncoding = outputEncoding = Encoding.Default;
106 #else                   
107                                 try {
108                                         inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
109                                         outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
110                                         // ArgumentException and NotSupportedException can be thrown as well
111                                 } catch {
112                                         // FIXME: I18N assemblies are not available when compiling mcs
113                                         // Use Latin 1 as it is fast and UTF-8 is never used as console code page
114                                         inputEncoding = outputEncoding = Encoding.Default;
115                                 }
116 #endif
117                         } else {
118                                 //
119                                 // On Unix systems (128), do not output the
120                                 // UTF-8 ZWNBSP (zero-width non-breaking space).
121                                 //
122                                 int code_page = 0;
123                                 EncodingHelper.InternalCodePage (ref code_page);
124
125                                 if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
126                                         || ((code_page & 0x10000000) != 0)))
127                                         inputEncoding = outputEncoding = EncodingHelper.UTF8Unmarked;
128                                 else
129                                         inputEncoding = outputEncoding = Encoding.Default;
130                         }
131
132                         SetupStreams (inputEncoding, outputEncoding);
133                 }
134
135                 static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding)
136                 {
137 #if !NET_2_1
138                         if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
139                                 stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
140                                 stdout = TextWriter.Synchronized (new CStreamWriter (OpenStandardOutput (0), outputEncoding, true) { AutoFlush = true });
141                                 stderr = TextWriter.Synchronized (new CStreamWriter (OpenStandardError (0), outputEncoding, true) { AutoFlush = true });
142                         } else
143 #endif
144                         {
145                                 stdin = TextReader.Synchronized (new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding));
146
147 #if MONOTOUCH
148                                 stdout = new NSLogWriter ();
149                                 stderr = new NSLogWriter ();
150 #else
151                                 stdout = TextWriter.Synchronized (new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding) { AutoFlush = true });
152                                 stderr = TextWriter.Synchronized (new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding) { AutoFlush = true });
153
154 #if MONODROID
155                                 if (LogcatTextWriter.IsRunningOnAndroid ()) {
156                                         stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout));
157                                         stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr));
158                                 }
159 #endif // MONODROID
160 #endif // MONOTOUCH
161                         }
162
163                         GC.SuppressFinalize (stdout);
164                         GC.SuppressFinalize (stderr);
165                         GC.SuppressFinalize (stdin);
166                 }
167
168                 public static TextWriter Error {
169                         get {
170                                 return stderr;
171                         }
172                 }
173
174                 public static TextWriter Out {
175                         get {
176                                 return stdout;
177                         }
178                 }
179
180                 public static TextReader In {
181                         get {
182                                 return stdin;
183                         }
184                 }
185
186                 private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
187                 {
188                         try {
189                                 // TODO: Should use __ConsoleStream from reference sources
190                                 return new FileStream (handle, access, false, bufferSize, false, true);
191                         } catch (IOException) {
192                                 return Stream.Null;
193                         }
194                 }
195
196                 public static Stream OpenStandardError ()
197                 {
198                         return OpenStandardError (0);
199                 }
200
201                 // calling any FileStream constructor with a handle normally
202                 // requires permissions UnmanagedCode permissions. In this 
203                 // case we assert this permission so the console can be used
204                 // in partial trust (i.e. without having UnmanagedCode).
205                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
206                 public static Stream OpenStandardError (int bufferSize)
207                 {
208                         return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
209                 }
210
211                 public static Stream OpenStandardInput ()
212                 {
213                         return OpenStandardInput (0);
214                 }
215
216                 // calling any FileStream constructor with a handle normally
217                 // requires permissions UnmanagedCode permissions. In this 
218                 // case we assert this permission so the console can be used
219                 // in partial trust (i.e. without having UnmanagedCode).
220                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
221                 public static Stream OpenStandardInput (int bufferSize)
222                 {
223                         return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
224                 }
225
226                 public static Stream OpenStandardOutput ()
227                 {
228                         return OpenStandardOutput (0);
229                 }
230
231                 // calling any FileStream constructor with a handle normally
232                 // requires permissions UnmanagedCode permissions. In this 
233                 // case we assert this permission so the console can be used
234                 // in partial trust (i.e. without having UnmanagedCode).
235                 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
236                 public static Stream OpenStandardOutput (int bufferSize)
237                 {
238                         return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
239                 }
240
241                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
242                 public static void SetError (TextWriter newError)
243                 {
244                         if (newError == null)
245                                 throw new ArgumentNullException ("newError");
246
247                         stderr = newError;
248                 }
249
250                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
251                 public static void SetIn (TextReader newIn)
252                 {
253                         if (newIn == null)
254                                 throw new ArgumentNullException ("newIn");
255
256                         stdin = newIn;
257                 }
258
259                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
260                 public static void SetOut (TextWriter newOut)
261                 {
262                         if (newOut == null)
263                                 throw new ArgumentNullException ("newOut");
264
265                         stdout = newOut;
266                 }
267
268                 public static void Write (bool value)
269                 {
270                         stdout.Write (value);
271                 }
272
273                 public static void Write (char value)
274                 {
275                         stdout.Write (value);
276                 }
277
278                 public static void Write (char[] buffer)
279                 {
280                         stdout.Write (buffer);
281                 }
282
283                 public static void Write (decimal value)
284                 {
285                         stdout.Write (value);
286                 }
287                 
288                 public static void Write (double value)
289                 {
290                         stdout.Write (value);
291                 }
292
293                 public static void Write (int value)
294                 {
295                         stdout.Write (value);
296                 }
297
298                 public static void Write (long value)
299                 {
300                         stdout.Write (value);
301                 }
302
303                 public static void Write (object value)
304                 {
305                         stdout.Write (value);
306                 }
307
308                 public static void Write (float value)
309                 {
310                         stdout.Write (value);
311                 }
312
313                 public static void Write (string value)
314                 {
315                         stdout.Write (value);
316                 }
317
318                 [CLSCompliant (false)]
319                 public static void Write (uint value)
320                 {
321                         stdout.Write (value);
322                 }
323
324                 [CLSCompliant (false)]
325                 public static void Write (ulong value)
326                 {
327                         stdout.Write (value);
328                 }
329
330                 public static void Write (string format, object arg0)
331                 {
332                         stdout.Write (format, arg0);
333                 }
334
335                 public static void Write (string format, params object[] arg)
336                 {
337                         if (arg == null)
338                                 stdout.Write (format);
339                         else
340                                 stdout.Write (format, arg);
341                 }
342
343                 public static void Write (char[] buffer, int index, int count)
344                 {
345                         stdout.Write (buffer, index, count);
346                 }
347
348                 public static void Write (string format, object arg0, object arg1)
349                 {
350                         stdout.Write (format, arg0, arg1);
351                 }
352
353                 public static void Write (string format, object arg0, object arg1, object arg2 )
354                 {
355                         stdout.Write (format, arg0, arg1, arg2);
356                 }
357
358                 [CLSCompliant (false)]
359                 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
360                 {
361                         ArgIterator iter = new ArgIterator (__arglist);
362                         int argCount = iter.GetRemainingCount();
363
364                         object[] args = new object [argCount + 4];
365                         args [0] = arg0;
366                         args [1] = arg1;
367                         args [2] = arg2;
368                         args [3] = arg3;
369                         for (int i = 0; i < argCount; i++) {
370                                 TypedReference typedRef = iter.GetNextArg ();
371                                 args [i + 4] = TypedReference.ToObject (typedRef);
372                         }
373
374                         stdout.Write (String.Format (format, args));
375                 }
376
377                 public static void WriteLine ()
378                 {
379                         stdout.WriteLine ();
380                 }
381
382                 public static void WriteLine (bool value)
383                 {
384                         stdout.WriteLine (value);
385                 }
386
387                 public static void WriteLine (char value)
388                 {
389                         stdout.WriteLine (value);
390                 }
391
392                 public static void WriteLine (char[] buffer)
393                 {
394                         stdout.WriteLine (buffer);
395                 }
396
397                 public static void WriteLine (decimal value)
398                 {
399                         stdout.WriteLine (value);
400                 }
401
402                 public static void WriteLine (double value)
403                 {
404                         stdout.WriteLine (value);
405                 }
406
407                 public static void WriteLine (int value)
408                 {
409                         stdout.WriteLine (value);
410                 }
411
412                 public static void WriteLine (long value)
413                 {
414                         stdout.WriteLine (value);
415                 }
416
417                 public static void WriteLine (object value)
418                 {
419                         stdout.WriteLine (value);
420                 }
421
422                 public static void WriteLine (float value)
423                 {
424                         stdout.WriteLine (value);
425                 }
426
427                 public static void WriteLine (string value)
428                 {
429                         stdout.WriteLine (value);
430                 }
431
432                 [CLSCompliant (false)]
433                 public static void WriteLine (uint value)
434                 {
435                         stdout.WriteLine (value);
436                 }
437
438                 [CLSCompliant (false)]
439                 public static void WriteLine (ulong value)
440                 {
441                         stdout.WriteLine (value);
442                 }
443
444                 public static void WriteLine (string format, object arg0)
445                 {
446                         stdout.WriteLine (format, arg0);
447                 }
448
449                 public static void WriteLine (string format, params object[] arg)
450                 {
451                         if (arg == null)
452                                 stdout.WriteLine (format);
453                         else
454                                 stdout.WriteLine (format, arg);
455                 }
456
457                 public static void WriteLine (char[] buffer, int index, int count)
458                 {
459                         stdout.WriteLine (buffer, index, count);
460                 }
461
462                 public static void WriteLine (string format, object arg0, object arg1)
463                 {
464                         stdout.WriteLine (format, arg0, arg1);
465                 }
466
467                 public static void WriteLine (string format, object arg0, object arg1, object arg2)
468                 {
469                         stdout.WriteLine (format, arg0, arg1, arg2);
470                 }
471
472                 [CLSCompliant (false)]
473                 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
474                 {
475                         ArgIterator iter = new ArgIterator (__arglist);
476                         int argCount = iter.GetRemainingCount();
477
478                         object[] args = new object [argCount + 4];
479                         args [0] = arg0;
480                         args [1] = arg1;
481                         args [2] = arg2;
482                         args [3] = arg3;
483                         for (int i = 0; i < argCount; i++) {
484                                 TypedReference typedRef = iter.GetNextArg ();
485                                 args [i + 4] = TypedReference.ToObject (typedRef);
486                         }
487
488                         stdout.WriteLine (String.Format (format, args));
489                 }
490
491 #if !NET_2_1
492                 public static int Read ()
493                 {
494                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
495                                 return ConsoleDriver.Read ();
496                         } else {
497                                 return stdin.Read ();
498                         }
499                 }
500
501                 public static string ReadLine ()
502                 {
503                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
504                                 return ConsoleDriver.ReadLine ();
505                         } else {
506                                 return stdin.ReadLine ();
507                         }
508                 }
509 #else
510                 public static int Read ()
511                 {
512                         return stdin.Read ();
513                 }
514
515                 public static string ReadLine ()
516                 {
517                         return stdin.ReadLine ();
518                 }
519
520 #endif
521
522                 // FIXME: Console should use these encodings when changed
523                 static Encoding inputEncoding;
524                 static Encoding outputEncoding;
525
526                 public static Encoding InputEncoding {
527                         get { return inputEncoding; }
528                         set {
529                                 inputEncoding = value;
530                                 SetupStreams (inputEncoding, outputEncoding);
531                         }
532                 }
533
534                 public static Encoding OutputEncoding {
535                         get { return outputEncoding; }
536                         set {
537                                 outputEncoding = value;
538                                 SetupStreams (inputEncoding, outputEncoding);
539                         }
540                 }
541
542 #if !NET_2_1
543                 public static ConsoleColor BackgroundColor {
544                         get { return ConsoleDriver.BackgroundColor; }
545                         set { ConsoleDriver.BackgroundColor = value; }
546                 }
547
548                 public static int BufferHeight {
549                         get { return ConsoleDriver.BufferHeight; }
550                         [MonoLimitation ("Implemented only on Windows")]
551                         set { ConsoleDriver.BufferHeight = value; }
552                 }
553
554                 public static int BufferWidth {
555                         get { return ConsoleDriver.BufferWidth; }
556                         [MonoLimitation ("Implemented only on Windows")]
557                         set { ConsoleDriver.BufferWidth = value; }
558                 }
559
560                 [MonoLimitation ("Implemented only on Windows")]
561                 public static bool CapsLock {
562                         get { return ConsoleDriver.CapsLock; }
563                 }
564
565                 public static int CursorLeft {
566                         get { return ConsoleDriver.CursorLeft; }
567                         set { ConsoleDriver.CursorLeft = value; }
568                 }
569
570                 public static int CursorTop {
571                         get { return ConsoleDriver.CursorTop; }
572                         set { ConsoleDriver.CursorTop = value; }
573                 }
574
575                 public static int CursorSize {
576                         get { return ConsoleDriver.CursorSize; }
577                         set { ConsoleDriver.CursorSize = value; }
578                 }
579
580                 public static bool CursorVisible {
581                         get { return ConsoleDriver.CursorVisible; }
582                         set { ConsoleDriver.CursorVisible = value; }
583                 }
584
585                 public static ConsoleColor ForegroundColor {
586                         get { return ConsoleDriver.ForegroundColor; }
587                         set { ConsoleDriver.ForegroundColor = value; }
588                 }
589
590                 public static bool KeyAvailable {
591                         get { return ConsoleDriver.KeyAvailable; }
592                 }
593
594                 public static int LargestWindowHeight {
595                         get { return ConsoleDriver.LargestWindowHeight; }
596                 }
597
598                 public static int LargestWindowWidth {
599                         get { return ConsoleDriver.LargestWindowWidth; }
600                 }
601
602                 [MonoLimitation ("Only works on windows")]
603                 public static bool NumberLock {
604                         get { return ConsoleDriver.NumberLock; }
605                 }
606
607                 public static string Title {
608                         get { return ConsoleDriver.Title; }
609                         set { ConsoleDriver.Title = value; }
610                 }
611
612                 public static bool TreatControlCAsInput {
613                         get { return ConsoleDriver.TreatControlCAsInput; }
614                         set { ConsoleDriver.TreatControlCAsInput = value; }
615                 }
616
617                 [MonoLimitation ("Only works on windows")]
618                 public static int WindowHeight {
619                         get { return ConsoleDriver.WindowHeight; }
620                         set { ConsoleDriver.WindowHeight = value; }
621                 }
622
623                 [MonoLimitation ("Only works on windows")]
624                 public static int WindowLeft {
625                         get { return ConsoleDriver.WindowLeft; }
626                         set { ConsoleDriver.WindowLeft = value; }
627                 }
628
629                 [MonoLimitation ("Only works on windows")]
630                 public static int WindowTop {
631                         get { return ConsoleDriver.WindowTop; }
632                         set { ConsoleDriver.WindowTop = value; }
633                 }
634
635                 [MonoLimitation ("Only works on windows")]
636                 public static int WindowWidth {
637                         get { return ConsoleDriver.WindowWidth; }
638                         set { ConsoleDriver.WindowWidth = value; }
639                 }
640
641                 public static bool IsErrorRedirected {
642                         get {
643                                 return ConsoleDriver.IsErrorRedirected;
644                         }
645                 }
646
647                 public static bool IsOutputRedirected {
648                         get {
649                                 return ConsoleDriver.IsOutputRedirected;
650                         }
651                 }
652
653                 public static bool IsInputRedirected {
654                         get {
655                                 return ConsoleDriver.IsInputRedirected;
656                         }
657                 }
658
659                 public static void Beep ()
660                 {
661                         Beep (1000, 500);
662                 }
663
664                 public static void Beep (int frequency, int duration)
665                 {
666                         if (frequency < 37 || frequency > 32767)
667                                 throw new ArgumentOutOfRangeException ("frequency");
668
669                         if (duration <= 0)
670                                 throw new ArgumentOutOfRangeException ("duration");
671
672                         ConsoleDriver.Beep (frequency, duration);
673                 }
674
675                 public static void Clear ()
676                 {
677                         ConsoleDriver.Clear ();
678                 }
679
680                 [MonoLimitation ("Implemented only on Windows")]
681                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
682                                                 int targetLeft, int targetTop)
683                 {
684                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
685                 }
686
687                 [MonoLimitation ("Implemented only on Windows")]
688                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
689                                                 int targetLeft, int targetTop, Char sourceChar,
690                                                 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
691                 {
692                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
693                                                         sourceChar, sourceForeColor, sourceBackColor);
694                 }
695
696                 public static ConsoleKeyInfo ReadKey ()
697                 {
698                         return ReadKey (false);
699                 }
700
701                 public static ConsoleKeyInfo ReadKey (bool intercept)
702                 {
703                         return ConsoleDriver.ReadKey (intercept);
704                 }
705
706                 public static void ResetColor ()
707                 {
708                         ConsoleDriver.ResetColor ();
709                 }
710
711                 [MonoLimitation ("Only works on windows")]
712                 public static void SetBufferSize (int width, int height)
713                 {
714                         ConsoleDriver.SetBufferSize (width, height);
715                 }
716
717                 public static void SetCursorPosition (int left, int top)
718                 {
719                         ConsoleDriver.SetCursorPosition (left, top);
720                 }
721
722                 public static void SetWindowPosition (int left, int top)
723                 {
724                         ConsoleDriver.SetWindowPosition (left, top);
725                 }
726
727                 public static void SetWindowSize (int width, int height)
728                 {
729                         ConsoleDriver.SetWindowSize (width, height);
730                 }
731
732                 static ConsoleCancelEventHandler cancel_event;
733                 public static event ConsoleCancelEventHandler CancelKeyPress {
734                         add {
735                                 if (ConsoleDriver.Initialized == false)
736                                         ConsoleDriver.Init ();
737
738                                 cancel_event += value;
739
740                                 if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
741                                         WindowsConsole.AddCtrlHandler();
742                         }
743                         remove {
744                                 if (ConsoleDriver.Initialized == false)
745                                         ConsoleDriver.Init ();
746
747                                 cancel_event -= value;
748
749                                 if (cancel_event == null && Environment.IsRunningOnWindows)
750                                 {
751                                         // Need to remove our hook if there's nothing left in the event
752                                         if (WindowsConsole.ctrlHandlerAdded)
753                                                 WindowsConsole.RemoveCtrlHandler();
754                                 }
755                         }
756                 }
757
758                 delegate void InternalCancelHandler ();
759                 
760 #pragma warning disable 414
761                 //
762                 // Used by console-io.c
763                 //
764                 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
765 #pragma warning restore 414             
766
767                 internal static void DoConsoleCancelEvent ()
768                 {
769                         bool exit = true;
770                         if (cancel_event != null) {
771                                 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
772                                 Delegate [] delegates = cancel_event.GetInvocationList ();
773                                 foreach (ConsoleCancelEventHandler d in delegates){
774                                         try {
775                                                 // Sender is always null here.
776                                                 d (null, args);
777                                         } catch {} // Ignore any exception.
778                                 }
779                                 exit = !args.Cancel;
780                         }
781
782                         if (exit)
783                                 Environment.Exit (58);
784                 }
785 #endif
786         }
787 }
788