2010-03-12 Jb Evain <jbevain@novell.com>
[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 NET_2_1 && !MONOTOUCH
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                         stdout.Write (format, arg);
308                 }
309
310                 public static void Write (char[] buffer, int index, int count)
311                 {
312                         stdout.Write (buffer, index, count);
313                 }
314
315                 public static void Write (string format, object arg0, object arg1)
316                 {
317                         stdout.Write (format, arg0, arg1);
318                 }
319
320                 public static void Write (string format, object arg0, object arg1, object arg2 )
321                 {
322                         stdout.Write (format, arg0, arg1, arg2);
323                 }
324
325                 [CLSCompliant (false)]
326                 public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
327                 {
328                         ArgIterator iter = new ArgIterator (__arglist);
329                         int argCount = iter.GetRemainingCount();
330
331                         object[] args = new object [argCount + 4];
332                         args [0] = arg0;
333                         args [1] = arg1;
334                         args [2] = arg2;
335                         args [3] = arg3;
336                         for (int i = 0; i < argCount; i++) {
337                                 TypedReference typedRef = iter.GetNextArg ();
338                                 args [i + 4] = TypedReference.ToObject (typedRef);
339                         }
340
341                         stdout.Write (String.Format (format, args));
342                 }
343
344                 public static void WriteLine ()
345                 {
346                         stdout.WriteLine ();
347                 }
348
349                 public static void WriteLine (bool value)
350                 {
351                         stdout.WriteLine (value);
352                 }
353
354                 public static void WriteLine (char value)
355                 {
356                         stdout.WriteLine (value);
357                 }
358
359                 public static void WriteLine (char[] buffer)
360                 {
361                         stdout.WriteLine (buffer);
362                 }
363
364                 public static void WriteLine (decimal value)
365                 {
366                         stdout.WriteLine (value);
367                 }
368
369                 public static void WriteLine (double value)
370                 {
371                         stdout.WriteLine (value);
372                 }
373
374                 public static void WriteLine (int value)
375                 {
376                         stdout.WriteLine (value);
377                 }
378
379                 public static void WriteLine (long value)
380                 {
381                         stdout.WriteLine (value);
382                 }
383
384                 public static void WriteLine (object value)
385                 {
386                         stdout.WriteLine (value);
387                 }
388
389                 public static void WriteLine (float value)
390                 {
391                         stdout.WriteLine (value);
392                 }
393
394                 public static void WriteLine (string value)
395                 {
396                         stdout.WriteLine (value);
397                 }
398
399                 [CLSCompliant (false)]
400                 public static void WriteLine (uint value)
401                 {
402                         stdout.WriteLine (value);
403                 }
404
405                 [CLSCompliant (false)]
406                 public static void WriteLine (ulong value)
407                 {
408                         stdout.WriteLine (value);
409                 }
410
411                 public static void WriteLine (string format, object arg0)
412                 {
413                         stdout.WriteLine (format, arg0);
414                 }
415
416                 public static void WriteLine (string format, params object[] arg)
417                 {
418                         stdout.WriteLine (format, arg);
419                 }
420
421                 public static void WriteLine (char[] buffer, int index, int count)
422                 {
423                         stdout.WriteLine (buffer, index, count);
424                 }
425
426                 public static void WriteLine (string format, object arg0, object arg1)
427                 {
428                         stdout.WriteLine (format, arg0, arg1);
429                 }
430
431                 public static void WriteLine (string format, object arg0, object arg1, object arg2)
432                 {
433                         stdout.WriteLine (format, arg0, arg1, arg2);
434                 }
435
436                 [CLSCompliant (false)]
437                 public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
438                 {
439                         ArgIterator iter = new ArgIterator (__arglist);
440                         int argCount = iter.GetRemainingCount();
441
442                         object[] args = new object [argCount + 4];
443                         args [0] = arg0;
444                         args [1] = arg1;
445                         args [2] = arg2;
446                         args [3] = arg3;
447                         for (int i = 0; i < argCount; i++) {
448                                 TypedReference typedRef = iter.GetNextArg ();
449                                 args [i + 4] = TypedReference.ToObject (typedRef);
450                         }
451
452                         stdout.WriteLine (String.Format (format, args));
453                 }
454
455 #if !NET_2_1
456                 public static int Read ()
457                 {
458                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
459                                 return ConsoleDriver.Read ();
460                         } else {
461                                 return stdin.Read ();
462                         }
463                 }
464
465                 public static string ReadLine ()
466                 {
467                         if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
468                                 return ConsoleDriver.ReadLine ();
469                         } else {
470                                 return stdin.ReadLine ();
471                         }
472                 }
473 #else
474                 public static int Read ()
475                 {
476                         return stdin.Read ();
477                 }
478
479                 public static string ReadLine ()
480                 {
481                         return stdin.ReadLine ();
482                 }
483
484 #endif
485
486 #if !NET_2_1
487                 // FIXME: Console should use these encodings when changed
488                 static Encoding inputEncoding;
489                 static Encoding outputEncoding;
490
491                 public static Encoding InputEncoding {
492                         get { return inputEncoding; }
493                         set { inputEncoding = value; }
494                 }
495
496                 public static Encoding OutputEncoding {
497                         get { return outputEncoding; }
498                         set { outputEncoding = value; }
499                 }
500
501                 public static ConsoleColor BackgroundColor {
502                         get { return ConsoleDriver.BackgroundColor; }
503                         set { ConsoleDriver.BackgroundColor = value; }
504                 }
505
506                 public static int BufferHeight {
507                         get { return ConsoleDriver.BufferHeight; }
508                         [MonoLimitation ("Implemented only on Windows")]
509                         set { ConsoleDriver.BufferHeight = value; }
510                 }
511
512                 public static int BufferWidth {
513                         get { return ConsoleDriver.BufferWidth; }
514                         [MonoLimitation ("Implemented only on Windows")]
515                         set { ConsoleDriver.BufferWidth = value; }
516                 }
517
518                 [MonoLimitation ("Implemented only on Windows")]
519                 public static bool CapsLock {
520                         get { return ConsoleDriver.CapsLock; }
521                 }
522
523                 public static int CursorLeft {
524                         get { return ConsoleDriver.CursorLeft; }
525                         set { ConsoleDriver.CursorLeft = value; }
526                 }
527
528                 public static int CursorTop {
529                         get { return ConsoleDriver.CursorTop; }
530                         set { ConsoleDriver.CursorTop = value; }
531                 }
532
533                 public static int CursorSize {
534                         get { return ConsoleDriver.CursorSize; }
535                         set { ConsoleDriver.CursorSize = value; }
536                 }
537
538                 public static bool CursorVisible {
539                         get { return ConsoleDriver.CursorVisible; }
540                         set { ConsoleDriver.CursorVisible = value; }
541                 }
542
543                 public static ConsoleColor ForegroundColor {
544                         get { return ConsoleDriver.ForegroundColor; }
545                         set { ConsoleDriver.ForegroundColor = value; }
546                 }
547
548                 public static bool KeyAvailable {
549                         get { return ConsoleDriver.KeyAvailable; }
550                 }
551
552                 public static int LargestWindowHeight {
553                         get { return ConsoleDriver.LargestWindowHeight; }
554                 }
555
556                 public static int LargestWindowWidth {
557                         get { return ConsoleDriver.LargestWindowWidth; }
558                 }
559
560                 [MonoLimitation ("Only works on windows")]
561                 public static bool NumberLock {
562                         get { return ConsoleDriver.NumberLock; }
563                 }
564
565                 public static string Title {
566                         get { return ConsoleDriver.Title; }
567                         set { ConsoleDriver.Title = value; }
568                 }
569
570                 public static bool TreatControlCAsInput {
571                         get { return ConsoleDriver.TreatControlCAsInput; }
572                         set { ConsoleDriver.TreatControlCAsInput = value; }
573                 }
574
575                 [MonoLimitation ("Only works on windows")]
576                 public static int WindowHeight {
577                         get { return ConsoleDriver.WindowHeight; }
578                         set { ConsoleDriver.WindowHeight = value; }
579                 }
580
581                 [MonoLimitation ("Only works on windows")]
582                 public static int WindowLeft {
583                         get { return ConsoleDriver.WindowLeft; }
584                         set { ConsoleDriver.WindowLeft = value; }
585                 }
586
587                 [MonoLimitation ("Only works on windows")]
588                 public static int WindowTop {
589                         get { return ConsoleDriver.WindowTop; }
590                         set { ConsoleDriver.WindowTop = value; }
591                 }
592
593                 [MonoLimitation ("Only works on windows")]
594                 public static int WindowWidth {
595                         get { return ConsoleDriver.WindowWidth; }
596                         set { ConsoleDriver.WindowWidth = value; }
597                 }
598
599                 public static void Beep ()
600                 {
601                         Beep (1000, 500);
602                 }
603
604                 public static void Beep (int frequency, int duration)
605                 {
606                         if (frequency < 37 || frequency > 32767)
607                                 throw new ArgumentOutOfRangeException ("frequency");
608
609                         if (duration <= 0)
610                                 throw new ArgumentOutOfRangeException ("duration");
611
612                         ConsoleDriver.Beep (frequency, duration);
613                 }
614
615                 public static void Clear ()
616                 {
617                         ConsoleDriver.Clear ();
618                 }
619
620                 [MonoLimitation ("Implemented only on Windows")]
621                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
622                                                 int targetLeft, int targetTop)
623                 {
624                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
625                 }
626
627                 [MonoLimitation ("Implemented only on Windows")]
628                 public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
629                                                 int targetLeft, int targetTop, Char sourceChar,
630                                                 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
631                 {
632                         ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
633                                                         sourceChar, sourceForeColor, sourceBackColor);
634                 }
635
636                 public static ConsoleKeyInfo ReadKey ()
637                 {
638                         return ReadKey (false);
639                 }
640
641                 public static ConsoleKeyInfo ReadKey (bool intercept)
642                 {
643                         return ConsoleDriver.ReadKey (intercept);
644                 }
645
646                 public static void ResetColor ()
647                 {
648                         ConsoleDriver.ResetColor ();
649                 }
650
651                 [MonoLimitation ("Only works on windows")]
652                 public static void SetBufferSize (int width, int height)
653                 {
654                         ConsoleDriver.SetBufferSize (width, height);
655                 }
656
657                 public static void SetCursorPosition (int left, int top)
658                 {
659                         ConsoleDriver.SetCursorPosition (left, top);
660                 }
661
662                 public static void SetWindowPosition (int left, int top)
663                 {
664                         ConsoleDriver.SetWindowPosition (left, top);
665                 }
666
667                 public static void SetWindowSize (int width, int height)
668                 {
669                         ConsoleDriver.SetWindowSize (width, height);
670                 }
671
672                 static ConsoleCancelEventHandler cancel_event;
673                 public static event ConsoleCancelEventHandler CancelKeyPress {
674                         add {
675                                 if (ConsoleDriver.Initialized == false)
676                                         ConsoleDriver.Init ();
677
678                                 cancel_event += value;
679                         }
680                         remove {
681                                 if (ConsoleDriver.Initialized == false)
682                                         ConsoleDriver.Init ();
683
684                                 cancel_event -= value;
685                         }
686                 }
687
688                 delegate void InternalCancelHandler ();
689                 
690 #pragma warning disable 414
691                 //
692                 // Used by console-io.c
693                 //
694                 static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
695 #pragma warning restore 414             
696
697                 internal static void DoConsoleCancelEvent ()
698                 {
699                         bool exit = true;
700                         if (cancel_event != null) {
701                                 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
702                                 Delegate [] delegates = cancel_event.GetInvocationList ();
703                                 foreach (ConsoleCancelEventHandler d in delegates){
704                                         try {
705                                                 // Sender is always null here.
706                                                 d (null, args);
707                                         } catch {} // Ignore any exception.
708                                 }
709                                 exit = !args.Cancel;
710                         }
711
712                         if (exit)
713                                 Environment.Exit (58);
714                 }
715 #endif
716         }
717 }
718