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