2 * $Id: mixedgauge.c,v 1.30 2012/11/18 16:30:20 tom Exp $
4 * mixedgauge.c -- implements the mixedgauge dialog
6 * Copyright 2007-2011,2012 Thomas E. Dickey
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.
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.
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.
23 * This is inspired by a patch from Kiran Cherupally
24 * (but different interface design).
29 #define LLEN(n) ((n) * MIXEDGAUGE_TAGS)
30 #define ItemData(i) &items[LLEN(i)]
31 #define ItemName(i) items[LLEN(i)]
32 #define ItemText(i) items[LLEN(i) + 1]
35 #define MIN_WIDE (10 + 2 * (2 + MARGIN))
42 int height
, old_height
, min_height
;
43 int width
, old_width
, min_width
;
44 int len_name
, len_text
;
46 DIALOG_LISTITEM
*list
;
50 status_string(char *given
, char **freeMe
)
55 if (isdigit(UCH(*given
))) {
58 result
= _("Succeeded");
67 result
= _("Completed");
70 result
= _("Checked");
76 result
= _("Skipped");
79 result
= _("In Progress");
91 } else if (*given
== '-') {
92 size_t need
= strlen(++given
);
93 char *temp
= dlg_malloc(char, need
);
95 sprintf(temp
, "%3s%%", given
);
97 } else if (!isspace(UCH(*given
))) {
105 /* This function displays status messages */
107 myprint_status(DIALOG_MIXEDGAUGE
* dlg
)
109 WINDOW
*win
= dlg
->dialog
;
110 int limit_y
= dlg
->height
;
111 int limit_x
= dlg
->width
;
115 int cells
= dlg
->len_text
- 2;
116 int lm
= limit_x
- dlg
->len_text
- 1;
117 int bm
= limit_y
; /* bottom margin */
118 int last_y
= 0, last_x
= 0;
121 const char *status
= "";
125 getyx(win
, last_y
, last_x
);
126 for (item
= 0; item
< dlg
->item_no
; ++item
) {
127 chtype attr
= A_NORMAL
;
129 y
= item
+ MARGIN
+ 1;
133 status
= status_string(dlg
->list
[item
].text
, &freeMe
);
134 if (status
== 0 || *status
== 0)
137 (void) wmove(win
, y
, 2 * MARGIN
);
138 dlg_print_text(win
, dlg
->list
[item
].name
, lm
, &attr
);
140 (void) wmove(win
, y
, lm
);
141 (void) waddch(win
, '[');
142 (void) wmove(win
, y
, lm
+ (cells
- (int) strlen(status
)) / 2);
144 (void) wmove(win
, y
, lm
+ 1);
145 (void) wattrset(win
, title_attr
);
146 for (j
= 0; j
< cells
; j
++)
147 (void) waddch(win
, ' ');
149 (void) wmove(win
, y
, lm
+ (cells
- (int) strlen(status
)) / 2);
150 (void) waddstr(win
, status
);
152 if ((title_attr
& A_REVERSE
) != 0) {
153 wattroff(win
, A_REVERSE
);
155 (void) wattrset(win
, A_REVERSE
);
157 (void) wmove(win
, y
, lm
+ 1);
159 if (sscanf(status
, "%f%%", &percent
) != 1)
161 xxx
= (int) ((cells
* (percent
+ 0.5)) / 100.0);
162 for (j
= 0; j
< xxx
; j
++) {
163 chtype ch1
= winch(win
);
164 if (title_attr
& A_REVERSE
) {
167 (void) waddch(win
, ch1
);
172 (void) wmove(win
, y
, lm
+ (cells
- (int) strlen(status
)) / 2);
173 (void) waddstr(win
, status
);
175 (void) wmove(win
, y
, limit_x
- 3);
176 (void) waddch(win
, ']');
177 (void) wnoutrefresh(win
);
180 wmove(win
, last_y
, last_x
);
184 mydraw_mixed_box(WINDOW
*win
, int y
, int x
, int height
, int width
,
185 chtype boxchar
, chtype borderchar
)
187 dlg_draw_box(win
, y
, x
, height
, width
, boxchar
, borderchar
);
189 chtype attr
= A_NORMAL
;
190 const char *message
= _("Overall Progress");
191 chtype save2
= dlg_get_attrs(win
);
192 (void) wattrset(win
, title_attr
);
193 (void) wmove(win
, y
, x
+ 2);
194 dlg_print_text(win
, message
, width
, &attr
);
195 (void) wattrset(win
, save2
);
200 clean_copy(const char *string
)
202 char *result
= dlg_strclone(string
);
204 dlg_trim_string(result
);
205 dlg_tab_correct_str(result
);
210 * Update mixed-gauge dialog (may be from pipe, may be via direct calls).
213 dlg_update_mixedgauge(DIALOG_MIXEDGAUGE
* dlg
, int percent
)
218 * Clear the area for the progress bar by filling it with spaces
219 * in the title-attribute, and write the percentage with that
222 (void) wmove(dlg
->dialog
, dlg
->height
- 3, 4);
223 (void) wattrset(dlg
->dialog
, gauge_attr
);
225 for (i
= 0; i
< (dlg
->width
- 2 * (3 + MARGIN
)); i
++)
226 (void) waddch(dlg
->dialog
, ' ');
228 (void) wmove(dlg
->dialog
, dlg
->height
- 3, (dlg
->width
/ 2) - 2);
229 (void) wprintw(dlg
->dialog
, "%3d%%", percent
);
232 * Now draw a bar in reverse, relative to the background.
233 * The window attribute was useful for painting the background,
234 * but requires some tweaks to reverse it.
236 x
= (percent
* (dlg
->width
- 2 * (3 + MARGIN
))) / 100;
237 if ((title_attr
& A_REVERSE
) != 0) {
238 wattroff(dlg
->dialog
, A_REVERSE
);
240 (void) wattrset(dlg
->dialog
, A_REVERSE
);
242 (void) wmove(dlg
->dialog
, dlg
->height
- 3, 4);
243 for (i
= 0; i
< x
; i
++) {
244 chtype ch
= winch(dlg
->dialog
);
245 if (title_attr
& A_REVERSE
) {
248 (void) waddch(dlg
->dialog
, ch
);
251 dlg_trace_win(dlg
->dialog
);
258 dlg_begin_mixedgauge(DIALOG_MIXEDGAUGE
* dlg
,
272 memset(dlg
, 0, sizeof(*dlg
));
274 dlg
->prompt
= clean_copy(aPrompt
);
275 dlg
->height
= dlg
->old_height
= aHeight
;
276 dlg
->width
= dlg
->old_width
= aWidth
;
277 dlg
->item_no
= aItemNo
;
279 dlg
->list
= dlg_calloc(DIALOG_LISTITEM
, (size_t) aItemNo
);
280 assert_ptr(dlg
->list
, "dialog_mixedgauge");
285 for (n
= 0; n
< aItemNo
; ++n
) {
286 int thisWidth
= (int) strlen(ItemName(n
));
287 if (dlg
->len_name
< thisWidth
)
288 dlg
->len_name
= thisWidth
;
289 dlg
->list
[n
].name
= ItemName(n
);
290 dlg
->list
[n
].text
= ItemText(n
);
293 dlg
->min_height
= MIN_HIGH
+ aItemNo
;
294 dlg
->min_width
= MIN_WIDE
+ dlg
->len_name
+ GUTTER
+ dlg
->len_text
;
296 if (dlg
->prompt
!= 0 && *(dlg
->prompt
) != 0)
297 dlg
->min_height
+= (2 * MARGIN
);
299 nodelay(stdscr
, TRUE
);
304 dlg_del_window(dlg
->dialog
);
305 dlg
->height
= dlg
->old_height
;
306 dlg
->width
= dlg
->old_width
;
310 dlg_auto_size(dlg
->title
, dlg
->prompt
,
315 dlg_print_size(dlg
->height
, dlg
->width
);
316 dlg_ctl_size(dlg
->height
, dlg
->width
);
318 /* center dialog box on screen */
319 x
= dlg_box_x_ordinate(dlg
->width
);
320 y
= dlg_box_y_ordinate(dlg
->height
);
322 dlg
->dialog
= dlg_new_window(dlg
->height
, dlg
->width
, y
, x
);
324 (void) werase(dlg
->dialog
);
325 dlg_draw_box2(dlg
->dialog
,
329 dialog_attr
, border_attr
, border2_attr
);
331 dlg_draw_title(dlg
->dialog
, dlg
->title
);
332 dlg_draw_helpline(dlg
->dialog
, FALSE
);
334 if ((dlg
->prompt
!= 0 && *(dlg
->prompt
) != 0)
335 && wmove(dlg
->dialog
, dlg
->item_no
, 0) != ERR
) {
336 dlg
->caption
= dlg_sub_window(dlg
->dialog
,
337 dlg
->height
- dlg
->item_no
- (2 * MARGIN
),
339 y
+ dlg
->item_no
+ (2 * MARGIN
),
341 (void) wattrset(dlg
->caption
, dialog_attr
);
342 dlg_print_autowrap(dlg
->caption
, dlg
->prompt
, dlg
->height
, dlg
->width
);
345 mydraw_mixed_box(dlg
->dialog
,
349 dlg
->width
- 2 * (2 + MARGIN
),
357 * Discard the mixed-gauge dialog.
360 dlg_finish_mixedgauge(DIALOG_MIXEDGAUGE
* dlg
, int status
)
362 (void) wrefresh(dlg
->dialog
);
364 nodelay(stdscr
, FALSE
);
367 dlg_del_window(dlg
->dialog
);
372 * Setup dialog, read mixed-gauge data from pipe.
375 dialog_mixedgauge(const char *title
,
383 DIALOG_MIXEDGAUGE dlg
;
386 dlg_begin_mixedgauge(&dlg
, &began
, title
, cprompt
, height
,
387 width
, item_no
, items
);
389 dlg_update_mixedgauge(&dlg
, percent
);
391 return dlg_finish_mixedgauge(&dlg
, DLG_EXIT_OK
);