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.


Ported palacios to Kbuild
[palacios.git] / scripts / 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, int height, int width);
29
30 static int hscroll, fd, file_size, bytes_read;
31 static int begin_reached = 1, end_reached, page_length;
32 static char *buf, *page;
33
34 /*
35  * Display text from a file in a dialog box.
36  */
37 int dialog_textbox(const char *title, const char *file, int height, int width)
38 {
39         int i, x, y, cur_x, cur_y, fpos, key = 0;
40         int passed_end;
41         char search_term[MAX_LEN + 1];
42         WINDOW *dialog, *text;
43
44         search_term[0] = '\0';  /* no search term entered yet */
45
46         /* Open input file for reading */
47         if ((fd = open(file, O_RDONLY)) == -1) {
48                 endwin();
49                 fprintf(stderr, "\nCan't open input file in dialog_textbox().\n");
50                 exit(-1);
51         }
52         /* Get file size. Actually, 'file_size' is the real file size - 1,
53            since it's only the last byte offset from the beginning */
54         if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
55                 endwin();
56                 fprintf(stderr, "\nError getting file size in dialog_textbox().\n");
57                 exit(-1);
58         }
59         /* Restore file pointer to beginning of file after getting file size */
60         if (lseek(fd, 0, SEEK_SET) == -1) {
61                 endwin();
62                 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
63                 exit(-1);
64         }
65         /* Allocate space for read buffer */
66         if ((buf = malloc(BUF_SIZE + 1)) == NULL) {
67                 endwin();
68                 fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n");
69                 exit(-1);
70         }
71         if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
72                 endwin();
73                 fprintf(stderr, "\nError reading file in dialog_textbox().\n");
74                 exit(-1);
75         }
76         buf[bytes_read] = '\0'; /* mark end of valid data */
77         page = buf;             /* page is pointer to start of page to be displayed */
78
79         /* center dialog box on screen */
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         /* Create window for text region, used for scrolling text */
89         text = subwin(dialog, height - 4, width - 2, y + 1, x + 1);
90         wattrset(text, dialog_attr);
91         wbkgdset(text, dialog_attr & A_COLOR);
92
93         keypad(text, TRUE);
94
95         /* register the new window, along with its borders */
96         draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
97
98         wattrset(dialog, border_attr);
99         mvwaddch(dialog, height - 3, 0, ACS_LTEE);
100         for (i = 0; i < width - 2; i++)
101                 waddch(dialog, ACS_HLINE);
102         wattrset(dialog, dialog_attr);
103         wbkgdset(dialog, dialog_attr & A_COLOR);
104         waddch(dialog, ACS_RTEE);
105
106         print_title(dialog, title, width);
107
108         print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
109         wnoutrefresh(dialog);
110         getyx(dialog, cur_y, cur_x);    /* Save cursor position */
111
112         /* Print first page of text */
113         attr_clear(text, height - 4, width - 2, dialog_attr);
114         print_page(text, height - 4, width - 2);
115         print_position(dialog, height, width);
116         wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
117         wrefresh(dialog);
118
119         while ((key != ESC) && (key != '\n')) {
120                 key = wgetch(dialog);
121                 switch (key) {
122                 case 'E':       /* Exit */
123                 case 'e':
124                 case 'X':
125                 case 'x':
126                         delwin(dialog);
127                         free(buf);
128                         close(fd);
129                         return 0;
130                 case 'g':       /* First page */
131                 case KEY_HOME:
132                         if (!begin_reached) {
133                                 begin_reached = 1;
134                                 /* First page not in buffer? */
135                                 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
136                                         endwin();
137                                         fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
138                                         exit(-1);
139                                 }
140                                 if (fpos > bytes_read) {        /* Yes, we have to read it in */
141                                         if (lseek(fd, 0, SEEK_SET) == -1) {
142                                                 endwin();
143                                                 fprintf(stderr, "\nError moving file pointer in "
144                                                                 "dialog_textbox().\n");
145                                                 exit(-1);
146                                         }
147                                         if ((bytes_read =
148                                              read(fd, buf, BUF_SIZE)) == -1) {
149                                                 endwin();
150                                                 fprintf(stderr, "\nError reading file in dialog_textbox().\n");
151                                                 exit(-1);
152                                         }
153                                         buf[bytes_read] = '\0';
154                                 }
155                                 page = buf;
156                                 print_page(text, height - 4, width - 2);
157                                 print_position(dialog, height, width);
158                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
159                                 wrefresh(dialog);
160                         }
161                         break;
162                 case 'G':       /* Last page */
163                 case KEY_END:
164
165                         end_reached = 1;
166                         /* Last page not in buffer? */
167                         if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
168                                 endwin();
169                                 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
170                                 exit(-1);
171                         }
172                         if (fpos < file_size) { /* Yes, we have to read it in */
173                                 if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
174                                         endwin();
175                                         fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
176                                         exit(-1);
177                                 }
178                                 if ((bytes_read =
179                                      read(fd, buf, BUF_SIZE)) == -1) {
180                                         endwin();
181                                         fprintf(stderr, "\nError reading file in dialog_textbox().\n");
182                                         exit(-1);
183                                 }
184                                 buf[bytes_read] = '\0';
185                         }
186                         page = buf + bytes_read;
187                         back_lines(height - 4);
188                         print_page(text, height - 4, width - 2);
189                         print_position(dialog, height, width);
190                         wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
191                         wrefresh(dialog);
192                         break;
193                 case 'K':       /* Previous line */
194                 case 'k':
195                 case KEY_UP:
196                         if (!begin_reached) {
197                                 back_lines(page_length + 1);
198
199                                 /* We don't call print_page() here but use scrolling to ensure
200                                    faster screen update. However, 'end_reached' and
201                                    'page_length' should still be updated, and 'page' should
202                                    point to start of next page. This is done by calling
203                                    get_line() in the following 'for' loop. */
204                                 scrollok(text, TRUE);
205                                 wscrl(text, -1);        /* Scroll text region down one line */
206                                 scrollok(text, FALSE);
207                                 page_length = 0;
208                                 passed_end = 0;
209                                 for (i = 0; i < height - 4; i++) {
210                                         if (!i) {
211                                                 /* print first line of page */
212                                                 print_line(text, 0, width - 2);
213                                                 wnoutrefresh(text);
214                                         } else
215                                                 /* Called to update 'end_reached' and 'page' */
216                                                 get_line();
217                                         if (!passed_end)
218                                                 page_length++;
219                                         if (end_reached && !passed_end)
220                                                 passed_end = 1;
221                                 }
222
223                                 print_position(dialog, height, width);
224                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
225                                 wrefresh(dialog);
226                         }
227                         break;
228                 case 'B':       /* Previous page */
229                 case 'b':
230                 case KEY_PPAGE:
231                         if (begin_reached)
232                                 break;
233                         back_lines(page_length + height - 4);
234                         print_page(text, height - 4, width - 2);
235                         print_position(dialog, height, width);
236                         wmove(dialog, cur_y, cur_x);
237                         wrefresh(dialog);
238                         break;
239                 case 'J':       /* Next line */
240                 case 'j':
241                 case KEY_DOWN:
242                         if (!end_reached) {
243                                 begin_reached = 0;
244                                 scrollok(text, TRUE);
245                                 scroll(text);   /* Scroll text region up one line */
246                                 scrollok(text, FALSE);
247                                 print_line(text, height - 5, width - 2);
248                                 wnoutrefresh(text);
249                                 print_position(dialog, height, width);
250                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
251                                 wrefresh(dialog);
252                         }
253                         break;
254                 case KEY_NPAGE: /* Next page */
255                 case ' ':
256                         if (end_reached)
257                                 break;
258
259                         begin_reached = 0;
260                         print_page(text, height - 4, width - 2);
261                         print_position(dialog, height, width);
262                         wmove(dialog, cur_y, cur_x);
263                         wrefresh(dialog);
264                         break;
265                 case '0':       /* Beginning of line */
266                 case 'H':       /* Scroll left */
267                 case 'h':
268                 case KEY_LEFT:
269                         if (hscroll <= 0)
270                                 break;
271
272                         if (key == '0')
273                                 hscroll = 0;
274                         else
275                                 hscroll--;
276                         /* Reprint current page to scroll horizontally */
277                         back_lines(page_length);
278                         print_page(text, height - 4, width - 2);
279                         wmove(dialog, cur_y, cur_x);
280                         wrefresh(dialog);
281                         break;
282                 case 'L':       /* Scroll right */
283                 case 'l':
284                 case KEY_RIGHT:
285                         if (hscroll >= MAX_LEN)
286                                 break;
287                         hscroll++;
288                         /* Reprint current page to scroll horizontally */
289                         back_lines(page_length);
290                         print_page(text, height - 4, width - 2);
291                         wmove(dialog, cur_y, cur_x);
292                         wrefresh(dialog);
293                         break;
294                 case ESC:
295                         break;
296                 }
297         }
298
299         delwin(dialog);
300         free(buf);
301         close(fd);
302         return -1;              /* ESC pressed */
303 }
304
305 /*
306  * Go back 'n' lines in text file. Called by dialog_textbox().
307  * 'page' will be updated to point to the desired line in 'buf'.
308  */
309 static void back_lines(int n)
310 {
311         int i, fpos;
312
313         begin_reached = 0;
314         /* We have to distinguish between end_reached and !end_reached
315            since at end of file, the line is not ended by a '\n'.
316            The code inside 'if' basically does a '--page' to move one
317            character backward so as to skip '\n' of the previous line */
318         if (!end_reached) {
319                 /* Either beginning of buffer or beginning of file reached? */
320                 if (page == buf) {
321                         if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
322                                 endwin();
323                                 fprintf(stderr, "\nError moving file pointer in "
324                                                 "back_lines().\n");
325                                 exit(-1);
326                         }
327                         if (fpos > bytes_read) {        /* Not beginning of file yet */
328                                 /* We've reached beginning of buffer, but not beginning of
329                                    file yet, so read previous part of file into buffer.
330                                    Note that we only move backward for BUF_SIZE/2 bytes,
331                                    but not BUF_SIZE bytes to avoid re-reading again in
332                                    print_page() later */
333                                 /* Really possible to move backward BUF_SIZE/2 bytes? */
334                                 if (fpos < BUF_SIZE / 2 + bytes_read) {
335                                         /* No, move less then */
336                                         if (lseek(fd, 0, SEEK_SET) == -1) {
337                                                 endwin();
338                                                 fprintf(stderr, "\nError moving file pointer in "
339                                                                 "back_lines().\n");
340                                                 exit(-1);
341                                         }
342                                         page = buf + fpos - bytes_read;
343                                 } else {        /* Move backward BUF_SIZE/2 bytes */
344                                         if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
345                                                 endwin();
346                                                 fprintf(stderr, "\nError moving file pointer "
347                                                                 "in back_lines().\n");
348                                                 exit(-1);
349                                         }
350                                         page = buf + BUF_SIZE / 2;
351                                 }
352                                 if ((bytes_read =
353                                      read(fd, buf, BUF_SIZE)) == -1) {
354                                         endwin();
355                                         fprintf(stderr, "\nError reading file in back_lines().\n");
356                                         exit(-1);
357                                 }
358                                 buf[bytes_read] = '\0';
359                         } else {        /* Beginning of file reached */
360                                 begin_reached = 1;
361                                 return;
362                         }
363                 }
364                 if (*(--page) != '\n') {        /* '--page' here */
365                         /* Something's wrong... */
366                         endwin();
367                         fprintf(stderr, "\nInternal error in back_lines().\n");
368                         exit(-1);
369                 }
370         }
371         /* Go back 'n' lines */
372         for (i = 0; i < n; i++)
373                 do {
374                         if (page == buf) {
375                                 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
376                                         endwin();
377                                         fprintf(stderr, "\nError moving file pointer in back_lines().\n");
378                                         exit(-1);
379                                 }
380                                 if (fpos > bytes_read) {
381                                         /* Really possible to move backward BUF_SIZE/2 bytes? */
382                                         if (fpos < BUF_SIZE / 2 + bytes_read) {
383                                                 /* No, move less then */
384                                                 if (lseek(fd, 0, SEEK_SET) == -1) {
385                                                         endwin();
386                                                         fprintf(stderr, "\nError moving file pointer "
387                                                                         "in back_lines().\n");
388                                                         exit(-1);
389                                                 }
390                                                 page = buf + fpos - bytes_read;
391                                         } else {        /* Move backward BUF_SIZE/2 bytes */
392                                                 if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
393                                                         endwin();
394                                                         fprintf(stderr, "\nError moving file pointer"
395                                                                         " in back_lines().\n");
396                                                         exit(-1);
397                                                 }
398                                                 page = buf + BUF_SIZE / 2;
399                                         }
400                                         if ((bytes_read =
401                                              read(fd, buf, BUF_SIZE)) == -1) {
402                                                 endwin();
403                                                 fprintf(stderr, "\nError reading file in "
404                                                                 "back_lines().\n");
405                                                 exit(-1);
406                                         }
407                                         buf[bytes_read] = '\0';
408                                 } else {        /* Beginning of file reached */
409                                         begin_reached = 1;
410                                         return;
411                                 }
412                         }
413                 } while (*(--page) != '\n');
414         page++;
415 }
416
417 /*
418  * Print a new page of text. Called by dialog_textbox().
419  */
420 static void print_page(WINDOW * win, int height, int width)
421 {
422         int i, passed_end = 0;
423
424         page_length = 0;
425         for (i = 0; i < height; i++) {
426                 print_line(win, i, width);
427                 if (!passed_end)
428                         page_length++;
429                 if (end_reached && !passed_end)
430                         passed_end = 1;
431         }
432         wnoutrefresh(win);
433 }
434
435 /*
436  * Print a new line of text. Called by dialog_textbox() and print_page().
437  */
438 static void print_line(WINDOW * win, int row, int width)
439 {
440         int y, x;
441         char *line;
442
443         line = get_line();
444         line += MIN(strlen(line), hscroll);     /* Scroll horizontally */
445         wmove(win, row, 0);     /* move cursor to correct line */
446         waddch(win, ' ');
447         waddnstr(win, line, MIN(strlen(line), width - 2));
448
449         getyx(win, y, x);
450         /* Clear 'residue' of previous line */
451 #if OLD_NCURSES
452         {
453                 int i;
454                 for (i = 0; i < width - x; i++)
455                         waddch(win, ' ');
456         }
457 #else
458         wclrtoeol(win);
459 #endif
460 }
461
462 /*
463  * Return current line of text. Called by dialog_textbox() and print_line().
464  * 'page' should point to start of current line before calling, and will be
465  * updated to point to start of next line.
466  */
467 static char *get_line(void)
468 {
469         int i = 0, fpos;
470         static char line[MAX_LEN + 1];
471
472         end_reached = 0;
473         while (*page != '\n') {
474                 if (*page == '\0') {
475                         /* Either end of file or end of buffer reached */
476                         if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
477                                 endwin();
478                                 fprintf(stderr, "\nError moving file pointer in "
479                                                 "get_line().\n");
480                                 exit(-1);
481                         }
482                         if (fpos < file_size) { /* Not end of file yet */
483                                 /* We've reached end of buffer, but not end of file yet,
484                                    so read next part of file into buffer */
485                                 if ((bytes_read =
486                                      read(fd, buf, BUF_SIZE)) == -1) {
487                                         endwin();
488                                         fprintf(stderr, "\nError reading file in get_line().\n");
489                                         exit(-1);
490                                 }
491                                 buf[bytes_read] = '\0';
492                                 page = buf;
493                         } else {
494                                 if (!end_reached)
495                                         end_reached = 1;
496                                 break;
497                         }
498                 } else if (i < MAX_LEN)
499                         line[i++] = *(page++);
500                 else {
501                         /* Truncate lines longer than MAX_LEN characters */
502                         if (i == MAX_LEN)
503                                 line[i++] = '\0';
504                         page++;
505                 }
506         }
507         if (i <= MAX_LEN)
508                 line[i] = '\0';
509         if (!end_reached)
510                 page++;         /* move pass '\n' */
511
512         return line;
513 }
514
515 /*
516  * Print current position
517  */
518 static void print_position(WINDOW * win, int height, int width)
519 {
520         int fpos, percent;
521
522         if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
523                 endwin();
524                 fprintf(stderr, "\nError moving file pointer in print_position().\n");
525                 exit(-1);
526         }
527         wattrset(win, position_indicator_attr);
528         wbkgdset(win, position_indicator_attr & A_COLOR);
529         percent = !file_size ?
530             100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
531         wmove(win, height - 3, width - 9);
532         wprintw(win, "(%3d%%)", percent);
533 }