kconfig/lxdialog/textbox.c
author "Yann E. MORIN" <yann.morin.1998@free.fr>
Thu Jan 10 00:27:13 2013 +0100 (2013-01-10)
changeset 3159 fb71cad4b085
parent 1 eeea35fbf182
permissions -rw-r--r--
arch/arm: OABI is no more, switch to only EABI

Well, leave the prompt as an OBSOLETE thing, scheduled to
be removed soon.

As an indication OABI lives its last days, gcc-4.8 will no
longer recognise non-EABI targets.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
     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 }