* ConsoleDriver.cs:
* TermInfoDriver.cs:
* IConsoleDriver.cs:
* Console.cs:
* WindowsConsoleDriver.cs: don't switch to the alternate window.
Trigger the cancel event. Retrieve the cursor position at the
beginning, as we're going to keep track of it instead of querying it
all the time.
svn path=/trunk/mcs/; revision=65680
+2006-09-19 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * ConsoleDriver.cs:
+ * TermInfoDriver.cs:
+ * IConsoleDriver.cs:
+ * Console.cs:
+ * WindowsConsoleDriver.cs: don't switch to the alternate window.
+ Trigger the cancel event. Retrieve the cursor position at the
+ beginning, as we're going to keep track of it instead of querying it
+ all the time.
+
2006-09-14 Jonathan Chambers <joncham@gmail.com>
* Environment.cs (ProcessorCount): Implement as icall.
2006-09-14 Jonathan Chambers <joncham@gmail.com>
* Environment.cs (ProcessorCount): Implement as icall.
inputEncoding = outputEncoding = Encoding.Default;
}
inputEncoding = outputEncoding = Encoding.Default;
}
- stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
- ((StreamWriter)stderr).AutoFlush = true;
- stderr = TextWriter.Synchronized (stderr, true);
+#if NET_2_0
+/*
+ if (ConsoleDriver.IsConsole) {
+ CStreamWriter w = new CStreamWriter (OpenStandardError (0), outputEncoding);
+ w.AutoFlush = true;
+ stderr = TextWriter.Synchronized (w, true);
+
+ w = new CStreamWriter (OpenStandardOutput (0), outputEncoding);
+ w.AutoFlush = true;
+ stdout = TextWriter.Synchronized (w, true);
+ } else {
+ */
+#endif
+ stderr = new UnexceptionalStreamWriter (OpenStandardError (0), outputEncoding);
+ ((StreamWriter)stderr).AutoFlush = true;
+ stderr = TextWriter.Synchronized (stderr, true);
- stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
- ((StreamWriter)stdout).AutoFlush = true;
- stdout = TextWriter.Synchronized (stdout, true);
+ stdout = new UnexceptionalStreamWriter (OpenStandardOutput (0), outputEncoding);
+ ((StreamWriter)stdout).AutoFlush = true;
+ stdout = TextWriter.Synchronized (stdout, true);
+#if NET_2_0
+ //}
+#endif
stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
stdin = TextReader.Synchronized (stdin);
stdin = new UnexceptionalStreamReader (OpenStandardInput (0), inputEncoding);
stdin = TextReader.Synchronized (stdin);
return OpenStandardError (0);
}
return OpenStandardError (0);
}
- // calling any FileStream constructor with an handle normally
+ // calling any FileStream constructor with a handle normally
// requires permissions UnmanagedCode permissions. In this
// case we assert this permission so the console can be used
// in partial trust (i.e. without having UnmanagedCode).
// requires permissions UnmanagedCode permissions. In this
// case we assert this permission so the console can be used
// in partial trust (i.e. without having UnmanagedCode).
return OpenStandardInput (0);
}
return OpenStandardInput (0);
}
- // calling any FileStream constructor with an handle normally
+ // calling any FileStream constructor with a handle normally
// requires permissions UnmanagedCode permissions. In this
// case we assert this permission so the console can be used
// in partial trust (i.e. without having UnmanagedCode).
// requires permissions UnmanagedCode permissions. In this
// case we assert this permission so the console can be used
// in partial trust (i.e. without having UnmanagedCode).
return OpenStandardOutput (0);
}
return OpenStandardOutput (0);
}
- // calling any FileStream constructor with an handle normally
+ // calling any FileStream constructor with a handle normally
// requires permissions UnmanagedCode permissions. In this
// case we assert this permission so the console can be used
// in partial trust (i.e. without having UnmanagedCode).
// requires permissions UnmanagedCode permissions. In this
// case we assert this permission so the console can be used
// in partial trust (i.e. without having UnmanagedCode).
public static int Read ()
{
public static int Read ()
{
+ if (ConsoleDriver.IsConsole) {
+ return ConsoleDriver.Read ();
+ } else {
+ return stdin.Read ();
+ }
public static string ReadLine ()
{
public static string ReadLine ()
{
- bool prevEcho = false;
- if (ConsoleDriver.Initialized) {
- prevEcho = ConsoleDriver.Echo;
- ConsoleDriver.Echo = true;
+ if (ConsoleDriver.IsConsole) {
+ return ConsoleDriver.ReadLine ();
+ } else {
+ return stdin.ReadLine ();
-
- string ret = stdin.ReadLine ();
- if (ConsoleDriver.Initialized)
- ConsoleDriver.Echo = prevEcho;
-
- return ret;
+ public static int Read ()
+ {
+ return stdin.Read ();
+ }
+
public static string ReadLine ()
{
return stdin.ReadLine ();
public static string ReadLine ()
{
return stdin.ReadLine ();
ConsoleDriver.SetWindowSize (width, height);
}
ConsoleDriver.SetWindowSize (width, height);
}
- [MonoTODO ("Implement add/remove hooks")]
public static event ConsoleCancelEventHandler CancelKeyPress;
public static event ConsoleCancelEventHandler CancelKeyPress;
+
+ delegate void InternalCancelHandler ();
+ static InternalCancelHandler cancel_handler = new InternalCancelHandler (DoConsoleCancelEvent);
+
+ internal static void DoConsoleCancelEvent ()
+ {
+ bool exit = true;
+ if (CancelKeyPress != null) {
+ ConsoleCancelEventArgs args = new ConsoleCancelEventArgs (ConsoleSpecialKey.ControlC);
+ Delegate [] delegates = CancelKeyPress.GetInvocationList ();
+ foreach (ConsoleCancelEventHandler d in delegates){
+ try {
+ // Sender is always null here.
+ d (null, args);
+ } catch {} // Ignore any exception.
+ }
+ exit = !args.Cancel;
+ }
+
+ if (exit)
+ Environment.Exit (58);
+ }
namespace System {
class ConsoleDriver {
static IConsoleDriver driver;
namespace System {
class ConsoleDriver {
static IConsoleDriver driver;
+ static bool is_console;
+ static bool called_isatty;
static ConsoleDriver ()
{
static ConsoleDriver ()
{
targetLeft, targetTop, sourceChar, sourceForeColor, sourceBackColor);
}
targetLeft, targetTop, sourceChar, sourceForeColor, sourceBackColor);
}
+ public static int Read ()
+ {
+ return ReadKey (false).KeyChar;
+ }
+
+ public static string ReadLine ()
+ {
+ return driver.ReadLine ();
+ }
+
public static ConsoleKeyInfo ReadKey (bool intercept)
{
return driver.ReadKey (intercept);
public static ConsoleKeyInfo ReadKey (bool intercept)
{
return driver.ReadKey (intercept);
driver.SetWindowSize (width, height);
}
driver.SetWindowSize (width, height);
}
+ public static bool IsConsole {
+ get {
+ if (called_isatty)
+ return is_console;
+
+ is_console = (Isatty (MonoIO.ConsoleOutput) && Isatty (MonoIO.ConsoleInput));
+ called_isatty = true;
+ return is_console;
+ }
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern bool Isatty (IntPtr handle);
+ static extern bool Isatty (IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int InternalKeyAvailable (int ms_timeout);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int InternalKeyAvailable (int ms_timeout);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern bool TtySetup (string teardown);
+ internal static extern bool TtySetup (string teardown, out byte verase, out byte vsusp, out byte intr);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool SetEcho (bool wantEcho);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool SetEcho (bool wantEcho);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool GetTtySize (IntPtr handle, out int width, out int height);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool GetTtySize (IntPtr handle, out int width, out int height);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void Suspend ();
void SetCursorPosition (int left, int top);
void SetWindowPosition (int left, int top);
void SetWindowSize (int width, int height);
void SetCursorPosition (int left, int top);
void SetWindowPosition (int left, int top);
void SetWindowSize (int width, int height);
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2005 Novell, Inc (http://www.novell.com)
+// (C) 2005,2006 Novell, Inc (http://www.novell.com)
#if NET_2_0
using System.Collections;
using System.IO;
#if NET_2_0
using System.Collections;
using System.IO;
namespace System {
class TermInfoDriver : IConsoleDriver {
static string [] locations = { "/etc/terminfo", "/usr/share/terminfo", "/usr/lib/terminfo" };
namespace System {
class TermInfoDriver : IConsoleDriver {
static string [] locations = { "/etc/terminfo", "/usr/share/terminfo", "/usr/lib/terminfo" };
string term;
Stream stdout;
Stream stdin;
string term;
Stream stdout;
Stream stdin;
+ byte verase;
+ byte vsusp;
+ byte intr;
int windowWidth;
int windowHeight;
int windowWidth;
int windowHeight;
byte [] buffer;
int readpos;
int writepos;
byte [] buffer;
int readpos;
int writepos;
- string enterCA, exitCA;
string keypadXmit, keypadLocal;
bool controlCAsInput;
bool inited;
string keypadXmit, keypadLocal;
bool controlCAsInput;
bool inited;
if (reader == null)
reader = new TermInfoReader (term, KnownTerminals.ansi);
if (reader == null)
reader = new TermInfoReader (term, KnownTerminals.ansi);
}
public bool Initialized {
}
public bool Initialized {
+
+ /* This should not happen any more, since it is checked for in Console */
+ if (!ConsoleDriver.IsConsole)
+ throw new IOException ("Not a tty.");
- enterCA = reader.Get (TermInfoStrings.EnterCaMode);
- exitCA = reader.Get (TermInfoStrings.ExitCaMode);
+ ConsoleDriver.SetEcho (false);
- if (enterCA != null && exitCA != null)
- endString = exitCA;
-
keypadXmit = reader.Get (TermInfoStrings.KeypadXmit);
keypadLocal = reader.Get (TermInfoStrings.KeypadLocal);
if (keypadXmit != null) {
keypadXmit = reader.Get (TermInfoStrings.KeypadXmit);
keypadLocal = reader.Get (TermInfoStrings.KeypadLocal);
if (keypadXmit != null) {
- WriteConsole (keypadXmit);
+ WriteConsole (keypadXmit); // Needed to get the arrows working
if (keypadLocal != null)
endString += keypadLocal;
}
if (keypadLocal != null)
endString += keypadLocal;
}
- if (!ConsoleDriver.Isatty (MonoIO.ConsoleOutput) || !ConsoleDriver.Isatty (MonoIO.ConsoleInput))
- throw new IOException ("Not a tty.");
-
origPair = reader.Get (TermInfoStrings.OrigPair);
origColors = reader.Get (TermInfoStrings.OrigColors);
setafcolor = MangleParameters (reader.Get (TermInfoStrings.SetAForeground));
origPair = reader.Get (TermInfoStrings.OrigPair);
origColors = reader.Get (TermInfoStrings.OrigColors);
setafcolor = MangleParameters (reader.Get (TermInfoStrings.SetAForeground));
if (resetColors != null)
endString += resetColors;
if (resetColors != null)
endString += resetColors;
- if (!ConsoleDriver.TtySetup (endString))
+ if (!ConsoleDriver.TtySetup (endString, out verase, out vsusp, out intr))
throw new IOException ("Error initializing terminal.");
throw new IOException ("Error initializing terminal.");
- if (enterCA != null && exitCA != null)
- WriteConsole (enterCA);
-
stdout = Console.OpenStandardOutput (0);
stdin = Console.OpenStandardInput (0);
clear = reader.Get (TermInfoStrings.ClearScreen);
stdout = Console.OpenStandardOutput (0);
stdin = Console.OpenStandardInput (0);
clear = reader.Get (TermInfoStrings.ClearScreen);
home_1_1 = (cursorAddress != result);
cursorAddress = MangleParameters (result);
}
home_1_1 = (cursorAddress != result);
cursorAddress = MangleParameters (result);
}
+
+ GetCursorPosition ();
+ if (noGetPosition) {
+ WriteConsole (clear);
+ cursorLeft = 0;
+ cursorTop = 0;
+ }
}
static string MangleParameters (string str)
}
static string MangleParameters (string str)
public ConsoleColor BackgroundColor {
get { return bgcolor; }
set {
public ConsoleColor BackgroundColor {
get { return bgcolor; }
set {
bgcolor = value;
WriteConsole (String.Format (setabcolor, TranslateColor (value)));
}
bgcolor = value;
WriteConsole (String.Format (setabcolor, TranslateColor (value)));
}
public ConsoleColor ForegroundColor {
get { return fgcolor; }
set {
public ConsoleColor ForegroundColor {
get { return fgcolor; }
set {
fgcolor = value;
WriteConsole (String.Format (setafcolor, TranslateColor (value)));
}
}
fgcolor = value;
WriteConsole (String.Format (setafcolor, TranslateColor (value)));
}
}
void GetCursorPosition ()
{
void GetCursorPosition ()
{
- if (noGetPosition)
- return;
-
int row = 0, col = 0;
bool prevEcho = Echo;
Echo = false;
int row = 0, col = 0;
bool prevEcho = Echo;
Echo = false;
public int BufferHeight {
get {
public int BufferHeight {
get {
- GetWindowDimensions ();
return bufferHeight;
}
set {
return bufferHeight;
}
set {
public int BufferWidth {
get {
public int BufferWidth {
get {
- GetWindowDimensions ();
return bufferWidth;
}
set {
return bufferWidth;
}
set {
public int CursorLeft {
get {
public int CursorLeft {
get {
GetCursorPosition ();
return cursorLeft;
}
set {
GetCursorPosition ();
return cursorLeft;
}
set {
SetCursorPosition (value, CursorTop);
cursorLeft = value;
}
SetCursorPosition (value, CursorTop);
cursorLeft = value;
}
public int CursorTop {
get {
public int CursorTop {
get {
GetCursorPosition ();
return cursorTop;
}
set {
GetCursorPosition ();
return cursorTop;
}
set {
SetCursorPosition (CursorLeft, value);
cursorTop = value;
}
SetCursorPosition (CursorLeft, value);
cursorTop = value;
}
public bool CursorVisible {
get {
public bool CursorVisible {
get {
return cursorVisible;
}
set {
return cursorVisible;
}
set {
cursorVisible = value;
WriteConsole ((value ? csrVisible : csrInvisible));
}
cursorVisible = value;
WriteConsole ((value ? csrVisible : csrInvisible));
}
public bool KeyAvailable {
get {
public bool KeyAvailable {
get {
return (writepos > readpos || ConsoleDriver.InternalKeyAvailable (0) > 0);
}
}
return (writepos > readpos || ConsoleDriver.InternalKeyAvailable (0) > 0);
}
}
get { return title; }
set {
get { return title; }
set {
title = value;
WriteConsole (String.Format (titleFormat, value));
}
title = value;
WriteConsole (String.Format (titleFormat, value));
}
if (controlCAsInput == value)
return;
if (controlCAsInput == value)
return;
ConsoleDriver.SetBreak (value);
controlCAsInput = value;
}
}
ConsoleDriver.SetBreak (value);
controlCAsInput = value;
}
}
+ // TODO: use this at the beginning and on every SIGWINCH
void GetWindowDimensions ()
{
void GetWindowDimensions ()
{
- //TODO: Handle SIGWINCH
-
/* Try the ioctl first */
if (!ConsoleDriver.GetTtySize (MonoIO.ConsoleOutput, out windowWidth, out windowHeight)) {
windowWidth = reader.Get (TermInfoNumbers.Columns);
/* Try the ioctl first */
if (!ConsoleDriver.GetTtySize (MonoIO.ConsoleOutput, out windowWidth, out windowHeight)) {
windowWidth = reader.Get (TermInfoNumbers.Columns);
- //windowTop = 0;
- //windowLeft = 0;
bufferHeight = windowHeight;
bufferWidth = windowWidth;
}
bufferHeight = windowHeight;
bufferWidth = windowWidth;
}
WriteConsole (clear);
}
public void Beep (int frequency, int duration)
{
WriteConsole (clear);
}
public void Beep (int frequency, int duration)
{
public ConsoleKeyInfo ReadKey (bool intercept)
{
public ConsoleKeyInfo ReadKey (bool intercept)
{
bool prevEcho = Echo;
if (prevEcho == intercept)
Echo = !intercept;
bool prevEcho = Echo;
if (prevEcho == intercept)
Echo = !intercept;
+ public string ReadLine ()
+ {
+ bool prevEcho = Echo;
+ if (prevEcho == false)
+ Echo = true;
+ StringBuilder builder = new StringBuilder ();
+ bool exit = false;
+ do {
+ ConsoleKeyInfo key = ReadKeyInternal ();
+ char c = key.KeyChar;
+ exit = (c == '\n');
+ if (!exit)
+ builder.Append (c);
+ stdout.WriteByte ((byte) c);
+ } while (!exit);
+ if (prevEcho == false)
+ Echo = prevEcho;
+ return builder.ToString ();
+ }
+
public void ResetColor ()
{
public void ResetColor ()
{
string str = (origPair != null) ? origPair : origColors;
WriteConsole (str);
}
string str = (origPair != null) ? origPair : origColors;
WriteConsole (str);
}
if (top < 0 || top >= bufferHeight)
throw new ArgumentOutOfRangeException ("top", "Value must be positive and below the buffer height.");
if (top < 0 || top >= bufferHeight)
throw new ArgumentOutOfRangeException ("top", "Value must be positive and below the buffer height.");
// Either CursorAddress or nothing.
// We might want to play with up/down/left/right/home when ca is not available.
if (cursorAddress == null)
// Either CursorAddress or nothing.
// We might want to play with up/down/left/right/home when ca is not available.
if (cursorAddress == null)
throw new ArgumentException (String.Empty, "Cannot write to the specified coordinates.");
}
throw new ArgumentException (String.Empty, "Cannot write to the specified coordinates.");
}
+ public string ReadLine ()
+ {
+ StringBuilder builder = new StringBuilder ();
+ bool exit = false;
+ do {
+ ConsoleKeyInfo key = ReadKey (false);
+ char c = key.KeyChar;
+ exit = (c == '\n');
+ if (!exit)
+ builder.Append (key.KeyChar);
+ } while (!exit);
+ return builder.ToString ();
+ }
+
public ConsoleKeyInfo ReadKey (bool intercept)
{
int eventsRead;
public ConsoleKeyInfo ReadKey (bool intercept)
{
int eventsRead;