ui/ncurses: Abstract text-screen code from sysinfo screen
[petitboot] / ui / ncurses / nc-textscreen.c
1 /*
2  *  Copyright (C) 2013 IBM Corporation
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; version 2 of the License.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17
18 #if defined(HAVE_CONFIG_H)
19 #include "config.h"
20 #endif
21
22 #include <string.h>
23
24 #include <talloc/talloc.h>
25 #include <types/types.h>
26 #include <log/log.h>
27 #include <util/util.h>
28
29 #include "nc-cui.h"
30 #include "nc-textscreen.h"
31
32 struct text_screen *text_screen_from_scr(struct nc_scr *scr)
33 {
34         struct text_screen *text_screen;
35         assert(scr->sig == pb_text_screen_sig);
36         text_screen = container_of(scr, struct text_screen, scr);
37         return text_screen;
38 }
39
40 void text_screen_draw(struct text_screen *screen)
41 {
42         int max_y, i;
43
44         max_y = getmaxy(screen->scr.sub_ncw);
45
46         max_y = min(max_y, screen->scroll_y + screen->n_lines);
47
48         for (i = screen->scroll_y; i < max_y; i++)
49                 mvwaddstr(screen->scr.sub_ncw, i, 1, screen->lines[i]);
50
51         wrefresh(screen->scr.sub_ncw);
52 }
53
54 static void text_screen_scroll(struct text_screen *screen, int key)
55 {
56         int win_lines = getmaxy(screen->scr.sub_ncw);
57         int delta;
58
59         if (key == KEY_UP)
60                 delta = -1;
61         else if (key == KEY_DOWN)
62                 delta = 1;
63         else
64                 return;
65
66         if (screen->scroll_y + delta < 0)
67                 return;
68         if (screen->scroll_y + delta + win_lines > screen->n_lines)
69                 return;
70
71         screen->scroll_y += delta;
72         wscrl(screen->scr.sub_ncw, delta);
73
74         if (delta > 0) {
75                 mvwaddstr(screen->scr.sub_ncw, win_lines - 1, 1,
76                                 screen->lines[screen->scroll_y+win_lines-1]);
77         } else if (delta < 0) {
78                 mvwaddstr(screen->scr.sub_ncw, 0, 1,
79                                 screen->lines[screen->scroll_y]);
80         }
81
82         wrefresh(screen->scr.sub_ncw);
83 }
84
85 void text_screen_clear(struct text_screen *screen)
86 {
87         talloc_free(screen->lines);
88         screen->n_lines = 0;
89         screen->n_alloc_lines = 16;
90         screen->lines = talloc_array(screen, char *, screen->n_alloc_lines);
91 }
92
93 void text_screen_append_line(struct text_screen *screen, const char *fmt, ...)
94 {
95         char *line;
96         va_list ap;
97
98         if (fmt) {
99                 va_start(ap, fmt);
100                 line = talloc_vasprintf(screen->lines, fmt, ap);
101                 va_end(ap);
102         } else {
103                 line = "";
104         }
105
106         if (screen->n_lines == screen->n_alloc_lines) {
107                 screen->n_alloc_lines *= 2;
108                 screen->lines = talloc_realloc(screen, screen->lines,
109                                                 char *, screen->n_alloc_lines);
110         }
111
112         screen->lines[screen->n_lines] = line;
113         screen->n_lines++;
114 }
115
116
117 void text_screen_process_key(struct nc_scr *scr, int key)
118 {
119         struct text_screen *screen = text_screen_from_scr(scr);
120
121         switch (key) {
122         case 'x':
123                 screen->on_exit(screen->cui);
124                 break;
125         case KEY_DOWN:
126         case KEY_UP:
127                 text_screen_scroll(screen, key);
128                 break;
129         default:
130                 break;
131         }
132 }
133
134 static void text_screen_resize(struct nc_scr *scr)
135 {
136         struct text_screen *screen = text_screen_from_scr(scr);
137         text_screen_draw(screen);
138 }
139
140 struct nc_scr *text_screen_scr(struct text_screen *screen)
141 {
142         return &screen->scr;
143 }
144
145 static int text_screen_post(struct nc_scr *scr)
146 {
147         nc_scr_frame_draw(scr);
148         redrawwin(scr->main_ncw);
149         wrefresh(scr->main_ncw);
150         return 0;
151 }
152
153 void text_screen_init(struct text_screen *screen, struct cui *cui,
154                 const char *title, void (*on_exit)(struct cui *))
155 {
156         nc_scr_init(&screen->scr, pb_text_screen_sig, 0,
157                         cui, text_screen_process_key,
158                         text_screen_post, NULL, text_screen_resize);
159
160         screen->cui = cui;
161         screen->on_exit = on_exit;
162
163         screen->scr.frame.ltitle = talloc_strdup(screen, title);
164         screen->scr.frame.rtitle = NULL;
165         screen->scr.frame.help = "x=exit";
166         scrollok(screen->scr.sub_ncw, true);
167 }