pause.c revision 217309
1217309Snwhitehorn/*
2217309Snwhitehorn *  $Id: pause.c,v 1.22 2010/04/28 00:29:50 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  pause.c -- implements the pause dialog
5217309Snwhitehorn *
6217309Snwhitehorn *  Copyright 2004-2009,2010	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[] = {
56217309Snwhitehorn	ENTERKEY_BINDINGS,
57217309Snwhitehorn	DLG_KEYS_DATA( DLGK_ENTER,	' ' ),
58217309Snwhitehorn	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	KEY_DOWN ),
59217309Snwhitehorn	DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
60217309Snwhitehorn	DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
61217309Snwhitehorn	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_UP ),
62217309Snwhitehorn	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
63217309Snwhitehorn	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
64217309Snwhitehorn	END_KEYS_BINDING
65217309Snwhitehorn    };
66217309Snwhitehorn    /* *INDENT-ON* */
67217309Snwhitehorn
68217309Snwhitehorn#ifdef KEY_RESIZE
69217309Snwhitehorn    int old_height = height;
70217309Snwhitehorn    int old_width = width;
71217309Snwhitehorn#endif
72217309Snwhitehorn
73217309Snwhitehorn    int i, x, y, step;
74217309Snwhitehorn    int button = 0;
75217309Snwhitehorn    int seconds_orig;
76217309Snwhitehorn    WINDOW *dialog;
77217309Snwhitehorn    const char **buttons = dlg_ok_labels();
78217309Snwhitehorn    bool have_buttons = (dlg_button_count(buttons) != 0);
79217309Snwhitehorn    int key = 0, fkey;
80217309Snwhitehorn    int result = DLG_EXIT_UNKNOWN;
81217309Snwhitehorn    int button_high = (have_buttons ? BTN_HIGH : MARGIN);
82217309Snwhitehorn    int guage_y;
83217309Snwhitehorn    char *prompt = dlg_strclone(cprompt);
84217309Snwhitehorn
85217309Snwhitehorn    curs_set(0);
86217309Snwhitehorn
87217309Snwhitehorn    dlg_tab_correct_str(prompt);
88217309Snwhitehorn
89217309Snwhitehorn    seconds_orig = (seconds > 0) ? seconds : 1;
90217309Snwhitehorn
91217309Snwhitehorn#ifdef KEY_RESIZE
92217309Snwhitehorn  retry:
93217309Snwhitehorn    height = old_height;
94217309Snwhitehorn    width = old_width;
95217309Snwhitehorn#endif
96217309Snwhitehorn
97217309Snwhitehorn    if (have_buttons) {
98217309Snwhitehorn	dlg_auto_size(title, prompt, &height, &width,
99217309Snwhitehorn		      MIN_HIGH,
100217309Snwhitehorn		      MIN_WIDE);
101217309Snwhitehorn	dlg_button_layout(buttons, &width);
102217309Snwhitehorn    } else {
103217309Snwhitehorn	dlg_auto_size(title, prompt, &height, &width,
104217309Snwhitehorn		      MIN_HIGH + MARGIN - BTN_HIGH,
105217309Snwhitehorn		      MIN_WIDE);
106217309Snwhitehorn    }
107217309Snwhitehorn    guage_y = height - button_high - (1 + 2 * MARGIN);
108217309Snwhitehorn    dlg_print_size(height, width);
109217309Snwhitehorn    dlg_ctl_size(height, width);
110217309Snwhitehorn
111217309Snwhitehorn    /* center dialog box on screen */
112217309Snwhitehorn    x = dlg_box_x_ordinate(width);
113217309Snwhitehorn    y = dlg_box_y_ordinate(height);
114217309Snwhitehorn
115217309Snwhitehorn    dialog = dlg_new_window(height, width, y, x);
116217309Snwhitehorn    dlg_register_window(dialog, "pause", binding);
117217309Snwhitehorn    dlg_register_buttons(dialog, "pause", buttons);
118217309Snwhitehorn
119217309Snwhitehorn    dlg_mouse_setbase(x, y);
120217309Snwhitehorn    nodelay(dialog, TRUE);
121217309Snwhitehorn
122217309Snwhitehorn    do {
123217309Snwhitehorn	(void) werase(dialog);
124217309Snwhitehorn	dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
125217309Snwhitehorn
126217309Snwhitehorn	dlg_draw_title(dialog, title);
127217309Snwhitehorn
128217309Snwhitehorn	wattrset(dialog, dialog_attr);
129217309Snwhitehorn	dlg_print_autowrap(dialog, prompt, height, width);
130217309Snwhitehorn
131217309Snwhitehorn	dlg_draw_box(dialog,
132217309Snwhitehorn		     guage_y, 2 + MARGIN,
133217309Snwhitehorn		     2 + MARGIN, width - 2 * (2 + MARGIN),
134217309Snwhitehorn		     dialog_attr,
135217309Snwhitehorn		     border_attr);
136217309Snwhitehorn
137217309Snwhitehorn	/*
138217309Snwhitehorn	 * Clear the area for the progress bar by filling it with spaces
139217309Snwhitehorn	 * in the title-attribute, and write the percentage with that
140217309Snwhitehorn	 * attribute.
141217309Snwhitehorn	 */
142217309Snwhitehorn	(void) wmove(dialog, guage_y + MARGIN, 4);
143217309Snwhitehorn	wattrset(dialog, title_attr);
144217309Snwhitehorn
145217309Snwhitehorn	for (i = 0; i < (width - 2 * (3 + MARGIN)); i++)
146217309Snwhitehorn	    (void) waddch(dialog, ' ');
147217309Snwhitehorn
148217309Snwhitehorn	(void) wmove(dialog, guage_y + MARGIN, (width / 2) - 2);
149217309Snwhitehorn	(void) wprintw(dialog, "%3d", seconds);
150217309Snwhitehorn
151217309Snwhitehorn	/*
152217309Snwhitehorn	 * Now draw a bar in reverse, relative to the background.
153217309Snwhitehorn	 * The window attribute was useful for painting the background,
154217309Snwhitehorn	 * but requires some tweaks to reverse it.
155217309Snwhitehorn	 */
156217309Snwhitehorn	x = (seconds * (width - 2 * (3 + MARGIN))) / seconds_orig;
157217309Snwhitehorn	if ((title_attr & A_REVERSE) != 0) {
158217309Snwhitehorn	    wattroff(dialog, A_REVERSE);
159217309Snwhitehorn	} else {
160217309Snwhitehorn	    wattrset(dialog, A_REVERSE);
161217309Snwhitehorn	}
162217309Snwhitehorn	(void) wmove(dialog, guage_y + MARGIN, 4);
163217309Snwhitehorn	for (i = 0; i < x; i++) {
164217309Snwhitehorn	    chtype ch = winch(dialog);
165217309Snwhitehorn	    if (title_attr & A_REVERSE) {
166217309Snwhitehorn		ch &= ~A_REVERSE;
167217309Snwhitehorn	    }
168217309Snwhitehorn	    (void) waddch(dialog, ch);
169217309Snwhitehorn	}
170217309Snwhitehorn
171217309Snwhitehorn	mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n');
172217309Snwhitehorn	if (have_buttons) {
173217309Snwhitehorn	    dlg_draw_bottom_box(dialog);
174217309Snwhitehorn	    dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
175217309Snwhitehorn	}
176217309Snwhitehorn	(void) wrefresh(dialog);
177217309Snwhitehorn
178217309Snwhitehorn	for (step = 0;
179217309Snwhitehorn	     (result == DLG_EXIT_UNKNOWN) && (step < 1000);
180217309Snwhitehorn	     step += MY_TIMEOUT) {
181217309Snwhitehorn
182217309Snwhitehorn	    napms(MY_TIMEOUT);
183217309Snwhitehorn	    key = dlg_mouse_wgetch_nowait(dialog, &fkey);
184217309Snwhitehorn	    if (key == ERR) {
185217309Snwhitehorn		;		/* ignore errors in nodelay mode */
186217309Snwhitehorn	    } else {
187217309Snwhitehorn		if (dlg_result_key(key, fkey, &result))
188217309Snwhitehorn		    break;
189217309Snwhitehorn	    }
190217309Snwhitehorn
191217309Snwhitehorn	    switch (key) {
192217309Snwhitehorn#ifdef KEY_RESIZE
193217309Snwhitehorn	    case KEY_RESIZE:
194217309Snwhitehorn		dlg_clear();	/* fill the background */
195217309Snwhitehorn		dlg_del_window(dialog);		/* delete this window */
196217309Snwhitehorn		refresh();	/* get it all onto the terminal */
197217309Snwhitehorn		goto retry;
198217309Snwhitehorn#endif
199217309Snwhitehorn	    case DLGK_FIELD_NEXT:
200217309Snwhitehorn		button = dlg_next_button(buttons, button);
201217309Snwhitehorn		if (button < 0)
202217309Snwhitehorn		    button = 0;
203217309Snwhitehorn		dlg_draw_buttons(dialog,
204217309Snwhitehorn				 height - 2, 0,
205217309Snwhitehorn				 buttons, button,
206217309Snwhitehorn				 FALSE, width);
207217309Snwhitehorn		break;
208217309Snwhitehorn	    case DLGK_FIELD_PREV:
209217309Snwhitehorn		button = dlg_prev_button(buttons, button);
210217309Snwhitehorn		if (button < 0)
211217309Snwhitehorn		    button = 0;
212217309Snwhitehorn		dlg_draw_buttons(dialog,
213217309Snwhitehorn				 height - 2, 0,
214217309Snwhitehorn				 buttons, button,
215217309Snwhitehorn				 FALSE, width);
216217309Snwhitehorn		break;
217217309Snwhitehorn	    case DLGK_ENTER:
218217309Snwhitehorn		/* Do not use dlg_exit_buttoncode() since we want to return
219217309Snwhitehorn		 * a cancel rather than ok if the timeout has not expired.
220217309Snwhitehorn		 */
221217309Snwhitehorn		result = button ? DLG_EXIT_CANCEL : DLG_EXIT_OK;
222217309Snwhitehorn		break;
223217309Snwhitehorn	    case DLGK_MOUSE(0):
224217309Snwhitehorn		result = DLG_EXIT_OK;
225217309Snwhitehorn		break;
226217309Snwhitehorn	    case DLGK_MOUSE(1):
227217309Snwhitehorn		result = DLG_EXIT_CANCEL;
228217309Snwhitehorn		break;
229217309Snwhitehorn	    case ERR:
230217309Snwhitehorn		break;
231217309Snwhitehorn	    default:
232217309Snwhitehorn		result = DLG_EXIT_OK;
233217309Snwhitehorn		break;
234217309Snwhitehorn	    }
235217309Snwhitehorn	}
236217309Snwhitehorn    } while ((result == DLG_EXIT_UNKNOWN) && (seconds-- > 0));
237217309Snwhitehorn
238217309Snwhitehorn    nodelay(dialog, FALSE);
239217309Snwhitehorn    curs_set(1);
240217309Snwhitehorn    dlg_mouse_free_regions();
241217309Snwhitehorn    dlg_del_window(dialog);
242217309Snwhitehorn    free(prompt);
243217309Snwhitehorn    return ((result == DLG_EXIT_UNKNOWN) ? DLG_EXIT_OK : result);
244217309Snwhitehorn}
245