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