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