xref: /freebsd/contrib/dialog/pause.c (revision 4c8945a06b01a5c8122cdeb402af36bb46a06acc)
1*4c8945a0SNathan Whitehorn /*
2*4c8945a0SNathan Whitehorn  *  $Id: pause.c,v 1.22 2010/04/28 00:29:50 tom Exp $
3*4c8945a0SNathan Whitehorn  *
4*4c8945a0SNathan Whitehorn  *  pause.c -- implements the pause dialog
5*4c8945a0SNathan Whitehorn  *
6*4c8945a0SNathan Whitehorn  *  Copyright 2004-2009,2010	Thomas E. Dickey
7*4c8945a0SNathan Whitehorn  *
8*4c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
9*4c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
10*4c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
11*4c8945a0SNathan Whitehorn  *
12*4c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
13*4c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
14*4c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*4c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
16*4c8945a0SNathan Whitehorn  *
17*4c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
18*4c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
19*4c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
20*4c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
21*4c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
22*4c8945a0SNathan Whitehorn  *
23*4c8945a0SNathan Whitehorn  *  This is adapted from source contributed by
24*4c8945a0SNathan Whitehorn  *	Yura Kalinichenko
25*4c8945a0SNathan Whitehorn  */
26*4c8945a0SNathan Whitehorn 
27*4c8945a0SNathan Whitehorn #include <dialog.h>
28*4c8945a0SNathan Whitehorn #include <dlg_keys.h>
29*4c8945a0SNathan Whitehorn 
30*4c8945a0SNathan Whitehorn #define MY_TIMEOUT 50
31*4c8945a0SNathan Whitehorn 
32*4c8945a0SNathan Whitehorn #define MIN_HIGH (4)
33*4c8945a0SNathan Whitehorn #define MIN_WIDE (10 + 2 * (2 + MARGIN))
34*4c8945a0SNathan Whitehorn #define BTN_HIGH (1 + 2 * MARGIN)
35*4c8945a0SNathan Whitehorn 
36*4c8945a0SNathan Whitehorn /*
37*4c8945a0SNathan Whitehorn  * This is like gauge, but can be interrupted.
38*4c8945a0SNathan Whitehorn  *
39*4c8945a0SNathan Whitehorn  * A pause box displays a meter along the bottom of the box.  The meter
40*4c8945a0SNathan Whitehorn  * indicates how many seconds remain until the end of the pause.  The pause
41*4c8945a0SNathan Whitehorn  * exits when timeout is reached (status OK) or the user presses:
42*4c8945a0SNathan Whitehorn  *   OK button (status OK)
43*4c8945a0SNathan Whitehorn  *   CANCEL button (status CANCEL)
44*4c8945a0SNathan Whitehorn  *   Esc key (status ESC)
45*4c8945a0SNathan Whitehorn  *
46*4c8945a0SNathan Whitehorn  */
47*4c8945a0SNathan Whitehorn int
48*4c8945a0SNathan Whitehorn dialog_pause(const char *title,
49*4c8945a0SNathan Whitehorn 	     const char *cprompt,
50*4c8945a0SNathan Whitehorn 	     int height,
51*4c8945a0SNathan Whitehorn 	     int width,
52*4c8945a0SNathan Whitehorn 	     int seconds)
53*4c8945a0SNathan Whitehorn {
54*4c8945a0SNathan Whitehorn     /* *INDENT-OFF* */
55*4c8945a0SNathan Whitehorn     static DLG_KEYS_BINDING binding[] = {
56*4c8945a0SNathan Whitehorn 	ENTERKEY_BINDINGS,
57*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_ENTER,	' ' ),
58*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	KEY_DOWN ),
59*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
60*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
61*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_UP ),
62*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
63*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
64*4c8945a0SNathan Whitehorn 	END_KEYS_BINDING
65*4c8945a0SNathan Whitehorn     };
66*4c8945a0SNathan Whitehorn     /* *INDENT-ON* */
67*4c8945a0SNathan Whitehorn 
68*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
69*4c8945a0SNathan Whitehorn     int old_height = height;
70*4c8945a0SNathan Whitehorn     int old_width = width;
71*4c8945a0SNathan Whitehorn #endif
72*4c8945a0SNathan Whitehorn 
73*4c8945a0SNathan Whitehorn     int i, x, y, step;
74*4c8945a0SNathan Whitehorn     int button = 0;
75*4c8945a0SNathan Whitehorn     int seconds_orig;
76*4c8945a0SNathan Whitehorn     WINDOW *dialog;
77*4c8945a0SNathan Whitehorn     const char **buttons = dlg_ok_labels();
78*4c8945a0SNathan Whitehorn     bool have_buttons = (dlg_button_count(buttons) != 0);
79*4c8945a0SNathan Whitehorn     int key = 0, fkey;
80*4c8945a0SNathan Whitehorn     int result = DLG_EXIT_UNKNOWN;
81*4c8945a0SNathan Whitehorn     int button_high = (have_buttons ? BTN_HIGH : MARGIN);
82*4c8945a0SNathan Whitehorn     int guage_y;
83*4c8945a0SNathan Whitehorn     char *prompt = dlg_strclone(cprompt);
84*4c8945a0SNathan Whitehorn 
85*4c8945a0SNathan Whitehorn     curs_set(0);
86*4c8945a0SNathan Whitehorn 
87*4c8945a0SNathan Whitehorn     dlg_tab_correct_str(prompt);
88*4c8945a0SNathan Whitehorn 
89*4c8945a0SNathan Whitehorn     seconds_orig = (seconds > 0) ? seconds : 1;
90*4c8945a0SNathan Whitehorn 
91*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
92*4c8945a0SNathan Whitehorn   retry:
93*4c8945a0SNathan Whitehorn     height = old_height;
94*4c8945a0SNathan Whitehorn     width = old_width;
95*4c8945a0SNathan Whitehorn #endif
96*4c8945a0SNathan Whitehorn 
97*4c8945a0SNathan Whitehorn     if (have_buttons) {
98*4c8945a0SNathan Whitehorn 	dlg_auto_size(title, prompt, &height, &width,
99*4c8945a0SNathan Whitehorn 		      MIN_HIGH,
100*4c8945a0SNathan Whitehorn 		      MIN_WIDE);
101*4c8945a0SNathan Whitehorn 	dlg_button_layout(buttons, &width);
102*4c8945a0SNathan Whitehorn     } else {
103*4c8945a0SNathan Whitehorn 	dlg_auto_size(title, prompt, &height, &width,
104*4c8945a0SNathan Whitehorn 		      MIN_HIGH + MARGIN - BTN_HIGH,
105*4c8945a0SNathan Whitehorn 		      MIN_WIDE);
106*4c8945a0SNathan Whitehorn     }
107*4c8945a0SNathan Whitehorn     guage_y = height - button_high - (1 + 2 * MARGIN);
108*4c8945a0SNathan Whitehorn     dlg_print_size(height, width);
109*4c8945a0SNathan Whitehorn     dlg_ctl_size(height, width);
110*4c8945a0SNathan Whitehorn 
111*4c8945a0SNathan Whitehorn     /* center dialog box on screen */
112*4c8945a0SNathan Whitehorn     x = dlg_box_x_ordinate(width);
113*4c8945a0SNathan Whitehorn     y = dlg_box_y_ordinate(height);
114*4c8945a0SNathan Whitehorn 
115*4c8945a0SNathan Whitehorn     dialog = dlg_new_window(height, width, y, x);
116*4c8945a0SNathan Whitehorn     dlg_register_window(dialog, "pause", binding);
117*4c8945a0SNathan Whitehorn     dlg_register_buttons(dialog, "pause", buttons);
118*4c8945a0SNathan Whitehorn 
119*4c8945a0SNathan Whitehorn     dlg_mouse_setbase(x, y);
120*4c8945a0SNathan Whitehorn     nodelay(dialog, TRUE);
121*4c8945a0SNathan Whitehorn 
122*4c8945a0SNathan Whitehorn     do {
123*4c8945a0SNathan Whitehorn 	(void) werase(dialog);
124*4c8945a0SNathan Whitehorn 	dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
125*4c8945a0SNathan Whitehorn 
126*4c8945a0SNathan Whitehorn 	dlg_draw_title(dialog, title);
127*4c8945a0SNathan Whitehorn 
128*4c8945a0SNathan Whitehorn 	wattrset(dialog, dialog_attr);
129*4c8945a0SNathan Whitehorn 	dlg_print_autowrap(dialog, prompt, height, width);
130*4c8945a0SNathan Whitehorn 
131*4c8945a0SNathan Whitehorn 	dlg_draw_box(dialog,
132*4c8945a0SNathan Whitehorn 		     guage_y, 2 + MARGIN,
133*4c8945a0SNathan Whitehorn 		     2 + MARGIN, width - 2 * (2 + MARGIN),
134*4c8945a0SNathan Whitehorn 		     dialog_attr,
135*4c8945a0SNathan Whitehorn 		     border_attr);
136*4c8945a0SNathan Whitehorn 
137*4c8945a0SNathan Whitehorn 	/*
138*4c8945a0SNathan Whitehorn 	 * Clear the area for the progress bar by filling it with spaces
139*4c8945a0SNathan Whitehorn 	 * in the title-attribute, and write the percentage with that
140*4c8945a0SNathan Whitehorn 	 * attribute.
141*4c8945a0SNathan Whitehorn 	 */
142*4c8945a0SNathan Whitehorn 	(void) wmove(dialog, guage_y + MARGIN, 4);
143*4c8945a0SNathan Whitehorn 	wattrset(dialog, title_attr);
144*4c8945a0SNathan Whitehorn 
145*4c8945a0SNathan Whitehorn 	for (i = 0; i < (width - 2 * (3 + MARGIN)); i++)
146*4c8945a0SNathan Whitehorn 	    (void) waddch(dialog, ' ');
147*4c8945a0SNathan Whitehorn 
148*4c8945a0SNathan Whitehorn 	(void) wmove(dialog, guage_y + MARGIN, (width / 2) - 2);
149*4c8945a0SNathan Whitehorn 	(void) wprintw(dialog, "%3d", seconds);
150*4c8945a0SNathan Whitehorn 
151*4c8945a0SNathan Whitehorn 	/*
152*4c8945a0SNathan Whitehorn 	 * Now draw a bar in reverse, relative to the background.
153*4c8945a0SNathan Whitehorn 	 * The window attribute was useful for painting the background,
154*4c8945a0SNathan Whitehorn 	 * but requires some tweaks to reverse it.
155*4c8945a0SNathan Whitehorn 	 */
156*4c8945a0SNathan Whitehorn 	x = (seconds * (width - 2 * (3 + MARGIN))) / seconds_orig;
157*4c8945a0SNathan Whitehorn 	if ((title_attr & A_REVERSE) != 0) {
158*4c8945a0SNathan Whitehorn 	    wattroff(dialog, A_REVERSE);
159*4c8945a0SNathan Whitehorn 	} else {
160*4c8945a0SNathan Whitehorn 	    wattrset(dialog, A_REVERSE);
161*4c8945a0SNathan Whitehorn 	}
162*4c8945a0SNathan Whitehorn 	(void) wmove(dialog, guage_y + MARGIN, 4);
163*4c8945a0SNathan Whitehorn 	for (i = 0; i < x; i++) {
164*4c8945a0SNathan Whitehorn 	    chtype ch = winch(dialog);
165*4c8945a0SNathan Whitehorn 	    if (title_attr & A_REVERSE) {
166*4c8945a0SNathan Whitehorn 		ch &= ~A_REVERSE;
167*4c8945a0SNathan Whitehorn 	    }
168*4c8945a0SNathan Whitehorn 	    (void) waddch(dialog, ch);
169*4c8945a0SNathan Whitehorn 	}
170*4c8945a0SNathan Whitehorn 
171*4c8945a0SNathan Whitehorn 	mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n');
172*4c8945a0SNathan Whitehorn 	if (have_buttons) {
173*4c8945a0SNathan Whitehorn 	    dlg_draw_bottom_box(dialog);
174*4c8945a0SNathan Whitehorn 	    dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
175*4c8945a0SNathan Whitehorn 	}
176*4c8945a0SNathan Whitehorn 	(void) wrefresh(dialog);
177*4c8945a0SNathan Whitehorn 
178*4c8945a0SNathan Whitehorn 	for (step = 0;
179*4c8945a0SNathan Whitehorn 	     (result == DLG_EXIT_UNKNOWN) && (step < 1000);
180*4c8945a0SNathan Whitehorn 	     step += MY_TIMEOUT) {
181*4c8945a0SNathan Whitehorn 
182*4c8945a0SNathan Whitehorn 	    napms(MY_TIMEOUT);
183*4c8945a0SNathan Whitehorn 	    key = dlg_mouse_wgetch_nowait(dialog, &fkey);
184*4c8945a0SNathan Whitehorn 	    if (key == ERR) {
185*4c8945a0SNathan Whitehorn 		;		/* ignore errors in nodelay mode */
186*4c8945a0SNathan Whitehorn 	    } else {
187*4c8945a0SNathan Whitehorn 		if (dlg_result_key(key, fkey, &result))
188*4c8945a0SNathan Whitehorn 		    break;
189*4c8945a0SNathan Whitehorn 	    }
190*4c8945a0SNathan Whitehorn 
191*4c8945a0SNathan Whitehorn 	    switch (key) {
192*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
193*4c8945a0SNathan Whitehorn 	    case KEY_RESIZE:
194*4c8945a0SNathan Whitehorn 		dlg_clear();	/* fill the background */
195*4c8945a0SNathan Whitehorn 		dlg_del_window(dialog);		/* delete this window */
196*4c8945a0SNathan Whitehorn 		refresh();	/* get it all onto the terminal */
197*4c8945a0SNathan Whitehorn 		goto retry;
198*4c8945a0SNathan Whitehorn #endif
199*4c8945a0SNathan Whitehorn 	    case DLGK_FIELD_NEXT:
200*4c8945a0SNathan Whitehorn 		button = dlg_next_button(buttons, button);
201*4c8945a0SNathan Whitehorn 		if (button < 0)
202*4c8945a0SNathan Whitehorn 		    button = 0;
203*4c8945a0SNathan Whitehorn 		dlg_draw_buttons(dialog,
204*4c8945a0SNathan Whitehorn 				 height - 2, 0,
205*4c8945a0SNathan Whitehorn 				 buttons, button,
206*4c8945a0SNathan Whitehorn 				 FALSE, width);
207*4c8945a0SNathan Whitehorn 		break;
208*4c8945a0SNathan Whitehorn 	    case DLGK_FIELD_PREV:
209*4c8945a0SNathan Whitehorn 		button = dlg_prev_button(buttons, button);
210*4c8945a0SNathan Whitehorn 		if (button < 0)
211*4c8945a0SNathan Whitehorn 		    button = 0;
212*4c8945a0SNathan Whitehorn 		dlg_draw_buttons(dialog,
213*4c8945a0SNathan Whitehorn 				 height - 2, 0,
214*4c8945a0SNathan Whitehorn 				 buttons, button,
215*4c8945a0SNathan Whitehorn 				 FALSE, width);
216*4c8945a0SNathan Whitehorn 		break;
217*4c8945a0SNathan Whitehorn 	    case DLGK_ENTER:
218*4c8945a0SNathan Whitehorn 		/* Do not use dlg_exit_buttoncode() since we want to return
219*4c8945a0SNathan Whitehorn 		 * a cancel rather than ok if the timeout has not expired.
220*4c8945a0SNathan Whitehorn 		 */
221*4c8945a0SNathan Whitehorn 		result = button ? DLG_EXIT_CANCEL : DLG_EXIT_OK;
222*4c8945a0SNathan Whitehorn 		break;
223*4c8945a0SNathan Whitehorn 	    case DLGK_MOUSE(0):
224*4c8945a0SNathan Whitehorn 		result = DLG_EXIT_OK;
225*4c8945a0SNathan Whitehorn 		break;
226*4c8945a0SNathan Whitehorn 	    case DLGK_MOUSE(1):
227*4c8945a0SNathan Whitehorn 		result = DLG_EXIT_CANCEL;
228*4c8945a0SNathan Whitehorn 		break;
229*4c8945a0SNathan Whitehorn 	    case ERR:
230*4c8945a0SNathan Whitehorn 		break;
231*4c8945a0SNathan Whitehorn 	    default:
232*4c8945a0SNathan Whitehorn 		result = DLG_EXIT_OK;
233*4c8945a0SNathan Whitehorn 		break;
234*4c8945a0SNathan Whitehorn 	    }
235*4c8945a0SNathan Whitehorn 	}
236*4c8945a0SNathan Whitehorn     } while ((result == DLG_EXIT_UNKNOWN) && (seconds-- > 0));
237*4c8945a0SNathan Whitehorn 
238*4c8945a0SNathan Whitehorn     nodelay(dialog, FALSE);
239*4c8945a0SNathan Whitehorn     curs_set(1);
240*4c8945a0SNathan Whitehorn     dlg_mouse_free_regions();
241*4c8945a0SNathan Whitehorn     dlg_del_window(dialog);
242*4c8945a0SNathan Whitehorn     free(prompt);
243*4c8945a0SNathan Whitehorn     return ((result == DLG_EXIT_UNKNOWN) ? DLG_EXIT_OK : result);
244*4c8945a0SNathan Whitehorn }
245