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 } 243