blob: fb57efe424d69501b052758bba083092d6505aa8 [file] [log] [blame]
Nicholas Flintham1e3d3112013-04-10 10:48:38 +01001/*
2 * textbox.c -- implements the text box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24static void back_lines(int n);
25static void print_page(WINDOW * win, int height, int width);
26static void print_line(WINDOW * win, int row, int width);
27static char *get_line(void);
28static void print_position(WINDOW * win);
29
30static int hscroll;
31static int begin_reached, end_reached, page_length;
32static const char *buf;
33static const char *page;
34
35static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
36 int cur_y, int cur_x)
37{
38 print_page(box, boxh, boxw);
39 print_position(dialog);
40 wmove(dialog, cur_y, cur_x);
41 wrefresh(dialog);
42}
43
44
45int dialog_textbox(const char *title, const char *tbuf,
46 int initial_height, int initial_width)
47{
48 int i, x, y, cur_x, cur_y, key = 0;
49 int height, width, boxh, boxw;
50 int passed_end;
51 WINDOW *dialog, *box;
52
53 begin_reached = 1;
54 end_reached = 0;
55 page_length = 0;
56 hscroll = 0;
57 buf = tbuf;
58 page = buf;
59
60do_resize:
61 getmaxyx(stdscr, height, width);
62 if (height < 8 || width < 8)
63 return -ERRDISPLAYTOOSMALL;
64 if (initial_height != 0)
65 height = initial_height;
66 else
67 if (height > 4)
68 height -= 4;
69 else
70 height = 0;
71 if (initial_width != 0)
72 width = initial_width;
73 else
74 if (width > 5)
75 width -= 5;
76 else
77 width = 0;
78
79
80 x = (COLS - width) / 2;
81 y = (LINES - height) / 2;
82
83 draw_shadow(stdscr, y, x, height, width);
84
85 dialog = newwin(height, width, y, x);
86 keypad(dialog, TRUE);
87
88
89 boxh = height - 4;
90 boxw = width - 2;
91 box = subwin(dialog, boxh, boxw, y + 1, x + 1);
92 wattrset(box, dlg.dialog.atr);
93 wbkgdset(box, dlg.dialog.atr & A_COLOR);
94
95 keypad(box, TRUE);
96
97
98 draw_box(dialog, 0, 0, height, width,
99 dlg.dialog.atr, dlg.border.atr);
100
101 wattrset(dialog, dlg.border.atr);
102 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
103 for (i = 0; i < width - 2; i++)
104 waddch(dialog, ACS_HLINE);
105 wattrset(dialog, dlg.dialog.atr);
106 wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
107 waddch(dialog, ACS_RTEE);
108
109 print_title(dialog, title, width);
110
111 print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
112 wnoutrefresh(dialog);
113 getyx(dialog, cur_y, cur_x);
114
115
116 attr_clear(box, boxh, boxw, dlg.dialog.atr);
117 refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
118
119 while ((key != KEY_ESC) && (key != '\n')) {
120 key = wgetch(dialog);
121 switch (key) {
122 case 'E':
123 case 'e':
124 case 'X':
125 case 'x':
126 delwin(box);
127 delwin(dialog);
128 return 0;
129 case 'g':
130 case KEY_HOME:
131 if (!begin_reached) {
132 begin_reached = 1;
133 page = buf;
134 refresh_text_box(dialog, box, boxh, boxw,
135 cur_y, cur_x);
136 }
137 break;
138 case 'G':
139 case KEY_END:
140
141 end_reached = 1;
142
143 page = buf + strlen(buf);
144 back_lines(boxh);
145 refresh_text_box(dialog, box, boxh, boxw,
146 cur_y, cur_x);
147 break;
148 case 'K':
149 case 'k':
150 case KEY_UP:
151 if (!begin_reached) {
152 back_lines(page_length + 1);
153
154 scrollok(box, TRUE);
155 wscrl(box, -1);
156 scrollok(box, FALSE);
157 page_length = 0;
158 passed_end = 0;
159 for (i = 0; i < boxh; i++) {
160 if (!i) {
161
162 print_line(box, 0, boxw);
163 wnoutrefresh(box);
164 } else
165
166 get_line();
167 if (!passed_end)
168 page_length++;
169 if (end_reached && !passed_end)
170 passed_end = 1;
171 }
172
173 print_position(dialog);
174 wmove(dialog, cur_y, cur_x);
175 wrefresh(dialog);
176 }
177 break;
178 case 'B':
179 case 'b':
180 case KEY_PPAGE:
181 if (begin_reached)
182 break;
183 back_lines(page_length + boxh);
184 refresh_text_box(dialog, box, boxh, boxw,
185 cur_y, cur_x);
186 break;
187 case 'J':
188 case 'j':
189 case KEY_DOWN:
190 if (!end_reached) {
191 begin_reached = 0;
192 scrollok(box, TRUE);
193 scroll(box);
194 scrollok(box, FALSE);
195 print_line(box, boxh - 1, boxw);
196 wnoutrefresh(box);
197 print_position(dialog);
198 wmove(dialog, cur_y, cur_x);
199 wrefresh(dialog);
200 }
201 break;
202 case KEY_NPAGE:
203 case ' ':
204 if (end_reached)
205 break;
206
207 begin_reached = 0;
208 refresh_text_box(dialog, box, boxh, boxw,
209 cur_y, cur_x);
210 break;
211 case '0':
212 case 'H':
213 case 'h':
214 case KEY_LEFT:
215 if (hscroll <= 0)
216 break;
217
218 if (key == '0')
219 hscroll = 0;
220 else
221 hscroll--;
222
223 back_lines(page_length);
224 refresh_text_box(dialog, box, boxh, boxw,
225 cur_y, cur_x);
226 break;
227 case 'L':
228 case 'l':
229 case KEY_RIGHT:
230 if (hscroll >= MAX_LEN)
231 break;
232 hscroll++;
233
234 back_lines(page_length);
235 refresh_text_box(dialog, box, boxh, boxw,
236 cur_y, cur_x);
237 break;
238 case KEY_ESC:
239 key = on_key_esc(dialog);
240 break;
241 case KEY_RESIZE:
242 back_lines(height);
243 delwin(box);
244 delwin(dialog);
245 on_key_resize();
246 goto do_resize;
247 }
248 }
249 delwin(box);
250 delwin(dialog);
251 return key;
252}
253
254static void back_lines(int n)
255{
256 int i;
257
258 begin_reached = 0;
259
260 for (i = 0; i < n; i++) {
261 if (*page == '\0') {
262 if (end_reached) {
263 end_reached = 0;
264 continue;
265 }
266 }
267 if (page == buf) {
268 begin_reached = 1;
269 return;
270 }
271 page--;
272 do {
273 if (page == buf) {
274 begin_reached = 1;
275 return;
276 }
277 page--;
278 } while (*page != '\n');
279 page++;
280 }
281}
282
283static void print_page(WINDOW * win, int height, int width)
284{
285 int i, passed_end = 0;
286
287 page_length = 0;
288 for (i = 0; i < height; i++) {
289 print_line(win, i, width);
290 if (!passed_end)
291 page_length++;
292 if (end_reached && !passed_end)
293 passed_end = 1;
294 }
295 wnoutrefresh(win);
296}
297
298static void print_line(WINDOW * win, int row, int width)
299{
300 char *line;
301
302 line = get_line();
303 line += MIN(strlen(line), hscroll);
304 wmove(win, row, 0);
305 waddch(win, ' ');
306 waddnstr(win, line, MIN(strlen(line), width - 2));
307
308
309#if OLD_NCURSES
310 {
311 int x = getcurx(win);
312 int i;
313 for (i = 0; i < width - x; i++)
314 waddch(win, ' ');
315 }
316#else
317 wclrtoeol(win);
318#endif
319}
320
321static char *get_line(void)
322{
323 int i = 0;
324 static char line[MAX_LEN + 1];
325
326 end_reached = 0;
327 while (*page != '\n') {
328 if (*page == '\0') {
329 if (!end_reached) {
330 end_reached = 1;
331 break;
332 }
333 } else if (i < MAX_LEN)
334 line[i++] = *(page++);
335 else {
336
337 if (i == MAX_LEN)
338 line[i++] = '\0';
339 page++;
340 }
341 }
342 if (i <= MAX_LEN)
343 line[i] = '\0';
344 if (!end_reached)
345 page++;
346
347 return line;
348}
349
350static void print_position(WINDOW * win)
351{
352 int percent;
353
354 wattrset(win, dlg.position_indicator.atr);
355 wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
356 percent = (page - buf) * 100 / strlen(buf);
357 wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
358 wprintw(win, "(%3d%%)", percent);
359}