// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0 || BOOTSTRAP_NET_2_0
-#define NET2_API
-#endif
+using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Security;
using System.Security.Permissions;
using System.Text;
namespace System
{
- public
-#if NET2_API
- static
-#else
- sealed
-#endif
- class Console
+ public static class Console
{
+#if !NET_2_1
private class WindowsConsole
{
+ public static bool ctrlHandlerAdded = false;
+ private delegate bool WindowsCancelHandler (int keyCode);
+ private static WindowsCancelHandler cancelHandler = new WindowsCancelHandler (DoWindowsConsoleCancelEvent);
+
[DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
private static extern int GetConsoleCP ();
[DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
private static extern int GetConsoleOutputCP ();
+ [DllImport ("kernel32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
+ private static extern bool SetConsoleCtrlHandler (WindowsCancelHandler handler, bool addHandler);
+
+ // Only call the event handler if Control-C was pressed (code == 0), nothing else
+ private static bool DoWindowsConsoleCancelEvent (int keyCode)
+ {
+ if (keyCode == 0)
+ DoConsoleCancelEvent ();
+ return keyCode == 0;
+ }
+
[MethodImpl (MethodImplOptions.NoInlining)]
public static int GetInputCodePage ()
{
{
return GetConsoleOutputCP ();
}
+
+ public static void AddCtrlHandler ()
+ {
+ SetConsoleCtrlHandler (cancelHandler, true);
+ ctrlHandlerAdded = true;
+ }
+
+ public static void RemoveCtrlHandler ()
+ {
+ SetConsoleCtrlHandler (cancelHandler, false);
+ ctrlHandlerAdded = false;
+ }
}
+#endif
internal static TextWriter stdout;
private static TextWriter stderr;
private static TextReader stdin;
+#if NET_4_5
+ static TextWriter console_stdout;
+ static TextWriter console_stderr;
+ static TextReader console_stdin;
+#endif
+
static Console ()
{
-#if !NET2_API || NET_2_1
+#if NET_2_1
Encoding inputEncoding;
Encoding outputEncoding;
#endif
//
// On Windows, follow the Windows tradition
//
+#if NET_2_1
+ // should never happen since Moonlight does not run on windows
+ inputEncoding = outputEncoding = Encoding.Default;
+#else
try {
inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
} catch {
// FIXME: I18N assemblies are not available when compiling mcs
// Use Latin 1 as it is fast and UTF-8 is never used as console code page
- inputEncoding = outputEncoding = Encoding.GetEncoding (28591);
+ inputEncoding = outputEncoding = Encoding.Default;
}
+#endif
} else {
//
// On Unix systems (128), do not output the
inputEncoding = outputEncoding = Encoding.Default;
}
- stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
- ((StreamWriter)stderr).AutoFlush = true;
- stderr = TextWriter.Synchronized (stderr, true);
+ SetupStreams (inputEncoding, outputEncoding);
+ }
-#if NET2_API && !NET_2_1
+ static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding)
+ {
+#if !NET_2_1
if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) {
StreamWriter w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
w.AutoFlush = true;
stdout = TextWriter.Synchronized (w, true);
+
+ w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
+ w.AutoFlush = true;
+ stderr = TextWriter.Synchronized (w, true);
+
stdin = new CStreamReader (OpenStandardInput (0), inputEncoding);
} else {
#endif
+#if FULL_AOT_RUNTIME
+ Type nslogwriter = Type.GetType ("MonoTouch.Foundation.NSLogWriter, monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
+ stdout = (TextWriter) Activator.CreateInstance (nslogwriter);
+#else
stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
((StreamWriter)stdout).AutoFlush = true;
+#endif
stdout = TextWriter.Synchronized (stdout, true);
+
+#if FULL_AOT_RUNTIME
+ stderr = (TextWriter) Activator.CreateInstance (nslogwriter);
+#else
+ stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
+ ((StreamWriter)stderr).AutoFlush = true;
+#endif
+ stderr = TextWriter.Synchronized (stderr, true);
+
stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
stdin = TextReader.Synchronized (stdin);
-#if NET2_API && !NET_2_1
+#if !NET_2_1
}
#endif
+#if NET_4_5
+ console_stderr = stderr;
+ console_stdout = stdout;
+ console_stdin = stdin;
+#endif
+
+#if MONODROID
+ if (LogcatTextWriter.IsRunningOnAndroid ()) {
+ stdout = TextWriter.Synchronized (new LogcatTextWriter ("mono-stdout", stdout));
+ stderr = TextWriter.Synchronized (new LogcatTextWriter ("mono-stderr", stderr));
+ }
+#endif // MONODROID
+
GC.SuppressFinalize (stdout);
GC.SuppressFinalize (stderr);
GC.SuppressFinalize (stdin);
}
-#if !NET2_API
- private Console ()
- {
- }
-#endif
-
public static TextWriter Error {
get {
return stderr;
}
}
+#if NET_4_5
+ public static bool IsErrorRedirected {
+ get {
+ return stderr != console_stderr || ConsoleDriver.IsErrorRedirected;
+ }
+ }
+
+ public static bool IsOutputRedirected {
+ get {
+ return stdout != console_stdout || ConsoleDriver.IsOutputRedirected;
+ }
+ }
+
+ public static bool IsInputRedirected {
+ get {
+ return stdin != console_stdin || ConsoleDriver.IsInputRedirected;
+ }
+ }
+#endif
+
+ private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
+ {
+#if MOONLIGHT
+ if (SecurityManager.SecurityEnabled && !Debugger.IsAttached && Environment.GetEnvironmentVariable ("MOONLIGHT_ENABLE_CONSOLE") == null)
+ return new NullStream ();
+#endif
+ try {
+ return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
+ } catch (IOException) {
+ return new NullStream ();
+ }
+ }
+
public static Stream OpenStandardError ()
{
return OpenStandardError (0);
[SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
public static Stream OpenStandardError (int bufferSize)
{
- try {
- return new FileStream (MonoIO.ConsoleError, FileAccess.Write, false, bufferSize, false, bufferSize == 0);
- } catch (IOException) {
- return new NullStream ();
- }
+ return Open (MonoIO.ConsoleError, FileAccess.Write, bufferSize);
}
public static Stream OpenStandardInput ()
[SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
public static Stream OpenStandardInput (int bufferSize)
{
- try {
- return new FileStream (MonoIO.ConsoleInput, FileAccess.Read, false, bufferSize, false, bufferSize == 0);
- } catch (IOException) {
- return new NullStream ();
- }
+ return Open (MonoIO.ConsoleInput, FileAccess.Read, bufferSize);
}
public static Stream OpenStandardOutput ()
[SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
public static Stream OpenStandardOutput (int bufferSize)
{
- try {
- return new FileStream (MonoIO.ConsoleOutput, FileAccess.Write, false, bufferSize, false, bufferSize == 0);
- } catch (IOException) {
- return new NullStream ();
- }
+ return Open (MonoIO.ConsoleOutput, FileAccess.Write, bufferSize);
}
[SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
public static void Write (string format, params object[] arg)
{
- stdout.Write (format, arg);
+ if (arg == null)
+ stdout.Write (format);
+ else
+ stdout.Write (format, arg);
}
public static void Write (char[] buffer, int index, int count)
stdout.Write (format, arg0, arg1, arg2);
}
-#if ! BOOTSTRAP_WITH_OLDLIB
[CLSCompliant (false)]
public static void Write (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
{
stdout.Write (String.Format (format, args));
}
-#endif
public static void WriteLine ()
{
public static void WriteLine (string format, params object[] arg)
{
- stdout.WriteLine (format, arg);
+ if (arg == null)
+ stdout.WriteLine (format);
+ else
+ stdout.WriteLine (format, arg);
}
public static void WriteLine (char[] buffer, int index, int count)
stdout.WriteLine (format, arg0, arg1, arg2);
}
-#if ! BOOTSTRAP_WITH_OLDLIB
[CLSCompliant (false)]
public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3, __arglist)
{
stdout.WriteLine (String.Format (format, args));
}
-#endif
-#if NET2_API && !NET_2_1
+#if !NET_2_1
public static int Read ()
{
if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) {
#endif
-#if NET2_API && !NET_2_1
+#if !NET_2_1
// FIXME: Console should use these encodings when changed
static Encoding inputEncoding;
static Encoding outputEncoding;
public static Encoding InputEncoding {
get { return inputEncoding; }
- set { inputEncoding = value; }
+ set {
+ inputEncoding = value;
+ SetupStreams (inputEncoding, outputEncoding);
+ }
}
public static Encoding OutputEncoding {
get { return outputEncoding; }
- set { outputEncoding = value; }
+ set {
+ outputEncoding = value;
+ SetupStreams (inputEncoding, outputEncoding);
+ }
}
public static ConsoleColor BackgroundColor {
public static int BufferHeight {
get { return ConsoleDriver.BufferHeight; }
+ [MonoLimitation ("Implemented only on Windows")]
set { ConsoleDriver.BufferHeight = value; }
}
public static int BufferWidth {
get { return ConsoleDriver.BufferWidth; }
+ [MonoLimitation ("Implemented only on Windows")]
set { ConsoleDriver.BufferWidth = value; }
}
+ [MonoLimitation ("Implemented only on Windows")]
public static bool CapsLock {
get { return ConsoleDriver.CapsLock; }
}
get { return ConsoleDriver.LargestWindowWidth; }
}
+ [MonoLimitation ("Only works on windows")]
public static bool NumberLock {
get { return ConsoleDriver.NumberLock; }
}
set { ConsoleDriver.TreatControlCAsInput = value; }
}
+ [MonoLimitation ("Only works on windows")]
public static int WindowHeight {
get { return ConsoleDriver.WindowHeight; }
set { ConsoleDriver.WindowHeight = value; }
}
+ [MonoLimitation ("Only works on windows")]
public static int WindowLeft {
get { return ConsoleDriver.WindowLeft; }
set { ConsoleDriver.WindowLeft = value; }
}
+ [MonoLimitation ("Only works on windows")]
public static int WindowTop {
get { return ConsoleDriver.WindowTop; }
set { ConsoleDriver.WindowTop = value; }
}
+ [MonoLimitation ("Only works on windows")]
public static int WindowWidth {
get { return ConsoleDriver.WindowWidth; }
set { ConsoleDriver.WindowWidth = value; }
ConsoleDriver.Clear ();
}
- [MonoTODO ("Not implemented")]
+ [MonoLimitation ("Implemented only on Windows")]
public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
int targetLeft, int targetTop)
{
- throw new NotImplementedException ();
+ ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop);
}
- [MonoTODO("Not implemented")]
+ [MonoLimitation ("Implemented only on Windows")]
public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
int targetLeft, int targetTop, Char sourceChar,
ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
{
- throw new NotImplementedException ();
+ ConsoleDriver.MoveBufferArea (sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop,
+ sourceChar, sourceForeColor, sourceBackColor);
}
public static ConsoleKeyInfo ReadKey ()
ConsoleDriver.ResetColor ();
}
+ [MonoLimitation ("Only works on windows")]
public static void SetBufferSize (int width, int height)
{
ConsoleDriver.SetBufferSize (width, height);
ConsoleDriver.Init ();
cancel_event += value;
+
+ if (Environment.IsRunningOnWindows && !WindowsConsole.ctrlHandlerAdded)
+ WindowsConsole.AddCtrlHandler();
}
remove {
if (ConsoleDriver.Initialized == false)
ConsoleDriver.Init ();
cancel_event -= value;
+
+ if (cancel_event == null && Environment.IsRunningOnWindows)
+ {
+ // Need to remove our hook if there's nothing left in the event
+ if (WindowsConsole.ctrlHandlerAdded)
+ WindowsConsole.RemoveCtrlHandler();
+ }
}
}
delegate void InternalCancelHandler ();
- static InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
+
+#pragma warning disable 414
+ //
+ // Used by console-io.c
+ //
+ static readonly InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
+#pragma warning restore 414
internal static void DoConsoleCancelEvent ()
{