| /* terminfo.c - read a terminfo entry from the command line */ |
| /* |
| * GRUB -- GRand Unified Bootloader |
| * Copyright (C) 2002,2004 Free Software Foundation, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| * |
| * ###################################################################### |
| * |
| * This file contains various functions dealing with different |
| * terminal capabilities. It knows the difference between a vt52 and vt100 |
| * terminal (and much more) and is mainly used the terminal emulation |
| * in the serial driver. |
| */ |
| |
| #include <shared.h> |
| #include "terminfo.h" |
| #include "tparm.h" |
| #include "serial.h" |
| |
| /* Current terminal capabilities. Default is "vt100". */ |
| struct terminfo term = |
| { |
| .name = "vt100", |
| .cursor_address = "\e[%i%p1%d;%p2%dH", |
| .clear_screen = "\e[H\e[J", |
| .enter_standout_mode = "\e[7m", |
| .exit_standout_mode = "\e[m" |
| }; |
| |
| /* A number of escape sequences are provided in the string valued |
| capabilities for easy encoding of characters there. Both \E and \e |
| map to an ESCAPE character, ^x maps to a control-x for any |
| appropriate x, and the sequences \n \l \r \t \b \f \s give a |
| newline, line-feed, return, tab, backspace, form-feed, and space. |
| Other escapes include \^ for ^, \\ for \, \, for comma, \: for :, |
| and \0 for null. (\0 will produce \200, which does not terminate a |
| string but behaves as a null character on most terminals, providĀ |
| ing CS7 is specified. See stty(1).) Finally, characters may be |
| given as three octal digits after a \. */ |
| |
| static char * |
| ti_unescape_memory (const char *in, const char *end) |
| { |
| static char out_buffer[256]; |
| char c; |
| char *out; |
| |
| out = out_buffer; |
| do |
| { |
| c = *(in++); |
| switch (c) |
| { |
| case '^': |
| if (*in >= 'A' && *in <= 'Z') |
| { |
| *out = (*in) - 'A'; |
| in++; |
| } |
| else |
| { |
| *out = '^'; |
| } |
| break; |
| case '\\': |
| c = *(in++); |
| if (c >= '0' && c <= '9') |
| { |
| // octal number |
| int n = 0; |
| do |
| { |
| n = (n << 4) | (c - '0'); |
| c = *(in++); |
| } |
| while (c >= '0' && c <= '9'); |
| |
| *out++ = (char)(n & 0xff); |
| |
| // redo last character |
| in--; |
| |
| break; |
| } |
| |
| switch (c) |
| { |
| case 'e': |
| case 'E': |
| *out++ = '\e'; |
| break; |
| case 'n': |
| *out++ = '\n'; |
| break; |
| case 'r': |
| *out++ = '\r'; |
| break; |
| case 't': |
| *out++ = '\t'; |
| break; |
| case 'b': |
| *out++ = '\b'; |
| break; |
| case 'f': |
| *out++ = '\f'; |
| break; |
| case 's': |
| *out++ = ' '; |
| break; |
| case '\\': |
| *out++ = '\\'; |
| break; |
| case '^': |
| *out++ = '^'; |
| break; |
| case ',': |
| *out++ = ','; |
| break; |
| case ':': |
| *out++ = ':'; |
| break; |
| case '0': |
| *out++ = '\200'; |
| break; |
| } |
| break; |
| default: |
| *out++ = c; |
| break; |
| } |
| } |
| while (in <= end); |
| |
| return out_buffer; |
| } |
| |
| char * |
| ti_unescape_string (const char *in) |
| { |
| return ti_unescape_memory (in, in + grub_strlen (in)); |
| } |
| |
| /* convert a memory region containing binary character into an external |
| * ascii representation. The binary characters will be replaced by an |
| * "ecsape notation". E.g. "033" will become "\e". */ |
| static char * |
| ti_escape_memory (const char *in, const char *end) |
| { |
| static char out_buffer[256]; |
| char c; |
| char *out; |
| |
| out = out_buffer; |
| do |
| { |
| c = *(in++); |
| switch (c) |
| { |
| case '\e': |
| *out++ = '\\'; *out++ = 'e'; break; |
| case ' ': |
| *out++ = '\\'; *out++ = 's'; break; |
| case '\\': |
| *out++ = '\\'; *out++ = '\\'; break; |
| case '0' ... '9': |
| case 'a' ... 'z': |
| case 'A' ... 'Z': |
| case '%': |
| case '+': |
| case '-': |
| case '*': |
| case '/': |
| case ';': |
| case ':': |
| case '{': |
| case '}': |
| case '[': |
| case ']': |
| *out++ = c; break; |
| case 0 ... 25: |
| *out++ = '^'; *out++ = 'A' + c; break; |
| default: |
| *out++ = '\\'; |
| *out++ = ((c >> 8) & 7) + '0'; |
| *out++ = ((c >> 4) & 7) + '0'; |
| *out++ = ((c >> 0) & 7) + '0'; |
| break; |
| } |
| } |
| while (in < end); |
| |
| *out++ = 0; |
| |
| return out_buffer; |
| } |
| |
| /* convert a string containing binary character into an external ascii |
| * representation. */ |
| char * |
| ti_escape_string (const char *in) |
| { |
| return ti_escape_memory (in, in + grub_strlen (in)); |
| } |
| |
| /* move the cursor to the given position starting with "0". */ |
| void |
| ti_cursor_address (int x, int y) |
| { |
| grub_putstr (grub_tparm (term.cursor_address, y, x)); |
| } |
| |
| /* clear the screen. */ |
| void |
| ti_clear_screen (void) |
| { |
| grub_putstr (grub_tparm (term.clear_screen)); |
| } |
| |
| /* enter reverse video */ |
| void |
| ti_enter_standout_mode (void) |
| { |
| grub_putstr (grub_tparm (term.enter_standout_mode)); |
| } |
| |
| /* exit reverse video */ |
| void |
| ti_exit_standout_mode (void) |
| { |
| grub_putstr (grub_tparm (term.exit_standout_mode)); |
| } |
| |
| /* set the current terminal emulation to use */ |
| void |
| ti_set_term (const struct terminfo *new) |
| { |
| grub_memmove (&term, new, sizeof (struct terminfo)); |
| } |
| |
| /* get the current terminal emulation */ |
| void |
| ti_get_term(struct terminfo *copy) |
| { |
| grub_memmove (copy, &term, sizeof (struct terminfo)); |
| } |