2 * $Id: mixedgauge.c,v 1.38 2022/04/03 22:38:16 tom Exp $
4 * mixedgauge.c -- implements the mixedgauge dialog
6 * Copyright 2007-2021,2022 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).
27 #include <dlg_internals.h>
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
) + 4;
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
;
114 int cells
= dlg
->len_text
- 2;
115 int lm
= limit_x
- dlg
->len_text
- 1;
116 int bm
= limit_y
; /* bottom margin */
117 int last_y
= 0, last_x
= 0;
123 getyx(win
, last_y
, last_x
);
124 for (item
= 0; item
< dlg
->item_no
; ++item
) {
125 const char *status
= "";
126 chtype attr
= A_NORMAL
;
127 int y
= item
+ MARGIN
+ 1;
132 status
= status_string(dlg
->list
[item
].text
, &freeMe
);
133 if (status
== 0 || *status
== 0) {
138 (void) wmove(win
, y
, 2 * MARGIN
);
139 dlg_attrset(win
, dialog_attr
);
140 dlg_print_text(win
, dlg
->list
[item
].name
, lm
, &attr
);
142 (void) wmove(win
, y
, lm
);
143 (void) waddch(win
, '[');
144 (void) wmove(win
, y
, lm
+ (cells
- (int) strlen(status
)) / 2);
146 (void) wmove(win
, y
, lm
+ 1);
147 dlg_attrset(win
, title_attr
);
148 for (j
= 0; j
< cells
; j
++)
149 (void) waddch(win
, ' ');
151 (void) wmove(win
, y
, lm
+ (cells
- (int) strlen(status
)) / 2);
152 (void) waddstr(win
, status
);
154 if ((title_attr
& A_REVERSE
) != 0) {
155 dlg_attroff(win
, A_REVERSE
);
157 dlg_attrset(win
, A_REVERSE
);
159 (void) wmove(win
, y
, lm
+ 1);
161 if (sscanf(status
, "%f%%", &percent
) != 1)
163 xxx
= (int) ((cells
* (percent
+ 0.5)) / 100.0);
164 for (j
= 0; j
< xxx
; j
++) {
165 chtype ch1
= winch(win
);
166 if (title_attr
& A_REVERSE
) {
169 (void) waddch(win
, ch1
);
174 (void) wmove(win
, y
, lm
+ (cells
- (int) strlen(status
)) / 2);
175 (void) waddstr(win
, status
);
177 (void) wmove(win
, y
, limit_x
- 3);
178 dlg_attrset(win
, dialog_attr
);
179 (void) waddch(win
, ']');
180 (void) wnoutrefresh(win
);
183 wmove(win
, last_y
, last_x
);
187 mydraw_mixed_box(WINDOW
*win
, int y
, int x
, int height
, int width
,
188 chtype boxchar
, chtype borderchar
)
190 dlg_draw_box(win
, y
, x
, height
, width
, boxchar
, borderchar
);
192 chtype attr
= A_NORMAL
;
193 const char *message
= _("Overall Progress");
194 chtype save2
= dlg_get_attrs(win
);
195 dlg_attrset(win
, title_attr
);
196 (void) wmove(win
, y
, x
+ 2);
197 dlg_print_text(win
, message
, width
, &attr
);
198 dlg_attrset(win
, save2
);
203 clean_copy(const char *string
)
205 char *result
= dlg_strclone(string
);
207 dlg_trim_string(result
);
208 dlg_tab_correct_str(result
);
213 * Update mixed-gauge dialog (may be from pipe, may be via direct calls).
216 dlg_update_mixedgauge(DIALOG_MIXEDGAUGE
* dlg
, int percent
)
221 * Clear the area for the progress bar by filling it with spaces
222 * in the title-attribute, and write the percentage with that
225 (void) wmove(dlg
->dialog
, dlg
->height
- 3, 4);
226 dlg_attrset(dlg
->dialog
, gauge_attr
);
228 for (i
= 0; i
< (dlg
->width
- 2 * (3 + MARGIN
)); i
++)
229 (void) waddch(dlg
->dialog
, ' ');
231 (void) wmove(dlg
->dialog
, dlg
->height
- 3, (dlg
->width
/ 2) - 2);
232 (void) wprintw(dlg
->dialog
, "%3d%%", percent
);
235 * Now draw a bar in reverse, relative to the background.
236 * The window attribute was useful for painting the background,
237 * but requires some tweaks to reverse it.
239 x
= (percent
* (dlg
->width
- 2 * (3 + MARGIN
))) / 100;
240 if ((title_attr
& A_REVERSE
) != 0) {
241 dlg_attroff(dlg
->dialog
, A_REVERSE
);
243 dlg_attrset(dlg
->dialog
, A_REVERSE
);
245 (void) wmove(dlg
->dialog
, dlg
->height
- 3, 4);
246 for (i
= 0; i
< x
; i
++) {
247 chtype ch
= winch(dlg
->dialog
);
248 if (title_attr
& A_REVERSE
) {
251 (void) waddch(dlg
->dialog
, ch
);
254 dlg_trace_win(dlg
->dialog
);
261 dlg_begin_mixedgauge(DIALOG_MIXEDGAUGE
* dlg
,
277 memset(dlg
, 0, sizeof(*dlg
));
279 dlg
->prompt
= clean_copy(aPrompt
);
280 dlg
->height
= dlg
->old_height
= aHeight
;
281 dlg
->width
= dlg
->old_width
= aWidth
;
282 dlg
->item_no
= aItemNo
;
284 dlg
->list
= dlg_calloc(DIALOG_LISTITEM
, (size_t) aItemNo
);
285 assert_ptr(dlg
->list
, "dialog_mixedgauge");
290 for (n
= 0; n
< aItemNo
; ++n
) {
291 int thisWidth
= (int) strlen(ItemName(n
));
292 if (dlg
->len_name
< thisWidth
)
293 dlg
->len_name
= thisWidth
;
294 dlg
->list
[n
].name
= ItemName(n
);
295 dlg
->list
[n
].text
= ItemText(n
);
298 dlg
->min_height
= MIN_HIGH
+ aItemNo
;
299 dlg
->min_width
= MIN_WIDE
+ dlg
->len_name
+ GUTTER
+ dlg
->len_text
;
301 if (dlg
->prompt
!= 0 && *(dlg
->prompt
) != 0)
302 dlg
->min_height
+= (2 * MARGIN
);
304 nodelay(stdscr
, TRUE
);
309 dlg_del_window(dlg
->dialog
);
310 dlg
->height
= dlg
->old_height
;
311 dlg
->width
= dlg
->old_width
;
315 dlg_auto_size(dlg
->title
, dlg
->prompt
,
320 dlg_print_size(dlg
->height
, dlg
->width
);
321 dlg_ctl_size(dlg
->height
, dlg
->width
);
323 /* center dialog box on screen */
324 x
= dlg_box_x_ordinate(dlg
->width
);
325 y
= dlg_box_y_ordinate(dlg
->height
);
327 dlg
->dialog
= dlg_new_window(dlg
->height
, dlg
->width
, y
, x
);
329 (void) werase(dlg
->dialog
);
330 dlg_draw_box2(dlg
->dialog
,
334 dialog_attr
, border_attr
, border2_attr
);
336 dlg_draw_title(dlg
->dialog
, dlg
->title
);
337 dlg_draw_helpline(dlg
->dialog
, FALSE
);
339 if ((dlg
->prompt
!= 0 && *(dlg
->prompt
) != 0)
340 && wmove(dlg
->dialog
, dlg
->item_no
, 0) != ERR
) {
341 dlg
->caption
= dlg_sub_window(dlg
->dialog
,
342 dlg
->height
- dlg
->item_no
- (2 * MARGIN
),
344 y
+ dlg
->item_no
+ (2 * MARGIN
),
346 dlg_attrset(dlg
->caption
, dialog_attr
);
347 dlg_print_autowrap(dlg
->caption
, dlg
->prompt
, dlg
->height
, dlg
->width
);
350 mydraw_mixed_box(dlg
->dialog
,
354 dlg
->width
- 2 * (2 + MARGIN
),
362 * Discard the mixed-gauge dialog.
365 dlg_finish_mixedgauge(DIALOG_MIXEDGAUGE
* dlg
, int status
)
367 (void) wrefresh(dlg
->dialog
);
369 nodelay(stdscr
, FALSE
);
372 dlg_del_window(dlg
->dialog
);
379 * Setup dialog, read mixed-gauge data from pipe.
382 dialog_mixedgauge(const char *title
,
390 DIALOG_MIXEDGAUGE dlg
;
393 DLG_TRACE(("# mixedgauge args:\n"));
394 DLG_TRACE2S("title", title
);
395 DLG_TRACE2S("message", cprompt
);
396 DLG_TRACE2N("height", height
);
397 DLG_TRACE2N("width", width
);
398 DLG_TRACE2N("percent", percent
);
399 DLG_TRACE2N("llength", item_no
);
400 /* FIXME dump the items[][] too */
402 dlg_begin_mixedgauge(&dlg
, &began
, title
, cprompt
, height
,
403 width
, item_no
, items
);
405 dlg_update_mixedgauge(&dlg
, percent
);
407 return dlg_finish_mixedgauge(&dlg
, DLG_EXIT_OK
);