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