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