1217309Snwhitehorn/*
2251843Sbapt *  $Id: progressbox.c,v 1.23 2012/12/21 10:00:05 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  progressbox.c -- implements the progress box
5217309Snwhitehorn *
6217309Snwhitehorn *  Copyright 2005	Valery Reznic
7251843Sbapt *  Copyright 2006-2012	Thomas E. Dickey
8217309Snwhitehorn *
9217309Snwhitehorn *  This program is free software; you can redistribute it and/or modify
10217309Snwhitehorn *  it under the terms of the GNU Lesser General Public License as
11217309Snwhitehorn *  published by the Free Software Foundation; either version 2.1 of the
12217309Snwhitehorn *  License, or (at your option) any later version.
13217309Snwhitehorn *
14217309Snwhitehorn *  This program is distributed in the hope that it will be useful, but
15217309Snwhitehorn *  WITHOUT ANY WARRANTY; without even the implied warranty of
16217309Snwhitehorn *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17217309Snwhitehorn *  Lesser General Public License for more details.
18217309Snwhitehorn *
19217309Snwhitehorn *  You should have received a copy of the GNU Lesser General Public
20217309Snwhitehorn *  License along with this program; if not, write to
21217309Snwhitehorn *	Free Software Foundation, Inc.
22217309Snwhitehorn *	51 Franklin St., Fifth Floor
23217309Snwhitehorn *	Boston, MA 02110, USA.
24217309Snwhitehorn */
25217309Snwhitehorn
26217309Snwhitehorn#include <dialog.h>
27217309Snwhitehorn#include <dlg_keys.h>
28217309Snwhitehorn
29217309Snwhitehorn#define MIN_HIGH (4)
30217309Snwhitehorn#define MIN_WIDE (10 + 2 * (2 + MARGIN))
31217309Snwhitehorn
32217309Snwhitehorntypedef struct {
33217309Snwhitehorn    DIALOG_CALLBACK obj;
34217309Snwhitehorn    WINDOW *text;
35217309Snwhitehorn    char line[MAX_LEN + 1];
36217309Snwhitehorn    int is_eof;
37217309Snwhitehorn} MY_OBJ;
38217309Snwhitehorn
39217309Snwhitehorn/*
40217309Snwhitehorn * Return current line of text.
41217309Snwhitehorn */
42217309Snwhitehornstatic char *
43217309Snwhitehornget_line(MY_OBJ * obj)
44217309Snwhitehorn{
45217309Snwhitehorn    FILE *fp = obj->obj.input;
46217309Snwhitehorn    int col = 0;
47217309Snwhitehorn    int j, tmpint, ch;
48217309Snwhitehorn
49251843Sbapt    for (;;) {
50217309Snwhitehorn	if ((ch = getc(fp)) == EOF) {
51217309Snwhitehorn	    obj->is_eof = 1;
52217309Snwhitehorn	    if (col) {
53217309Snwhitehorn		break;
54217309Snwhitehorn	    } else {
55217309Snwhitehorn		return NULL;
56217309Snwhitehorn	    }
57217309Snwhitehorn	}
58217309Snwhitehorn	if (ch == '\n')
59217309Snwhitehorn	    break;
60217309Snwhitehorn	if (ch == '\r')
61217309Snwhitehorn	    break;
62251843Sbapt	if (col >= MAX_LEN)
63251843Sbapt	    continue;
64217309Snwhitehorn	if ((ch == TAB) && (dialog_vars.tab_correct)) {
65217309Snwhitehorn	    tmpint = dialog_state.tab_len
66217309Snwhitehorn		- (col % dialog_state.tab_len);
67217309Snwhitehorn	    for (j = 0; j < tmpint; j++) {
68251843Sbapt		if (col < MAX_LEN) {
69217309Snwhitehorn		    obj->line[col] = ' ';
70251843Sbapt		    ++col;
71251843Sbapt		} else {
72251843Sbapt		    break;
73251843Sbapt		}
74217309Snwhitehorn	    }
75217309Snwhitehorn	} else {
76217309Snwhitehorn	    obj->line[col] = (char) ch;
77217309Snwhitehorn	    ++col;
78217309Snwhitehorn	}
79217309Snwhitehorn    }
80217309Snwhitehorn
81217309Snwhitehorn    obj->line[col] = '\0';
82217309Snwhitehorn
83217309Snwhitehorn    return obj->line;
84217309Snwhitehorn}
85217309Snwhitehorn
86217309Snwhitehorn/*
87217309Snwhitehorn * Print a new line of text.
88217309Snwhitehorn */
89217309Snwhitehornstatic void
90217309Snwhitehornprint_line(MY_OBJ * obj, WINDOW *win, int row, int width)
91217309Snwhitehorn{
92217309Snwhitehorn    int i, y, x;
93217309Snwhitehorn    char *line = obj->line;
94217309Snwhitehorn
95217309Snwhitehorn    (void) wmove(win, row, 0);	/* move cursor to correct line */
96217309Snwhitehorn    (void) waddch(win, ' ');
97217309Snwhitehorn#ifdef NCURSES_VERSION
98217309Snwhitehorn    (void) waddnstr(win, line, MIN((int) strlen(line), width - 2));
99217309Snwhitehorn#else
100217309Snwhitehorn    line[MIN((int) strlen(line), width - 2)] = '\0';
101217309Snwhitehorn    waddstr(win, line);
102217309Snwhitehorn#endif
103217309Snwhitehorn
104217309Snwhitehorn    getyx(win, y, x);
105251843Sbapt    (void) y;
106217309Snwhitehorn    /* Clear 'residue' of previous line */
107217309Snwhitehorn    for (i = 0; i < width - x; i++)
108217309Snwhitehorn	(void) waddch(win, ' ');
109217309Snwhitehorn}
110217309Snwhitehorn
111220749Snwhitehornstatic int
112220749Snwhitehornpause_for_ok(WINDOW *dialog, int height, int width)
113220749Snwhitehorn{
114220749Snwhitehorn    /* *INDENT-OFF* */
115220749Snwhitehorn    static DLG_KEYS_BINDING binding[] = {
116224014Snwhitehorn	HELPKEY_BINDINGS,
117220749Snwhitehorn	ENTERKEY_BINDINGS,
118251843Sbapt	TRAVERSE_BINDINGS,
119220749Snwhitehorn	END_KEYS_BINDING
120220749Snwhitehorn    };
121220749Snwhitehorn    /* *INDENT-ON* */
122220749Snwhitehorn
123251843Sbapt    int button;
124220749Snwhitehorn    int key = 0, fkey;
125220749Snwhitehorn    int result = DLG_EXIT_UNKNOWN;
126220749Snwhitehorn    const char **buttons = dlg_ok_label();
127220749Snwhitehorn    int check;
128251843Sbapt    int save_nocancel = dialog_vars.nocancel;
129251843Sbapt    bool redraw = TRUE;
130220749Snwhitehorn
131251843Sbapt    dialog_vars.nocancel = TRUE;
132251843Sbapt    button = dlg_default_button();
133251843Sbapt
134220749Snwhitehorn    dlg_register_window(dialog, "progressbox", binding);
135220749Snwhitehorn    dlg_register_buttons(dialog, "progressbox", buttons);
136220749Snwhitehorn
137251843Sbapt    dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
138220749Snwhitehorn    mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n');
139220749Snwhitehorn
140220749Snwhitehorn    while (result == DLG_EXIT_UNKNOWN) {
141251843Sbapt	if (redraw) {
142251843Sbapt	    redraw = FALSE;
143251843Sbapt	    if (button < 0)
144251843Sbapt		button = 0;
145251843Sbapt	    dlg_draw_buttons(dialog,
146251843Sbapt			     height - 2, 0,
147251843Sbapt			     buttons, button,
148251843Sbapt			     FALSE, width);
149251843Sbapt	}
150251843Sbapt
151220749Snwhitehorn	key = dlg_mouse_wgetch(dialog, &fkey);
152220749Snwhitehorn	if (dlg_result_key(key, fkey, &result))
153220749Snwhitehorn	    break;
154220749Snwhitehorn
155220749Snwhitehorn	if (!fkey && (check = dlg_char_to_button(key, buttons)) >= 0) {
156251843Sbapt	    result = dlg_ok_buttoncode(check);
157220749Snwhitehorn	    break;
158220749Snwhitehorn	}
159220749Snwhitehorn
160220749Snwhitehorn	if (fkey) {
161220749Snwhitehorn	    switch (key) {
162251843Sbapt	    case DLGK_FIELD_NEXT:
163251843Sbapt		button = dlg_next_button(buttons, button);
164251843Sbapt		redraw = TRUE;
165220749Snwhitehorn		break;
166251843Sbapt	    case DLGK_FIELD_PREV:
167251843Sbapt		button = dlg_prev_button(buttons, button);
168251843Sbapt		redraw = TRUE;
169220749Snwhitehorn		break;
170251843Sbapt	    case DLGK_ENTER:
171251843Sbapt		result = dlg_ok_buttoncode(button);
172220749Snwhitehorn		break;
173220749Snwhitehorn	    default:
174251843Sbapt		if (is_DLGK_MOUSE(key)) {
175251843Sbapt		    result = dlg_ok_buttoncode(key - M_EVENT);
176251843Sbapt		    if (result < 0)
177251843Sbapt			result = DLG_EXIT_OK;
178251843Sbapt		} else {
179251843Sbapt		    beep();
180251843Sbapt		}
181220749Snwhitehorn		break;
182220749Snwhitehorn	    }
183251843Sbapt
184220749Snwhitehorn	} else {
185220749Snwhitehorn	    beep();
186220749Snwhitehorn	}
187220749Snwhitehorn    }
188220749Snwhitehorn    dlg_unregister_window(dialog);
189251843Sbapt
190251843Sbapt    dialog_vars.nocancel = save_nocancel;
191220749Snwhitehorn    return result;
192220749Snwhitehorn}
193220749Snwhitehorn
194217309Snwhitehornint
195220749Snwhitehorndlg_progressbox(const char *title,
196220749Snwhitehorn		const char *cprompt,
197220749Snwhitehorn		int height,
198220749Snwhitehorn		int width,
199220749Snwhitehorn		int pauseopt,
200220749Snwhitehorn		FILE *fp)
201217309Snwhitehorn{
202217309Snwhitehorn    int i;
203217309Snwhitehorn    int x, y, thigh;
204217309Snwhitehorn    WINDOW *dialog, *text;
205217309Snwhitehorn    MY_OBJ *obj;
206217309Snwhitehorn    char *prompt = dlg_strclone(cprompt);
207220749Snwhitehorn    int result;
208217309Snwhitehorn
209217309Snwhitehorn    dlg_tab_correct_str(prompt);
210217309Snwhitehorn    dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, MIN_WIDE);
211217309Snwhitehorn    dlg_print_size(height, width);
212217309Snwhitehorn    dlg_ctl_size(height, width);
213217309Snwhitehorn
214217309Snwhitehorn    x = dlg_box_x_ordinate(width);
215217309Snwhitehorn    y = dlg_box_y_ordinate(height);
216217309Snwhitehorn    thigh = height - (2 * MARGIN);
217217309Snwhitehorn
218217309Snwhitehorn    dialog = dlg_new_window(height, width, y, x);
219217309Snwhitehorn
220251843Sbapt    dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
221217309Snwhitehorn    dlg_draw_title(dialog, title);
222224014Snwhitehorn    dlg_draw_helpline(dialog, FALSE);
223217309Snwhitehorn
224217309Snwhitehorn    if (*prompt != '\0') {
225217309Snwhitehorn	int y2, x2;
226217309Snwhitehorn
227251843Sbapt	(void) wattrset(dialog, dialog_attr);
228217309Snwhitehorn	dlg_print_autowrap(dialog, prompt, height, width);
229217309Snwhitehorn	getyx(dialog, y2, x2);
230251843Sbapt	(void) x2;
231217309Snwhitehorn	++y2;
232217309Snwhitehorn	wmove(dialog, y2, MARGIN);
233217309Snwhitehorn	for (i = 0; i < getmaxx(dialog) - 2 * MARGIN; i++)
234217309Snwhitehorn	    (void) waddch(dialog, dlg_boxchar(ACS_HLINE));
235217309Snwhitehorn	y += y2;
236217309Snwhitehorn	thigh -= y2;
237217309Snwhitehorn    }
238217309Snwhitehorn
239217309Snwhitehorn    /* Create window for text region, used for scrolling text */
240217309Snwhitehorn    text = dlg_sub_window(dialog,
241217309Snwhitehorn			  thigh,
242217309Snwhitehorn			  width - (2 * MARGIN),
243217309Snwhitehorn			  y + MARGIN,
244217309Snwhitehorn			  x + MARGIN);
245217309Snwhitehorn
246217309Snwhitehorn    (void) wrefresh(dialog);
247217309Snwhitehorn
248217309Snwhitehorn    (void) wmove(dialog, thigh, (MARGIN + 1));
249217309Snwhitehorn    (void) wnoutrefresh(dialog);
250217309Snwhitehorn
251217309Snwhitehorn    obj = dlg_calloc(MY_OBJ, 1);
252220749Snwhitehorn    assert_ptr(obj, "dlg_progressbox");
253217309Snwhitehorn
254220749Snwhitehorn    obj->obj.input = fp;
255217309Snwhitehorn    obj->obj.win = dialog;
256217309Snwhitehorn    obj->text = text;
257217309Snwhitehorn
258217309Snwhitehorn    dlg_attr_clear(text, thigh, getmaxx(text), dialog_attr);
259217309Snwhitehorn    for (i = 0; get_line(obj); i++) {
260217309Snwhitehorn	if (i < thigh) {
261217309Snwhitehorn	    print_line(obj, text, i, width - (2 * MARGIN));
262217309Snwhitehorn	} else {
263217309Snwhitehorn	    scrollok(text, TRUE);
264217309Snwhitehorn	    scroll(text);
265217309Snwhitehorn	    scrollok(text, FALSE);
266217309Snwhitehorn	    print_line(obj, text, thigh - 1, width - (2 * MARGIN));
267217309Snwhitehorn	}
268217309Snwhitehorn	(void) wrefresh(text);
269251843Sbapt	dlg_trace_win(dialog);
270217309Snwhitehorn	if (obj->is_eof)
271217309Snwhitehorn	    break;
272217309Snwhitehorn    }
273220749Snwhitehorn
274220749Snwhitehorn    if (pauseopt) {
275220749Snwhitehorn	scrollok(text, TRUE);
276220749Snwhitehorn	wscrl(text, 1 + MARGIN);
277220749Snwhitehorn	(void) wrefresh(text);
278220749Snwhitehorn	result = pause_for_ok(dialog, height, width);
279220749Snwhitehorn    } else {
280220749Snwhitehorn	wrefresh(dialog);
281220749Snwhitehorn	result = DLG_EXIT_OK;
282220749Snwhitehorn    }
283220749Snwhitehorn
284217309Snwhitehorn    dlg_del_window(dialog);
285217309Snwhitehorn    free(prompt);
286217309Snwhitehorn    free(obj);
287217309Snwhitehorn
288251843Sbapt    return result;
289217309Snwhitehorn}
290220749Snwhitehorn
291220749Snwhitehorn/*
292220749Snwhitehorn * Display text from a stdin in a scrolling window.
293220749Snwhitehorn */
294220749Snwhitehornint
295220749Snwhitehorndialog_progressbox(const char *title, const char *cprompt, int height, int width)
296220749Snwhitehorn{
297220749Snwhitehorn    int result;
298220749Snwhitehorn    result = dlg_progressbox(title,
299220749Snwhitehorn			     cprompt,
300220749Snwhitehorn			     height,
301220749Snwhitehorn			     width,
302220749Snwhitehorn			     FALSE,
303220749Snwhitehorn			     dialog_state.pipe_input);
304220749Snwhitehorn    dialog_state.pipe_input = 0;
305220749Snwhitehorn    return result;
306220749Snwhitehorn}
307