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.
32 using System.Collections;
35 using System.Runtime.InteropServices;
37 class TermInfoDriver : IConsoleDriver {
38 /* Do not rename this field, its looked up from the runtime */
39 static bool need_window_dimensions = true;
41 static string [] locations = { "/etc/terminfo", "/usr/share/terminfo", "/usr/lib/terminfo" };
43 TermInfoReader reader;
46 string title = String.Empty;
47 string titleFormat = String.Empty;
48 bool cursorVisible = true;
70 string keypadXmit, keypadLocal;
77 ConsoleColor fgcolor = ConsoleColor.White;
78 ConsoleColor bgcolor = ConsoleColor.Black;
79 bool color16 = false; // terminal supports 16 colors
87 bool home_1_1; // if true, we have to add 1 to x and y when using cursorAddress
88 int rl_startx = -1, rl_starty = -1;
93 static string SearchTerminfo (string term)
95 if (term == null || term == String.Empty)
98 // Ignore TERMINFO and TERMINFO_DIRS by now
99 //string terminfo = Environment.GetEnvironmentVariable ("TERMINFO");
100 //string terminfoDirs = Environment.GetEnvironmentVariable ("TERMINFO_DIRS");
102 foreach (string dir in locations) {
103 if (!Directory.Exists (dir))
106 string path = Path.Combine (dir, term.Substring (0, 1));
107 if (!Directory.Exists (dir))
110 path = Path.Combine (path, term);
111 if (!File.Exists (path))
120 void WriteConsole (string str)
125 stdout.InternalWriteString (str);
128 public TermInfoDriver ()
129 : this (Environment.GetEnvironmentVariable ("TERM"))
133 public TermInfoDriver (string term)
136 File.Delete ("console.log");
137 logger = new StreamWriter (File.OpenWrite ("console.log"));
141 if (term == "xterm") {
142 reader = new TermInfoReader (term, KnownTerminals.xterm);
144 } else if (term == "linux") {
145 reader = new TermInfoReader (term, KnownTerminals.linux);
148 string filename = SearchTerminfo (term);
149 if (filename != null)
150 reader = new TermInfoReader (term, filename);
154 reader = new TermInfoReader (term, KnownTerminals.ansi);
156 if (!(Console.stdout is CStreamWriter)) {
157 // Application set its own stdout, we need a reference to the real stdout
158 stdout = new CStreamWriter (Console.OpenStandardOutput (0), Console.OutputEncoding);
159 ((StreamWriter) stdout).AutoFlush = true;
161 stdout = (CStreamWriter) Console.stdout;
165 public bool Initialized {
166 get { return inited; }
174 /* This should not happen any more, since it is checked for in Console */
175 if (!ConsoleDriver.IsConsole)
176 throw new IOException ("Not a tty.");
180 ConsoleDriver.SetEcho (false);
182 string endString = null;
183 keypadXmit = reader.Get (TermInfoStrings.KeypadXmit);
184 keypadLocal = reader.Get (TermInfoStrings.KeypadLocal);
185 if (keypadXmit != null) {
186 WriteConsole (keypadXmit); // Needed to get the arrows working
187 if (keypadLocal != null)
188 endString += keypadLocal;
191 origPair = reader.Get (TermInfoStrings.OrigPair);
192 origColors = reader.Get (TermInfoStrings.OrigColors);
193 setfgcolor = MangleParameters (reader.Get (TermInfoStrings.SetAForeground));
194 setbgcolor = MangleParameters (reader.Get (TermInfoStrings.SetABackground));
195 // lighter fg colours are 90 -> 97 rather than 30 -> 37
196 setlfgcolor = color16 ? setfgcolor.Replace ("[3", "[9") : setfgcolor;
197 // lighter bg colours are 100 -> 107 rather than 40 -> 47
198 setlbgcolor = color16 ? setbgcolor.Replace ("[4", "[10") : setbgcolor;
199 string resetColors = (origColors == null) ? origPair : origColors;
200 if (resetColors != null)
201 endString += resetColors;
203 if (!ConsoleDriver.TtySetup (endString, out verase, out vsusp, out intr))
204 throw new IOException ("Error initializing terminal.");
206 stdin = new StreamReader (Console.OpenStandardInput (0), Console.InputEncoding);
207 clear = reader.Get (TermInfoStrings.ClearScreen);
208 bell = reader.Get (TermInfoStrings.Bell);
210 clear = reader.Get (TermInfoStrings.CursorHome);
211 clear += reader.Get (TermInfoStrings.ClrEos);
214 csrVisible = reader.Get (TermInfoStrings.CursorNormal);
215 if (csrVisible == null)
216 csrVisible = reader.Get (TermInfoStrings.CursorVisible);
218 csrInvisible = reader.Get (TermInfoStrings.CursorInvisible);
219 if (term == "cygwin" || term == "linux" || (term != null && term.StartsWith ("xterm")) ||
220 term == "rxvt" || term == "dtterm") {
221 titleFormat = "\x1b]0;{0}\x7"; // icon + window title
222 } else if (term == "iris-ansi") {
223 titleFormat = "\x1bP1.y{0}\x1b\\"; // not tested
224 } else if (term == "sun-cmd") {
225 titleFormat = "\x1b]l{0}\x1b\\"; // not tested
228 cursorAddress = reader.Get (TermInfoStrings.CursorAddress);
229 if (cursorAddress != null) {
230 string result = cursorAddress.Replace ("%i", String.Empty);
231 home_1_1 = (cursorAddress != result);
232 cursorAddress = MangleParameters (result);
235 GetCursorPosition ();
237 logger.WriteLine ("noGetPosition: {0} left: {1} top: {2}", noGetPosition, cursorLeft, cursorTop);
241 WriteConsole (clear);
247 static string MangleParameters (string str)
252 str = str.Replace ("{", "{{");
253 str = str.Replace ("}", "}}");
254 str = str.Replace ("%p1%d", "{0}");
255 return str.Replace ("%p2%d", "{1}");
258 static int TranslateColor (ConsoleColor desired, out bool light)
262 case ConsoleColor.Black:
265 case ConsoleColor.DarkRed:
268 case ConsoleColor.DarkGreen:
271 case ConsoleColor.DarkYellow:
274 case ConsoleColor.DarkBlue:
277 case ConsoleColor.DarkMagenta:
280 case ConsoleColor.DarkCyan:
283 case ConsoleColor.Gray:
287 case ConsoleColor.DarkGray:
290 case ConsoleColor.Red:
293 case ConsoleColor.Green:
296 case ConsoleColor.Yellow:
299 case ConsoleColor.Blue:
302 case ConsoleColor.Magenta:
305 case ConsoleColor.Cyan:
308 case ConsoleColor.White:
321 if (cursorLeft >= WindowWidth) {
324 if (cursorTop >= WindowHeight) {
325 // Writing beyond the initial screen
326 if (rl_starty != -1) rl_starty--;
332 // Should never get called unless inited
333 public void WriteSpecialKey (ConsoleKeyInfo key)
336 case ConsoleKey.Backspace:
337 if (cursorLeft > 0) {
338 if (cursorLeft <= rl_startx && cursorTop == rl_starty)
341 SetCursorPosition (cursorLeft, cursorTop);
343 SetCursorPosition (cursorLeft, cursorTop);
346 logger.WriteLine ("BS left: {0} top: {1}", cursorLeft, cursorTop);
351 int n = 8 - (cursorLeft % 8);
352 for (int i = 0; i < n; i++)
355 case ConsoleKey.Clear:
357 case ConsoleKey.Enter:
363 logger.WriteLine ("left: {0} top: {1}", cursorLeft, cursorTop);
368 // Should never get called unless inited
369 public void WriteSpecialKey (char c)
371 WriteSpecialKey (CreateKeyInfoFromInt (c));
374 public bool IsSpecialKey (ConsoleKeyInfo key)
380 case ConsoleKey.Backspace:
384 case ConsoleKey.Clear:
386 case ConsoleKey.Enter:
389 if (cursorTop >= WindowHeight) {
395 // CStreamWriter will handle writing this key
401 public bool IsSpecialKey (char c)
403 return IsSpecialKey (CreateKeyInfoFromInt (c));
406 public ConsoleColor BackgroundColor {
422 int colour = TranslateColor (value, out light);
425 WriteConsole (String.Format (setlbgcolor, colour));
427 WriteConsole (String.Format (setbgcolor, colour));
431 public ConsoleColor ForegroundColor {
447 int colour = TranslateColor (value, out light);
450 WriteConsole (String.Format (setlfgcolor, colour));
452 WriteConsole (String.Format (setfgcolor, colour));
456 void GetCursorPosition ()
458 int row = 0, col = 0;
460 WriteConsole ("\x1b[6n");
461 if (ConsoleDriver.InternalKeyAvailable (1000) <= 0) {
462 noGetPosition = true;
466 int b = stdin.Read ();
467 while (b != '\x1b') {
469 if (ConsoleDriver.InternalKeyAvailable (100) <= 0)
476 AddToBuffer ('\x1b');
485 while ((b >= '0') && (b <= '9')) {
486 row = row * 10 + b - '0';
489 // Row/col is 0 based
497 while ((b >= '0') && (b <= '9')) {
498 col = col * 10 + b - '0';
501 // Row/col is 0 based
506 logger.WriteLine ("GetCursorPosition: {0}, {1}", col, row);
514 public int BufferHeight {
527 throw new NotSupportedException ();
531 public int BufferWidth {
544 throw new NotSupportedException ();
548 public bool CapsLock {
554 throw new NotSupportedException ();
558 public int CursorLeft {
571 SetCursorPosition (value, CursorTop);
575 public int CursorTop {
588 SetCursorPosition (CursorLeft, value);
592 public bool CursorVisible {
598 return cursorVisible;
605 cursorVisible = value;
606 WriteConsole ((value ? csrVisible : csrInvisible));
610 // we have CursorNormal vs. CursorVisible...
612 public int CursorSize {
627 public bool KeyAvailable {
633 return (writepos > readpos || ConsoleDriver.InternalKeyAvailable (0) > 0);
637 // We don't know these next 2 values, so return something reasonable
638 public int LargestWindowHeight {
639 get { return WindowHeight; }
642 public int LargestWindowWidth {
643 get { return WindowWidth; }
646 public bool NumberLock {
652 throw new NotSupportedException ();
656 public string Title {
670 WriteConsole (String.Format (titleFormat, value));
674 public bool TreatControlCAsInput {
679 return controlCAsInput;
686 if (controlCAsInput == value)
689 ConsoleDriver.SetBreak (value);
690 controlCAsInput = value;
694 void GetWindowDimensions ()
696 /* Try the ioctl first */
697 if (!ConsoleDriver.GetTtySize (MonoIO.ConsoleOutput, out windowWidth, out windowHeight)) {
698 windowWidth = reader.Get (TermInfoNumbers.Columns);
699 string env = Environment.GetEnvironmentVariable ("COLUMNS");
702 windowWidth = (int) UInt32.Parse (env);
707 windowHeight = reader.Get (TermInfoNumbers.Lines);
708 env = Environment.GetEnvironmentVariable ("LINES");
711 windowHeight = (int) UInt32.Parse (env);
717 bufferHeight = windowHeight;
718 bufferWidth = windowWidth;
719 need_window_dimensions = false;
722 public int WindowHeight {
728 if (need_window_dimensions)
729 GetWindowDimensions ();
737 throw new NotSupportedException ();
741 public int WindowLeft {
747 //GetWindowDimensions ();
755 throw new NotSupportedException ();
759 public int WindowTop {
765 //GetWindowDimensions ();
773 throw new NotSupportedException ();
777 public int WindowWidth {
783 if (need_window_dimensions)
784 GetWindowDimensions ();
792 throw new NotSupportedException ();
802 WriteConsole (clear);
805 public void Beep (int frequency, int duration)
814 public void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight,
815 int targetLeft, int targetTop, Char sourceChar,
816 ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
822 throw new NotImplementedException ();
825 void AddToBuffer (int b)
827 if (buffer == null) {
828 buffer = new char [1024];
829 } else if (writepos >= buffer.Length) {
830 char [] newbuf = new char [buffer.Length * 2];
831 Buffer.BlockCopy (buffer, 0, newbuf, 0, buffer.Length);
835 buffer [writepos++] = (char) b;
840 if (readpos >= writepos) {
841 readpos = writepos = 0;
845 ConsoleKeyInfo CreateKeyInfoFromInt (int n)
848 ConsoleKey key = (ConsoleKey)n;
854 key = ConsoleKey.Enter;
855 } else if (n == 8 || n == 9 || n == 12 || n == 13 || n == 19) {
856 /* Values in ConsoleKey */
857 } else if (n >= 1 && n <= 26) {
858 // For Ctrl-a to Ctrl-z.
860 key = ConsoleKey.A + n - 1;
861 } else if (n == 27) {
862 key = ConsoleKey.Escape;
863 } else if (n >= 'a' && n <= 'z') {
864 key = ConsoleKey.A - 'a' + n;
865 } else if (n >= 'A' && n <= 'Z') {
867 } else if (n >= '0' && n <= '9') {
872 return new ConsoleKeyInfo (c, key, shift, alt, ctrl);
875 object GetKeyFromBuffer (bool cooked)
877 if (readpos >= writepos)
880 int next = buffer [readpos];
881 if (!cooked || !rootmap.StartsWith (next)) {
884 return CreateKeyInfoFromInt (next);
888 TermInfoStrings str = rootmap.Match (buffer, readpos, writepos - readpos, out used);
893 if (keymap [str] != null) {
894 key = (ConsoleKeyInfo) keymap [str];
898 return CreateKeyInfoFromInt (next);
906 ConsoleKeyInfo ReadKeyInternal (out bool fresh)
915 if ((o = GetKeyFromBuffer (true)) == null) {
917 if (ConsoleDriver.InternalKeyAvailable (150) > 0) {
919 AddToBuffer (stdin.Read ());
920 } while (ConsoleDriver.InternalKeyAvailable (0) > 0);
921 } else if (stdin.Peek () != -1) {
923 AddToBuffer (stdin.Read ());
924 } while (stdin.Peek () != -1);
926 if ((o = GetKeyFromBuffer (false)) != null)
929 AddToBuffer (stdin.Read ());
932 o = GetKeyFromBuffer (true);
935 // freshly read character
938 // this char was pre-buffered (e.g. not fresh)
942 return (ConsoleKeyInfo) o;
945 #region Input echoing optimization
948 // check if we've got pending input we can read immediately
949 return readpos < writepos || stdin.Peek () != -1;
952 char [] echobuf = null;
955 // Queues a character to be echo'd back to the console
956 void QueueEcho (char c)
959 echobuf = new char [1024];
961 echobuf[echon++] = c;
963 if (echon == echobuf.Length || !InputPending ()) {
964 // blit our echo buffer to the console
965 stdout.InternalWriteChars (echobuf, echon);
970 // Queues a key to be echo'd back to the console
971 void Echo (ConsoleKeyInfo key)
973 if (!IsSpecialKey (key)) {
974 QueueEcho (key.KeyChar);
978 // flush pending echo's
981 WriteSpecialKey (key);
984 // Flush the pending echo queue
990 // flush our echo buffer to the console
991 stdout.InternalWriteChars (echobuf, echon);
996 public int Read ([In, Out] char [] dest, int index, int count)
998 bool fresh, echo = false;
1001 int BoL = 0; // Beginning-of-Line marker (can't backspace beyond this)
1005 sbuf = new StringBuilder ();
1007 // consume buffered keys first (do not echo, these have already been echo'd)
1009 if ((o = GetKeyFromBuffer (true)) == null)
1012 key = (ConsoleKeyInfo) o;
1015 if (key.Key != ConsoleKey.Backspace) {
1016 if (key.Key == ConsoleKey.Enter)
1020 } else if (sbuf.Length > BoL) {
1025 // continue reading until Enter is hit
1026 rl_startx = cursorLeft;
1027 rl_starty = cursorTop;
1030 key = ReadKeyInternal (out fresh);
1031 echo = echo || fresh;
1034 if (key.Key != ConsoleKey.Backspace) {
1035 if (key.Key == ConsoleKey.Enter)
1039 } else if (sbuf.Length > BoL) {
1045 // echo fresh keys back to the console
1048 } while (key.Key != ConsoleKey.Enter);
1055 // copy up to count chars into dest
1057 while (count > 0 && nread < sbuf.Length) {
1058 dest[index + nread] = sbuf[nread];
1063 // put the rest back into our key buffer
1064 for (int i = nread; i < sbuf.Length; i++)
1065 AddToBuffer (sbuf[i]);
1070 public ConsoleKeyInfo ReadKey (bool intercept)
1074 ConsoleKeyInfo key = ReadKeyInternal (out fresh);
1076 if (!intercept && fresh) {
1077 // echo the fresh key back to the console
1085 public string ReadLine ()
1090 // Hack to make Iron Python work (since it goes behind our backs
1091 // when writing to the console thus preventing us from keeping
1092 // cursor state normally).
1093 GetCursorPosition ();
1095 StringBuilder builder = new StringBuilder ();
1096 bool fresh, echo = false;
1100 rl_startx = cursorLeft;
1101 rl_starty = cursorTop;
1104 key = ReadKeyInternal (out fresh);
1105 echo = echo || fresh;
1108 if (key.Key != ConsoleKey.Enter) {
1109 if (key.Key != ConsoleKey.Backspace) {
1111 } else if (builder.Length > 0) {
1114 // skips over echoing the key to the console
1119 // echo fresh keys back to the console
1122 } while (key.Key != ConsoleKey.Enter);
1129 return builder.ToString ();
1132 public void ResetColor ()
1138 string str = (origPair != null) ? origPair : origColors;
1142 public void SetBufferSize (int width, int height)
1148 throw new NotImplementedException (String.Empty);
1151 public void SetCursorPosition (int left, int top)
1157 if (bufferWidth == 0 && need_window_dimensions)
1158 GetWindowDimensions ();
1160 if (left < 0 || left >= bufferWidth)
1161 throw new ArgumentOutOfRangeException ("left", "Value must be positive and below the buffer width.");
1163 if (top < 0 || top >= bufferHeight)
1164 throw new ArgumentOutOfRangeException ("top", "Value must be positive and below the buffer height.");
1166 // Either CursorAddress or nothing.
1167 // We might want to play with up/down/left/right/home when ca is not available.
1168 if (cursorAddress == null)
1169 throw new NotSupportedException ("This terminal does not suport setting the cursor position.");
1171 int one = (home_1_1 ? 1 : 0);
1172 WriteConsole (String.Format (cursorAddress, top + one, left + one));
1177 public void SetWindowPosition (int left, int top)
1183 // No need to throw exceptions here.
1184 //throw new NotSupportedException ();
1187 public void SetWindowSize (int width, int height)
1193 // No need to throw exceptions here.
1194 //throw new NotSupportedException ();
1198 void CreateKeyMap ()
1200 keymap = new Hashtable ();
1201 keymap [TermInfoStrings.KeyBackspace] = new ConsoleKeyInfo ('\0', ConsoleKey.Backspace, false, false, false);
1202 keymap [TermInfoStrings.KeyClear] = new ConsoleKeyInfo ('\0', ConsoleKey.Clear, false, false, false);
1203 // Delete character...
1204 keymap [TermInfoStrings.KeyDown] = new ConsoleKeyInfo ('\0', ConsoleKey.DownArrow, false, false, false);
1205 keymap [TermInfoStrings.KeyF1] = new ConsoleKeyInfo ('\0', ConsoleKey.F1, false, false, false);
1206 keymap [TermInfoStrings.KeyF10] = new ConsoleKeyInfo ('\0', ConsoleKey.F10, false, false, false);
1207 keymap [TermInfoStrings.KeyF2] = new ConsoleKeyInfo ('\0', ConsoleKey.F2, false, false, false);
1208 keymap [TermInfoStrings.KeyF3] = new ConsoleKeyInfo ('\0', ConsoleKey.F3, false, false, false);
1209 keymap [TermInfoStrings.KeyF4] = new ConsoleKeyInfo ('\0', ConsoleKey.F4, false, false, false);
1210 keymap [TermInfoStrings.KeyF5] = new ConsoleKeyInfo ('\0', ConsoleKey.F5, false, false, false);
1211 keymap [TermInfoStrings.KeyF6] = new ConsoleKeyInfo ('\0', ConsoleKey.F6, false, false, false);
1212 keymap [TermInfoStrings.KeyF7] = new ConsoleKeyInfo ('\0', ConsoleKey.F7, false, false, false);
1213 keymap [TermInfoStrings.KeyF8] = new ConsoleKeyInfo ('\0', ConsoleKey.F8, false, false, false);
1214 keymap [TermInfoStrings.KeyF9] = new ConsoleKeyInfo ('\0', ConsoleKey.F9, false, false, false);
1215 keymap [TermInfoStrings.KeyHome] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, false, false, false);
1217 keymap [TermInfoStrings.KeyLeft] = new ConsoleKeyInfo ('\0', ConsoleKey.LeftArrow, false, false, false);
1218 keymap [TermInfoStrings.KeyLl] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad1, false, false, false);
1219 keymap [TermInfoStrings.KeyNpage] = new ConsoleKeyInfo ('\0', ConsoleKey.PageDown, false, false, false);
1220 keymap [TermInfoStrings.KeyPpage] = new ConsoleKeyInfo ('\0', ConsoleKey.PageUp, false, false, false);
1221 keymap [TermInfoStrings.KeyRight] = new ConsoleKeyInfo ('\0', ConsoleKey.RightArrow, false, false, false);
1222 keymap [TermInfoStrings.KeySf] = new ConsoleKeyInfo ('\0', ConsoleKey.PageDown, false, false, false);
1223 keymap [TermInfoStrings.KeySr] = new ConsoleKeyInfo ('\0', ConsoleKey.PageUp, false, false, false);
1224 keymap [TermInfoStrings.KeyUp] = new ConsoleKeyInfo ('\0', ConsoleKey.UpArrow, false, false, false);
1225 keymap [TermInfoStrings.KeyA1] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad7, false, false, false);
1226 keymap [TermInfoStrings.KeyA3] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad9, false, false, false);
1227 keymap [TermInfoStrings.KeyB2] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad5, false, false, false);
1228 keymap [TermInfoStrings.KeyC1] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad1, false, false, false);
1229 keymap [TermInfoStrings.KeyC3] = new ConsoleKeyInfo ('\0', ConsoleKey.NumPad3, false, false, false);
1230 keymap [TermInfoStrings.KeyBtab] = new ConsoleKeyInfo ('\0', ConsoleKey.Tab, true, false, false);
1231 keymap [TermInfoStrings.KeyBeg] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, false, false, false);
1232 keymap [TermInfoStrings.KeyCopy] = new ConsoleKeyInfo ('C', ConsoleKey.C, false, true, false);
1233 keymap [TermInfoStrings.KeyEnd] = new ConsoleKeyInfo ('\0', ConsoleKey.End, false, false, false);
1234 keymap [TermInfoStrings.KeyEnter] = new ConsoleKeyInfo ('\n', ConsoleKey.Enter, false, false, false);
1235 keymap [TermInfoStrings.KeyHelp] = new ConsoleKeyInfo ('\0', ConsoleKey.Help, false, false, false);
1236 keymap [TermInfoStrings.KeyPrint] = new ConsoleKeyInfo ('\0', ConsoleKey.Print, false, false, false);
1237 keymap [TermInfoStrings.KeyUndo] = new ConsoleKeyInfo ('Z', ConsoleKey.Z , false, true, false);
1238 keymap [TermInfoStrings.KeySbeg] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, true, false, false);
1239 keymap [TermInfoStrings.KeyScopy] = new ConsoleKeyInfo ('C', ConsoleKey.C , true, true, false);
1240 keymap [TermInfoStrings.KeySdc] = new ConsoleKeyInfo ('\x9', ConsoleKey.Delete, true, false, false);
1241 keymap [TermInfoStrings.KeyShelp] = new ConsoleKeyInfo ('\0', ConsoleKey.Help, true, false, false);
1242 keymap [TermInfoStrings.KeyShome] = new ConsoleKeyInfo ('\0', ConsoleKey.Home, true, false, false);
1243 keymap [TermInfoStrings.KeySleft] = new ConsoleKeyInfo ('\0', ConsoleKey.LeftArrow, true, false, false);
1244 keymap [TermInfoStrings.KeySprint] = new ConsoleKeyInfo ('\0', ConsoleKey.Print, true, false, false);
1245 keymap [TermInfoStrings.KeySright] = new ConsoleKeyInfo ('\0', ConsoleKey.RightArrow, true, false, false);
1246 keymap [TermInfoStrings.KeySundo] = new ConsoleKeyInfo ('Z', ConsoleKey.Z, true, false, false);
1247 keymap [TermInfoStrings.KeyF11] = new ConsoleKeyInfo ('\0', ConsoleKey.F11, false, false, false);
1248 keymap [TermInfoStrings.KeyF12] = new ConsoleKeyInfo ('\0', ConsoleKey.F12 , false, false, false);
1249 keymap [TermInfoStrings.KeyF13] = new ConsoleKeyInfo ('\0', ConsoleKey.F13, false, false, false);
1250 keymap [TermInfoStrings.KeyF14] = new ConsoleKeyInfo ('\0', ConsoleKey.F14, false, false, false);
1251 keymap [TermInfoStrings.KeyF15] = new ConsoleKeyInfo ('\0', ConsoleKey.F15, false, false, false);
1252 keymap [TermInfoStrings.KeyF16] = new ConsoleKeyInfo ('\0', ConsoleKey.F16, false, false, false);
1253 keymap [TermInfoStrings.KeyF17] = new ConsoleKeyInfo ('\0', ConsoleKey.F17, false, false, false);
1254 keymap [TermInfoStrings.KeyF18] = new ConsoleKeyInfo ('\0', ConsoleKey.F18, false, false, false);
1255 keymap [TermInfoStrings.KeyF19] = new ConsoleKeyInfo ('\0', ConsoleKey.F19, false, false, false);
1256 keymap [TermInfoStrings.KeyF20] = new ConsoleKeyInfo ('\0', ConsoleKey.F20, false, false, false);
1257 keymap [TermInfoStrings.KeyF21] = new ConsoleKeyInfo ('\0', ConsoleKey.F21, false, false, false);
1258 keymap [TermInfoStrings.KeyF22] = new ConsoleKeyInfo ('\0', ConsoleKey.F22, false, false, false);
1259 keymap [TermInfoStrings.KeyF23] = new ConsoleKeyInfo ('\0', ConsoleKey.F23, false, false, false);
1260 keymap [TermInfoStrings.KeyF24] = new ConsoleKeyInfo ('\0', ConsoleKey.F24, false, false, false);
1269 rootmap = new ByteMatcher ();
1270 AddStringMapping (TermInfoStrings.KeyBackspace);
1271 AddStringMapping (TermInfoStrings.KeyClear);
1272 AddStringMapping (TermInfoStrings.KeyDown);
1273 AddStringMapping (TermInfoStrings.KeyF1);
1274 AddStringMapping (TermInfoStrings.KeyF10);
1275 AddStringMapping (TermInfoStrings.KeyF2);
1276 AddStringMapping (TermInfoStrings.KeyF3);
1277 AddStringMapping (TermInfoStrings.KeyF4);
1278 AddStringMapping (TermInfoStrings.KeyF5);
1279 AddStringMapping (TermInfoStrings.KeyF6);
1280 AddStringMapping (TermInfoStrings.KeyF7);
1281 AddStringMapping (TermInfoStrings.KeyF8);
1282 AddStringMapping (TermInfoStrings.KeyF9);
1283 AddStringMapping (TermInfoStrings.KeyHome);
1284 AddStringMapping (TermInfoStrings.KeyLeft);
1285 AddStringMapping (TermInfoStrings.KeyLl);
1286 AddStringMapping (TermInfoStrings.KeyNpage);
1287 AddStringMapping (TermInfoStrings.KeyPpage);
1288 AddStringMapping (TermInfoStrings.KeyRight);
1289 AddStringMapping (TermInfoStrings.KeySf);
1290 AddStringMapping (TermInfoStrings.KeySr);
1291 AddStringMapping (TermInfoStrings.KeyUp);
1292 AddStringMapping (TermInfoStrings.KeyA1);
1293 AddStringMapping (TermInfoStrings.KeyA3);
1294 AddStringMapping (TermInfoStrings.KeyB2);
1295 AddStringMapping (TermInfoStrings.KeyC1);
1296 AddStringMapping (TermInfoStrings.KeyC3);
1297 AddStringMapping (TermInfoStrings.KeyBtab);
1298 AddStringMapping (TermInfoStrings.KeyBeg);
1299 AddStringMapping (TermInfoStrings.KeyCopy);
1300 AddStringMapping (TermInfoStrings.KeyEnd);
1301 AddStringMapping (TermInfoStrings.KeyEnter);
1302 AddStringMapping (TermInfoStrings.KeyHelp);
1303 AddStringMapping (TermInfoStrings.KeyPrint);
1304 AddStringMapping (TermInfoStrings.KeyUndo);
1305 AddStringMapping (TermInfoStrings.KeySbeg);
1306 AddStringMapping (TermInfoStrings.KeyScopy);
1307 AddStringMapping (TermInfoStrings.KeySdc);
1308 AddStringMapping (TermInfoStrings.KeyShelp);
1309 AddStringMapping (TermInfoStrings.KeyShome);
1310 AddStringMapping (TermInfoStrings.KeySleft);
1311 AddStringMapping (TermInfoStrings.KeySprint);
1312 AddStringMapping (TermInfoStrings.KeySright);
1313 AddStringMapping (TermInfoStrings.KeySundo);
1314 AddStringMapping (TermInfoStrings.KeyF11);
1315 AddStringMapping (TermInfoStrings.KeyF12);
1316 AddStringMapping (TermInfoStrings.KeyF13);
1317 AddStringMapping (TermInfoStrings.KeyF14);
1318 AddStringMapping (TermInfoStrings.KeyF15);
1319 AddStringMapping (TermInfoStrings.KeyF16);
1320 AddStringMapping (TermInfoStrings.KeyF17);
1321 AddStringMapping (TermInfoStrings.KeyF18);
1322 AddStringMapping (TermInfoStrings.KeyF19);
1323 AddStringMapping (TermInfoStrings.KeyF20);
1324 AddStringMapping (TermInfoStrings.KeyF21);
1325 AddStringMapping (TermInfoStrings.KeyF22);
1326 AddStringMapping (TermInfoStrings.KeyF23);
1327 AddStringMapping (TermInfoStrings.KeyF24);
1332 void AddStringMapping (TermInfoStrings s)
1334 byte [] bytes = reader.GetStringBytes (s);
1338 rootmap.AddMapping (s, bytes);
1343 Hashtable map = new Hashtable ();
1344 Hashtable starts = new Hashtable ();
1346 public void AddMapping (TermInfoStrings key, byte [] val)
1348 if (val.Length == 0)
1352 starts [(int) val [0]] = true;
1359 public bool StartsWith (int c)
1361 return (starts [c] != null);
1364 public TermInfoStrings Match (char [] buffer, int offset, int length, out int used)
1366 foreach (byte [] bytes in map.Keys) {
1367 for (int i = 0; i < bytes.Length && i < length; i++) {
1368 if ((char) bytes [i] != buffer [offset + i])
1371 if (bytes.Length - 1 == i) {
1372 used = bytes.Length;
1373 return (TermInfoStrings) map [bytes];
1379 return (TermInfoStrings) (-1);