Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/dialog/pause.c
39476 views
1
/*
2
* $Id: pause.c,v 1.48 2020/11/23 00:38:19 tom Exp $
3
*
4
* pause.c -- implements the pause dialog
5
*
6
* Copyright 2004-2019,2020 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
TRAVERSE_BINDINGS,
59
END_KEYS_BINDING
60
};
61
/* *INDENT-ON* */
62
63
#ifdef KEY_RESIZE
64
int old_height = height;
65
int old_width = width;
66
#endif
67
68
int i, x, y, step;
69
int button = dlg_default_button();
70
int seconds_orig;
71
WINDOW *dialog;
72
const char **buttons = dlg_ok_labels();
73
bool have_buttons = (dlg_button_count(buttons) != 0);
74
bool first;
75
int key, fkey;
76
int result = DLG_EXIT_UNKNOWN;
77
int button_high = (have_buttons ? BTN_HIGH : MARGIN);
78
int gauge_y;
79
char *prompt;
80
int save_timeout = dialog_vars.timeout_secs;
81
82
DLG_TRACE(("# pause args:\n"));
83
DLG_TRACE2S("title", title);
84
DLG_TRACE2S("message", cprompt);
85
DLG_TRACE2N("height", height);
86
DLG_TRACE2N("width", width);
87
DLG_TRACE2N("seconds", seconds);
88
89
curs_set(0);
90
91
seconds_orig = (seconds > 0) ? seconds : 1;
92
dialog_vars.pause_secs = seconds_orig;
93
dialog_vars.timeout_secs = 0;
94
95
#ifdef KEY_RESIZE
96
retry:
97
#endif
98
99
prompt = dlg_strclone(cprompt);
100
dlg_tab_correct_str(prompt);
101
102
if (have_buttons) {
103
dlg_auto_size(title, prompt, &height, &width,
104
MIN_HIGH,
105
MIN_WIDE);
106
dlg_button_layout(buttons, &width);
107
} else {
108
dlg_auto_size(title, prompt, &height, &width,
109
MIN_HIGH + MARGIN - BTN_HIGH,
110
MIN_WIDE);
111
}
112
gauge_y = height - button_high - (1 + 2 * MARGIN);
113
dlg_print_size(height, width);
114
dlg_ctl_size(height, width);
115
116
/* center dialog box on screen */
117
x = dlg_box_x_ordinate(width);
118
y = dlg_box_y_ordinate(height);
119
120
dialog = dlg_new_window(height, width, y, x);
121
dlg_register_window(dialog, "pause", binding);
122
dlg_register_buttons(dialog, "pause", buttons);
123
124
dlg_mouse_setbase(x, y);
125
nodelay(dialog, TRUE);
126
127
first = TRUE;
128
do {
129
(void) werase(dialog);
130
dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
131
132
dlg_draw_title(dialog, title);
133
dlg_draw_helpline(dialog, FALSE);
134
135
dlg_attrset(dialog, dialog_attr);
136
dlg_print_autowrap(dialog, prompt, height, width);
137
138
dlg_draw_box2(dialog,
139
gauge_y, 2 + MARGIN,
140
2 + MARGIN, width - 2 * (2 + MARGIN),
141
dialog_attr,
142
border_attr,
143
border2_attr);
144
145
/*
146
* Clear the area for the progress bar by filling it with spaces
147
* in the title-attribute, and write the percentage with that
148
* attribute.
149
*/
150
(void) wmove(dialog, gauge_y + MARGIN, 4);
151
dlg_attrset(dialog, title_attr);
152
153
for (i = 0; i < (width - 2 * (3 + MARGIN)); i++)
154
(void) waddch(dialog, ' ');
155
156
(void) wmove(dialog, gauge_y + MARGIN, (width / 2) - 2);
157
(void) wprintw(dialog, "%3d", seconds);
158
159
/*
160
* Now draw a bar in reverse, relative to the background.
161
* The window attribute was useful for painting the background,
162
* but requires some tweaks to reverse it.
163
*/
164
x = (seconds * (width - 2 * (3 + MARGIN))) / seconds_orig;
165
if ((title_attr & A_REVERSE) != 0) {
166
dlg_attroff(dialog, A_REVERSE);
167
} else {
168
dlg_attrset(dialog, A_REVERSE);
169
}
170
(void) wmove(dialog, gauge_y + MARGIN, 4);
171
for (i = 0; i < x; i++) {
172
chtype ch = winch(dialog);
173
if (title_attr & A_REVERSE) {
174
ch &= ~A_REVERSE;
175
}
176
(void) waddch(dialog, ch);
177
}
178
179
mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n');
180
if (have_buttons) {
181
dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
182
dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
183
}
184
if (first) {
185
(void) wrefresh(dialog);
186
dlg_trace_win(dialog);
187
first = FALSE;
188
}
189
190
for (step = 0;
191
(result == DLG_EXIT_UNKNOWN) && (step < 1000);
192
step += MY_TIMEOUT) {
193
194
napms(MY_TIMEOUT);
195
key = dlg_mouse_wgetch_nowait(dialog, &fkey);
196
if (key == ERR) {
197
; /* ignore errors in nodelay mode */
198
} else if (dlg_result_key(key, fkey, &result)) {
199
if (!dlg_button_key(result, &button, &key, &fkey))
200
break;
201
}
202
203
switch (key) {
204
#ifdef KEY_RESIZE
205
case KEY_RESIZE:
206
dlg_will_resize(dialog);
207
height = old_height;
208
width = old_width;
209
free(prompt);
210
_dlg_resize_cleanup(dialog);
211
goto retry;
212
#endif
213
case DLGK_FIELD_NEXT:
214
button = dlg_next_button(buttons, button);
215
if (button < 0)
216
button = 0;
217
dlg_draw_buttons(dialog,
218
height - 2, 0,
219
buttons, button,
220
FALSE, width);
221
break;
222
case DLGK_FIELD_PREV:
223
button = dlg_prev_button(buttons, button);
224
if (button < 0)
225
button = 0;
226
dlg_draw_buttons(dialog,
227
height - 2, 0,
228
buttons, button,
229
FALSE, width);
230
break;
231
case DLGK_ENTER:
232
result = dlg_enter_buttoncode(button);
233
break;
234
case DLGK_LEAVE:
235
result = dlg_ok_buttoncode(button);
236
break;
237
case ERR:
238
break;
239
default:
240
if (is_DLGK_MOUSE(key)) {
241
result = dlg_ok_buttoncode(key - M_EVENT);
242
if (result < 0)
243
result = DLG_EXIT_OK;
244
}
245
break;
246
}
247
}
248
} while ((result == DLG_EXIT_UNKNOWN) && (seconds-- > 0));
249
dlg_add_last_key(-1);
250
251
curs_set(1);
252
dlg_mouse_free_regions();
253
dlg_del_window(dialog);
254
free(prompt);
255
256
dialog_vars.timeout_secs = save_timeout;
257
258
return ((result == DLG_EXIT_UNKNOWN) ? DLG_EXIT_OK : result);
259
}
260
261