1217309Snwhitehorn/*
2251843Sbapt *  $Id: pause.c,v 1.36 2012/07/03 00:01:59 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  pause.c -- implements the pause dialog
5217309Snwhitehorn *
6251843Sbapt *  Copyright 2004-2011,2012	Thomas E. Dickey
7217309Snwhitehorn *
8217309Snwhitehorn *  This program is free software; you can redistribute it and/or modify
9217309Snwhitehorn *  it under the terms of the GNU Lesser General Public License, version 2.1
10217309Snwhitehorn *  as published by the Free Software Foundation.
11217309Snwhitehorn *
12217309Snwhitehorn *  This program is distributed in the hope that it will be useful, but
13217309Snwhitehorn *  WITHOUT ANY WARRANTY; without even the implied warranty of
14217309Snwhitehorn *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15217309Snwhitehorn *  Lesser General Public License for more details.
16217309Snwhitehorn *
17217309Snwhitehorn *  You should have received a copy of the GNU Lesser General Public
18217309Snwhitehorn *  License along with this program; if not, write to
19217309Snwhitehorn *	Free Software Foundation, Inc.
20217309Snwhitehorn *	51 Franklin St., Fifth Floor
21217309Snwhitehorn *	Boston, MA 02110, USA.
22217309Snwhitehorn *
23217309Snwhitehorn *  This is adapted from source contributed by
24217309Snwhitehorn *	Yura Kalinichenko
25217309Snwhitehorn */
26217309Snwhitehorn
27217309Snwhitehorn#include <dialog.h>
28217309Snwhitehorn#include <dlg_keys.h>
29217309Snwhitehorn
30217309Snwhitehorn#define MY_TIMEOUT 50
31217309Snwhitehorn
32217309Snwhitehorn#define MIN_HIGH (4)
33217309Snwhitehorn#define MIN_WIDE (10 + 2 * (2 + MARGIN))
34217309Snwhitehorn#define BTN_HIGH (1 + 2 * MARGIN)
35217309Snwhitehorn
36217309Snwhitehorn/*
37217309Snwhitehorn * This is like gauge, but can be interrupted.
38217309Snwhitehorn *
39217309Snwhitehorn * A pause box displays a meter along the bottom of the box.  The meter
40217309Snwhitehorn * indicates how many seconds remain until the end of the pause.  The pause
41217309Snwhitehorn * exits when timeout is reached (status OK) or the user presses:
42217309Snwhitehorn *   OK button (status OK)
43217309Snwhitehorn *   CANCEL button (status CANCEL)
44217309Snwhitehorn *   Esc key (status ESC)
45217309Snwhitehorn *
46217309Snwhitehorn */
47217309Snwhitehornint
48217309Snwhitehorndialog_pause(const char *title,
49217309Snwhitehorn	     const char *cprompt,
50217309Snwhitehorn	     int height,
51217309Snwhitehorn	     int width,
52217309Snwhitehorn	     int seconds)
53217309Snwhitehorn{
54217309Snwhitehorn    /* *INDENT-OFF* */
55217309Snwhitehorn    static DLG_KEYS_BINDING binding[] = {
56224014Snwhitehorn	HELPKEY_BINDINGS,
57217309Snwhitehorn	ENTERKEY_BINDINGS,
58251843Sbapt	TRAVERSE_BINDINGS,
59217309Snwhitehorn	END_KEYS_BINDING
60217309Snwhitehorn    };
61217309Snwhitehorn    /* *INDENT-ON* */
62217309Snwhitehorn
63217309Snwhitehorn#ifdef KEY_RESIZE
64217309Snwhitehorn    int old_height = height;
65217309Snwhitehorn    int old_width = width;
66217309Snwhitehorn#endif
67217309Snwhitehorn
68217309Snwhitehorn    int i, x, y, step;
69251843Sbapt    int button = dlg_default_button();
70217309Snwhitehorn    int seconds_orig;
71217309Snwhitehorn    WINDOW *dialog;
72217309Snwhitehorn    const char **buttons = dlg_ok_labels();
73217309Snwhitehorn    bool have_buttons = (dlg_button_count(buttons) != 0);
74251843Sbapt    bool first;
75217309Snwhitehorn    int key = 0, fkey;
76217309Snwhitehorn    int result = DLG_EXIT_UNKNOWN;
77217309Snwhitehorn    int button_high = (have_buttons ? BTN_HIGH : MARGIN);
78220749Snwhitehorn    int gauge_y;
79217309Snwhitehorn    char *prompt = dlg_strclone(cprompt);
80251843Sbapt    int save_timeout = dialog_vars.timeout_secs;
81217309Snwhitehorn
82217309Snwhitehorn    curs_set(0);
83217309Snwhitehorn
84217309Snwhitehorn    dlg_tab_correct_str(prompt);
85217309Snwhitehorn
86251843Sbapt    dialog_vars.timeout_secs = 0;
87217309Snwhitehorn    seconds_orig = (seconds > 0) ? seconds : 1;
88217309Snwhitehorn
89217309Snwhitehorn#ifdef KEY_RESIZE
90217309Snwhitehorn  retry:
91217309Snwhitehorn    height = old_height;
92217309Snwhitehorn    width = old_width;
93217309Snwhitehorn#endif
94217309Snwhitehorn
95217309Snwhitehorn    if (have_buttons) {
96217309Snwhitehorn	dlg_auto_size(title, prompt, &height, &width,
97217309Snwhitehorn		      MIN_HIGH,
98217309Snwhitehorn		      MIN_WIDE);
99217309Snwhitehorn	dlg_button_layout(buttons, &width);
100217309Snwhitehorn    } else {
101217309Snwhitehorn	dlg_auto_size(title, prompt, &height, &width,
102217309Snwhitehorn		      MIN_HIGH + MARGIN - BTN_HIGH,
103217309Snwhitehorn		      MIN_WIDE);
104217309Snwhitehorn    }
105220749Snwhitehorn    gauge_y = height - button_high - (1 + 2 * MARGIN);
106217309Snwhitehorn    dlg_print_size(height, width);
107217309Snwhitehorn    dlg_ctl_size(height, width);
108217309Snwhitehorn
109217309Snwhitehorn    /* center dialog box on screen */
110217309Snwhitehorn    x = dlg_box_x_ordinate(width);
111217309Snwhitehorn    y = dlg_box_y_ordinate(height);
112217309Snwhitehorn
113217309Snwhitehorn    dialog = dlg_new_window(height, width, y, x);
114217309Snwhitehorn    dlg_register_window(dialog, "pause", binding);
115217309Snwhitehorn    dlg_register_buttons(dialog, "pause", buttons);
116217309Snwhitehorn
117217309Snwhitehorn    dlg_mouse_setbase(x, y);
118217309Snwhitehorn    nodelay(dialog, TRUE);
119217309Snwhitehorn
120251843Sbapt    first = TRUE;
121217309Snwhitehorn    do {
122217309Snwhitehorn	(void) werase(dialog);
123251843Sbapt	dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
124217309Snwhitehorn
125217309Snwhitehorn	dlg_draw_title(dialog, title);
126224014Snwhitehorn	dlg_draw_helpline(dialog, FALSE);
127217309Snwhitehorn
128251843Sbapt	(void) wattrset(dialog, dialog_attr);
129217309Snwhitehorn	dlg_print_autowrap(dialog, prompt, height, width);
130217309Snwhitehorn
131251843Sbapt	dlg_draw_box2(dialog,
132251843Sbapt		      gauge_y, 2 + MARGIN,
133251843Sbapt		      2 + MARGIN, width - 2 * (2 + MARGIN),
134251843Sbapt		      dialog_attr,
135251843Sbapt		      border_attr,
136251843Sbapt		      border2_attr);
137217309Snwhitehorn
138217309Snwhitehorn	/*
139217309Snwhitehorn	 * Clear the area for the progress bar by filling it with spaces
140217309Snwhitehorn	 * in the title-attribute, and write the percentage with that
141217309Snwhitehorn	 * attribute.
142217309Snwhitehorn	 */
143220749Snwhitehorn	(void) wmove(dialog, gauge_y + MARGIN, 4);
144251843Sbapt	(void) wattrset(dialog, title_attr);
145217309Snwhitehorn
146217309Snwhitehorn	for (i = 0; i < (width - 2 * (3 + MARGIN)); i++)
147217309Snwhitehorn	    (void) waddch(dialog, ' ');
148217309Snwhitehorn
149220749Snwhitehorn	(void) wmove(dialog, gauge_y + MARGIN, (width / 2) - 2);
150217309Snwhitehorn	(void) wprintw(dialog, "%3d", seconds);
151217309Snwhitehorn
152217309Snwhitehorn	/*
153217309Snwhitehorn	 * Now draw a bar in reverse, relative to the background.
154217309Snwhitehorn	 * The window attribute was useful for painting the background,
155217309Snwhitehorn	 * but requires some tweaks to reverse it.
156217309Snwhitehorn	 */
157217309Snwhitehorn	x = (seconds * (width - 2 * (3 + MARGIN))) / seconds_orig;
158217309Snwhitehorn	if ((title_attr & A_REVERSE) != 0) {
159217309Snwhitehorn	    wattroff(dialog, A_REVERSE);
160217309Snwhitehorn	} else {
161251843Sbapt	    (void) wattrset(dialog, A_REVERSE);
162217309Snwhitehorn	}
163220749Snwhitehorn	(void) wmove(dialog, gauge_y + MARGIN, 4);
164217309Snwhitehorn	for (i = 0; i < x; i++) {
165217309Snwhitehorn	    chtype ch = winch(dialog);
166217309Snwhitehorn	    if (title_attr & A_REVERSE) {
167217309Snwhitehorn		ch &= ~A_REVERSE;
168217309Snwhitehorn	    }
169217309Snwhitehorn	    (void) waddch(dialog, ch);
170217309Snwhitehorn	}
171217309Snwhitehorn
172217309Snwhitehorn	mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n');
173217309Snwhitehorn	if (have_buttons) {
174251843Sbapt	    dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
175217309Snwhitehorn	    dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
176217309Snwhitehorn	}
177251843Sbapt	if (first) {
178251843Sbapt	    (void) wrefresh(dialog);
179251843Sbapt	    dlg_trace_win(dialog);
180251843Sbapt	    first = FALSE;
181251843Sbapt	}
182217309Snwhitehorn
183217309Snwhitehorn	for (step = 0;
184217309Snwhitehorn	     (result == DLG_EXIT_UNKNOWN) && (step < 1000);
185217309Snwhitehorn	     step += MY_TIMEOUT) {
186217309Snwhitehorn
187217309Snwhitehorn	    napms(MY_TIMEOUT);
188217309Snwhitehorn	    key = dlg_mouse_wgetch_nowait(dialog, &fkey);
189217309Snwhitehorn	    if (key == ERR) {
190217309Snwhitehorn		;		/* ignore errors in nodelay mode */
191217309Snwhitehorn	    } else {
192217309Snwhitehorn		if (dlg_result_key(key, fkey, &result))
193217309Snwhitehorn		    break;
194217309Snwhitehorn	    }
195217309Snwhitehorn
196217309Snwhitehorn	    switch (key) {
197217309Snwhitehorn#ifdef KEY_RESIZE
198217309Snwhitehorn	    case KEY_RESIZE:
199217309Snwhitehorn		dlg_clear();	/* fill the background */
200217309Snwhitehorn		dlg_del_window(dialog);		/* delete this window */
201217309Snwhitehorn		refresh();	/* get it all onto the terminal */
202217309Snwhitehorn		goto retry;
203217309Snwhitehorn#endif
204217309Snwhitehorn	    case DLGK_FIELD_NEXT:
205217309Snwhitehorn		button = dlg_next_button(buttons, button);
206217309Snwhitehorn		if (button < 0)
207217309Snwhitehorn		    button = 0;
208217309Snwhitehorn		dlg_draw_buttons(dialog,
209217309Snwhitehorn				 height - 2, 0,
210217309Snwhitehorn				 buttons, button,
211217309Snwhitehorn				 FALSE, width);
212217309Snwhitehorn		break;
213217309Snwhitehorn	    case DLGK_FIELD_PREV:
214217309Snwhitehorn		button = dlg_prev_button(buttons, button);
215217309Snwhitehorn		if (button < 0)
216217309Snwhitehorn		    button = 0;
217217309Snwhitehorn		dlg_draw_buttons(dialog,
218217309Snwhitehorn				 height - 2, 0,
219217309Snwhitehorn				 buttons, button,
220217309Snwhitehorn				 FALSE, width);
221217309Snwhitehorn		break;
222217309Snwhitehorn	    case DLGK_ENTER:
223224014Snwhitehorn		result = dlg_enter_buttoncode(button);
224217309Snwhitehorn		break;
225217309Snwhitehorn	    case ERR:
226217309Snwhitehorn		break;
227217309Snwhitehorn	    default:
228251843Sbapt		if (is_DLGK_MOUSE(key)) {
229251843Sbapt		    result = dlg_ok_buttoncode(key - M_EVENT);
230251843Sbapt		    if (result < 0)
231251843Sbapt			result = DLG_EXIT_OK;
232251843Sbapt		}
233217309Snwhitehorn		break;
234217309Snwhitehorn	    }
235217309Snwhitehorn	}
236217309Snwhitehorn    } while ((result == DLG_EXIT_UNKNOWN) && (seconds-- > 0));
237217309Snwhitehorn
238217309Snwhitehorn    curs_set(1);
239217309Snwhitehorn    dlg_mouse_free_regions();
240217309Snwhitehorn    dlg_del_window(dialog);
241217309Snwhitehorn    free(prompt);
242251843Sbapt
243251843Sbapt    dialog_vars.timeout_secs = save_timeout;
244251843Sbapt
245217309Snwhitehorn    return ((result == DLG_EXIT_UNKNOWN) ? DLG_EXIT_OK : result);
246217309Snwhitehorn}
247