xref: /freebsd/contrib/dialog/progressbox.c (revision 682c9e0fed0115eb6f283e755901c0aac90e86e8)
14c8945a0SNathan Whitehorn /*
2*682c9e0fSNathan Whitehorn  *  $Id: progressbox.c,v 1.13 2011/06/27 08:18:20 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  progressbox.c -- implements the progress box
54c8945a0SNathan Whitehorn  *
64c8945a0SNathan Whitehorn  *  Copyright 2005	Valery Reznic
77a1c0d96SNathan Whitehorn  *  Copyright 2006-2011	Thomas E. Dickey
84c8945a0SNathan Whitehorn  *
94c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
104c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License as
114c8945a0SNathan Whitehorn  *  published by the Free Software Foundation; either version 2.1 of the
124c8945a0SNathan Whitehorn  *  License, or (at your option) any later version.
134c8945a0SNathan Whitehorn  *
144c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
154c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
164c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
174c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
184c8945a0SNathan Whitehorn  *
194c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
204c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
214c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
224c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
234c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
244c8945a0SNathan Whitehorn  */
254c8945a0SNathan Whitehorn 
264c8945a0SNathan Whitehorn #include <dialog.h>
274c8945a0SNathan Whitehorn #include <dlg_keys.h>
284c8945a0SNathan Whitehorn 
294c8945a0SNathan Whitehorn #define MIN_HIGH (4)
304c8945a0SNathan Whitehorn #define MIN_WIDE (10 + 2 * (2 + MARGIN))
314c8945a0SNathan Whitehorn 
324c8945a0SNathan Whitehorn typedef struct {
334c8945a0SNathan Whitehorn     DIALOG_CALLBACK obj;
344c8945a0SNathan Whitehorn     WINDOW *text;
354c8945a0SNathan Whitehorn     char line[MAX_LEN + 1];
364c8945a0SNathan Whitehorn     int is_eof;
374c8945a0SNathan Whitehorn } MY_OBJ;
384c8945a0SNathan Whitehorn 
394c8945a0SNathan Whitehorn /*
404c8945a0SNathan Whitehorn  * Return current line of text.
414c8945a0SNathan Whitehorn  */
424c8945a0SNathan Whitehorn static char *
434c8945a0SNathan Whitehorn get_line(MY_OBJ * obj)
444c8945a0SNathan Whitehorn {
454c8945a0SNathan Whitehorn     FILE *fp = obj->obj.input;
464c8945a0SNathan Whitehorn     int col = 0;
474c8945a0SNathan Whitehorn     int j, tmpint, ch;
484c8945a0SNathan Whitehorn 
494c8945a0SNathan Whitehorn     while (1) {
504c8945a0SNathan Whitehorn 	if ((ch = getc(fp)) == EOF) {
514c8945a0SNathan Whitehorn 	    obj->is_eof = 1;
524c8945a0SNathan Whitehorn 	    if (col) {
534c8945a0SNathan Whitehorn 		break;
544c8945a0SNathan Whitehorn 	    } else {
554c8945a0SNathan Whitehorn 		return NULL;
564c8945a0SNathan Whitehorn 	    }
574c8945a0SNathan Whitehorn 	}
584c8945a0SNathan Whitehorn 	if (ch == '\n')
594c8945a0SNathan Whitehorn 	    break;
604c8945a0SNathan Whitehorn 	if (ch == '\r')
614c8945a0SNathan Whitehorn 	    break;
624c8945a0SNathan Whitehorn 	if ((ch == TAB) && (dialog_vars.tab_correct)) {
634c8945a0SNathan Whitehorn 	    tmpint = dialog_state.tab_len
644c8945a0SNathan Whitehorn 		- (col % dialog_state.tab_len);
654c8945a0SNathan Whitehorn 	    for (j = 0; j < tmpint; j++) {
664c8945a0SNathan Whitehorn 		if (col < MAX_LEN)
674c8945a0SNathan Whitehorn 		    obj->line[col] = ' ';
684c8945a0SNathan Whitehorn 		++col;
694c8945a0SNathan Whitehorn 	    }
704c8945a0SNathan Whitehorn 	} else {
714c8945a0SNathan Whitehorn 	    obj->line[col] = (char) ch;
724c8945a0SNathan Whitehorn 	    ++col;
734c8945a0SNathan Whitehorn 	}
744c8945a0SNathan Whitehorn 	if (col >= MAX_LEN)
754c8945a0SNathan Whitehorn 	    break;
764c8945a0SNathan Whitehorn     }
774c8945a0SNathan Whitehorn 
784c8945a0SNathan Whitehorn     obj->line[col] = '\0';
794c8945a0SNathan Whitehorn 
804c8945a0SNathan Whitehorn     return obj->line;
814c8945a0SNathan Whitehorn }
824c8945a0SNathan Whitehorn 
834c8945a0SNathan Whitehorn /*
844c8945a0SNathan Whitehorn  * Print a new line of text.
854c8945a0SNathan Whitehorn  */
864c8945a0SNathan Whitehorn static void
874c8945a0SNathan Whitehorn print_line(MY_OBJ * obj, WINDOW *win, int row, int width)
884c8945a0SNathan Whitehorn {
894c8945a0SNathan Whitehorn     int i, y, x;
904c8945a0SNathan Whitehorn     char *line = obj->line;
914c8945a0SNathan Whitehorn 
924c8945a0SNathan Whitehorn     (void) wmove(win, row, 0);	/* move cursor to correct line */
934c8945a0SNathan Whitehorn     (void) waddch(win, ' ');
944c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
954c8945a0SNathan Whitehorn     (void) waddnstr(win, line, MIN((int) strlen(line), width - 2));
964c8945a0SNathan Whitehorn #else
974c8945a0SNathan Whitehorn     line[MIN((int) strlen(line), width - 2)] = '\0';
984c8945a0SNathan Whitehorn     waddstr(win, line);
994c8945a0SNathan Whitehorn #endif
1004c8945a0SNathan Whitehorn 
1014c8945a0SNathan Whitehorn     getyx(win, y, x);
1024c8945a0SNathan Whitehorn     /* Clear 'residue' of previous line */
1034c8945a0SNathan Whitehorn     for (i = 0; i < width - x; i++)
1044c8945a0SNathan Whitehorn 	(void) waddch(win, ' ');
1054c8945a0SNathan Whitehorn }
1064c8945a0SNathan Whitehorn 
1077a1c0d96SNathan Whitehorn static int
1087a1c0d96SNathan Whitehorn pause_for_ok(WINDOW *dialog, int height, int width)
1097a1c0d96SNathan Whitehorn {
1107a1c0d96SNathan Whitehorn     /* *INDENT-OFF* */
1117a1c0d96SNathan Whitehorn     static DLG_KEYS_BINDING binding[] = {
112*682c9e0fSNathan Whitehorn 	HELPKEY_BINDINGS,
1137a1c0d96SNathan Whitehorn 	ENTERKEY_BINDINGS,
1147a1c0d96SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_ENTER,	' ' ),
1157a1c0d96SNathan Whitehorn 	END_KEYS_BINDING
1167a1c0d96SNathan Whitehorn     };
1177a1c0d96SNathan Whitehorn     /* *INDENT-ON* */
1187a1c0d96SNathan Whitehorn 
1197a1c0d96SNathan Whitehorn     int button = 0;
1207a1c0d96SNathan Whitehorn     int key = 0, fkey;
1217a1c0d96SNathan Whitehorn     int result = DLG_EXIT_UNKNOWN;
1227a1c0d96SNathan Whitehorn     const char **buttons = dlg_ok_label();
1237a1c0d96SNathan Whitehorn     int check;
1247a1c0d96SNathan Whitehorn 
1257a1c0d96SNathan Whitehorn     dlg_register_window(dialog, "progressbox", binding);
1267a1c0d96SNathan Whitehorn     dlg_register_buttons(dialog, "progressbox", buttons);
1277a1c0d96SNathan Whitehorn 
1287a1c0d96SNathan Whitehorn     dlg_draw_bottom_box(dialog);
1297a1c0d96SNathan Whitehorn     mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n');
1307a1c0d96SNathan Whitehorn     dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
1317a1c0d96SNathan Whitehorn 
1327a1c0d96SNathan Whitehorn     while (result == DLG_EXIT_UNKNOWN) {
1337a1c0d96SNathan Whitehorn 	key = dlg_mouse_wgetch(dialog, &fkey);
1347a1c0d96SNathan Whitehorn 	if (dlg_result_key(key, fkey, &result))
1357a1c0d96SNathan Whitehorn 	    break;
1367a1c0d96SNathan Whitehorn 
1377a1c0d96SNathan Whitehorn 	if (!fkey && (check = dlg_char_to_button(key, buttons)) >= 0) {
1387a1c0d96SNathan Whitehorn 	    result = check ? DLG_EXIT_HELP : DLG_EXIT_OK;
1397a1c0d96SNathan Whitehorn 	    break;
1407a1c0d96SNathan Whitehorn 	}
1417a1c0d96SNathan Whitehorn 
1427a1c0d96SNathan Whitehorn 	if (fkey) {
1437a1c0d96SNathan Whitehorn 	    switch (key) {
1447a1c0d96SNathan Whitehorn 	    case DLGK_ENTER:
1457a1c0d96SNathan Whitehorn 		result = button ? DLG_EXIT_HELP : DLG_EXIT_OK;
1467a1c0d96SNathan Whitehorn 		break;
1477a1c0d96SNathan Whitehorn 	    case DLGK_MOUSE(0):
1487a1c0d96SNathan Whitehorn 		result = DLG_EXIT_OK;
1497a1c0d96SNathan Whitehorn 		break;
1507a1c0d96SNathan Whitehorn 	    case DLGK_MOUSE(1):
1517a1c0d96SNathan Whitehorn 		result = DLG_EXIT_HELP;
1527a1c0d96SNathan Whitehorn 		break;
1537a1c0d96SNathan Whitehorn 	    default:
1547a1c0d96SNathan Whitehorn 		beep();
1557a1c0d96SNathan Whitehorn 		break;
1567a1c0d96SNathan Whitehorn 	    }
1577a1c0d96SNathan Whitehorn 	} else {
1587a1c0d96SNathan Whitehorn 	    beep();
1597a1c0d96SNathan Whitehorn 	}
1607a1c0d96SNathan Whitehorn     }
1617a1c0d96SNathan Whitehorn     dlg_unregister_window(dialog);
1627a1c0d96SNathan Whitehorn     return result;
1637a1c0d96SNathan Whitehorn }
1647a1c0d96SNathan Whitehorn 
1654c8945a0SNathan Whitehorn int
1667a1c0d96SNathan Whitehorn dlg_progressbox(const char *title,
1677a1c0d96SNathan Whitehorn 		const char *cprompt,
1687a1c0d96SNathan Whitehorn 		int height,
1697a1c0d96SNathan Whitehorn 		int width,
1707a1c0d96SNathan Whitehorn 		int pauseopt,
1717a1c0d96SNathan Whitehorn 		FILE *fp)
1724c8945a0SNathan Whitehorn {
1734c8945a0SNathan Whitehorn     int i;
1744c8945a0SNathan Whitehorn     int x, y, thigh;
1754c8945a0SNathan Whitehorn     WINDOW *dialog, *text;
1764c8945a0SNathan Whitehorn     MY_OBJ *obj;
1774c8945a0SNathan Whitehorn     char *prompt = dlg_strclone(cprompt);
1787a1c0d96SNathan Whitehorn     int result;
1794c8945a0SNathan Whitehorn 
1804c8945a0SNathan Whitehorn     dlg_tab_correct_str(prompt);
1814c8945a0SNathan Whitehorn     dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, MIN_WIDE);
1824c8945a0SNathan Whitehorn     dlg_print_size(height, width);
1834c8945a0SNathan Whitehorn     dlg_ctl_size(height, width);
1844c8945a0SNathan Whitehorn 
1854c8945a0SNathan Whitehorn     x = dlg_box_x_ordinate(width);
1864c8945a0SNathan Whitehorn     y = dlg_box_y_ordinate(height);
1874c8945a0SNathan Whitehorn     thigh = height - (2 * MARGIN);
1884c8945a0SNathan Whitehorn 
1894c8945a0SNathan Whitehorn     dialog = dlg_new_window(height, width, y, x);
1904c8945a0SNathan Whitehorn 
1914c8945a0SNathan Whitehorn     dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
1924c8945a0SNathan Whitehorn     dlg_draw_title(dialog, title);
193*682c9e0fSNathan Whitehorn     dlg_draw_helpline(dialog, FALSE);
1944c8945a0SNathan Whitehorn 
1954c8945a0SNathan Whitehorn     if (*prompt != '\0') {
1964c8945a0SNathan Whitehorn 	int y2, x2;
1974c8945a0SNathan Whitehorn 
1984c8945a0SNathan Whitehorn 	wattrset(dialog, dialog_attr);
1994c8945a0SNathan Whitehorn 	dlg_print_autowrap(dialog, prompt, height, width);
2004c8945a0SNathan Whitehorn 	getyx(dialog, y2, x2);
2014c8945a0SNathan Whitehorn 	++y2;
2024c8945a0SNathan Whitehorn 	wmove(dialog, y2, MARGIN);
2034c8945a0SNathan Whitehorn 	for (i = 0; i < getmaxx(dialog) - 2 * MARGIN; i++)
2044c8945a0SNathan Whitehorn 	    (void) waddch(dialog, dlg_boxchar(ACS_HLINE));
2054c8945a0SNathan Whitehorn 	y += y2;
2064c8945a0SNathan Whitehorn 	thigh -= y2;
2074c8945a0SNathan Whitehorn     }
2084c8945a0SNathan Whitehorn 
2094c8945a0SNathan Whitehorn     /* Create window for text region, used for scrolling text */
2104c8945a0SNathan Whitehorn     text = dlg_sub_window(dialog,
2114c8945a0SNathan Whitehorn 			  thigh,
2124c8945a0SNathan Whitehorn 			  width - (2 * MARGIN),
2134c8945a0SNathan Whitehorn 			  y + MARGIN,
2144c8945a0SNathan Whitehorn 			  x + MARGIN);
2154c8945a0SNathan Whitehorn 
2164c8945a0SNathan Whitehorn     (void) wrefresh(dialog);
2174c8945a0SNathan Whitehorn 
2184c8945a0SNathan Whitehorn     (void) wmove(dialog, thigh, (MARGIN + 1));
2194c8945a0SNathan Whitehorn     (void) wnoutrefresh(dialog);
2204c8945a0SNathan Whitehorn 
2214c8945a0SNathan Whitehorn     obj = dlg_calloc(MY_OBJ, 1);
2227a1c0d96SNathan Whitehorn     assert_ptr(obj, "dlg_progressbox");
2234c8945a0SNathan Whitehorn 
2247a1c0d96SNathan Whitehorn     obj->obj.input = fp;
2254c8945a0SNathan Whitehorn     obj->obj.win = dialog;
2264c8945a0SNathan Whitehorn     obj->text = text;
2274c8945a0SNathan Whitehorn 
2284c8945a0SNathan Whitehorn     dlg_attr_clear(text, thigh, getmaxx(text), dialog_attr);
2294c8945a0SNathan Whitehorn     for (i = 0; get_line(obj); i++) {
2304c8945a0SNathan Whitehorn 	if (i < thigh) {
2314c8945a0SNathan Whitehorn 	    print_line(obj, text, i, width - (2 * MARGIN));
2324c8945a0SNathan Whitehorn 	} else {
2334c8945a0SNathan Whitehorn 	    scrollok(text, TRUE);
2344c8945a0SNathan Whitehorn 	    scroll(text);
2354c8945a0SNathan Whitehorn 	    scrollok(text, FALSE);
2364c8945a0SNathan Whitehorn 	    print_line(obj, text, thigh - 1, width - (2 * MARGIN));
2374c8945a0SNathan Whitehorn 	}
2384c8945a0SNathan Whitehorn 	(void) wrefresh(text);
2394c8945a0SNathan Whitehorn 	if (obj->is_eof)
2404c8945a0SNathan Whitehorn 	    break;
2414c8945a0SNathan Whitehorn     }
2427a1c0d96SNathan Whitehorn 
2437a1c0d96SNathan Whitehorn     if (pauseopt) {
2447a1c0d96SNathan Whitehorn 	scrollok(text, TRUE);
2457a1c0d96SNathan Whitehorn 	wscrl(text, 1 + MARGIN);
2467a1c0d96SNathan Whitehorn 	(void) wrefresh(text);
2477a1c0d96SNathan Whitehorn 	result = pause_for_ok(dialog, height, width);
2487a1c0d96SNathan Whitehorn     } else {
2497a1c0d96SNathan Whitehorn 	wrefresh(dialog);
2507a1c0d96SNathan Whitehorn 	result = DLG_EXIT_OK;
2517a1c0d96SNathan Whitehorn     }
2527a1c0d96SNathan Whitehorn 
2534c8945a0SNathan Whitehorn     dlg_del_window(dialog);
2544c8945a0SNathan Whitehorn     free(prompt);
2554c8945a0SNathan Whitehorn     free(obj);
2564c8945a0SNathan Whitehorn 
2574c8945a0SNathan Whitehorn     return DLG_EXIT_OK;
2584c8945a0SNathan Whitehorn }
2597a1c0d96SNathan Whitehorn 
2607a1c0d96SNathan Whitehorn /*
2617a1c0d96SNathan Whitehorn  * Display text from a stdin in a scrolling window.
2627a1c0d96SNathan Whitehorn  */
2637a1c0d96SNathan Whitehorn int
2647a1c0d96SNathan Whitehorn dialog_progressbox(const char *title, const char *cprompt, int height, int width)
2657a1c0d96SNathan Whitehorn {
2667a1c0d96SNathan Whitehorn     int result;
2677a1c0d96SNathan Whitehorn     result = dlg_progressbox(title,
2687a1c0d96SNathan Whitehorn 			     cprompt,
2697a1c0d96SNathan Whitehorn 			     height,
2707a1c0d96SNathan Whitehorn 			     width,
2717a1c0d96SNathan Whitehorn 			     FALSE,
2727a1c0d96SNathan Whitehorn 			     dialog_state.pipe_input);
2737a1c0d96SNathan Whitehorn     dialog_state.pipe_input = 0;
2747a1c0d96SNathan Whitehorn     return result;
2757a1c0d96SNathan Whitehorn }
276