From: Jeremy Kerr Date: Mon, 9 Dec 2013 03:30:19 +0000 (+0800) Subject: ui/ncurses: Abstract text-screen code from sysinfo screen X-Git-Tag: v1.0.0~240 X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=commitdiff_plain;h=445f43743b73fbd63cccba7fa7ae890c907fe6dd ui/ncurses: Abstract text-screen code from sysinfo screen We want to implement help screens, which are very similar to the sysinfo screen - show a set of lines, and allow scrolling. This change splits the text-screen rendering code into a new nc-textinfo module. Signed-off-by: Jeremy Kerr --- diff --git a/ui/ncurses/Makefile.am b/ui/ncurses/Makefile.am index 61ed67e..c03bdb7 100644 --- a/ui/ncurses/Makefile.am +++ b/ui/ncurses/Makefile.am @@ -41,6 +41,8 @@ libpbnc_la_SOURCES = \ nc-scr.h \ nc-sysinfo.c \ nc-sysinfo.h \ + nc-textscreen.c \ + nc-textscreen.h \ nc-widgets.c \ nc-widgets.h diff --git a/ui/ncurses/nc-scr.h b/ui/ncurses/nc-scr.h index 060ee40..50cce33 100644 --- a/ui/ncurses/nc-scr.h +++ b/ui/ncurses/nc-scr.h @@ -44,7 +44,7 @@ enum pb_nc_sig { pb_pmenu_sig = 222, pb_item_sig = 333, pb_boot_editor_sig = 444, - pb_sysinfo_screen_sig = 555, + pb_text_screen_sig = 555, pb_config_screen_sig = 666, pb_removed_sig = -777, }; diff --git a/ui/ncurses/nc-sysinfo.c b/ui/ncurses/nc-sysinfo.c index 1a3d3f5..e907e3d 100644 --- a/ui/ncurses/nc-sysinfo.c +++ b/ui/ncurses/nc-sysinfo.c @@ -27,104 +27,16 @@ #include #include "nc-cui.h" +#include "nc-textscreen.h" #include "nc-sysinfo.h" struct sysinfo_screen { - struct nc_scr scr; - struct cui *cui; - char **lines; - int n_lines; - int n_alloc_lines; - int scroll_y; - void (*on_exit)(struct cui *); + struct text_screen text_scr; }; -static struct sysinfo_screen *sysinfo_screen_from_scr(struct nc_scr *scr) -{ - struct sysinfo_screen *sysinfo_screen; - - assert(scr->sig == pb_sysinfo_screen_sig); - sysinfo_screen = (struct sysinfo_screen *) - ((char *)scr - (size_t)&((struct sysinfo_screen *)0)->scr); - assert(sysinfo_screen->scr.sig == pb_sysinfo_screen_sig); - return sysinfo_screen; -} - -static void sysinfo_screen_draw(struct sysinfo_screen *screen) -{ - int max_y, i; - - max_y = getmaxy(screen->scr.sub_ncw); - - max_y = min(max_y, screen->scroll_y + screen->n_lines); - - for (i = screen->scroll_y; i < max_y; i++) - mvwaddstr(screen->scr.sub_ncw, i, 1, screen->lines[i]); - - wrefresh(screen->scr.sub_ncw); -} - -static void sysinfo_screen_scroll(struct sysinfo_screen *screen, int key) -{ - int win_lines = getmaxy(screen->scr.sub_ncw); - int delta; - - if (key == KEY_UP) - delta = -1; - else if (key == KEY_DOWN) - delta = 1; - else - return; - - if (screen->scroll_y + delta < 0) - return; - if (screen->scroll_y + delta + win_lines > screen->n_lines - 1) - return; - - screen->scroll_y += delta; - wscrl(screen->scr.sub_ncw, delta); - - if (delta > 0) { - mvwaddstr(screen->scr.sub_ncw, win_lines - 1, 1, - screen->lines[screen->scroll_y+win_lines-1]); - } else if (delta < 0) { - mvwaddstr(screen->scr.sub_ncw, 0, 1, - screen->lines[screen->scroll_y]); - } - - wrefresh(screen->scr.sub_ncw); -} - -static void sysinfo_clear(struct sysinfo_screen *screen) +struct nc_scr *sysinfo_screen_scr(struct sysinfo_screen *screen) { - talloc_free(screen->lines); - screen->n_lines = 0; - screen->n_alloc_lines = 16; - screen->lines = talloc_array(screen, char *, screen->n_alloc_lines); -} - -static __attribute__((format(printf, 2, 3))) void sysinfo_screen_append_line( - struct sysinfo_screen *screen, const char *fmt, ...) -{ - char *line; - va_list ap; - - if (fmt) { - va_start(ap, fmt); - line = talloc_vasprintf(screen->lines, fmt, ap); - va_end(ap); - } else { - line = ""; - } - - if (screen->n_lines == screen->n_alloc_lines) { - screen->n_alloc_lines *= 2; - screen->lines = talloc_realloc(screen, screen->lines, - char *, screen->n_alloc_lines); - } - - screen->lines[screen->n_lines] = line; - screen->n_lines++; + return text_screen_scr(&screen->text_scr); } static void if_info_mac_str(struct interface_info *info, @@ -138,9 +50,9 @@ static void sysinfo_screen_populate(struct sysinfo_screen *screen, { unsigned int i; - sysinfo_clear(screen); + text_screen_clear(&screen->text_scr); -#define line(...) sysinfo_screen_append_line(screen, __VA_ARGS__) +#define line(...) text_screen_append_line(&screen->text_scr, __VA_ARGS__) if (!sysinfo) { line("Waiting for system information..."); return; @@ -183,39 +95,11 @@ static void sysinfo_screen_populate(struct sysinfo_screen *screen, #undef line } -static void sysinfo_screen_process_key(struct nc_scr *scr, int key) -{ - struct sysinfo_screen *screen = sysinfo_screen_from_scr(scr); - - switch (key) { - case 'x': - screen->on_exit(screen->cui); - break; - case KEY_DOWN: - case KEY_UP: - sysinfo_screen_scroll(screen, key); - break; - default: - break; - } -} - -static void sysinfo_screen_resize(struct nc_scr *scr) -{ - struct sysinfo_screen *screen = sysinfo_screen_from_scr(scr); - sysinfo_screen_draw(screen); -} - -struct nc_scr *sysinfo_screen_scr(struct sysinfo_screen *screen) -{ - return &screen->scr; -} - void sysinfo_screen_update(struct sysinfo_screen *screen, const struct system_info *sysinfo) { sysinfo_screen_populate(screen, sysinfo); - sysinfo_screen_draw(screen); + text_screen_draw(&screen->text_scr); } struct sysinfo_screen *sysinfo_screen_init(struct cui *cui, @@ -225,23 +109,10 @@ struct sysinfo_screen *sysinfo_screen_init(struct cui *cui, struct sysinfo_screen *screen; screen = talloc_zero(cui, struct sysinfo_screen); - nc_scr_init(&screen->scr, pb_sysinfo_screen_sig, 0, - cui, sysinfo_screen_process_key, - NULL, NULL, sysinfo_screen_resize); - - screen->cui = cui; - screen->on_exit = on_exit; + text_screen_init(&screen->text_scr, cui, + "Petitboot System Information", on_exit); - screen->scr.frame.ltitle = talloc_strdup(screen, - "Petitboot System Information"); - screen->scr.frame.rtitle = NULL; - screen->scr.frame.help = talloc_strdup(screen, "x=exit"); - nc_scr_frame_draw(&screen->scr); - - sysinfo_screen_populate(screen, sysinfo); - wrefresh(screen->scr.main_ncw); - scrollok(screen->scr.sub_ncw, true); - sysinfo_screen_draw(screen); + sysinfo_screen_update(screen, sysinfo); return screen; } diff --git a/ui/ncurses/nc-textscreen.c b/ui/ncurses/nc-textscreen.c new file mode 100644 index 0000000..3b0d01d --- /dev/null +++ b/ui/ncurses/nc-textscreen.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2013 IBM Corporation + * + * 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 + */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include + +#include +#include +#include +#include + +#include "nc-cui.h" +#include "nc-textscreen.h" + +struct text_screen *text_screen_from_scr(struct nc_scr *scr) +{ + struct text_screen *text_screen; + assert(scr->sig == pb_text_screen_sig); + text_screen = container_of(scr, struct text_screen, scr); + return text_screen; +} + +void text_screen_draw(struct text_screen *screen) +{ + int max_y, i; + + max_y = getmaxy(screen->scr.sub_ncw); + + max_y = min(max_y, screen->scroll_y + screen->n_lines); + + for (i = screen->scroll_y; i < max_y; i++) + mvwaddstr(screen->scr.sub_ncw, i, 1, screen->lines[i]); + + wrefresh(screen->scr.sub_ncw); +} + +static void text_screen_scroll(struct text_screen *screen, int key) +{ + int win_lines = getmaxy(screen->scr.sub_ncw); + int delta; + + if (key == KEY_UP) + delta = -1; + else if (key == KEY_DOWN) + delta = 1; + else + return; + + if (screen->scroll_y + delta < 0) + return; + if (screen->scroll_y + delta + win_lines > screen->n_lines) + return; + + screen->scroll_y += delta; + wscrl(screen->scr.sub_ncw, delta); + + if (delta > 0) { + mvwaddstr(screen->scr.sub_ncw, win_lines - 1, 1, + screen->lines[screen->scroll_y+win_lines-1]); + } else if (delta < 0) { + mvwaddstr(screen->scr.sub_ncw, 0, 1, + screen->lines[screen->scroll_y]); + } + + wrefresh(screen->scr.sub_ncw); +} + +void text_screen_clear(struct text_screen *screen) +{ + talloc_free(screen->lines); + screen->n_lines = 0; + screen->n_alloc_lines = 16; + screen->lines = talloc_array(screen, char *, screen->n_alloc_lines); +} + +void text_screen_append_line(struct text_screen *screen, const char *fmt, ...) +{ + char *line; + va_list ap; + + if (fmt) { + va_start(ap, fmt); + line = talloc_vasprintf(screen->lines, fmt, ap); + va_end(ap); + } else { + line = ""; + } + + if (screen->n_lines == screen->n_alloc_lines) { + screen->n_alloc_lines *= 2; + screen->lines = talloc_realloc(screen, screen->lines, + char *, screen->n_alloc_lines); + } + + screen->lines[screen->n_lines] = line; + screen->n_lines++; +} + + +void text_screen_process_key(struct nc_scr *scr, int key) +{ + struct text_screen *screen = text_screen_from_scr(scr); + + switch (key) { + case 'x': + screen->on_exit(screen->cui); + break; + case KEY_DOWN: + case KEY_UP: + text_screen_scroll(screen, key); + break; + default: + break; + } +} + +static void text_screen_resize(struct nc_scr *scr) +{ + struct text_screen *screen = text_screen_from_scr(scr); + text_screen_draw(screen); +} + +struct nc_scr *text_screen_scr(struct text_screen *screen) +{ + return &screen->scr; +} + +static int text_screen_post(struct nc_scr *scr) +{ + nc_scr_frame_draw(scr); + redrawwin(scr->main_ncw); + wrefresh(scr->main_ncw); + return 0; +} + +void text_screen_init(struct text_screen *screen, struct cui *cui, + const char *title, void (*on_exit)(struct cui *)) +{ + nc_scr_init(&screen->scr, pb_text_screen_sig, 0, + cui, text_screen_process_key, + text_screen_post, NULL, text_screen_resize); + + screen->cui = cui; + screen->on_exit = on_exit; + + screen->scr.frame.ltitle = talloc_strdup(screen, title); + screen->scr.frame.rtitle = NULL; + screen->scr.frame.help = "x=exit"; + scrollok(screen->scr.sub_ncw, true); +} diff --git a/ui/ncurses/nc-textscreen.h b/ui/ncurses/nc-textscreen.h new file mode 100644 index 0000000..92c6bfe --- /dev/null +++ b/ui/ncurses/nc-textscreen.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2013 IBM Corporation + * + * 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 + */ + +#ifndef _NC_TEXTSCREEN_H +#define _NC_TEXTSCREEN_H + +#include "types/types.h" +#include "nc-cui.h" + +struct text_screen { + struct nc_scr scr; + struct cui *cui; + char **lines; + int n_lines; + int n_alloc_lines; + int scroll_y; + void (*on_exit)(struct cui *); +}; + +void text_screen_init(struct text_screen *screen, struct cui *cui, + const char *title, void (*on_exit)(struct cui *)); + +struct text_screen *text_screen_from_scr(struct nc_scr *scr); +struct nc_scr *text_screen_scr(struct text_screen *screen); + +/* content modification */ +void text_screen_clear(struct text_screen *screen); +void text_screen_append_line(struct text_screen *screen, + const char *fmt, ...) __attribute__((format(printf, 2, 3))); + +/* interaction */ +void text_screen_process_key(struct nc_scr *scr, int key); +void text_screen_draw(struct text_screen *screen); + + +#endif /* defined _NC_TEXTSCREEN_H */