diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2013-02-27 14:15:34 +0800 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2013-04-15 14:54:21 +0800 |
commit | 6eb39a03bf66d91c37ca5d14dd61a90850a921d3 (patch) | |
tree | a416a0ef8fd7c1f6338481eedf3dd04e8236bad3 /ui/ncurses/nc-boot-editor.c | |
parent | e3ebf4d2ebe3464257655f059ea020565a536643 (diff) | |
download | talos-petitboot-6eb39a03bf66d91c37ca5d14dd61a90850a921d3.tar.gz talos-petitboot-6eb39a03bf66d91c37ca5d14dd61a90850a921d3.zip |
ui/ncurses: ked -> boot-editor
git mv ui/ncurses/nc-ked.c ui/ncurses/nc-boot-editor.c
git mv ui/ncurses/nc-ked.h ui/ncurses/nc-boot-editor.h
find ui/ncurses -type f |
xargs sed -i -e s/nc-ked\./nc-boot-editor./g \
-e s/ked/boot_editor/g
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'ui/ncurses/nc-boot-editor.c')
-rw-r--r-- | ui/ncurses/nc-boot-editor.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/ui/ncurses/nc-boot-editor.c b/ui/ncurses/nc-boot-editor.c new file mode 100644 index 0000000..a9256ff --- /dev/null +++ b/ui/ncurses/nc-boot-editor.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2009 Sony Computer Entertainment Inc. + * Copyright 2009 Sony Corp. + * + * 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; version 2 of the License. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _GNU_SOURCE + +#include <assert.h> +#include <string.h> + +#include "log/log.h" +#include "talloc/talloc.h" +#include "nc-boot-editor.h" + +static struct boot_editor *boot_editor_from_scr(struct nc_scr *scr) +{ + struct boot_editor *boot_editor; + + assert(scr->sig == pb_boot_editor_sig); + boot_editor = (struct boot_editor *) + ((char *)scr - (size_t)&((struct boot_editor *)0)->scr); + assert(boot_editor->scr.sig == pb_boot_editor_sig); + return boot_editor; +} + +static struct boot_editor *boot_editor_from_arg(void *arg) +{ + struct boot_editor *boot_editor = arg; + + assert(boot_editor->scr.sig == pb_boot_editor_sig); + return boot_editor; +} + +/** + * boot_editor_move_cursor - Move the cursor, setting correct attributes. + * @req: An ncurses request or char to send to form_driver(). + */ + +static int boot_editor_move_cursor(struct boot_editor *boot_editor, int req) +{ + int result; + + wchgat(boot_editor->scr.sub_ncw, 1, + boot_editor_attr_field_selected, 0, 0); + result = form_driver(boot_editor->ncf, req); + wchgat(boot_editor->scr.sub_ncw, 1, boot_editor->attr_cursor, 0, 0); + wrefresh(boot_editor->scr.main_ncw); + return result; +} + +/** + * boot_editor_insert_mode_set - Set the insert mode. + */ + +static void boot_editor_insert_mode_set(struct boot_editor *boot_editor, + int req) +{ + switch (req) { + case REQ_INS_MODE: + boot_editor->attr_cursor = boot_editor_attr_cursor_ins; + break; + case REQ_OVL_MODE: + boot_editor->attr_cursor = boot_editor_attr_cursor_ovl; + break; + default: + assert(0 && "bad req"); + break; + } + boot_editor_move_cursor(boot_editor, req); +} + +/** + * boot_editor_insert_mode_tog - Toggle the insert mode. + */ + +static void boot_editor_insert_mode_tog(struct boot_editor *boot_editor) +{ + if (boot_editor->attr_cursor == boot_editor_attr_cursor_ins) + boot_editor_insert_mode_set(boot_editor, REQ_OVL_MODE); + else + boot_editor_insert_mode_set(boot_editor, REQ_INS_MODE); +} + +/** + * boot_editor_move_field - Move selected field, setting correct attributes. + * @req: An ncurses request to send to form_driver(). + */ + +static int boot_editor_move_field(struct boot_editor *boot_editor, int req) +{ + int result; + + set_field_back(current_field(boot_editor->ncf), + boot_editor_attr_field_normal); + + result = form_driver(boot_editor->ncf, req); + + set_field_back(current_field(boot_editor->ncf), + boot_editor_attr_field_selected); + + boot_editor_move_cursor(boot_editor, REQ_END_FIELD); + return result; +} + +static int boot_editor_post(struct nc_scr *scr) +{ + struct boot_editor *boot_editor = boot_editor_from_scr(scr); + + post_form(boot_editor->ncf); + + nc_scr_frame_draw(scr); + boot_editor_move_field(boot_editor, REQ_FIRST_FIELD); + boot_editor_move_field(boot_editor, REQ_END_FIELD); + boot_editor_insert_mode_set(boot_editor, REQ_INS_MODE); + + redrawwin(boot_editor->scr.main_ncw); + wrefresh(boot_editor->scr.main_ncw); + + return 0; +} + +static int boot_editor_unpost(struct nc_scr *scr) +{ + return unpost_form(boot_editor_from_scr(scr)->ncf); +} + +static void boot_editor_resize(struct nc_scr *scr) +{ + /* FIXME: forms can't be resized, need to recreate here */ + boot_editor_unpost(scr); + boot_editor_post(scr); +} + +/** + * boot_editor_chomp - Eat leading and trailing WS. + */ + +static char *boot_editor_chomp(char *s) +{ + char *start; + char *end; + char *const s_end = s + strlen(s); + + for (; s < s_end; s++) + if (*s != ' ' && *s != '\t') + break; + + start = end = s; + + for (; s < s_end; s++) + if (*s != ' ' && *s != '\t') + end = s; + *(end + 1) = 0; + return start; +} + +static struct pb_kexec_data *boot_editor_prepare_data( + struct boot_editor *boot_editor) +{ + struct pb_kexec_data *kd; + char *s; + + kd = talloc(boot_editor, struct pb_kexec_data); + + if (!kd) + return NULL; + + s = boot_editor_chomp(field_buffer(boot_editor->fields[0], 0)); + kd->image = *s ? talloc_strdup(kd, s) : NULL; + + s = boot_editor_chomp(field_buffer(boot_editor->fields[1], 0)); + kd->initrd = *s ? talloc_strdup(kd, s) : NULL; + + s = boot_editor_chomp(field_buffer(boot_editor->fields[2], 0)); + kd->args = *s ? talloc_strdup(kd, s) : NULL; + + return kd; +} + +/** + * boot_editor_process_key - Process a user keystroke. + * + * Called from the cui via the scr:process_key method. + */ + +static void boot_editor_process_key(struct nc_scr *scr) +{ + struct boot_editor *boot_editor = boot_editor_from_scr(scr); + struct pb_kexec_data *kd; + + while (1) { + int c = getch(); + + if (c == ERR) + return; + + /* DBGS("%d (%o)\n", c, c); */ + + switch (c) { + default: + boot_editor_move_cursor(boot_editor, c); + break; + + /* hot keys */ + case 27: /* ESC */ + boot_editor->on_exit(boot_editor, + boot_editor_cancel, NULL); + nc_flush_keys(); + return; + case '\n': + case '\r': + form_driver(boot_editor->ncf, REQ_VALIDATION); + kd = boot_editor_prepare_data(boot_editor); + boot_editor->on_exit(boot_editor, + boot_editor_update, kd); + nc_flush_keys(); + return; + + /* insert mode */ + case KEY_IC: + boot_editor_insert_mode_tog(boot_editor); + break; + + /* form nav */ + case KEY_PPAGE: + boot_editor_move_field(boot_editor, REQ_FIRST_FIELD); + break; + case KEY_NPAGE: + boot_editor_move_field(boot_editor, REQ_LAST_FIELD); + break; + case KEY_DOWN: + boot_editor_move_field(boot_editor, REQ_NEXT_FIELD); + break; + case KEY_UP: + boot_editor_move_field(boot_editor, REQ_PREV_FIELD); + break; + + /* field nav */ + case KEY_HOME: + boot_editor_move_cursor(boot_editor, REQ_BEG_FIELD); + break; + case KEY_END: + boot_editor_move_cursor(boot_editor, REQ_END_FIELD); + break; + case KEY_LEFT: + boot_editor_move_cursor(boot_editor, REQ_LEFT_CHAR); + break; + case KEY_RIGHT: + boot_editor_move_cursor(boot_editor, REQ_RIGHT_CHAR); + break; + case KEY_BACKSPACE: + if (boot_editor_move_cursor(boot_editor, REQ_LEFT_CHAR) + == E_OK) + boot_editor_move_cursor(boot_editor, + REQ_DEL_CHAR); + break; + case KEY_DC: + boot_editor_move_cursor(boot_editor, REQ_DEL_CHAR); + break; + } + } +} + +/** + * boot_editor_destructor - The talloc destructor for a boot_editor. + */ + +static int boot_editor_destructor(void *arg) +{ + struct boot_editor *boot_editor = boot_editor_from_arg(arg); + FIELD **f; + + for (f = boot_editor->fields; *f; f++) + free_field(*f); + + free_form(boot_editor->ncf); + boot_editor->scr.sig = pb_removed_sig; + + return 0; +} + +static FIELD *boot_editor_setup_field(unsigned int y, unsigned int x, char *str) +{ + FIELD *f; + + f = new_field(1, COLS - 1 - x, y, x, 0, 0); + field_opts_off(f, O_STATIC | O_WRAP); + set_max_field(f, 256); + set_field_buffer(f, 0, str); + set_field_status(f, 0); + return f; +} + +static FIELD *boot_editor_setup_label(unsigned int y, unsigned int x, char *str) +{ + FIELD *f; + + f = new_field(1, strlen(str), y, x, 0, 0); + field_opts_off(f, O_ACTIVE); + set_field_buffer(f, 0, str); + return f; +} + +struct boot_editor *boot_editor_init(void *ui_ctx, + const struct pb_kexec_data *kd, + void (*on_exit)(struct boot_editor *, + enum boot_editor_result, + struct pb_kexec_data *)) +{ + struct boot_editor *boot_editor; + + pb_log("%s: image: '%s'\n", __func__, kd->image); + pb_log("%s: initrd: '%s'\n", __func__, kd->initrd); + pb_log("%s: args: '%s'\n", __func__, kd->args); + + assert(on_exit); + + boot_editor = talloc_zero(ui_ctx, struct boot_editor); + + if (!boot_editor) + return NULL; + + talloc_set_destructor(boot_editor, boot_editor_destructor); + + nc_scr_init(&boot_editor->scr, pb_boot_editor_sig, 0, + ui_ctx, boot_editor_process_key, + boot_editor_post, boot_editor_unpost, boot_editor_resize); + + boot_editor->scr.frame.title = talloc_strdup(boot_editor, + "Petitboot Option Editor"); + boot_editor->scr.frame.help = talloc_strdup(boot_editor, + "ESC=cancel, Enter=accept"); + + boot_editor->on_exit = on_exit; + + boot_editor->fields = talloc_array(boot_editor, FIELD *, 7); + + boot_editor->fields[0] = boot_editor_setup_field(0, 9, kd->image); + boot_editor->fields[1] = boot_editor_setup_field(1, 9, kd->initrd); + boot_editor->fields[2] = boot_editor_setup_field(2, 9, kd->args); + boot_editor->fields[3] = boot_editor_setup_label(0, 1, "image:"); + boot_editor->fields[4] = boot_editor_setup_label(1, 1, "initrd:"); + boot_editor->fields[5] = boot_editor_setup_label(2, 1, "args:"); + boot_editor->fields[6] = NULL; + + boot_editor->ncf = new_form(boot_editor->fields); + + set_form_win(boot_editor->ncf, boot_editor->scr.main_ncw); + set_form_sub(boot_editor->ncf, boot_editor->scr.sub_ncw); + + return boot_editor; +} |