1217309Snwhitehorn/* 2224014Snwhitehorn * $Id: mixedgauge.c,v 1.24 2011/06/27 08:16:38 tom Exp $ 3217309Snwhitehorn * 4217309Snwhitehorn * mixedgauge.c -- implements the mixedgauge dialog 5217309Snwhitehorn * 6220749Snwhitehorn * Copyright 2007-2010,2011 Thomas E. Dickey 7217309Snwhitehorn * 8217309Snwhitehorn * This program is free software; you can redistribute it and/or modify 9217309Snwhitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 10217309Snwhitehorn * as published by the Free Software Foundation. 11217309Snwhitehorn * 12217309Snwhitehorn * This program is distributed in the hope that it will be useful, but 13217309Snwhitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 14217309Snwhitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15217309Snwhitehorn * Lesser General Public License for more details. 16217309Snwhitehorn * 17217309Snwhitehorn * You should have received a copy of the GNU Lesser General Public 18217309Snwhitehorn * License along with this program; if not, write to 19217309Snwhitehorn * Free Software Foundation, Inc. 20217309Snwhitehorn * 51 Franklin St., Fifth Floor 21217309Snwhitehorn * Boston, MA 02110, USA. 22217309Snwhitehorn * 23217309Snwhitehorn * This is inspired by a patch from Kiran Cherupally 24217309Snwhitehorn * (but different interface design). 25217309Snwhitehorn */ 26217309Snwhitehorn 27217309Snwhitehorn#include <dialog.h> 28217309Snwhitehorn 29217309Snwhitehorn#define LLEN(n) ((n) * MIXEDGAUGE_TAGS) 30217309Snwhitehorn#define ItemData(i) &items[LLEN(i)] 31217309Snwhitehorn#define ItemName(i) items[LLEN(i)] 32217309Snwhitehorn#define ItemText(i) items[LLEN(i) + 1] 33217309Snwhitehorn 34217309Snwhitehorn#define MIN_HIGH (4) 35217309Snwhitehorn#define MIN_WIDE (10 + 2 * (2 + MARGIN)) 36217309Snwhitehorn 37217309Snwhitehorntypedef struct { 38217309Snwhitehorn WINDOW *dialog; 39217309Snwhitehorn WINDOW *caption; 40217309Snwhitehorn const char *title; 41217309Snwhitehorn char *prompt; 42217309Snwhitehorn int height, old_height, min_height; 43217309Snwhitehorn int width, old_width, min_width; 44217309Snwhitehorn int len_name, len_text; 45217309Snwhitehorn int item_no; 46217309Snwhitehorn DIALOG_LISTITEM *list; 47217309Snwhitehorn} DIALOG_MIXEDGAUGE; 48217309Snwhitehorn 49217309Snwhitehornstatic const char * 50217309Snwhitehornstatus_string(char *given, char **freeMe) 51217309Snwhitehorn{ 52217309Snwhitehorn const char *result; 53217309Snwhitehorn 54217309Snwhitehorn *freeMe = 0; 55217309Snwhitehorn if (isdigit(UCH(*given))) { 56217309Snwhitehorn switch (*given) { 57217309Snwhitehorn case '0': 58217309Snwhitehorn result = _("Succeeded"); 59217309Snwhitehorn break; 60217309Snwhitehorn case '1': 61217309Snwhitehorn result = _("Failed"); 62217309Snwhitehorn break; 63217309Snwhitehorn case '2': 64217309Snwhitehorn result = _("Passed"); 65217309Snwhitehorn break; 66217309Snwhitehorn case '3': 67217309Snwhitehorn result = _("Completed"); 68217309Snwhitehorn break; 69217309Snwhitehorn case '4': 70217309Snwhitehorn result = _("Checked"); 71217309Snwhitehorn break; 72217309Snwhitehorn case '5': 73217309Snwhitehorn result = _("Done"); 74217309Snwhitehorn break; 75217309Snwhitehorn case '6': 76217309Snwhitehorn result = _("Skipped"); 77217309Snwhitehorn break; 78217309Snwhitehorn case '7': 79217309Snwhitehorn result = _("In Progress"); 80217309Snwhitehorn break; 81217309Snwhitehorn case '8': 82217309Snwhitehorn result = ""; 83217309Snwhitehorn break; 84217309Snwhitehorn case '9': 85217309Snwhitehorn result = _("N/A"); 86217309Snwhitehorn break; 87217309Snwhitehorn default: 88217309Snwhitehorn result = "?"; 89217309Snwhitehorn break; 90217309Snwhitehorn } 91217309Snwhitehorn } else if (*given == '-') { 92220749Snwhitehorn size_t need = strlen(++given); 93217309Snwhitehorn char *temp = dlg_malloc(char, need); 94217309Snwhitehorn *freeMe = temp; 95217309Snwhitehorn sprintf(temp, "%3s%%", given); 96217309Snwhitehorn result = temp; 97217309Snwhitehorn } else if (!isspace(UCH(*given))) { 98217309Snwhitehorn result = given; 99217309Snwhitehorn } else { 100217309Snwhitehorn result = 0; 101217309Snwhitehorn } 102217309Snwhitehorn return result; 103217309Snwhitehorn} 104217309Snwhitehorn 105217309Snwhitehorn/* This function displays status messages */ 106217309Snwhitehornstatic void 107217309Snwhitehornmyprint_status(DIALOG_MIXEDGAUGE * dlg) 108217309Snwhitehorn{ 109217309Snwhitehorn WINDOW *win = dlg->dialog; 110217309Snwhitehorn int limit_y = dlg->height; 111217309Snwhitehorn int limit_x = dlg->width; 112217309Snwhitehorn 113217309Snwhitehorn int y = MARGIN; 114217309Snwhitehorn int item; 115217309Snwhitehorn int cells = dlg->len_text - 2; 116217309Snwhitehorn int rm = limit_x; /* right margin */ 117217309Snwhitehorn int lm = limit_x - dlg->len_text - 1; 118217309Snwhitehorn int bm = limit_y; /* bottom margin */ 119217309Snwhitehorn int last_y = 0, last_x = 0; 120217309Snwhitehorn int j, xxx; 121217309Snwhitehorn float percent; 122217309Snwhitehorn const char *status = ""; 123217309Snwhitehorn char *freeMe = 0; 124217309Snwhitehorn 125217309Snwhitehorn if (win) { 126217309Snwhitehorn rm -= (2 * MARGIN); 127217309Snwhitehorn bm -= (2 * MARGIN); 128217309Snwhitehorn } 129217309Snwhitehorn if (win != 0) 130217309Snwhitehorn getyx(win, last_y, last_x); 131217309Snwhitehorn for (item = 0; item < dlg->item_no; ++item) { 132217309Snwhitehorn chtype attr = A_NORMAL; 133217309Snwhitehorn 134217309Snwhitehorn y = item + MARGIN + 1; 135217309Snwhitehorn if (y > bm) 136217309Snwhitehorn break; 137217309Snwhitehorn 138217309Snwhitehorn status = status_string(dlg->list[item].text, &freeMe); 139217309Snwhitehorn if (status == 0 || *status == 0) 140217309Snwhitehorn continue; 141217309Snwhitehorn 142217309Snwhitehorn (void) wmove(win, y, 2 * MARGIN); 143217309Snwhitehorn dlg_print_text(win, dlg->list[item].name, lm, &attr); 144217309Snwhitehorn 145217309Snwhitehorn (void) wmove(win, y, lm); 146217309Snwhitehorn (void) waddch(win, '['); 147217309Snwhitehorn (void) wmove(win, y, lm + (cells - (int) strlen(status)) / 2); 148217309Snwhitehorn if (freeMe) { 149217309Snwhitehorn (void) wmove(win, y, lm + 1); 150217309Snwhitehorn wattrset(win, title_attr); 151217309Snwhitehorn for (j = 0; j < cells; j++) 152217309Snwhitehorn (void) waddch(win, ' '); 153217309Snwhitehorn 154217309Snwhitehorn (void) wmove(win, y, lm + (cells - (int) strlen(status)) / 2); 155217309Snwhitehorn (void) waddstr(win, status); 156217309Snwhitehorn 157217309Snwhitehorn if ((title_attr & A_REVERSE) != 0) { 158217309Snwhitehorn wattroff(win, A_REVERSE); 159217309Snwhitehorn } else { 160217309Snwhitehorn wattrset(win, A_REVERSE); 161217309Snwhitehorn } 162217309Snwhitehorn (void) wmove(win, y, lm + 1); 163217309Snwhitehorn 164217309Snwhitehorn if (sscanf(status, "%f%%", &percent) != 1) 165217309Snwhitehorn percent = 0.0; 166217309Snwhitehorn xxx = (int) ((cells * (percent + 0.5)) / 100.0); 167217309Snwhitehorn for (j = 0; j < xxx; j++) { 168217309Snwhitehorn chtype ch1 = winch(win); 169217309Snwhitehorn if (title_attr & A_REVERSE) { 170217309Snwhitehorn ch1 &= ~A_REVERSE; 171217309Snwhitehorn } 172217309Snwhitehorn (void) waddch(win, ch1); 173217309Snwhitehorn } 174217309Snwhitehorn free(freeMe); 175217309Snwhitehorn 176217309Snwhitehorn } else { 177217309Snwhitehorn (void) wmove(win, y, lm + (cells - (int) strlen(status)) / 2); 178217309Snwhitehorn (void) waddstr(win, status); 179217309Snwhitehorn } 180217309Snwhitehorn (void) wmove(win, y, limit_x - 3); 181217309Snwhitehorn (void) waddch(win, ']'); 182217309Snwhitehorn (void) wnoutrefresh(win); 183217309Snwhitehorn } 184217309Snwhitehorn} 185217309Snwhitehorn 186217309Snwhitehornstatic void 187217309Snwhitehornmydraw_mixed_box(WINDOW *win, int y, int x, int height, int width, 188217309Snwhitehorn chtype boxchar, chtype borderchar) 189217309Snwhitehorn{ 190217309Snwhitehorn dlg_draw_box(win, y, x, height, width, boxchar, borderchar); 191217309Snwhitehorn { 192217309Snwhitehorn chtype attr = A_NORMAL; 193220749Snwhitehorn const char *message = _("Overall Progress"); 194220749Snwhitehorn chtype save2 = dlg_get_attrs(win); 195217309Snwhitehorn wattrset(win, title_attr); 196217309Snwhitehorn (void) wmove(win, y, x + 2); 197217309Snwhitehorn dlg_print_text(win, message, width, &attr); 198217309Snwhitehorn wattrset(win, save2); 199217309Snwhitehorn } 200217309Snwhitehorn} 201217309Snwhitehorn 202217309Snwhitehornstatic char * 203217309Snwhitehornclean_copy(const char *string) 204217309Snwhitehorn{ 205217309Snwhitehorn char *result = dlg_strclone(string); 206217309Snwhitehorn 207217309Snwhitehorn dlg_trim_string(result); 208217309Snwhitehorn dlg_tab_correct_str(result); 209217309Snwhitehorn return result; 210217309Snwhitehorn} 211217309Snwhitehorn 212217309Snwhitehorn/* 213217309Snwhitehorn * Update mixed-gauge dialog (may be from pipe, may be via direct calls). 214217309Snwhitehorn */ 215217309Snwhitehornstatic void 216217309Snwhitehorndlg_update_mixedgauge(DIALOG_MIXEDGAUGE * dlg, int percent) 217217309Snwhitehorn{ 218217309Snwhitehorn int i, x; 219217309Snwhitehorn 220217309Snwhitehorn /* 221217309Snwhitehorn * Clear the area for the progress bar by filling it with spaces 222217309Snwhitehorn * in the title-attribute, and write the percentage with that 223217309Snwhitehorn * attribute. 224217309Snwhitehorn */ 225217309Snwhitehorn (void) wmove(dlg->dialog, dlg->height - 3, 4); 226220749Snwhitehorn wattrset(dlg->dialog, gauge_attr); 227217309Snwhitehorn 228217309Snwhitehorn for (i = 0; i < (dlg->width - 2 * (3 + MARGIN)); i++) 229217309Snwhitehorn (void) waddch(dlg->dialog, ' '); 230217309Snwhitehorn 231217309Snwhitehorn (void) wmove(dlg->dialog, dlg->height - 3, (dlg->width / 2) - 2); 232217309Snwhitehorn (void) wprintw(dlg->dialog, "%3d%%", percent); 233217309Snwhitehorn 234217309Snwhitehorn /* 235217309Snwhitehorn * Now draw a bar in reverse, relative to the background. 236217309Snwhitehorn * The window attribute was useful for painting the background, 237217309Snwhitehorn * but requires some tweaks to reverse it. 238217309Snwhitehorn */ 239217309Snwhitehorn x = (percent * (dlg->width - 2 * (3 + MARGIN))) / 100; 240217309Snwhitehorn if ((title_attr & A_REVERSE) != 0) { 241217309Snwhitehorn wattroff(dlg->dialog, A_REVERSE); 242217309Snwhitehorn } else { 243217309Snwhitehorn wattrset(dlg->dialog, A_REVERSE); 244217309Snwhitehorn } 245217309Snwhitehorn (void) wmove(dlg->dialog, dlg->height - 3, 4); 246217309Snwhitehorn for (i = 0; i < x; i++) { 247217309Snwhitehorn chtype ch = winch(dlg->dialog); 248217309Snwhitehorn if (title_attr & A_REVERSE) { 249217309Snwhitehorn ch &= ~A_REVERSE; 250217309Snwhitehorn } 251217309Snwhitehorn (void) waddch(dlg->dialog, ch); 252217309Snwhitehorn } 253217309Snwhitehorn myprint_status(dlg); 254217309Snwhitehorn} 255217309Snwhitehorn 256217309Snwhitehorn/* 257217309Snwhitehorn * Setup dialog. 258217309Snwhitehorn */ 259217309Snwhitehornstatic void 260217309Snwhitehorndlg_begin_mixedgauge(DIALOG_MIXEDGAUGE * dlg, 261217309Snwhitehorn int *began, 262217309Snwhitehorn const char *aTitle, 263217309Snwhitehorn const char *aPrompt, 264217309Snwhitehorn int aHeight, 265217309Snwhitehorn int aWidth, 266217309Snwhitehorn int aItemNo, 267217309Snwhitehorn char **items) 268217309Snwhitehorn{ 269217309Snwhitehorn int n, y, x; 270217309Snwhitehorn 271217309Snwhitehorn if (!*began) { 272217309Snwhitehorn curs_set(0); 273217309Snwhitehorn 274217309Snwhitehorn memset(dlg, 0, sizeof(*dlg)); 275217309Snwhitehorn dlg->title = aTitle; 276217309Snwhitehorn dlg->prompt = clean_copy(aPrompt); 277217309Snwhitehorn dlg->height = dlg->old_height = aHeight; 278217309Snwhitehorn dlg->width = dlg->old_width = aWidth; 279217309Snwhitehorn dlg->item_no = aItemNo; 280217309Snwhitehorn 281217309Snwhitehorn dlg->list = dlg_calloc(DIALOG_LISTITEM, (size_t) aItemNo); 282217309Snwhitehorn assert_ptr(dlg->list, "dialog_mixedgauge"); 283217309Snwhitehorn 284217309Snwhitehorn dlg->len_name = 0; 285217309Snwhitehorn dlg->len_text = 15; 286217309Snwhitehorn 287217309Snwhitehorn for (n = 0; n < aItemNo; ++n) { 288217309Snwhitehorn int thisWidth = (int) strlen(ItemName(n)); 289217309Snwhitehorn if (dlg->len_name < thisWidth) 290217309Snwhitehorn dlg->len_name = thisWidth; 291217309Snwhitehorn dlg->list[n].name = ItemName(n); 292217309Snwhitehorn dlg->list[n].text = ItemText(n); 293217309Snwhitehorn } 294217309Snwhitehorn 295217309Snwhitehorn dlg->min_height = MIN_HIGH + aItemNo; 296217309Snwhitehorn dlg->min_width = MIN_WIDE + dlg->len_name + GUTTER + dlg->len_text; 297217309Snwhitehorn 298217309Snwhitehorn if (dlg->prompt != 0 && *(dlg->prompt) != 0) 299217309Snwhitehorn dlg->min_height += (2 * MARGIN); 300217309Snwhitehorn#ifdef KEY_RESIZE 301217309Snwhitehorn nodelay(stdscr, TRUE); 302217309Snwhitehorn#endif 303217309Snwhitehorn } 304217309Snwhitehorn#ifdef KEY_RESIZE 305217309Snwhitehorn else { 306217309Snwhitehorn dlg_del_window(dlg->dialog); 307217309Snwhitehorn dlg->height = dlg->old_height; 308217309Snwhitehorn dlg->width = dlg->old_width; 309217309Snwhitehorn } 310217309Snwhitehorn#endif 311217309Snwhitehorn 312217309Snwhitehorn dlg_auto_size(dlg->title, dlg->prompt, 313217309Snwhitehorn &(dlg->height), 314217309Snwhitehorn &(dlg->width), 315217309Snwhitehorn dlg->min_height, 316217309Snwhitehorn dlg->min_width); 317217309Snwhitehorn dlg_print_size(dlg->height, dlg->width); 318217309Snwhitehorn dlg_ctl_size(dlg->height, dlg->width); 319217309Snwhitehorn 320217309Snwhitehorn /* center dialog box on screen */ 321217309Snwhitehorn x = dlg_box_x_ordinate(dlg->width); 322217309Snwhitehorn y = dlg_box_y_ordinate(dlg->height); 323217309Snwhitehorn 324217309Snwhitehorn dlg->dialog = dlg_new_window(dlg->height, dlg->width, y, x); 325217309Snwhitehorn 326217309Snwhitehorn (void) werase(dlg->dialog); 327217309Snwhitehorn dlg_draw_box(dlg->dialog, 328217309Snwhitehorn 0, 0, 329217309Snwhitehorn dlg->height, 330217309Snwhitehorn dlg->width, 331217309Snwhitehorn dialog_attr, border_attr); 332217309Snwhitehorn 333217309Snwhitehorn dlg_draw_title(dlg->dialog, dlg->title); 334224014Snwhitehorn dlg_draw_helpline(dlg->dialog, FALSE); 335217309Snwhitehorn 336217309Snwhitehorn if ((dlg->prompt != 0 && *(dlg->prompt) != 0) 337217309Snwhitehorn && wmove(dlg->dialog, dlg->item_no, 0) != ERR) { 338217309Snwhitehorn dlg->caption = dlg_sub_window(dlg->dialog, 339217309Snwhitehorn dlg->height - dlg->item_no - (2 * MARGIN), 340217309Snwhitehorn dlg->width, 341217309Snwhitehorn y + dlg->item_no + (2 * MARGIN), 342217309Snwhitehorn x); 343217309Snwhitehorn wattrset(dlg->caption, dialog_attr); 344217309Snwhitehorn dlg_print_autowrap(dlg->caption, dlg->prompt, dlg->height, dlg->width); 345217309Snwhitehorn } 346217309Snwhitehorn 347217309Snwhitehorn mydraw_mixed_box(dlg->dialog, 348217309Snwhitehorn dlg->height - 4, 349217309Snwhitehorn 2 + MARGIN, 350217309Snwhitehorn 2 + MARGIN, 351217309Snwhitehorn dlg->width - 2 * (2 + MARGIN), 352217309Snwhitehorn dialog_attr, 353217309Snwhitehorn border_attr); 354217309Snwhitehorn 355217309Snwhitehorn *began += 1; 356217309Snwhitehorn} 357217309Snwhitehorn 358217309Snwhitehorn/* 359217309Snwhitehorn * Discard the mixed-gauge dialog. 360217309Snwhitehorn */ 361217309Snwhitehornstatic int 362217309Snwhitehorndlg_finish_mixedgauge(DIALOG_MIXEDGAUGE * dlg, int status) 363217309Snwhitehorn{ 364217309Snwhitehorn (void) wrefresh(dlg->dialog); 365217309Snwhitehorn#ifdef KEY_RESIZE 366217309Snwhitehorn nodelay(stdscr, FALSE); 367217309Snwhitehorn#endif 368217309Snwhitehorn curs_set(1); 369217309Snwhitehorn dlg_del_window(dlg->dialog); 370217309Snwhitehorn return status; 371217309Snwhitehorn} 372217309Snwhitehorn 373217309Snwhitehorn/* 374217309Snwhitehorn * Setup dialog, read mixed-gauge data from pipe. 375217309Snwhitehorn */ 376217309Snwhitehornint 377217309Snwhitehorndialog_mixedgauge(const char *title, 378217309Snwhitehorn const char *cprompt, 379217309Snwhitehorn int height, 380217309Snwhitehorn int width, 381217309Snwhitehorn int percent, 382217309Snwhitehorn int item_no, 383217309Snwhitehorn char **items) 384217309Snwhitehorn{ 385217309Snwhitehorn DIALOG_MIXEDGAUGE dlg; 386217309Snwhitehorn int began = 0; 387217309Snwhitehorn 388217309Snwhitehorn dlg_begin_mixedgauge(&dlg, &began, title, cprompt, height, 389217309Snwhitehorn width, item_no, items); 390217309Snwhitehorn 391217309Snwhitehorn dlg_update_mixedgauge(&dlg, percent); 392217309Snwhitehorn 393217309Snwhitehorn return dlg_finish_mixedgauge(&dlg, DLG_EXIT_OK); 394217309Snwhitehorn} 395