1 /* 2 * $Id: pause.c,v 1.36 2012/07/03 00:01:59 tom Exp $ 3 * 4 * pause.c -- implements the pause dialog 5 * 6 * Copyright 2004-2011,2012 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 = 0, fkey; 76 int result = DLG_EXIT_UNKNOWN; 77 int button_high = (have_buttons ? BTN_HIGH : MARGIN); 78 int gauge_y; 79 char *prompt = dlg_strclone(cprompt); 80 int save_timeout = dialog_vars.timeout_secs; 81 82 curs_set(0); 83 84 dlg_tab_correct_str(prompt); 85 86 dialog_vars.timeout_secs = 0; 87 seconds_orig = (seconds > 0) ? seconds : 1; 88 89 #ifdef KEY_RESIZE 90 retry: 91 height = old_height; 92 width = old_width; 93 #endif 94 95 if (have_buttons) { 96 dlg_auto_size(title, prompt, &height, &width, 97 MIN_HIGH, 98 MIN_WIDE); 99 dlg_button_layout(buttons, &width); 100 } else { 101 dlg_auto_size(title, prompt, &height, &width, 102 MIN_HIGH + MARGIN - BTN_HIGH, 103 MIN_WIDE); 104 } 105 gauge_y = height - button_high - (1 + 2 * MARGIN); 106 dlg_print_size(height, width); 107 dlg_ctl_size(height, width); 108 109 /* center dialog box on screen */ 110 x = dlg_box_x_ordinate(width); 111 y = dlg_box_y_ordinate(height); 112 113 dialog = dlg_new_window(height, width, y, x); 114 dlg_register_window(dialog, "pause", binding); 115 dlg_register_buttons(dialog, "pause", buttons); 116 117 dlg_mouse_setbase(x, y); 118 nodelay(dialog, TRUE); 119 120 first = TRUE; 121 do { 122 (void) werase(dialog); 123 dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 124 125 dlg_draw_title(dialog, title); 126 dlg_draw_helpline(dialog, FALSE); 127 128 (void) wattrset(dialog, dialog_attr); 129 dlg_print_autowrap(dialog, prompt, height, width); 130 131 dlg_draw_box2(dialog, 132 gauge_y, 2 + MARGIN, 133 2 + MARGIN, width - 2 * (2 + MARGIN), 134 dialog_attr, 135 border_attr, 136 border2_attr); 137 138 /* 139 * Clear the area for the progress bar by filling it with spaces 140 * in the title-attribute, and write the percentage with that 141 * attribute. 142 */ 143 (void) wmove(dialog, gauge_y + MARGIN, 4); 144 (void) wattrset(dialog, title_attr); 145 146 for (i = 0; i < (width - 2 * (3 + MARGIN)); i++) 147 (void) waddch(dialog, ' '); 148 149 (void) wmove(dialog, gauge_y + MARGIN, (width / 2) - 2); 150 (void) wprintw(dialog, "%3d", seconds); 151 152 /* 153 * Now draw a bar in reverse, relative to the background. 154 * The window attribute was useful for painting the background, 155 * but requires some tweaks to reverse it. 156 */ 157 x = (seconds * (width - 2 * (3 + MARGIN))) / seconds_orig; 158 if ((title_attr & A_REVERSE) != 0) { 159 wattroff(dialog, A_REVERSE); 160 } else { 161 (void) wattrset(dialog, A_REVERSE); 162 } 163 (void) wmove(dialog, gauge_y + MARGIN, 4); 164 for (i = 0; i < x; i++) { 165 chtype ch = winch(dialog); 166 if (title_attr & A_REVERSE) { 167 ch &= ~A_REVERSE; 168 } 169 (void) waddch(dialog, ch); 170 } 171 172 mouse_mkbutton(height - 2, width / 2 - 4, 6, '\n'); 173 if (have_buttons) { 174 dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 175 dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); 176 } 177 if (first) { 178 (void) wrefresh(dialog); 179 dlg_trace_win(dialog); 180 first = FALSE; 181 } 182 183 for (step = 0; 184 (result == DLG_EXIT_UNKNOWN) && (step < 1000); 185 step += MY_TIMEOUT) { 186 187 napms(MY_TIMEOUT); 188 key = dlg_mouse_wgetch_nowait(dialog, &fkey); 189 if (key == ERR) { 190 ; /* ignore errors in nodelay mode */ 191 } else { 192 if (dlg_result_key(key, fkey, &result)) 193 break; 194 } 195 196 switch (key) { 197 #ifdef KEY_RESIZE 198 case KEY_RESIZE: 199 dlg_clear(); /* fill the background */ 200 dlg_del_window(dialog); /* delete this window */ 201 refresh(); /* get it all onto the terminal */ 202 goto retry; 203 #endif 204 case DLGK_FIELD_NEXT: 205 button = dlg_next_button(buttons, button); 206 if (button < 0) 207 button = 0; 208 dlg_draw_buttons(dialog, 209 height - 2, 0, 210 buttons, button, 211 FALSE, width); 212 break; 213 case DLGK_FIELD_PREV: 214 button = dlg_prev_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_ENTER: 223 result = dlg_enter_buttoncode(button); 224 break; 225 case ERR: 226 break; 227 default: 228 if (is_DLGK_MOUSE(key)) { 229 result = dlg_ok_buttoncode(key - M_EVENT); 230 if (result < 0) 231 result = DLG_EXIT_OK; 232 } 233 break; 234 } 235 } 236 } while ((result == DLG_EXIT_UNKNOWN) && (seconds-- > 0)); 237 238 curs_set(1); 239 dlg_mouse_free_regions(); 240 dlg_del_window(dialog); 241 free(prompt); 242 243 dialog_vars.timeout_secs = save_timeout; 244 245 return ((result == DLG_EXIT_UNKNOWN) ? DLG_EXIT_OK : result); 246 } 247