2 // System.ConsoleDriver
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2005,2006 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if (NET_2_0||BOOTSTRAP_NET_2_0) && !NET_2_1
32 using System.Collections;
35 using System.Runtime.InteropServices;
37 class TermInfoDriver : IConsoleDriver {
39 // This points to a variable that is updated by unmanage code on window size changes.
40 unsafe static int *native_terminal_size;
42 // The current size that we believe we have
43 static int terminal_size;
45 //static uint flag = 0xdeadbeef;
46 static string [] locations = { "/etc/terminfo", "/usr/share/terminfo", "/usr/lib/terminfo" };
48 TermInfoReader reader;
51 string title = String.Empty;
52 string titleFormat = String.Empty;
53 bool cursorVisible = true;
72 string keypadXmit, keypadLocal;
75 object initLock = new object ();
80 ConsoleColor fgcolor = ConsoleColor.White;
81 ConsoleColor bgcolor = ConsoleColor.Black;
82 bool color16 = false; // terminal supports 16 colors
90 bool home_1_1; // if true, we have to add 1 to x and y when using cursorAddress
91 int rl_startx = -1, rl_starty = -1;
92 byte [] control_characters; // Indexed by ControlCharacters.XXXXXX
97 static string SearchTerminfo (string term)
99 if (term == null || term == String.Empty)
102 // Ignore TERMINFO and TERMINFO_DIRS by now
103 //string terminfo = Environment.GetEnvironmentVariable ("TERMINFO");
104 //string terminfoDirs = Environment.GetEnvironmentVariable ("TERMINFO_DIRS");
106 foreach (string dir in locations) {
107 if (!Directory.Exists (dir))
110 string path = Path.Combine (dir, term.Substring (0, 1));
111 if (!Directory.Exists (dir))
114 path = Path.Combine (path, term);
115 if (!File.Exists (path))
124 void WriteConsole (string str)
129 stdout.InternalWriteString (str);
132 public TermInfoDriver ()
133 : this (Environment.GetEnvironmentVariable ("TERM"))
137 public TermInfoDriver (string term)
140 File.Delete ("console.log");
141 logger = new StreamWriter (File.OpenWrite ("console.log"));
145 if (term == "xterm") {
146 reader = new TermInfoReader (term, KnownTerminals.xterm);
148 } else if (term == "linux") {
149 reader = new TermInfoReader (term, KnownTerminals.linux);
152 string filename = SearchTerminfo (term);
153 if (filename != null)
154 reader = new TermInfoReader (term, filename);
158 reader = new TermInfoReader (term, KnownTerminals.ansi);
160 if (!(Console.stdout is CStreamWriter)) {
161 // Application set its own stdout, we need a reference to the real stdout
162 stdout = new CStreamWriter (Console.OpenStandardOutput (0), Console.OutputEncoding);
163 ((StreamWriter) stdout).AutoFlush = true;
165 stdout = (CStreamWriter) Console.stdout;
169 public bool Initialized {
170 get { return inited; }
183 /* This should not happen any more, since it is checked for in Console */
184 if (!ConsoleDriver.IsConsole)
185 throw new IOException ("Not a tty.");
187 ConsoleDriver.SetEcho (false);
189 string endString = null;
190 keypadXmit = reader.Get (TermInfoStrings.KeypadXmit);
191 keypadLocal = reader.Get (TermInfoStrings.KeypadLocal);
192 if (keypadXmit != null) {
193 WriteConsole (keypadXmit); // Needed to get the arrows working
194 if (keypadLocal != null)
195 endString += keypadLocal;
198 origPair = reader.Get (TermInfoStrings.OrigPair);
199 origColors = reader.Get (TermInfoStrings.OrigColors);
200 setfgcolor = MangleParameters (reader.Get (TermInfoStrings.SetAForeground));
201 setbgcolor = MangleParameters (reader.Get (TermInfoStrings.SetABackground));
202 // lighter fg colours are 90 -> 97 rather than 30 -> 37
203 setlfgcolor = color16 ? setfgcolor.Replace ("[3", "[9") : setfgcolor;
204 // lighter bg colours are 100 -> 107 rather than 40 -> 47
205 setlbgcolor = color16 ? setbgcolor.Replace ("[4", "[10") : setbgcolor;
206 string resetColors = (origColors == null) ? origPair : origColors;
207 if (resetColors != null)
208 endString += resetColors;
211 if (!ConsoleDriver.TtySetup (keypadXmit, endString, out control_characters, out native_terminal_size))
212 throw new IOException ("Error initializing terminal.");
215 stdin = new StreamReader (Console.OpenStandardInput (0), Console.InputEncoding);
216 clear = reader.Get (TermInfoStrings.ClearScreen);
217 bell = reader.Get (TermInfoStrings.Bell);
219 clear = reader.Get (TermInfoStrings.CursorHome);
220 clear += reader.Get (TermInfoStrings.ClrEos);
223 csrVisible = reader.Get (TermInfoStrings.CursorNormal);
224 if (csrVisible == null)
225 csrVisible = reader.Get (TermInfoStrings.CursorVisible);
227 csrInvisible = reader.Get (TermInfoStrings.CursorInvisible);
228 if (term == "cygwin" || term == "linux" || (term != null && term.StartsWith ("xterm")) ||
229 term == "rxvt" || term == "dtterm") {
230 titleFormat = "\x1b]0;{0}\x7"; // icon + window title
231 } else if (term == "iris-ansi") {
232 titleFormat = "\x1bP1.y{0}\x1b\\"; // not tested
233 } else if (term == "sun-cmd") {
234 titleFormat = "\x1b]l{0}\x1b\\"; // not tested
237 cursorAddress = reader.Get (TermInfoStrings.CursorAddress);
238 if (cursorAddress != null) {
239 string result = cursorAddress.Replace ("%i", String.Empty);
240 home_1_1 = (cursorAddress != result);
241 cursorAddress = MangleParameters (result);
244 GetCursorPosition ();
246 logger.WriteLine ("noGetPosition: {0} left: {1} top: {2}", noGetPosition, cursorLeft, cursorTop);
250 WriteConsole (clear);
257 static string MangleParameters (string str)
262 str = str.Replace ("{", "{{");
263 str = str.Replace ("}", "}}");
264 str = str.Replace ("%p1%d", "{0}");
265 return str.Replace ("%p2%d", "{1}");
268 static int TranslateColor (ConsoleColor desired, out bool light)
272 case ConsoleColor.Black:
275 case ConsoleColor.DarkRed:
278 case ConsoleColor.DarkGreen:
281 case ConsoleColor.DarkYellow:
284 case ConsoleColor.DarkBlue:
287 case ConsoleColor.DarkMagenta:
290 case ConsoleColor.DarkCyan:
293 case ConsoleColor.Gray:
297 case ConsoleColor.DarkGray:
300 case ConsoleColor.Red:
303 case ConsoleColor.Green:
306 case ConsoleColor.Yellow:
309 case ConsoleColor.Blue:
312 case ConsoleColor.Magenta:
315 case ConsoleColor.Cyan:
318 case ConsoleColor.White:
331 if (cursorLeft >= WindowWidth) {
334 if (cursorTop >= WindowHeight) {
335 // Writing beyond the initial screen
336 if (rl_starty != -1) rl_starty--;
342 // Should never get called unless inited
343 public void WriteSpecialKey (ConsoleKeyInfo key)
346 case ConsoleKey.Backspace:
347 if (cursorLeft > 0) {
348 if (cursorLeft <= rl_startx && cursorTop == rl_starty)
351 SetCursorPosition (cursorLeft, cursorTop);
353 SetCursorPosition (cursorLeft, cursorTop);
356 logger.WriteLine ("BS left: {0} top: {1}", cursorLeft, cursorTop);
361 int n = 8 - (cursorLeft % 8);
362 for (int i = 0; i < n; i++)
365 case ConsoleKey.Clear:
366 WriteConsole (clear);
370 case ConsoleKey.Enter:
376 logger.WriteLine ("left: {0} top: {1}", cursorLeft, cursorTop);
381 // Should never get called unless inited
382 public void WriteSpecialKey (char c)
384 WriteSpecialKey (CreateKeyInfoFromInt (c, false));
387 public bool IsSpecialKey (ConsoleKeyInfo key)
393 case ConsoleKey.Backspace:
397 case ConsoleKey.Clear:
399 case ConsoleKey.Enter:
402 if (cursorTop >= WindowHeight) {
408 // CStreamWriter will handle writing this key
414 public bool IsSpecialKey (char c)
416 return IsSpecialKey (CreateKeyInfoFromInt (c, false));
419 public ConsoleColor BackgroundColor {
435 int colour = TranslateColor (value, out light);
438 WriteConsole (String.Format (setlbgcolor, colour));
440 WriteConsole (String.Format (setbgcolor, colour));
444 public ConsoleColor ForegroundColor {
460 int colour = TranslateColor (value, out light);
463 WriteConsole (String.Format (setlfgcolor, colour));
465 WriteConsole (String.Format (setfgcolor, colour));
469 void GetCursorPosition ()
471 int row = 0, col = 0;
473 WriteConsole ("\x1b[6n");
474 if (ConsoleDriver.InternalKeyAvailable (1000) <= 0) {
475 noGetPosition = true;
479 int b = stdin.Read ();
480 while (b != '\x1b') {
482 if (ConsoleDriver.InternalKeyAvailable (100) <= 0)
489 AddToBuffer ('\x1b');
498 while ((b >= '0') && (b <= '9')) {
499 row = row * 10 + b - '0';
502 // Row/col is 0 based
510 while ((b >= '0') && (b <= '9')) {
511 col = col * 10 + b - '0';
514 // Row/col is 0 based
519 logger.WriteLine ("GetCursorPosition: {0}, {1}", col, row);
527 public int BufferHeight {
540 throw new NotSupportedException ();
544 public int BufferWidth {
557 throw new NotSupportedException ();
561 public bool CapsLock {
567 throw new NotSupportedException ();
571 public int CursorLeft {
584 SetCursorPosition (value, CursorTop);
588 public int CursorTop {
601 SetCursorPosition (CursorLeft, value);
605 public bool CursorVisible {
611 return cursorVisible;
618 cursorVisible = value;
619 WriteConsole ((value ? csrVisible : csrInvisible));
623 // we have CursorNormal vs. CursorVisible...
625 public int CursorSize {
640 public bool KeyAvailable {
646 return (writepos > readpos || ConsoleDriver.InternalKeyAvailable (0) > 0);
650 // We don't know these next 2 values, so return something reasonable
651 public int LargestWindowHeight {
652 get { return WindowHeight; }
655 public int LargestWindowWidth {
656 get { return WindowWidth; }
659 public bool NumberLock {
665 throw new NotSupportedException ();
669 public string Title {
683 WriteConsole (String.Format (titleFormat, value));
687 public bool TreatControlCAsInput {
692 return controlCAsInput;
699 if (controlCAsInput == value)
702 ConsoleDriver.SetBreak (value);
703 controlCAsInput = value;
707 unsafe void CheckWindowDimensions ()
712 if (terminal_size == *native_terminal_size)
715 terminal_size = *native_terminal_size;
716 if (*native_terminal_size == -1){
717 int c = reader.Get (TermInfoNumbers.Columns);
721 c = reader.Get (TermInfoNumbers.Lines);
725 windowWidth = terminal_size >> 16;
726 windowHeight = terminal_size & 0xffff;
728 bufferHeight = windowHeight;
729 bufferWidth = windowWidth;
733 public int WindowHeight {
739 CheckWindowDimensions ();
747 throw new NotSupportedException ();
751 public int WindowLeft {
757 //CheckWindowDimensions ();
765 throw new NotSupportedException ();
769 public int WindowTop {
775 //CheckWindowDimensions ();
783 throw new NotSupportedException ();
787 public int WindowWidth {
793 CheckWindowDimensions ();
801 throw new NotSupportedException ();
811 WriteConsole (clear);
816 public void Beep (int frequency, int duration)
825 public void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
826 int targetLeft, int targetTop, Char sourceChar,
827 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
833 throw new NotImplementedException ();
836 void AddToBuffer (int b)
838 if (buffer == null) {
839 buffer = new char [1024];
840 } else if (writepos >= buffer.Length) {
841 char [] newbuf = new char [buffer.Length * 2];
842 Buffer.BlockCopy (buffer, 0, newbuf, 0, buffer.Length);
846 buffer [writepos++] = (char) b;
851 if (readpos >= writepos) {
852 readpos = writepos = 0;
856 ConsoleKeyInfo CreateKeyInfoFromInt (int n, bool alt)
859 ConsoleKey key = (ConsoleKey)n;
864 key = ConsoleKey.Enter;
865 } else if (n == 8 || n == 9 || n == 12 || n == 13 || n == 19) {
866 /* Values in ConsoleKey */
867 } else if (n >= 1 && n <= 26) {
868 // For Ctrl-a to Ctrl-z.
870 key = ConsoleKey.A + n - 1;
871 } else if (n == 27) {
872 key = ConsoleKey.Escape;
873 } else if (n >= 'a' && n <= 'z') {
874 key = ConsoleKey.A - 'a' + n;
875 } else if (n >= 'A' && n <= 'Z') {
877 } else if (n >= '0' && n <= '9') {
882 return new ConsoleKeyInfo (c, key, shift, alt, ctrl);
885 object GetKeyFromBuffer (bool cooked)
887 if (readpos >= writepos)
890 int next = buffer [readpos];
891 if (!cooked || !rootmap.StartsWith (next)) {
894 return CreateKeyInfoFromInt (next, false);
898 TermInfoStrings str = rootmap.Match (buffer, readpos, writepos - readpos, out used);
899 if ((int) str == -1){
900 // Escape sequences: alt keys are sent as ESC-key
901 if (buffer [readpos] == 27 && (writepos - readpos) >= 2){
904 if (buffer [readpos+1] == 127)
905 return new ConsoleKeyInfo ((char)8, ConsoleKey.Backspace, false, true, false);
906 return CreateKeyInfoFromInt (buffer [readpos+1], true);
912 if (keymap [str] != null) {
913 key = (ConsoleKeyInfo) keymap [str];
917 return CreateKeyInfoFromInt (next, false);
925 ConsoleKeyInfo ReadKeyInternal (out bool fresh)
934 if ((o = GetKeyFromBuffer (true)) == null) {
936 if (ConsoleDriver.InternalKeyAvailable (150) > 0) {
938 AddToBuffer (stdin.Read ());
939 } while (ConsoleDriver.InternalKeyAvailable (0) > 0);
940 } else if (stdin.DataAvailable ()) {
942 AddToBuffer (stdin.Read ());
943 } while (stdin.DataAvailable ());
945 if ((o = GetKeyFromBuffer (false)) != null)
948 AddToBuffer (stdin.Read ());
951 o = GetKeyFromBuffer (true);
954 // freshly read character
957 // this char was pre-buffered (e.g. not fresh)
961 return (ConsoleKeyInfo) o;
964 #region Input echoing optimization
967 // check if we've got pending input we can read immediately
968 return readpos < writepos || stdin.DataAvailable ();
971 char [] echobuf = null;
974 // Queues a character to be echo'd back to the console
975 void QueueEcho (char c)
978 echobuf = new char [1024];
980 echobuf[echon++] = c;
982 if (echon == echobuf.Length || !InputPending ()) {
983 // blit our echo buffer to the console
984 stdout.InternalWriteChars (echobuf, echon);
989 // Queues a key to be echo'd back to the console
990 void Echo (ConsoleKeyInfo key)
992 if (!IsSpecialKey (key)) {
993 QueueEcho (key.KeyChar);
997 // flush pending echo's
1000 WriteSpecialKey (key);
1003 // Flush the pending echo queue
1009 // flush our echo buffer to the console
1010 stdout.InternalWriteChars (echobuf, echon);
1015 public int Read ([In, Out] char [] dest, int index, int count)
1017 bool fresh, echo = false;
1020 int BoL = 0; // Beginning-of-Line marker (can't backspace beyond this)
1024 sbuf = new StringBuilder ();
1026 // consume buffered keys first (do not echo, these have already been echo'd)
1028 if ((o = GetKeyFromBuffer (true)) == null)
1031 key = (ConsoleKeyInfo) o;
1034 if (key.Key != ConsoleKey.Backspace) {
1035 if (key.Key == ConsoleKey.Enter)
1039 } else if (sbuf.Length > BoL) {
1044 // continue reading until Enter is hit
1045 rl_startx = cursorLeft;
1046 rl_starty = cursorTop;
1049 key = ReadKeyInternal (out fresh);
1050 echo = echo || fresh;
1053 if (key.Key != ConsoleKey.Backspace) {
1054 if (key.Key == ConsoleKey.Enter)
1058 } else if (sbuf.Length > BoL) {
1064 // echo fresh keys back to the console
1067 } while (key.Key != ConsoleKey.Enter);
1074 // copy up to count chars into dest
1076 while (count > 0 && nread < sbuf.Length) {
1077 dest[index + nread] = sbuf[nread];
1082 // put the rest back into our key buffer
1083 for (int i = nread; i < sbuf.Length; i++)
1084 AddToBuffer (sbuf[i]);
1089 public ConsoleKeyInfo ReadKey (bool intercept)
1093 ConsoleKeyInfo key = ReadKeyInternal (out fresh);
1095 if (!intercept && fresh) {
1096 // echo the fresh key back to the console
1104 public string ReadLine ()
1109 // Hack to make Iron Python work (since it goes behind our backs
1110 // when writing to the console thus preventing us from keeping
1111 // cursor state normally).
1112 GetCursorPosition ();
1114 StringBuilder builder = new StringBuilder ();
1115 bool fresh, echo = false;
1119 rl_startx = cursorLeft;
1120 rl_starty = cursorTop;
1121 char eof = (char) control_characters [ControlCharacters.EOF];
1124 key = ReadKeyInternal (out fresh);
1125 echo = echo || fresh;
1127 // EOF -> Ctrl-D (EOT) pressed.
1128 if (c == eof && c != 0 && builder.Length == 0)
1131 if (key.Key != ConsoleKey.Enter) {
1132 if (key.Key != ConsoleKey.Backspace) {
1134 } else if (builder.Length > 0) {
1137 // skips over echoing the key to the console
1142 // echo fresh keys back to the console
1145 } while (key.Key != ConsoleKey.Enter);
1152 return builder.ToString ();
1155 public void ResetColor ()
1161 string str = (origPair != null) ? origPair : origColors;
1165 public void SetBufferSize (int width, int height)
1171 throw new NotImplementedException (String.Empty);
1174 public void SetCursorPosition (int left, int top)
1180 if (bufferWidth == 0)
1181 CheckWindowDimensions ();
1183 if (left < 0 || left >= bufferWidth)
1184 throw new ArgumentOutOfRangeException ("left", "Value must be positive and below the buffer width.");
1186 if (top < 0 || top >= bufferHeight)
1187 throw new ArgumentOutOfRangeException ("top", "Value must be positive and below the buffer height.");
1189 // Either CursorAddress or nothing.
1190 // We might want to play with up/down/left/right/home when ca is not available.
1191 if (cursorAddress == null)
1192 throw new NotSupportedException ("This terminal does not suport setting the cursor position.");
1194 int one = (home_1_1 ? 1 : 0);
1195 WriteConsole (String.Format (cursorAddress, top + one, left + one));
1200 public void SetWindowPosition (int left, int top)
1206 // No need to throw exceptions here.
1207 //throw new NotSupportedException ();
1210 public void SetWindowSize (int width, int height)
1216 // No need to throw exceptions here.
1217 //throw new NotSupportedException ();
1221 void CreateKeyMap ()
1223 keymap = new Hashtable ();
1225 keymap [TermInfoStrings.KeyBackspace] = new ConsoleKeyInfo ('\0', ConsoleKey.Backspace, false, false, false);
1226 keymap [TermInfoStrings.KeyClear] = new ConsoleKeyInfo ('\0', ConsoleKey.Clear, false, false, false);
1227 // Delete character...
1228 keymap [TermInfoStrings.KeyDown] = new ConsoleKeyInfo ('\0', ConsoleKey.DownArrow, false, false, false);
1229 keymap [TermInfoStrings.KeyF1] = new ConsoleKeyInfo ('\0', ConsoleKey.F1, false, false, false);
1230 keymap [TermInfoStrings.KeyF10] = new ConsoleKeyInfo ('\0', ConsoleKey.F10, false, false, false);
1231 keymap [TermInfoStrings.KeyF2] = new ConsoleKeyInfo ('\0', ConsoleKey.F2, false, false, false);
1232 keymap [TermInfoStrings.KeyF3] = new ConsoleKeyInfo ('\0', ConsoleKey.F3, false, false, false);
1233 keymap [TermInfoStrings.KeyF4] = new ConsoleKeyInfo ('\0', ConsoleKey.F4, false, false, false);
1234 keymap [TermInfoStrings.KeyF5] = new ConsoleKeyInfo ('\0', ConsoleKey.F5, false, false, false);
1235 keymap [TermInfoStrings.KeyF6] = new ConsoleKeyInfo ('\0', ConsoleKey.F6, false, false, false);
1236 keymap [TermInfoStrings.KeyF7] = new ConsoleKeyInfo ('\0', ConsoleKey.F7, false, false, false);
1237 keymap [TermInfoStrings.KeyF8] = new ConsoleKeyInfo ('\0', ConsoleKey.F8, false, false, false);
1238 keymap [TermInfoStrings.KeyF9] = new ConsoleKeyInfo ('\0', ConsoleKey.F9, false, false, false);
1239 keymap [TermInfoStrings.KeyHome] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, false, false, false);
1240 keymap [TermInfoStrings.KeyLeft] = new ConsoleKeyInfo ('\0', ConsoleKey.LeftArrow, false, false, false);
1241 keymap [TermInfoStrings.KeyLl] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad1, false, false, false);
1242 keymap [TermInfoStrings.KeyNpage] = new ConsoleKeyInfo ('\0', ConsoleKey.PageDown, false, false, false);
1243 keymap [TermInfoStrings.KeyPpage] = new ConsoleKeyInfo ('\0', ConsoleKey.PageUp, false, false, false);
1244 keymap [TermInfoStrings.KeyRight] = new ConsoleKeyInfo ('\0', ConsoleKey.RightArrow, false, false, false);
1245 keymap [TermInfoStrings.KeySf] = new ConsoleKeyInfo ('\0', ConsoleKey.PageDown, false, false, false);
1246 keymap [TermInfoStrings.KeySr] = new ConsoleKeyInfo ('\0', ConsoleKey.PageUp, false, false, false);
1247 keymap [TermInfoStrings.KeyUp] = new ConsoleKeyInfo ('\0', ConsoleKey.UpArrow, false, false, false);
1248 keymap [TermInfoStrings.KeyA1] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad7, false, false, false);
1249 keymap [TermInfoStrings.KeyA3] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad9, false, false, false);
1250 keymap [TermInfoStrings.KeyB2] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad5, false, false, false);
1251 keymap [TermInfoStrings.KeyC1] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad1, false, false, false);
1252 keymap [TermInfoStrings.KeyC3] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad3, false, false, false);
1253 keymap [TermInfoStrings.KeyBtab] = new ConsoleKeyInfo ('\0', ConsoleKey.Tab, true, false, false);
1254 keymap [TermInfoStrings.KeyBeg] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, false, false, false);
1255 keymap [TermInfoStrings.KeyCopy] = new ConsoleKeyInfo ('C', ConsoleKey.C, false, true, false);
1256 keymap [TermInfoStrings.KeyEnd] = new ConsoleKeyInfo ('\0', ConsoleKey.End, false, false, false);
1257 keymap [TermInfoStrings.KeyEnter] = new ConsoleKeyInfo ('\n', ConsoleKey.Enter, false, false, false);
1258 keymap [TermInfoStrings.KeyHelp] = new ConsoleKeyInfo ('\0', ConsoleKey.Help, false, false, false);
1259 keymap [TermInfoStrings.KeyPrint] = new ConsoleKeyInfo ('\0', ConsoleKey.Print, false, false, false);
1260 keymap [TermInfoStrings.KeyUndo] = new ConsoleKeyInfo ('Z', ConsoleKey.Z , false, true, false);
1261 keymap [TermInfoStrings.KeySbeg] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, true, false, false);
1262 keymap [TermInfoStrings.KeyScopy] = new ConsoleKeyInfo ('C', ConsoleKey.C , true, true, false);
1263 keymap [TermInfoStrings.KeySdc] = new ConsoleKeyInfo ('\x9', ConsoleKey.Delete, true, false, false);
1264 keymap [TermInfoStrings.KeyShelp] = new ConsoleKeyInfo ('\0', ConsoleKey.Help, true, false, false);
1265 keymap [TermInfoStrings.KeyShome] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, true, false, false);
1266 keymap [TermInfoStrings.KeySleft] = new ConsoleKeyInfo ('\0', ConsoleKey.LeftArrow, true, false, false);
1267 keymap [TermInfoStrings.KeySprint] = new ConsoleKeyInfo ('\0', ConsoleKey.Print, true, false, false);
1268 keymap [TermInfoStrings.KeySright] = new ConsoleKeyInfo ('\0', ConsoleKey.RightArrow, true, false, false);
1269 keymap [TermInfoStrings.KeySundo] = new ConsoleKeyInfo ('Z', ConsoleKey.Z, true, false, false);
1270 keymap [TermInfoStrings.KeyF11] = new ConsoleKeyInfo ('\0', ConsoleKey.F11, false, false, false);
1271 keymap [TermInfoStrings.KeyF12] = new ConsoleKeyInfo ('\0', ConsoleKey.F12 , false, false, false);
1272 keymap [TermInfoStrings.KeyF13] = new ConsoleKeyInfo ('\0', ConsoleKey.F13, false, false, false);
1273 keymap [TermInfoStrings.KeyF14] = new ConsoleKeyInfo ('\0', ConsoleKey.F14, false, false, false);
1274 keymap [TermInfoStrings.KeyF15] = new ConsoleKeyInfo ('\0', ConsoleKey.F15, false, false, false);
1275 keymap [TermInfoStrings.KeyF16] = new ConsoleKeyInfo ('\0', ConsoleKey.F16, false, false, false);
1276 keymap [TermInfoStrings.KeyF17] = new ConsoleKeyInfo ('\0', ConsoleKey.F17, false, false, false);
1277 keymap [TermInfoStrings.KeyF18] = new ConsoleKeyInfo ('\0', ConsoleKey.F18, false, false, false);
1278 keymap [TermInfoStrings.KeyF19] = new ConsoleKeyInfo ('\0', ConsoleKey.F19, false, false, false);
1279 keymap [TermInfoStrings.KeyF20] = new ConsoleKeyInfo ('\0', ConsoleKey.F20, false, false, false);
1280 keymap [TermInfoStrings.KeyF21] = new ConsoleKeyInfo ('\0', ConsoleKey.F21, false, false, false);
1281 keymap [TermInfoStrings.KeyF22] = new ConsoleKeyInfo ('\0', ConsoleKey.F22, false, false, false);
1282 keymap [TermInfoStrings.KeyF23] = new ConsoleKeyInfo ('\0', ConsoleKey.F23, false, false, false);
1283 keymap [TermInfoStrings.KeyF24] = new ConsoleKeyInfo ('\0', ConsoleKey.F24, false, false, false);
1284 // These were previously missing:
1285 keymap [TermInfoStrings.KeyDc] = new ConsoleKeyInfo ('\0', ConsoleKey.Delete, false, false, false);
1286 keymap [TermInfoStrings.KeyIc] = new ConsoleKeyInfo ('\0', ConsoleKey.Insert, false, false, false);
1290 // The keys that we know about and use
1292 static TermInfoStrings [] UsedKeys = {
1293 TermInfoStrings.KeyBackspace,
1294 TermInfoStrings.KeyClear,
1295 TermInfoStrings.KeyDown,
1296 TermInfoStrings.KeyF1,
1297 TermInfoStrings.KeyF10,
1298 TermInfoStrings.KeyF2,
1299 TermInfoStrings.KeyF3,
1300 TermInfoStrings.KeyF4,
1301 TermInfoStrings.KeyF5,
1302 TermInfoStrings.KeyF6,
1303 TermInfoStrings.KeyF7,
1304 TermInfoStrings.KeyF8,
1305 TermInfoStrings.KeyF9,
1306 TermInfoStrings.KeyHome,
1307 TermInfoStrings.KeyLeft,
1308 TermInfoStrings.KeyLl,
1309 TermInfoStrings.KeyNpage,
1310 TermInfoStrings.KeyPpage,
1311 TermInfoStrings.KeyRight,
1312 TermInfoStrings.KeySf,
1313 TermInfoStrings.KeySr,
1314 TermInfoStrings.KeyUp,
1315 TermInfoStrings.KeyA1,
1316 TermInfoStrings.KeyA3,
1317 TermInfoStrings.KeyB2,
1318 TermInfoStrings.KeyC1,
1319 TermInfoStrings.KeyC3,
1320 TermInfoStrings.KeyBtab,
1321 TermInfoStrings.KeyBeg,
1322 TermInfoStrings.KeyCopy,
1323 TermInfoStrings.KeyEnd,
1324 TermInfoStrings.KeyEnter,
1325 TermInfoStrings.KeyHelp,
1326 TermInfoStrings.KeyPrint,
1327 TermInfoStrings.KeyUndo,
1328 TermInfoStrings.KeySbeg,
1329 TermInfoStrings.KeyScopy,
1330 TermInfoStrings.KeySdc,
1331 TermInfoStrings.KeyShelp,
1332 TermInfoStrings.KeyShome,
1333 TermInfoStrings.KeySleft,
1334 TermInfoStrings.KeySprint,
1335 TermInfoStrings.KeySright,
1336 TermInfoStrings.KeySundo,
1337 TermInfoStrings.KeyF11,
1338 TermInfoStrings.KeyF12,
1339 TermInfoStrings.KeyF13,
1340 TermInfoStrings.KeyF14,
1341 TermInfoStrings.KeyF15,
1342 TermInfoStrings.KeyF16,
1343 TermInfoStrings.KeyF17,
1344 TermInfoStrings.KeyF18,
1345 TermInfoStrings.KeyF19,
1346 TermInfoStrings.KeyF20,
1347 TermInfoStrings.KeyF21,
1348 TermInfoStrings.KeyF22,
1349 TermInfoStrings.KeyF23,
1350 TermInfoStrings.KeyF24,
1352 // These were missing
1353 TermInfoStrings.KeyDc,
1354 TermInfoStrings.KeyIc
1363 rootmap = new ByteMatcher ();
1365 foreach (TermInfoStrings tis in UsedKeys)
1366 AddStringMapping (tis);
1368 rootmap.AddMapping (TermInfoStrings.KeyBackspace, new byte [] { control_characters [ControlCharacters.Erase] });
1373 void AddStringMapping (TermInfoStrings s)
1375 byte [] bytes = reader.GetStringBytes (s);
1379 rootmap.AddMapping (s, bytes);
1384 Hashtable map = new Hashtable ();
1385 Hashtable starts = new Hashtable ();
1387 public void AddMapping (TermInfoStrings key, byte [] val)
1389 if (val.Length == 0)
1393 starts [(int) val [0]] = true;
1400 public bool StartsWith (int c)
1402 return (starts [c] != null);
1405 public TermInfoStrings Match (char [] buffer, int offset, int length, out int used)
1407 foreach (byte [] bytes in map.Keys) {
1408 for (int i = 0; i < bytes.Length && i < length; i++) {
1409 if ((char) bytes [i] != buffer [offset + i])
1412 if (bytes.Length - 1 == i) {
1413 used = bytes.Length;
1414 return (TermInfoStrings) map [bytes];
1420 return (TermInfoStrings) (-1);