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