Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / tools / kconfig / lxdialog / textbox.c
1 /*
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
24 static void back_lines(int n);
25 static void print_page(WINDOW * win, int height, int width);
26 static void print_line(WINDOW * win, int row, int width);
27 static char *get_line(void);
28 static void print_position(WINDOW * win);
29
30 static int hscroll;
31 static int begin_reached, end_reached, page_length;
32 static const char *buf;
33 static const char *page;
34
35 /*
36  * refresh window content
37  */
38 static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
39                                                           int cur_y, int cur_x)
40 {
41         print_page(box, boxh, boxw);
42         print_position(dialog);
43         wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
44         wrefresh(dialog);
45 }
46
47
48 /*
49  * Display text from a file in a dialog box.
50  */
51 int dialog_textbox(const char *title, const char *tbuf,
52                    int initial_height, int initial_width)
53 {
54         int i, x, y, cur_x, cur_y, key = 0;
55         int height, width, boxh, boxw;
56         int passed_end;
57         WINDOW *dialog, *box;
58
59         begin_reached = 1;
60         end_reached = 0;
61         page_length = 0;
62         hscroll = 0;
63         buf = tbuf;
64         page = buf;     /* page is pointer to start of page to be displayed */
65
66 do_resize:
67         getmaxyx(stdscr, height, width);
68         if (height < 8 || width < 8)
69                 return -ERRDISPLAYTOOSMALL;
70         if (initial_height != 0)
71                 height = initial_height;
72         else
73                 if (height > 4)
74                         height -= 4;
75                 else
76                         height = 0;
77         if (initial_width != 0)
78                 width = initial_width;
79         else
80                 if (width > 5)
81                         width -= 5;
82                 else
83                         width = 0;
84
85         /* center dialog box on screen */
86         x = (COLS - width) / 2;
87         y = (LINES - height) / 2;
88
89         draw_shadow(stdscr, y, x, height, width);
90
91         dialog = newwin(height, width, y, x);
92         keypad(dialog, TRUE);
93
94         /* Create window for box region, used for scrolling text */
95         boxh = height - 4;
96         boxw = width - 2;
97         box = subwin(dialog, boxh, boxw, y + 1, x + 1);
98         wattrset(box, dlg.dialog.atr);
99         wbkgdset(box, dlg.dialog.atr & A_COLOR);
100
101         keypad(box, TRUE);
102
103         /* register the new window, along with its borders */
104         draw_box(dialog, 0, 0, height, width,
105                  dlg.dialog.atr, dlg.border.atr);
106
107         wattrset(dialog, dlg.border.atr);
108         mvwaddch(dialog, height - 3, 0, ACS_LTEE);
109         for (i = 0; i < width - 2; i++)
110                 waddch(dialog, ACS_HLINE);
111         wattrset(dialog, dlg.dialog.atr);
112         wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
113         waddch(dialog, ACS_RTEE);
114
115         print_title(dialog, title, width);
116
117         print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
118         wnoutrefresh(dialog);
119         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
120
121         /* Print first page of text */
122         attr_clear(box, boxh, boxw, dlg.dialog.atr);
123         refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
124
125         while ((key != KEY_ESC) && (key != '\n')) {
126                 key = wgetch(dialog);
127                 switch (key) {
128                 case 'E':       /* Exit */
129                 case 'e':
130                 case 'X':
131                 case 'x':
132                         delwin(box);
133                         delwin(dialog);
134                         return 0;
135                 case 'g':       /* First page */
136                 case KEY_HOME:
137                         if (!begin_reached) {
138                                 begin_reached = 1;
139                                 page = buf;
140                                 refresh_text_box(dialog, box, boxh, boxw,
141                                                  cur_y, cur_x);
142                         }
143                         break;
144                 case 'G':       /* Last page */
145                 case KEY_END:
146
147                         end_reached = 1;
148                         /* point to last char in buf */
149                         page = buf + strlen(buf);
150                         back_lines(boxh);
151                         refresh_text_box(dialog, box, boxh, boxw,
152                                          cur_y, cur_x);
153                         break;
154                 case 'K':       /* Previous line */
155                 case 'k':
156                 case KEY_UP:
157                         if (!begin_reached) {
158                                 back_lines(page_length + 1);
159
160                                 /* We don't call print_page() here but use
161                                  * scrolling to ensure faster screen update.
162                                  * However, 'end_reached' and 'page_length'
163                                  * should still be updated, and 'page' should
164                                  * point to start of next page. This is done
165                                  * by calling get_line() in the following
166                                  * 'for' loop. */
167                                 scrollok(box, TRUE);
168                                 wscrl(box, -1); /* Scroll box region down one line */
169                                 scrollok(box, FALSE);
170                                 page_length = 0;
171                                 passed_end = 0;
172                                 for (i = 0; i < boxh; i++) {
173                                         if (!i) {
174                                                 /* print first line of page */
175                                                 print_line(box, 0, boxw);
176                                                 wnoutrefresh(box);
177                                         } else
178                                                 /* Called to update 'end_reached' and 'page' */
179                                                 get_line();
180                                         if (!passed_end)
181                                                 page_length++;
182                                         if (end_reached && !passed_end)
183                                                 passed_end = 1;
184                                 }
185
186                                 print_position(dialog);
187                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
188                                 wrefresh(dialog);
189                         }
190                         break;
191                 case 'B':       /* Previous page */
192                 case 'b':
193                 case KEY_PPAGE:
194                         if (begin_reached)
195                                 break;
196                         back_lines(page_length + boxh);
197                         refresh_text_box(dialog, box, boxh, boxw,
198                                          cur_y, cur_x);
199                         break;
200                 case 'J':       /* Next line */
201                 case 'j':
202                 case KEY_DOWN:
203                         if (!end_reached) {
204                                 begin_reached = 0;
205                                 scrollok(box, TRUE);
206                                 scroll(box);    /* Scroll box region up one line */
207                                 scrollok(box, FALSE);
208                                 print_line(box, boxh - 1, boxw);
209                                 wnoutrefresh(box);
210                                 print_position(dialog);
211                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
212                                 wrefresh(dialog);
213                         }
214                         break;
215                 case KEY_NPAGE: /* Next page */
216                 case ' ':
217                         if (end_reached)
218                                 break;
219
220                         begin_reached = 0;
221                         refresh_text_box(dialog, box, boxh, boxw,
222                                          cur_y, cur_x);
223                         break;
224                 case '0':       /* Beginning of line */
225                 case 'H':       /* Scroll left */
226                 case 'h':
227                 case KEY_LEFT:
228                         if (hscroll <= 0)
229                                 break;
230
231                         if (key == '0')
232                                 hscroll = 0;
233                         else
234                                 hscroll--;
235                         /* Reprint current page to scroll horizontally */
236                         back_lines(page_length);
237                         refresh_text_box(dialog, box, boxh, boxw,
238                                          cur_y, cur_x);
239                         break;
240                 case 'L':       /* Scroll right */
241                 case 'l':
242                 case KEY_RIGHT:
243                         if (hscroll >= MAX_LEN)
244                                 break;
245                         hscroll++;
246                         /* Reprint current page to scroll horizontally */
247                         back_lines(page_length);
248                         refresh_text_box(dialog, box, boxh, boxw,
249                                          cur_y, cur_x);
250                         break;
251                 case KEY_ESC:
252                         key = on_key_esc(dialog);
253                         break;
254                 case KEY_RESIZE:
255                         back_lines(height);
256                         delwin(box);
257                         delwin(dialog);
258                         on_key_resize();
259                         goto do_resize;
260                 }
261         }
262         delwin(box);
263         delwin(dialog);
264         return key;             /* ESC pressed */
265 }
266
267 /*
268  * Go back 'n' lines in text. Called by dialog_textbox().
269  * 'page' will be updated to point to the desired line in 'buf'.
270  */
271 static void back_lines(int n)
272 {
273         int i;
274
275         begin_reached = 0;
276         /* Go back 'n' lines */
277         for (i = 0; i < n; i++) {
278                 if (*page == '\0') {
279                         if (end_reached) {
280                                 end_reached = 0;
281                                 continue;
282                         }
283                 }
284                 if (page == buf) {
285                         begin_reached = 1;
286                         return;
287                 }
288                 page--;
289                 do {
290                         if (page == buf) {
291                                 begin_reached = 1;
292                                 return;
293                         }
294                         page--;
295                 } while (*page != '\n');
296                 page++;
297         }
298 }
299
300 /*
301  * Print a new page of text. Called by dialog_textbox().
302  */
303 static void print_page(WINDOW * win, int height, int width)
304 {
305         int i, passed_end = 0;
306
307         page_length = 0;
308         for (i = 0; i < height; i++) {
309                 print_line(win, i, width);
310                 if (!passed_end)
311                         page_length++;
312                 if (end_reached && !passed_end)
313                         passed_end = 1;
314         }
315         wnoutrefresh(win);
316 }
317
318 /*
319  * Print a new line of text. Called by dialog_textbox() and print_page().
320  */
321 static void print_line(WINDOW * win, int row, int width)
322 {
323         int y, x;
324         char *line;
325
326         line = get_line();
327         line += MIN(strlen(line), hscroll);     /* Scroll horizontally */
328         wmove(win, row, 0);     /* move cursor to correct line */
329         waddch(win, ' ');
330         waddnstr(win, line, MIN(strlen(line), width - 2));
331
332         getyx(win, y, x);
333         /* Clear 'residue' of previous line */
334 #if OLD_NCURSES
335         {
336                 int i;
337                 for (i = 0; i < width - x; i++)
338                         waddch(win, ' ');
339         }
340 #else
341         wclrtoeol(win);
342 #endif
343 }
344
345 /*
346  * Return current line of text. Called by dialog_textbox() and print_line().
347  * 'page' should point to start of current line before calling, and will be
348  * updated to point to start of next line.
349  */
350 static char *get_line(void)
351 {
352         int i = 0;
353         static char line[MAX_LEN + 1];
354
355         end_reached = 0;
356         while (*page != '\n') {
357                 if (*page == '\0') {
358                         if (!end_reached) {
359                                 end_reached = 1;
360                                 break;
361                         }
362                 } else if (i < MAX_LEN)
363                         line[i++] = *(page++);
364                 else {
365                         /* Truncate lines longer than MAX_LEN characters */
366                         if (i == MAX_LEN)
367                                 line[i++] = '\0';
368                         page++;
369                 }
370         }
371         if (i <= MAX_LEN)
372                 line[i] = '\0';
373         if (!end_reached)
374                 page++;         /* move pass '\n' */
375
376         return line;
377 }
378
379 /*
380  * Print current position
381  */
382 static void print_position(WINDOW * win)
383 {
384         int percent;
385
386         wattrset(win, dlg.position_indicator.atr);
387         wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
388         percent = (page - buf) * 100 / strlen(buf);
389         wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
390         wprintw(win, "(%3d%%)", percent);
391 }