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