1*1b8adde7SWilliam Kucharski /* terminfo.c - read a terminfo entry from the command line */
2*1b8adde7SWilliam Kucharski /*
3*1b8adde7SWilliam Kucharski  *  GRUB  --  GRand Unified Bootloader
4*1b8adde7SWilliam Kucharski  *  Copyright (C) 2002,2004  Free Software Foundation, Inc.
5*1b8adde7SWilliam Kucharski  *
6*1b8adde7SWilliam Kucharski  *  This program is free software; you can redistribute it and/or modify
7*1b8adde7SWilliam Kucharski  *  it under the terms of the GNU General Public License as published by
8*1b8adde7SWilliam Kucharski  *  the Free Software Foundation; either version 2 of the License, or
9*1b8adde7SWilliam Kucharski  *  (at your option) any later version.
10*1b8adde7SWilliam Kucharski  *
11*1b8adde7SWilliam Kucharski  *  This program is distributed in the hope that it will be useful,
12*1b8adde7SWilliam Kucharski  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*1b8adde7SWilliam Kucharski  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*1b8adde7SWilliam Kucharski  *  GNU General Public License for more details.
15*1b8adde7SWilliam Kucharski  *
16*1b8adde7SWilliam Kucharski  *  You should have received a copy of the GNU General Public License
17*1b8adde7SWilliam Kucharski  *  along with this program; if not, write to the Free Software
18*1b8adde7SWilliam Kucharski  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*1b8adde7SWilliam Kucharski  *
20*1b8adde7SWilliam Kucharski  * ######################################################################
21*1b8adde7SWilliam Kucharski  *
22*1b8adde7SWilliam Kucharski  * This file contains various functions dealing with different
23*1b8adde7SWilliam Kucharski  * terminal capabilities. It knows the difference between a vt52 and vt100
24*1b8adde7SWilliam Kucharski  * terminal (and much more) and is mainly used the terminal emulation
25*1b8adde7SWilliam Kucharski  * in the serial driver.
26*1b8adde7SWilliam Kucharski  */
27*1b8adde7SWilliam Kucharski 
28*1b8adde7SWilliam Kucharski #include <shared.h>
29*1b8adde7SWilliam Kucharski #include "terminfo.h"
30*1b8adde7SWilliam Kucharski #include "tparm.h"
31*1b8adde7SWilliam Kucharski #include "serial.h"
32*1b8adde7SWilliam Kucharski 
33*1b8adde7SWilliam Kucharski /* Current terminal capabilities. Default is "vt100".  */
34*1b8adde7SWilliam Kucharski struct terminfo term =
35*1b8adde7SWilliam Kucharski   {
36*1b8adde7SWilliam Kucharski     .name                = "vt100",
37*1b8adde7SWilliam Kucharski     .cursor_address      = "\e[%i%p1%d;%p2%dH",
38*1b8adde7SWilliam Kucharski     .clear_screen        = "\e[H\e[J",
39*1b8adde7SWilliam Kucharski     .enter_standout_mode = "\e[7m",
40*1b8adde7SWilliam Kucharski     .exit_standout_mode  = "\e[m"
41*1b8adde7SWilliam Kucharski   };
42*1b8adde7SWilliam Kucharski 
43*1b8adde7SWilliam Kucharski /* A number of escape sequences are provided in the string valued
44*1b8adde7SWilliam Kucharski    capabilities for easy encoding of characters there.  Both \E and \e
45*1b8adde7SWilliam Kucharski    map to an ESCAPE character, ^x maps to a control-x for any
46*1b8adde7SWilliam Kucharski    appropriate x, and the sequences \n \l \r \t \b \f \s give a
47*1b8adde7SWilliam Kucharski    newline, line-feed, return, tab, backspace, form-feed, and space.
48*1b8adde7SWilliam Kucharski    Other escapes include \^ for ^, \\ for \, \, for comma, \: for :,
49*1b8adde7SWilliam Kucharski    and \0 for null.  (\0 will produce \200, which does not terminate a
50*1b8adde7SWilliam Kucharski    string but behaves as a null character on most terminals, provid�
51*1b8adde7SWilliam Kucharski    ing CS7 is specified.  See stty(1).)  Finally, characters may be
52*1b8adde7SWilliam Kucharski    given as three octal digits after a \.  */
53*1b8adde7SWilliam Kucharski 
54*1b8adde7SWilliam Kucharski char *
ti_unescape_memory(const char * in,const char * end)55*1b8adde7SWilliam Kucharski ti_unescape_memory (const char *in, const char *end)
56*1b8adde7SWilliam Kucharski {
57*1b8adde7SWilliam Kucharski   static char out_buffer[256];
58*1b8adde7SWilliam Kucharski   char c;
59*1b8adde7SWilliam Kucharski   char *out;
60*1b8adde7SWilliam Kucharski 
61*1b8adde7SWilliam Kucharski   out = out_buffer;
62*1b8adde7SWilliam Kucharski   do
63*1b8adde7SWilliam Kucharski     {
64*1b8adde7SWilliam Kucharski       c = *(in++);
65*1b8adde7SWilliam Kucharski       switch (c)
66*1b8adde7SWilliam Kucharski 	{
67*1b8adde7SWilliam Kucharski 	case '^':
68*1b8adde7SWilliam Kucharski 	  if (*in >= 'A' && *in <= 'Z')
69*1b8adde7SWilliam Kucharski 	    {
70*1b8adde7SWilliam Kucharski 	      *out = (*in) - 'A';
71*1b8adde7SWilliam Kucharski 	      in++;
72*1b8adde7SWilliam Kucharski 	    }
73*1b8adde7SWilliam Kucharski 	  else
74*1b8adde7SWilliam Kucharski 	    {
75*1b8adde7SWilliam Kucharski 	      *out = '^';
76*1b8adde7SWilliam Kucharski 	    }
77*1b8adde7SWilliam Kucharski 	  break;
78*1b8adde7SWilliam Kucharski 	case '\\':
79*1b8adde7SWilliam Kucharski 	  c = *(in++);
80*1b8adde7SWilliam Kucharski 	  if (c >= '0' && c <= '9')
81*1b8adde7SWilliam Kucharski 	    {
82*1b8adde7SWilliam Kucharski 	      // octal number
83*1b8adde7SWilliam Kucharski 	      int n = 0;
84*1b8adde7SWilliam Kucharski 	      do
85*1b8adde7SWilliam Kucharski 		{
86*1b8adde7SWilliam Kucharski 		  n = (n << 4) | (c - '0');
87*1b8adde7SWilliam Kucharski 		  c = *(in++);
88*1b8adde7SWilliam Kucharski 		}
89*1b8adde7SWilliam Kucharski 	      while (c >= '0' && c <= '9');
90*1b8adde7SWilliam Kucharski 
91*1b8adde7SWilliam Kucharski 	      *out++ = (char)(n & 0xff);
92*1b8adde7SWilliam Kucharski 
93*1b8adde7SWilliam Kucharski 	      // redo last character
94*1b8adde7SWilliam Kucharski 	      in--;
95*1b8adde7SWilliam Kucharski 
96*1b8adde7SWilliam Kucharski 	      break;
97*1b8adde7SWilliam Kucharski 	    }
98*1b8adde7SWilliam Kucharski 
99*1b8adde7SWilliam Kucharski 	  switch (c)
100*1b8adde7SWilliam Kucharski 	    {
101*1b8adde7SWilliam Kucharski 	    case 'e':
102*1b8adde7SWilliam Kucharski 	    case 'E':
103*1b8adde7SWilliam Kucharski 	      *out++ = '\e';
104*1b8adde7SWilliam Kucharski 	      break;
105*1b8adde7SWilliam Kucharski 	    case 'n':
106*1b8adde7SWilliam Kucharski 	      *out++ = '\n';
107*1b8adde7SWilliam Kucharski 	      break;
108*1b8adde7SWilliam Kucharski 	    case 'r':
109*1b8adde7SWilliam Kucharski 	      *out++ = '\r';
110*1b8adde7SWilliam Kucharski 	      break;
111*1b8adde7SWilliam Kucharski 	    case 't':
112*1b8adde7SWilliam Kucharski 	      *out++ = '\t';
113*1b8adde7SWilliam Kucharski 	      break;
114*1b8adde7SWilliam Kucharski 	    case 'b':
115*1b8adde7SWilliam Kucharski 	      *out++ = '\b';
116*1b8adde7SWilliam Kucharski 	      break;
117*1b8adde7SWilliam Kucharski 	    case 'f':
118*1b8adde7SWilliam Kucharski 	      *out++ = '\f';
119*1b8adde7SWilliam Kucharski 	      break;
120*1b8adde7SWilliam Kucharski 	    case 's':
121*1b8adde7SWilliam Kucharski 	      *out++ = ' ';
122*1b8adde7SWilliam Kucharski 	      break;
123*1b8adde7SWilliam Kucharski 	    case '\\':
124*1b8adde7SWilliam Kucharski 	      *out++ = '\\';
125*1b8adde7SWilliam Kucharski 	      break;
126*1b8adde7SWilliam Kucharski 	    case '^':
127*1b8adde7SWilliam Kucharski 	      *out++ = '^';
128*1b8adde7SWilliam Kucharski 	      break;
129*1b8adde7SWilliam Kucharski 	    case ',':
130*1b8adde7SWilliam Kucharski 	      *out++ = ',';
131*1b8adde7SWilliam Kucharski 	      break;
132*1b8adde7SWilliam Kucharski 	    case ':':
133*1b8adde7SWilliam Kucharski 	      *out++ = ':';
134*1b8adde7SWilliam Kucharski 	      break;
135*1b8adde7SWilliam Kucharski 	    case '0':
136*1b8adde7SWilliam Kucharski 	      *out++ = '\200';
137*1b8adde7SWilliam Kucharski 	      break;
138*1b8adde7SWilliam Kucharski 	    }
139*1b8adde7SWilliam Kucharski 	  break;
140*1b8adde7SWilliam Kucharski 	default:
141*1b8adde7SWilliam Kucharski 	  *out++ = c;
142*1b8adde7SWilliam Kucharski 	  break;
143*1b8adde7SWilliam Kucharski 	}
144*1b8adde7SWilliam Kucharski     }
145*1b8adde7SWilliam Kucharski   while (in <= end);
146*1b8adde7SWilliam Kucharski 
147*1b8adde7SWilliam Kucharski   return out_buffer;
148*1b8adde7SWilliam Kucharski }
149*1b8adde7SWilliam Kucharski 
150*1b8adde7SWilliam Kucharski char *
ti_unescape_string(const char * in)151*1b8adde7SWilliam Kucharski ti_unescape_string (const char *in)
152*1b8adde7SWilliam Kucharski {
153*1b8adde7SWilliam Kucharski   return ti_unescape_memory (in, in + grub_strlen (in));
154*1b8adde7SWilliam Kucharski }
155*1b8adde7SWilliam Kucharski 
156*1b8adde7SWilliam Kucharski /* convert a memory region containing binary character into an external
157*1b8adde7SWilliam Kucharski  * ascii representation. The binary characters will be replaced by an
158*1b8adde7SWilliam Kucharski  * "ecsape notation". E.g. "033" will become "\e". */
159*1b8adde7SWilliam Kucharski char *
ti_escape_memory(const char * in,const char * end)160*1b8adde7SWilliam Kucharski ti_escape_memory (const char *in, const char *end)
161*1b8adde7SWilliam Kucharski {
162*1b8adde7SWilliam Kucharski   static char out_buffer[256];
163*1b8adde7SWilliam Kucharski   char c;
164*1b8adde7SWilliam Kucharski   char *out;
165*1b8adde7SWilliam Kucharski 
166*1b8adde7SWilliam Kucharski   out = out_buffer;
167*1b8adde7SWilliam Kucharski   do
168*1b8adde7SWilliam Kucharski     {
169*1b8adde7SWilliam Kucharski       c = *(in++);
170*1b8adde7SWilliam Kucharski       switch (c)
171*1b8adde7SWilliam Kucharski 	{
172*1b8adde7SWilliam Kucharski 	case '\e':
173*1b8adde7SWilliam Kucharski 	  *out++ = '\\'; *out++ = 'e'; break;
174*1b8adde7SWilliam Kucharski 	case ' ':
175*1b8adde7SWilliam Kucharski 	  *out++ = '\\'; *out++ = 's'; break;
176*1b8adde7SWilliam Kucharski 	case '\\':
177*1b8adde7SWilliam Kucharski 	  *out++ = '\\'; *out++ = '\\'; break;
178*1b8adde7SWilliam Kucharski 	case '0' ... '9':
179*1b8adde7SWilliam Kucharski 	case 'a' ... 'z':
180*1b8adde7SWilliam Kucharski 	case 'A' ... 'Z':
181*1b8adde7SWilliam Kucharski 	case '%':
182*1b8adde7SWilliam Kucharski 	case '+':
183*1b8adde7SWilliam Kucharski 	case '-':
184*1b8adde7SWilliam Kucharski 	case '*':
185*1b8adde7SWilliam Kucharski 	case '/':
186*1b8adde7SWilliam Kucharski 	case ';':
187*1b8adde7SWilliam Kucharski 	case ':':
188*1b8adde7SWilliam Kucharski 	case '{':
189*1b8adde7SWilliam Kucharski 	case '}':
190*1b8adde7SWilliam Kucharski 	case '[':
191*1b8adde7SWilliam Kucharski 	case ']':
192*1b8adde7SWilliam Kucharski 	  *out++ = c; break;
193*1b8adde7SWilliam Kucharski 	case 0 ... 25:
194*1b8adde7SWilliam Kucharski 	  *out++ = '^'; *out++ = 'A' + c; break;
195*1b8adde7SWilliam Kucharski 	default:
196*1b8adde7SWilliam Kucharski 	  *out++ = '\\';
197*1b8adde7SWilliam Kucharski 	  *out++ = ((c >> 8) & 7) + '0';
198*1b8adde7SWilliam Kucharski 	  *out++ = ((c >> 4) & 7) + '0';
199*1b8adde7SWilliam Kucharski 	  *out++ = ((c >> 0) & 7) + '0';
200*1b8adde7SWilliam Kucharski 	  break;
201*1b8adde7SWilliam Kucharski 	}
202*1b8adde7SWilliam Kucharski     }
203*1b8adde7SWilliam Kucharski   while (in < end);
204*1b8adde7SWilliam Kucharski 
205*1b8adde7SWilliam Kucharski   *out++ = 0;
206*1b8adde7SWilliam Kucharski 
207*1b8adde7SWilliam Kucharski   return out_buffer;
208*1b8adde7SWilliam Kucharski }
209*1b8adde7SWilliam Kucharski 
210*1b8adde7SWilliam Kucharski /* convert a string containing binary character into an external ascii
211*1b8adde7SWilliam Kucharski  * representation. */
212*1b8adde7SWilliam Kucharski char *
ti_escape_string(const char * in)213*1b8adde7SWilliam Kucharski ti_escape_string (const char *in)
214*1b8adde7SWilliam Kucharski {
215*1b8adde7SWilliam Kucharski   return ti_escape_memory (in, in + grub_strlen (in));
216*1b8adde7SWilliam Kucharski }
217*1b8adde7SWilliam Kucharski 
218*1b8adde7SWilliam Kucharski /* move the cursor to the given position starting with "0". */
219*1b8adde7SWilliam Kucharski void
ti_cursor_address(int x,int y)220*1b8adde7SWilliam Kucharski ti_cursor_address (int x, int y)
221*1b8adde7SWilliam Kucharski {
222*1b8adde7SWilliam Kucharski   grub_putstr (grub_tparm (term.cursor_address, y, x));
223*1b8adde7SWilliam Kucharski }
224*1b8adde7SWilliam Kucharski 
225*1b8adde7SWilliam Kucharski /* clear the screen. */
226*1b8adde7SWilliam Kucharski void
ti_clear_screen(void)227*1b8adde7SWilliam Kucharski ti_clear_screen (void)
228*1b8adde7SWilliam Kucharski {
229*1b8adde7SWilliam Kucharski   grub_putstr (grub_tparm (term.clear_screen));
230*1b8adde7SWilliam Kucharski }
231*1b8adde7SWilliam Kucharski 
232*1b8adde7SWilliam Kucharski /* enter reverse video */
233*1b8adde7SWilliam Kucharski void
ti_enter_standout_mode(void)234*1b8adde7SWilliam Kucharski ti_enter_standout_mode (void)
235*1b8adde7SWilliam Kucharski {
236*1b8adde7SWilliam Kucharski   grub_putstr (grub_tparm (term.enter_standout_mode));
237*1b8adde7SWilliam Kucharski }
238*1b8adde7SWilliam Kucharski 
239*1b8adde7SWilliam Kucharski /* exit reverse video */
240*1b8adde7SWilliam Kucharski void
ti_exit_standout_mode(void)241*1b8adde7SWilliam Kucharski ti_exit_standout_mode (void)
242*1b8adde7SWilliam Kucharski {
243*1b8adde7SWilliam Kucharski   grub_putstr (grub_tparm (term.exit_standout_mode));
244*1b8adde7SWilliam Kucharski }
245*1b8adde7SWilliam Kucharski 
246*1b8adde7SWilliam Kucharski /* set the current terminal emulation to use */
247*1b8adde7SWilliam Kucharski void
ti_set_term(const struct terminfo * new)248*1b8adde7SWilliam Kucharski ti_set_term (const struct terminfo *new)
249*1b8adde7SWilliam Kucharski {
250*1b8adde7SWilliam Kucharski   grub_memmove (&term, new, sizeof (struct terminfo));
251*1b8adde7SWilliam Kucharski }
252*1b8adde7SWilliam Kucharski 
253*1b8adde7SWilliam Kucharski /* get the current terminal emulation */
254*1b8adde7SWilliam Kucharski void
ti_get_term(struct terminfo * copy)255*1b8adde7SWilliam Kucharski ti_get_term(struct terminfo *copy)
256*1b8adde7SWilliam Kucharski {
257*1b8adde7SWilliam Kucharski   grub_memmove (copy, &term, sizeof (struct terminfo));
258*1b8adde7SWilliam Kucharski }
259