kconfig/lxdialog/textbox.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 1 eeea35fbf182
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

Signed-off-by: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
     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 }