2 // System.TermInfoReader
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2005 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.
34 // This class reads data from a byte array or file containing the terminfo capabilities
35 // information for any given terminal. The maximum allowed size is 4096 bytes.
37 // Terminfo database files are divided in the following sections:
41 // Boolean capabilities
42 // Numeric capabilities
43 // Offset of string capabilities
44 // String capabilities
46 // The header is as follows:
48 // Magic number (0x1 and 0x1A)
49 // Terminal names size
50 // Boolean section size
51 // Numeric section size
52 // String offsets section size
55 // After the header, there's a NUL terminated string containing terminal names separated
56 // by the character '|'. The last one is the terminal description.
58 // The boolean capabilities section has bytes that are set to 1 if the capability is supported
59 // and 0 otherwise. If the index of a capability is greater than the section size, 0 is assumed.
61 // The numeric capabilities section holds 2-byte integers in little endian format. No negative
62 // values are allowed and the absence of a capability is marked as two 0xFF.
64 // The string offsets section contains 2-byte integer offsets into the string capabilies section.
65 // If the capability is not supported, the index will be two 0xFF bytes.
67 // The string capabilities section contains NUL terminated strings starting at the offsets found
68 // in the previous section.
70 // Terminal capabilities indexes are found in /usr/include/term.h file and described in
74 class TermInfoReader {
81 //string [] names; // Last one is the description
86 public TermInfoReader (string term, string filename)
88 using (FileStream st = File.OpenRead (filename)) {
89 long length = st.Length;
91 throw new Exception ("File must be smaller than 4K");
93 buffer = new byte [(int) length];
94 if (st.Read (buffer, 0, buffer.Length) != buffer.Length)
95 throw new Exception ("Short read");
97 ReadHeader (buffer, ref booleansOffset);
98 ReadNames (buffer, ref booleansOffset);
103 public TermInfoReader (string term, byte [] buffer)
106 throw new ArgumentNullException ("buffer");
108 this.buffer = buffer;
109 ReadHeader (buffer, ref booleansOffset);
110 ReadNames (buffer, ref booleansOffset);
113 // public string Term {
114 // get { return term; }
117 void ReadHeader (byte [] buffer, ref int position)
119 short magic = GetInt16 (buffer, position);
122 throw new Exception (String.Format ("Magic number is wrong: {0}", magic));
124 /*nameSize =*/ GetInt16 (buffer, position);
126 boolSize = GetInt16 (buffer, position);
128 numSize = GetInt16 (buffer, position);
130 strOffsets = GetInt16 (buffer, position);
132 /*strSize =*/ GetInt16 (buffer, position);
136 void ReadNames (byte [] buffer, ref int position)
138 string prev = GetString (buffer, position);
139 position += prev.Length + 1;
140 //names = prev.Split ('|');
143 public bool Get (TermInfoBooleans boolean)
145 int x = (int) boolean;
146 if (x < 0 || boolean >= TermInfoBooleans.Last || x >= boolSize)
149 int offset = booleansOffset;
150 offset += (int) boolean;
151 return (buffer [offset] != 0);
154 public int Get (TermInfoNumbers number)
156 int x = (int) number;
157 if (x < 0 || number >= TermInfoNumbers.Last || x > numSize)
160 int offset = booleansOffset + boolSize;
161 if ((offset % 2) == 1)
164 offset += ((int) number) * 2;
165 return GetInt16 (buffer, offset);
168 public string Get (TermInfoStrings tstr)
171 if (x < 0 || tstr >= TermInfoStrings.Last || x > strOffsets)
174 int offset = booleansOffset + boolSize;
175 if ((offset % 2) == 1)
178 offset += numSize * 2;
179 int off2 = GetInt16 (buffer, offset + (int) tstr * 2);
183 return GetString (buffer, offset + strOffsets * 2 + off2);
186 public byte [] GetStringBytes (TermInfoStrings tstr)
189 if (x < 0 || tstr >= TermInfoStrings.Last || x > strOffsets)
192 int offset = booleansOffset + boolSize;
193 if ((offset % 2) == 1)
196 offset += numSize * 2;
197 int off2 = GetInt16 (buffer, offset + (int) tstr * 2);
201 return GetStringBytes (buffer, offset + strOffsets * 2 + off2);
204 short GetInt16 (byte [] buffer, int offset)
206 int uno = (int) buffer [offset];
207 int dos = (int) buffer [offset + 1];
208 if (uno == 255 && dos == 255)
211 return (short) (uno + dos * 256);
214 string GetString (byte [] buffer, int offset)
218 while (buffer [off++] != 0)
221 return Encoding.ASCII.GetString (buffer, offset, length);
224 byte [] GetStringBytes (byte [] buffer, int offset)
228 while (buffer [off++] != 0)
231 byte [] result = new byte [length];
232 Buffer.BlockCopyInternal (buffer, offset, result, 0, length);
236 internal static string Escape (string s)
238 StringBuilder sb = new StringBuilder ();
239 for (int i = 0; i < s.Length; i++) {
240 char current = s [i];
241 if (Char.IsControl (current)) {
242 sb.AppendFormat ("\\x{0:X2}", (int) current);
248 return sb.ToString ();