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