/* terminfo.c - simple terminfo module */ /* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2003,2004,2005,2007 Free Software Foundation, Inc. * * VAS_EBOOT 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 3 of the License, or * (at your option) any later version. * * VAS_EBOOT 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 VAS_EBOOT. If not, see . */ /* * This file contains various functions dealing with different * terminal capabilities. For example, vt52 and vt100. */ #include #include #include #include #include #include #include #include #include #include #include #if defined(__powerpc__) && defined(VAS_EBOOT_MACHINE_IEEE1275) #include #endif VAS_EBOOT_MOD_LICENSE ("GPLv3+"); #define ANSI_CSI 0x9b #define ANSI_CSI_STR "\x9b" static struct VasEBoot_term_output *terminfo_outputs; /* Get current terminfo name. */ char * VasEBoot_terminfo_get_current (struct VasEBoot_term_output *term) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; return data->name; } /* Free *PTR and set *PTR to NULL, to prevent double-free. */ static void VasEBoot_terminfo_free (char **ptr) { VasEBoot_free (*ptr); *ptr = 0; } static void VasEBoot_terminfo_all_free (struct VasEBoot_term_output *term) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; /* Free previously allocated memory. */ VasEBoot_terminfo_free (&data->name); VasEBoot_terminfo_free (&data->gotoxy); VasEBoot_terminfo_free (&data->cls); VasEBoot_terminfo_free (&data->reverse_video_on); VasEBoot_terminfo_free (&data->reverse_video_off); VasEBoot_terminfo_free (&data->cursor_on); VasEBoot_terminfo_free (&data->cursor_off); } /* Set current terminfo type. */ VasEBoot_err_t VasEBoot_terminfo_set_current (struct VasEBoot_term_output *term, const char *str) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; /* TODO * Lookup user specified terminfo type. If found, set term variables * as appropriate. Otherwise return an error. * * How should this be done? * a. A static table included in this module. * - I do not like this idea. * b. A table stored in the configuration directory. * - Users must convert their terminfo settings if we have not already. * c. Look for terminfo files in the configuration directory. * - /usr/share/terminfo is 6.3M on my system. * - /usr/share/terminfo is not on most users boot partition. * + Copying the terminfo files you want to use to the VasEBoot * configuration directory is easier then (b). * d. Your idea here. */ VasEBoot_terminfo_all_free (term); if (VasEBoot_strcmp ("vt100", str) == 0) { data->name = VasEBoot_strdup ("vt100"); data->gotoxy = VasEBoot_strdup ("\e[%i%p1%d;%p2%dH"); data->cls = VasEBoot_strdup ("\e[H\e[J"); data->reverse_video_on = VasEBoot_strdup ("\e[7m"); data->reverse_video_off = VasEBoot_strdup ("\e[m"); data->cursor_on = VasEBoot_strdup ("\e[?25h"); data->cursor_off = VasEBoot_strdup ("\e[?25l"); data->setcolor = NULL; return VasEBoot_errno; } if (VasEBoot_strcmp ("vt100-color", str) == 0) { data->name = VasEBoot_strdup ("vt100-color"); data->gotoxy = VasEBoot_strdup ("\e[%i%p1%d;%p2%dH"); data->cls = VasEBoot_strdup ("\e[H\e[J"); data->reverse_video_on = VasEBoot_strdup ("\e[7m"); data->reverse_video_off = VasEBoot_strdup ("\e[m"); data->cursor_on = VasEBoot_strdup ("\e[?25h"); data->cursor_off = VasEBoot_strdup ("\e[?25l"); data->setcolor = VasEBoot_strdup ("\e[3%p1%dm\e[4%p2%dm"); return VasEBoot_errno; } if (VasEBoot_strcmp ("arc", str) == 0) { data->name = VasEBoot_strdup ("arc"); data->gotoxy = VasEBoot_strdup (ANSI_CSI_STR "%i%p1%d;%p2%dH"); data->cls = VasEBoot_strdup (ANSI_CSI_STR "2J"); data->reverse_video_on = VasEBoot_strdup (ANSI_CSI_STR "7m"); data->reverse_video_off = VasEBoot_strdup (ANSI_CSI_STR "0m"); data->cursor_on = 0; data->cursor_off = 0; data->setcolor = VasEBoot_strdup (ANSI_CSI_STR "3%p1%dm" ANSI_CSI_STR "4%p2%dm"); return VasEBoot_errno; } if (VasEBoot_strcmp ("ieee1275", str) == 0 || VasEBoot_strcmp ("ieee1275-nocursor", str) == 0) { data->name = VasEBoot_strdup ("ieee1275"); data->gotoxy = VasEBoot_strdup ("\e[%i%p1%d;%p2%dH"); /* Clear the screen. Using serial console, screen(1) only recognizes the * ANSI escape sequence. Using video console, Apple Open Firmware * (version 3.1.1) only recognizes the literal ^L. So use both. */ data->cls = VasEBoot_strdup (" \e[2J"); data->reverse_video_on = VasEBoot_strdup ("\e[7m"); data->reverse_video_off = VasEBoot_strdup ("\e[m"); if (VasEBoot_strcmp ("ieee1275", str) == 0) { data->cursor_on = VasEBoot_strdup ("\e[?25h"); data->cursor_off = VasEBoot_strdup ("\e[?25l"); } else { data->cursor_on = 0; data->cursor_off = 0; } data->setcolor = VasEBoot_strdup ("\e[3%p1%dm\e[4%p2%dm"); return VasEBoot_errno; } if (VasEBoot_strcmp ("dumb", str) == 0) { data->name = VasEBoot_strdup ("dumb"); data->gotoxy = NULL; data->cls = NULL; data->reverse_video_on = NULL; data->reverse_video_off = NULL; data->cursor_on = NULL; data->cursor_off = NULL; data->setcolor = NULL; return VasEBoot_errno; } return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("unknown terminfo type `%s'"), str); } VasEBoot_err_t VasEBoot_terminfo_output_register (struct VasEBoot_term_output *term, const char *type) { VasEBoot_err_t err; struct VasEBoot_terminfo_output_state *data; err = VasEBoot_terminfo_set_current (term, type); if (err) return err; data = (struct VasEBoot_terminfo_output_state *) term->data; data->next = terminfo_outputs; terminfo_outputs = term; return VAS_EBOOT_ERR_NONE; } VasEBoot_err_t VasEBoot_terminfo_output_unregister (struct VasEBoot_term_output *term) { struct VasEBoot_term_output **ptr; for (ptr = &terminfo_outputs; *ptr; ptr = &((struct VasEBoot_terminfo_output_state *) (*ptr)->data)->next) if (*ptr == term) { VasEBoot_terminfo_all_free (term); *ptr = ((struct VasEBoot_terminfo_output_state *) (*ptr)->data)->next; return VAS_EBOOT_ERR_NONE; } return VasEBoot_error (VAS_EBOOT_ERR_BUG, "terminal not found"); } /* Wrapper for VasEBoot_putchar to write strings. */ static void putstr (struct VasEBoot_term_output *term, const char *str) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; while (*str) data->put (term, *str++); } struct VasEBoot_term_coordinate VasEBoot_terminfo_getxy (struct VasEBoot_term_output *term) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; return data->pos; } void VasEBoot_terminfo_gotoxy (struct VasEBoot_term_output *term, struct VasEBoot_term_coordinate pos) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; if (pos.x > VasEBoot_term_width (term) || pos.y > VasEBoot_term_height (term)) { VasEBoot_error (VAS_EBOOT_ERR_BUG, "invalid point (%u,%u)", pos.x, pos.y); return; } if (data->gotoxy) putstr (term, VasEBoot_terminfo_tparm (data->gotoxy, pos.y, pos.x)); else { if ((pos.y == data->pos.y) && (pos.x == data->pos.x - 1)) data->put (term, '\b'); } data->pos = pos; } /* Clear the screen. */ void VasEBoot_terminfo_cls (struct VasEBoot_term_output *term) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; putstr (term, VasEBoot_terminfo_tparm (data->cls)); VasEBoot_terminfo_gotoxy (term, (struct VasEBoot_term_coordinate) { 0, 0 }); } void VasEBoot_terminfo_setcolorstate (struct VasEBoot_term_output *term, const VasEBoot_term_color_state state) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; if (data->setcolor) { int fg; int bg; /* Map from VGA to terminal colors. */ const int colormap[8] = { 0, /* Black. */ 4, /* Blue. */ 2, /* Green. */ 6, /* Cyan. */ 1, /* Red. */ 5, /* Magenta. */ 3, /* Yellow. */ 7, /* White. */ }; switch (state) { case VAS_EBOOT_TERM_COLOR_STANDARD: case VAS_EBOOT_TERM_COLOR_NORMAL: fg = VasEBoot_term_normal_color & 0x0f; bg = VasEBoot_term_normal_color >> 4; break; case VAS_EBOOT_TERM_COLOR_HIGHLIGHT: fg = VasEBoot_term_highlight_color & 0x0f; bg = VasEBoot_term_highlight_color >> 4; break; default: return; } putstr (term, VasEBoot_terminfo_tparm (data->setcolor, colormap[fg & 7], colormap[bg & 7])); return; } switch (state) { case VAS_EBOOT_TERM_COLOR_STANDARD: case VAS_EBOOT_TERM_COLOR_NORMAL: putstr (term, VasEBoot_terminfo_tparm (data->reverse_video_off)); break; case VAS_EBOOT_TERM_COLOR_HIGHLIGHT: putstr (term, VasEBoot_terminfo_tparm (data->reverse_video_on)); break; default: break; } } void VasEBoot_terminfo_setcursor (struct VasEBoot_term_output *term, const int on) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; if (on) putstr (term, VasEBoot_terminfo_tparm (data->cursor_on)); else putstr (term, VasEBoot_terminfo_tparm (data->cursor_off)); } /* The terminfo version of putchar. */ void VasEBoot_terminfo_putchar (struct VasEBoot_term_output *term, const struct VasEBoot_unicode_glyph *c) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; /* Keep track of the cursor. */ switch (c->base) { case '\a': break; case '\b': case 127: if (data->pos.x > 0) data->pos.x--; break; case '\n': if (data->pos.y < VasEBoot_term_height (term) - 1) data->pos.y++; break; case '\r': data->pos.x = 0; break; default: if ((int) data->pos.x + c->estimated_width >= (int) VasEBoot_term_width (term) + 1) { data->pos.x = 0; if (data->pos.y < VasEBoot_term_height (term) - 1) data->pos.y++; data->put (term, '\r'); data->put (term, '\n'); } data->pos.x += c->estimated_width; break; } data->put (term, c->base); } struct VasEBoot_term_coordinate VasEBoot_terminfo_getwh (struct VasEBoot_term_output *term) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) term->data; return data->size; } static void VasEBoot_terminfo_readkey (struct VasEBoot_term_input *term, int *keys, int *len, int max_len, int (*readkey) (struct VasEBoot_term_input *term)) { int c; #define CONTINUE_READ \ { \ VasEBoot_uint64_t start; \ /* On 9600 we have to wait up to 12 milliseconds. */ \ start = VasEBoot_get_time_ms (); \ do \ c = readkey (term); \ while (c == -1 && VasEBoot_get_time_ms () - start < 100); \ if (c == -1) \ return; \ \ if (*len >= max_len) \ return; \ \ keys[*len] = c; \ (*len)++; \ } c = readkey (term); if (c < 0) { *len = 0; return; } *len = 1; keys[0] = c; if (c != ANSI_CSI && c != VAS_EBOOT_TERM_ESC) { /* Backspace: Ctrl-h. */ if (c == 0x7f) c = VAS_EBOOT_TERM_BACKSPACE; if (c < 0x20 && c != VAS_EBOOT_TERM_TAB && c!= VAS_EBOOT_TERM_BACKSPACE && c != '\n' && c != '\r') c = VAS_EBOOT_TERM_CTRL | (c - 1 + 'a'); *len = 1; keys[0] = c; return; } { static struct { char key; unsigned ascii; } three_code_table[] = { {'4', VAS_EBOOT_TERM_KEY_DC}, {'A', VAS_EBOOT_TERM_KEY_UP}, {'B', VAS_EBOOT_TERM_KEY_DOWN}, {'C', VAS_EBOOT_TERM_KEY_RIGHT}, {'D', VAS_EBOOT_TERM_KEY_LEFT}, {'F', VAS_EBOOT_TERM_KEY_END}, {'H', VAS_EBOOT_TERM_KEY_HOME}, {'K', VAS_EBOOT_TERM_KEY_END}, {'P', VAS_EBOOT_TERM_KEY_DC}, {'?', VAS_EBOOT_TERM_KEY_PPAGE}, {'/', VAS_EBOOT_TERM_KEY_NPAGE}, {'@', VAS_EBOOT_TERM_KEY_INSERT}, }; static unsigned four_code_table[] = { [1] = VAS_EBOOT_TERM_KEY_HOME, [3] = VAS_EBOOT_TERM_KEY_DC, [5] = VAS_EBOOT_TERM_KEY_PPAGE, [6] = VAS_EBOOT_TERM_KEY_NPAGE, [7] = VAS_EBOOT_TERM_KEY_HOME, [8] = VAS_EBOOT_TERM_KEY_END, [17] = VAS_EBOOT_TERM_KEY_F6, [18] = VAS_EBOOT_TERM_KEY_F7, [19] = VAS_EBOOT_TERM_KEY_F8, [20] = VAS_EBOOT_TERM_KEY_F9, [21] = VAS_EBOOT_TERM_KEY_F10, [23] = VAS_EBOOT_TERM_KEY_F11, [24] = VAS_EBOOT_TERM_KEY_F12, }; char fx_key[] = { 'P', 'Q', 'w', 'x', 't', 'u', 'q', 'r', 'p', 'M', 'A', 'B', 'H', 'F' }; unsigned fx_code[] = { VAS_EBOOT_TERM_KEY_F1, VAS_EBOOT_TERM_KEY_F2, VAS_EBOOT_TERM_KEY_F3, VAS_EBOOT_TERM_KEY_F4, VAS_EBOOT_TERM_KEY_F5, VAS_EBOOT_TERM_KEY_F6, VAS_EBOOT_TERM_KEY_F7, VAS_EBOOT_TERM_KEY_F8, VAS_EBOOT_TERM_KEY_F9, VAS_EBOOT_TERM_KEY_F10, VAS_EBOOT_TERM_KEY_F11, VAS_EBOOT_TERM_KEY_F12, VAS_EBOOT_TERM_KEY_HOME, VAS_EBOOT_TERM_KEY_END }; unsigned i; if (c == VAS_EBOOT_TERM_ESC) { CONTINUE_READ; if (c == 'O') { CONTINUE_READ; for (i = 0; i < ARRAY_SIZE (fx_key); i++) if (fx_key[i] == c) { keys[0] = fx_code[i]; *len = 1; return; } } if (c != '[') return; } CONTINUE_READ; for (i = 0; i < ARRAY_SIZE (three_code_table); i++) if (three_code_table[i].key == c) { keys[0] = three_code_table[i].ascii; *len = 1; return; } switch (c) { case '[': CONTINUE_READ; if (c >= 'A' && c <= 'E') { keys[0] = VAS_EBOOT_TERM_KEY_F1 + c - 'A'; *len = 1; return; } return; case 'O': CONTINUE_READ; for (i = 0; i < ARRAY_SIZE (fx_key); i++) if (fx_key[i] == c) { keys[0] = fx_code[i]; *len = 1; return; } return; case '0': { int num = 0; CONTINUE_READ; if (c != '0' && c != '1') return; num = (c - '0') * 10; CONTINUE_READ; if (c < '0' || c > '9') return; num += (c - '0'); if (num == 0 || num > 12) return; CONTINUE_READ; if (c != 'q') return; keys[0] = fx_code[num - 1]; *len = 1; return; } case '1' ... '9': { unsigned val = c - '0'; CONTINUE_READ; if (c >= '0' && c <= '9') { val = val * 10 + (c - '0'); CONTINUE_READ; } if (c != '~') return; if (val >= ARRAY_SIZE (four_code_table) || four_code_table[val] == 0) return; keys[0] = four_code_table[val]; *len = 1; return; } default: return; } } #undef CONTINUE_READ } /* The terminfo version of getkey. */ int VasEBoot_terminfo_getkey (struct VasEBoot_term_input *termi) { struct VasEBoot_terminfo_input_state *data = (struct VasEBoot_terminfo_input_state *) (termi->data); if (data->npending) { int ret; data->npending--; ret = data->input_buf[0]; VasEBoot_memmove (data->input_buf, data->input_buf + 1, data->npending * sizeof (data->input_buf[0])); return ret; } VasEBoot_terminfo_readkey (termi, data->input_buf, &data->npending, VAS_EBOOT_TERMINFO_READKEY_MAX_LEN, data->readkey); #if defined(__powerpc__) && defined(VAS_EBOOT_MACHINE_IEEE1275) if (data->npending == 1 && data->input_buf[0] == VAS_EBOOT_TERM_ESC && VasEBoot_ieee1275_test_flag (VAS_EBOOT_IEEE1275_FLAG_BROKEN_REPEAT) && VasEBoot_get_time_ms () - data->last_key_time < 1000 && (data->last_key & VAS_EBOOT_TERM_EXTENDED)) { data->npending = 0; data->last_key_time = VasEBoot_get_time_ms (); return data->last_key; } #endif if (data->npending) { int ret; data->npending--; ret = data->input_buf[0]; #if defined(__powerpc__) && defined(VAS_EBOOT_MACHINE_IEEE1275) if (VasEBoot_ieee1275_test_flag (VAS_EBOOT_IEEE1275_FLAG_BROKEN_REPEAT)) { data->last_key = ret; data->last_key_time = VasEBoot_get_time_ms (); } #endif VasEBoot_memmove (data->input_buf, data->input_buf + 1, data->npending * sizeof (data->input_buf[0])); return ret; } return VAS_EBOOT_TERM_NO_KEY; } VasEBoot_err_t VasEBoot_terminfo_input_init (struct VasEBoot_term_input *termi) { struct VasEBoot_terminfo_input_state *data = (struct VasEBoot_terminfo_input_state *) (termi->data); data->npending = 0; return VAS_EBOOT_ERR_NONE; } VasEBoot_err_t VasEBoot_terminfo_output_init (struct VasEBoot_term_output *term) { VasEBoot_terminfo_cls (term); return VAS_EBOOT_ERR_NONE; } /* VAS_EBOOT Command. */ static VasEBoot_err_t print_terminfo (void) { const char *encoding_names[(VAS_EBOOT_TERM_CODE_TYPE_MASK >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT) + 1] = { /* VGA and glyph descriptor types are just for completeness, they are not used on terminfo terminals. */ [VAS_EBOOT_TERM_CODE_TYPE_ASCII >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT] = _("ASCII"), [VAS_EBOOT_TERM_CODE_TYPE_CP437 >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT] = "CP-437", [VAS_EBOOT_TERM_CODE_TYPE_UTF8_LOGICAL >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT] = _("UTF-8"), [VAS_EBOOT_TERM_CODE_TYPE_UTF8_VISUAL >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT] /* TRANSLATORS: visually ordered UTF-8 is a non-compliant encoding based on UTF-8 with right-to-left languages written in reverse. Used on some terminals. Normal UTF-8 is refered as "logically-ordered UTF-8" by opposition. */ = _("visually-ordered UTF-8"), [VAS_EBOOT_TERM_CODE_TYPE_VISUAL_GLYPHS >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT] = "Glyph descriptors", _("Unknown encoding"), _("Unknown encoding"), _("Unknown encoding") }; struct VasEBoot_term_output *cur; VasEBoot_puts_ (N_("Current terminfo types:")); for (cur = terminfo_outputs; cur; cur = ((struct VasEBoot_terminfo_output_state *) cur->data)->next) VasEBoot_printf ("%s: %s\t%s\t%dx%d\n", cur->name, VasEBoot_terminfo_get_current(cur), encoding_names[(cur->flags & VAS_EBOOT_TERM_CODE_TYPE_MASK) >> VAS_EBOOT_TERM_CODE_TYPE_SHIFT], ((struct VasEBoot_terminfo_output_state *) cur->data)->pos.x, ((struct VasEBoot_terminfo_output_state *) cur->data)->pos.y); return VAS_EBOOT_ERR_NONE; } static const struct VasEBoot_arg_option options[] = { {"ascii", 'a', 0, N_("Terminal is ASCII-only [default]."), 0, ARG_TYPE_NONE}, {"utf8", 'u', 0, N_("Terminal is logical-ordered UTF-8."), 0, ARG_TYPE_NONE}, {"visual-utf8", 'v', 0, N_("Terminal is visually-ordered UTF-8."), 0, ARG_TYPE_NONE}, {"geometry", 'g', 0, N_("Terminal has specified geometry."), /* TRANSLATORS: "x" has to be entered in, like an identifier, so please don't use better Unicode codepoints. */ N_("WIDTHxHEIGHT."), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; enum { OPTION_ASCII, OPTION_UTF8, OPTION_VISUAL_UTF8, OPTION_GEOMETRY }; static VasEBoot_err_t VasEBoot_cmd_terminfo (VasEBoot_extcmd_context_t ctxt, int argc, char **args) { struct VasEBoot_term_output *cur; int encoding = VAS_EBOOT_TERM_CODE_TYPE_ASCII; struct VasEBoot_arg_list *state = ctxt->state; int w = 0, h = 0; if (argc == 0) return print_terminfo (); if (state[OPTION_ASCII].set) encoding = VAS_EBOOT_TERM_CODE_TYPE_ASCII; if (state[OPTION_UTF8].set) encoding = VAS_EBOOT_TERM_CODE_TYPE_UTF8_LOGICAL; if (state[OPTION_VISUAL_UTF8].set) encoding = VAS_EBOOT_TERM_CODE_TYPE_UTF8_VISUAL; if (state[OPTION_GEOMETRY].set) { const char *ptr = state[OPTION_GEOMETRY].arg; w = VasEBoot_strtoul (ptr, &ptr, 0); if (VasEBoot_errno) return VasEBoot_errno; if (*ptr != 'x') return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("incorrect terminal dimensions specification")); ptr++; h = VasEBoot_strtoul (ptr, &ptr, 0); if (VasEBoot_errno) return VasEBoot_errno; } for (cur = terminfo_outputs; cur; cur = ((struct VasEBoot_terminfo_output_state *) cur->data)->next) if (VasEBoot_strcmp (args[0], cur->name) == 0 || (VasEBoot_strcmp (args[0], "ofconsole") == 0 && VasEBoot_strcmp ("console", cur->name) == 0)) { cur->flags = (cur->flags & ~VAS_EBOOT_TERM_CODE_TYPE_MASK) | encoding; if (w && h) { struct VasEBoot_terminfo_output_state *data = (struct VasEBoot_terminfo_output_state *) cur->data; data->size.x = w; data->size.y = h; } if (argc == 1) return VAS_EBOOT_ERR_NONE; return VasEBoot_terminfo_set_current (cur, args[1]); } return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("terminal %s isn't found or it's not handled by terminfo"), args[0]); } static VasEBoot_extcmd_t cmd; VAS_EBOOT_MOD_INIT(terminfo) { cmd = VasEBoot_register_extcmd ("terminfo", VasEBoot_cmd_terminfo, 0, N_("[[-a|-u|-v] [-g WxH] [TERM] [TYPE]]"), N_("Set terminfo type of TERM to TYPE.\n"), options); } VAS_EBOOT_MOD_FINI(terminfo) { VasEBoot_unregister_extcmd (cmd); }