2 * Copyright (c) 2013-2014 Devin Teske <dteske@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
32 #define _BSD_SOURCE /* to get dprintf() prototype in stdio.h below */
43 #include "dialog_util.h"
47 #include "dpv_private.h"
49 #define FLABEL_MAX 1024
51 static int fheight
= 0; /* initialized by dprompt_init() */
52 static char dprompt
[PROMPT_MAX
+ 1] = "";
53 static char *dprompt_pos
= (char *)(0); /* treated numerically */
55 /* Display characteristics */
59 static uint8_t dprompt_free_mask
;
60 static char *done
= NULL
;
61 static char *fail
= NULL
;
62 static char *pend
= NULL
;
63 int display_limit
= DISPLAY_LIMIT_DEFAULT
; /* Max entries to show */
64 int label_size
= LABEL_SIZE_DEFAULT
; /* Max width for labels */
65 int pbar_size
= PBAR_SIZE_DEFAULT
; /* Mini-progressbar size */
66 static int gauge_percent
= 0;
67 static int done_size
, done_lsize
, done_rsize
;
68 static int fail_size
, fail_lsize
, fail_rsize
;
69 static int mesg_size
, mesg_lsize
, mesg_rsize
;
70 static int pend_size
, pend_lsize
, pend_rsize
;
71 static int pct_lsize
, pct_rsize
;
72 static void *gauge
= NULL
;
74 static char spin
[SPIN_SIZE
+ 1] = "/-\\|";
75 static char msg
[PROMPT_MAX
+ 1];
76 static char *spin_cp
= spin
;
78 /* Function prototypes */
79 static char spin_char(void);
80 static int dprompt_add_files(struct dpv_file_node
*file_list
,
81 struct dpv_file_node
*curfile
, int pct
);
84 * Returns a pointer to the current spin character in the spin string and
85 * advances the global position to the next character for the next call.
96 /* Advance the spinner to the next char */
97 if (++spin_cp
>= (spin
+ SPIN_SIZE
))
104 * Initialize heights and widths based on various strings and environment
105 * variables (such as ENV_USE_COLOR).
108 dprompt_init(struct dpv_file_node
*file_list
)
116 struct dpv_file_node
*curfile
;
119 * Initialize dialog(3) `colors' support and draw backtitle
121 if (use_libdialog
&& !debug
) {
122 init_dialog(stdin
, stdout
);
123 dialog_vars
.colors
= 1;
124 if (backtitle
!= NULL
) {
125 dialog_vars
.backtitle
= (char *)backtitle
;
130 /* Calculate width of dialog(3) or [X]dialog(1) --gauge box */
131 dwidth
= label_size
+ pbar_size
+ 9;
134 * Calculate height of dialog(3) or [X]dialog(1) --gauge box
137 max_rows
= dialog_maxrows();
138 /* adjust max_rows for backtitle and/or dialog(3) statusLine */
139 if (backtitle
!= NULL
)
140 max_rows
-= use_shadow
? 3 : 2;
141 if (use_libdialog
&& use_shadow
)
143 /* add lines for `-p text' */
144 numlines
= dialog_prompt_numlines(pprompt
, 0);
146 warnx("`-p text' is %i line%s long", numlines
,
147 numlines
== 1 ? "" : "s");
149 /* adjust dheight for various implementations */
151 dheight
-= dialog_prompt_nlstate(pprompt
);
152 nls
= dialog_prompt_nlstate(pprompt
);
153 } else if (use_xdialog
) {
154 if (pprompt
== NULL
|| *pprompt
== '\0')
156 } else if (use_libdialog
) {
157 if (pprompt
!= NULL
&& *pprompt
!= '\0')
160 /* limit the number of display items (necessary per dialog(1,3)) */
161 if (display_limit
== 0 || display_limit
> DPV_DISPLAY_LIMIT
)
162 display_limit
= DPV_DISPLAY_LIMIT
;
163 /* verify fheight will fit (stop if we hit 1) */
164 for (; display_limit
> 0; display_limit
--) {
165 nthfile
= numlines
= 0;
166 fheight
= (int)dpv_nfiles
> display_limit
?
167 (unsigned int)display_limit
: dpv_nfiles
;
168 for (curfile
= file_list
; curfile
!= NULL
;
169 curfile
= curfile
->next
) {
171 numlines
+= dialog_prompt_numlines(curfile
->name
, nls
);
172 if ((nthfile
% display_limit
) == 0) {
173 if (numlines
> fheight
)
175 numlines
= nthfile
= 0;
178 if (numlines
> fheight
)
180 if ((dheight
+ fheight
+
181 (int)dialog_prompt_numlines(aprompt
, use_dialog
) -
182 (use_dialog
? (int)dialog_prompt_nlstate(aprompt
) : 0))
186 /* don't show any items if we run the risk of hitting a blank set */
187 if ((max_rows
- (use_shadow
? 5 : 4)) >= fheight
)
191 /* add lines for `-a text' */
192 numlines
= dialog_prompt_numlines(aprompt
, use_dialog
);
194 warnx("`-a text' is %i line%s long", numlines
,
195 numlines
== 1 ? "" : "s");
198 /* If using Xdialog(1), adjust accordingly (based on testing) */
200 dheight
+= dheight
/ 4;
202 /* For wide mode, long prefix (`pprompt') or append (`aprompt')
203 * strings will bump width */
205 len
= (int)dialog_prompt_longestline(pprompt
, 0); /* !nls */
206 if ((len
+ 4) > dwidth
)
208 len
= (int)dialog_prompt_longestline(aprompt
, 1); /* nls */
209 if ((len
+ 4) > dwidth
)
213 /* Enforce width constraints to maximum values */
214 max_cols
= dialog_maxcols();
215 if (max_cols
> 0 && dwidth
> max_cols
)
218 /* Optimize widths to sane values*/
219 if (pbar_size
> dwidth
- 9) {
220 pbar_size
= dwidth
- 9;
222 /* -9 = "| - [" ... "] |" */
225 label_size
= dwidth
- 8;
226 /* -8 = "| " ... " - |" */
227 else if (label_size
> (dwidth
- pbar_size
- 9) || wide
)
228 label_size
= no_labels
? 0 : dwidth
- pbar_size
- 9;
229 /* -9 = "| " ... " - [" ... "] |" */
231 /* Hide labels if requested */
235 /* Touch up the height (now that we know dwidth) */
236 dheight
+= dialog_prompt_wrappedlines(pprompt
, dwidth
- 4, 0);
237 dheight
+= dialog_prompt_wrappedlines(aprompt
, dwidth
- 4, 1);
240 warnx("dheight = %i dwidth = %i fheight = %i",
241 dheight
, dwidth
, fheight
);
243 /* Calculate left/right portions of % */
244 pct_lsize
= (pbar_size
- 4) / 2; /* -4 == printf("%-3s%%", pct) */
245 pct_rsize
= pct_lsize
;
246 /* If not evenly divisible by 2, increment the right-side */
247 if ((pct_rsize
+ pct_rsize
+ 4) != pbar_size
)
250 /* Initialize "Done" text */
251 if (done
== NULL
&& (done
= msg_done
) == NULL
) {
252 if ((done
= getenv(ENV_MSG_DONE
)) != NULL
)
253 done_size
= strlen(done
);
255 done_size
= strlen(DPV_DONE_DEFAULT
);
256 if ((done
= malloc(done_size
+ 1)) == NULL
)
257 errx(EXIT_FAILURE
, "Out of memory?!");
258 dprompt_free_mask
|= FM_DONE
;
259 snprintf(done
, done_size
+ 1, DPV_DONE_DEFAULT
);
262 if (pbar_size
< done_size
) {
263 done_lsize
= done_rsize
= 0;
264 *(done
+ pbar_size
) = '\0';
265 done_size
= pbar_size
;
267 /* Calculate left/right portions for mini-progressbar */
268 done_lsize
= (pbar_size
- done_size
) / 2;
269 done_rsize
= done_lsize
;
270 /* If not evenly divisible by 2, increment the right-side */
271 if ((done_rsize
+ done_size
+ done_lsize
) != pbar_size
)
275 /* Initialize "Fail" text */
276 if (fail
== NULL
&& (fail
= msg_fail
) == NULL
) {
277 if ((fail
= getenv(ENV_MSG_FAIL
)) != NULL
)
278 fail_size
= strlen(fail
);
280 fail_size
= strlen(DPV_FAIL_DEFAULT
);
281 if ((fail
= malloc(fail_size
+ 1)) == NULL
)
282 errx(EXIT_FAILURE
, "Out of memory?!");
283 dprompt_free_mask
|= FM_FAIL
;
284 snprintf(fail
, fail_size
+ 1, DPV_FAIL_DEFAULT
);
287 if (pbar_size
< fail_size
) {
288 fail_lsize
= fail_rsize
= 0;
289 *(fail
+ pbar_size
) = '\0';
290 fail_size
= pbar_size
;
292 /* Calculate left/right portions for mini-progressbar */
293 fail_lsize
= (pbar_size
- fail_size
) / 2;
294 fail_rsize
= fail_lsize
;
295 /* If not evenly divisible by 2, increment the right-side */
296 if ((fail_rsize
+ fail_size
+ fail_lsize
) != pbar_size
)
300 /* Initialize "Pending" text */
301 if (pend
== NULL
&& (pend
= msg_pending
) == NULL
) {
302 if ((pend
= getenv(ENV_MSG_PENDING
)) != NULL
)
303 pend_size
= strlen(pend
);
305 pend_size
= strlen(DPV_PENDING_DEFAULT
);
306 if ((pend
= malloc(pend_size
+ 1)) == NULL
)
307 errx(EXIT_FAILURE
, "Out of memory?!");
308 dprompt_free_mask
|= FM_PEND
;
309 snprintf(pend
, pend_size
+ 1, DPV_PENDING_DEFAULT
);
312 if (pbar_size
< pend_size
) {
313 pend_lsize
= pend_rsize
= 0;
314 *(pend
+ pbar_size
) = '\0';
315 pend_size
= pbar_size
;
317 /* Calculate left/right portions for mini-progressbar */
318 pend_lsize
= (pbar_size
- pend_size
) / 2;
319 pend_rsize
= pend_lsize
;
320 /* If not evenly divisible by 2, increment the right-side */
321 if ((pend_rsize
+ pend_lsize
+ pend_size
) != pbar_size
)
326 warnx("label_size = %i pbar_size = %i", label_size
, pbar_size
);
332 * Clear the [X]dialog(1) `--gauge' prompt buffer.
339 dprompt_pos
= dprompt
;
343 * Append to the [X]dialog(1) `--gauge' prompt buffer. Syntax is like printf(3)
344 * and returns the number of bytes appended to the buffer.
347 dprompt_add(const char *format
, ...)
352 if (dprompt_pos
>= (dprompt
+ PROMPT_MAX
))
355 va_start(ap
, format
);
356 len
= vsnprintf(dprompt_pos
, (size_t)(PROMPT_MAX
-
357 (dprompt_pos
- dprompt
)), format
, ap
);
360 errx(EXIT_FAILURE
, "%s: Oops, dprompt buffer overflow",
363 if ((dprompt_pos
+ len
) < (dprompt
+ PROMPT_MAX
))
366 dprompt_pos
= dprompt
+ PROMPT_MAX
;
372 * Append active files to the [X]dialog(1) `--gauge' prompt buffer. Syntax
373 * requires a pointer to the head of the dpv_file_node linked-list. Returns the
374 * number of files processed successfully.
377 dprompt_add_files(struct dpv_file_node
*file_list
,
378 struct dpv_file_node
*curfile
, int pct
)
381 char bold_code
= 'b'; /* default: enabled */
382 char color_code
= '4'; /* default: blue */
383 uint8_t after_curfile
= curfile
!= NULL
? FALSE
: TRUE
;
391 enum dprompt_state dstate
;
401 struct dpv_file_node
*fp
;
402 char flabel
[FLABEL_MAX
+ 1];
404 char pbar
[pbar_size
+ 16]; /* +15 for optional color */
405 char pbar_cap
[sizeof(pbar
)];
406 char pbar_fill
[sizeof(pbar
)];
409 /* Override color defaults with that of main progress bar */
410 if (use_colors
|| use_shadow
) { /* NB: shadow enables color */
411 color_code
= gauge_color
[0];
412 /* NB: str[1] aka bg is unused */
413 bold_code
= gauge_color
[2];
417 * Create mini-progressbar for current file (if applicable)
420 if (pbar_size
>= 0 && pct
>= 0 && curfile
!= NULL
&&
421 (curfile
->length
>= 0 || dialog_test
)) {
422 snprintf(pbar
, pbar_size
+ 1, "%*s%3u%%%*s", pct_lsize
, "",
425 /* Calculate the fill-width of progressbar */
426 pwidth
= pct
* pbar_size
/ 100;
427 /* Round up based on one-tenth of a percent */
428 if ((pct
* pbar_size
% 100) > 50)
432 * Make two copies of pbar. Make one represent the fill
433 * and the other the remainder (cap). We'll insert the
434 * ANSI delimiter in between.
438 strncat(pbar_fill
, (const char *)(pbar
), dwidth
);
439 *(pbar_fill
+ pwidth
) = '\0';
440 strncat(pbar_cap
, (const char *)(pbar
+pwidth
), dwidth
);
442 /* Finalize the mini [color] progressbar */
443 snprintf(pbar
, sizeof(pbar
),
444 "\\Z%c\\Zr\\Z%c%s%s%s\\Zn", bold_code
, color_code
,
445 pbar_fill
, "\\ZR", pbar_cap
);
449 for (fp
= file_list
; fp
!= NULL
; fp
= fp
->next
) {
450 flabel_size
= label_size
;
455 * Support multiline filenames (where the filename is taken as
456 * the last line and the text leading up to the last line can
457 * be used as (for example) a heading/separator between files.
460 nls
= dialog_prompt_nlstate(pprompt
);
461 nlines
+= dialog_prompt_numlines(name
, nls
);
462 lastline
= dialog_prompt_lastline(name
, 1);
463 if (name
!= lastline
) {
466 dprompt_add("%s", name
);
471 /* Support color codes (for dialog(1,3)) in file names */
472 if ((use_dialog
|| use_libdialog
) && use_color
) {
474 while (*cp
!= '\0') {
475 if (*cp
== '\\' && *(cp
+ 1) != '\0' &&
476 *(++cp
) == 'Z' && *(cp
+ 1) != '\0') {
482 if (flabel_size
> FLABEL_MAX
)
483 flabel_size
= FLABEL_MAX
;
486 /* If no mini-progressbar, increase label width */
487 if (pbar_size
< 0 && flabel_size
<= FLABEL_MAX
- 2 &&
491 /* If name is too long, add an ellipsis */
492 if (snprintf(flabel
, flabel_size
+ 1, "%s", name
) >
493 flabel_size
) sprintf(flabel
+ flabel_size
- 3, "...");
496 * Append the label (processing the current file differently)
498 if (fp
== curfile
&& pct
< 100) {
500 * Add an ellipsis to current file name if it will fit.
501 * There may be an ellipsis already from truncating the
502 * label (in which case, we already have one).
504 cp
= flabel
+ strlen(flabel
);
505 if (cp
< (flabel
+ flabel_size
))
506 snprintf(cp
, flabel_size
-
507 (cp
- flabel
) + 1, "...");
509 /* Append label (with spinner and optional color) */
510 dprompt_add("%s%-*s%s %c", use_color
? "\\Zb" : "",
511 flabel_size
, flabel
, use_color
? "\\Zn" : "",
514 dprompt_add("%-*s%s %s", flabel_size
,
515 flabel
, use_color
? "\\Zn" : "", " ");
518 * Append pbar/status (processing the current file differently)
520 dstate
= DPROMPT_NONE
;
522 dstate
= DPROMPT_CUSTOM_MSG
;
523 else if (pbar_size
< 0)
524 dstate
= DPROMPT_NONE
;
525 else if (pbar_size
< 4)
526 dstate
= DPROMPT_MINIMAL
;
527 else if (after_curfile
)
528 dstate
= DPROMPT_PENDING
;
529 else if (fp
== curfile
) {
532 dstate
= DPROMPT_DETAILS
;
533 else if (fp
->status
== DPV_STATUS_RUNNING
)
534 dstate
= DPROMPT_DETAILS
;
536 dstate
= DPROMPT_END_STATE
;
538 else if (dialog_test
) /* status/length ignored */
540 DPROMPT_PBAR
: DPROMPT_END_STATE
;
541 else if (fp
->status
== DPV_STATUS_RUNNING
)
542 dstate
= fp
->length
< 0 ?
543 DPROMPT_DETAILS
: DPROMPT_PBAR
;
544 else /* not running */
545 dstate
= fp
->length
< 0 ?
546 DPROMPT_DETAILS
: DPROMPT_END_STATE
;
547 } else { /* before curfile */
549 dstate
= DPROMPT_END_STATE
;
551 dstate
= fp
->length
< 0 ?
552 DPROMPT_DETAILS
: DPROMPT_END_STATE
;
555 " [\\Z%c%s%-*s%s%-*s\\Zn]\\n" :
557 if (fp
->status
== DPV_STATUS_FAILED
) {
558 bg_code
= "\\Zr\\Z1"; /* Red */
559 estext_lsize
= fail_lsize
;
560 estext_rsize
= fail_rsize
;
562 } else { /* e.g., DPV_STATUS_DONE */
563 bg_code
= "\\Zr\\Z2"; /* Green */
564 estext_lsize
= done_lsize
;
565 estext_rsize
= done_rsize
;
569 case DPROMPT_PENDING
: /* Future file(s) */
570 dprompt_add(" [%-*s%s%-*s]\\n",
571 pend_lsize
, "", pend
, pend_rsize
, "");
573 case DPROMPT_PBAR
: /* Current file */
574 dprompt_add(" [%s]\\n", pbar
);
576 case DPROMPT_END_STATE
: /* Past/Current file(s) */
578 dprompt_add(format
, bold_code
, bg_code
,
579 estext_lsize
, "", estext
,
583 estext_lsize
, "", estext
,
586 case DPROMPT_DETAILS
: /* Past/Current file(s) */
587 humanize_number(human
, pbar_size
+ 2, fp
->read
, "",
588 HN_AUTOSCALE
, HN_NOSPACE
| HN_DIVISOR_1000
);
590 /* Calculate center alignment */
591 hlen
= (int)strlen(human
);
592 lsize
= (pbar_size
- hlen
) / 2;
594 if ((lsize
+hlen
+rsize
) != pbar_size
)
598 dprompt_add(format
, bold_code
, bg_code
,
599 lsize
, "", human
, rsize
, "");
602 lsize
, "", human
, rsize
, "");
604 case DPROMPT_CUSTOM_MSG
: /* File-specific message override */
605 snprintf(msg
, PROMPT_MAX
+ 1, "%s", fp
->msg
);
606 if (pbar_size
< (mesg_size
= strlen(msg
))) {
607 mesg_lsize
= mesg_rsize
= 0;
608 *(msg
+ pbar_size
) = '\0';
609 mesg_size
= pbar_size
;
611 mesg_lsize
= (pbar_size
- mesg_size
) / 2;
612 mesg_rsize
= mesg_lsize
;
613 if ((mesg_rsize
+ mesg_size
+ mesg_lsize
)
618 dprompt_add(format
, bold_code
, bg_code
,
619 mesg_lsize
, "", msg
, mesg_rsize
, "");
621 dprompt_add(format
, mesg_lsize
, "", msg
,
624 case DPROMPT_MINIMAL
: /* Short progress bar, minimal room */
626 dprompt_add(format
, bold_code
, bg_code
,
627 pbar_size
, "", "", 0, "");
629 dprompt_add(format
, pbar_size
, "", "", 0, "");
631 case DPROMPT_NONE
: /* pbar_size < 0 */
636 * NB: Leading space required for the case when
637 * spin_char() returns a single backslash [\] which
638 * without the space, changes the meaning of `\n'
642 /* Stop building if we've hit the internal limit */
643 if (nthfile
>= display_limit
)
646 /* If this is the current file, all others are pending */
648 after_curfile
= TRUE
;
652 * Since we cannot change the height/width of the [X]dialog(1) widget
653 * after spawn, to make things look nice let's pad the height so that
654 * the `-a text' always appears in the same spot.
656 * NOTE: fheight is calculated in dprompt_init(). It represents the
657 * maximum height required to display the set of items (broken up into
658 * pieces of display_limit chunks) whose names contain the most
659 * newlines for any given set.
661 while (nlines
< fheight
) {
670 * Process the dpv_file_node linked-list of named files, re-generating the
671 * [X]dialog(1) `--gauge' prompt text for the current state of transfers.
674 dprompt_recreate(struct dpv_file_node
*file_list
,
675 struct dpv_file_node
*curfile
, int pct
)
680 * Re-Build the prompt text
683 if (display_limit
> 0)
684 dprompt_add_files(file_list
, curfile
, pct
);
686 /* Xdialog(1) requires newlines (a) escaped and (b) in triplicate */
688 /* Replace `\n' with `\n\\n\n' in dprompt */
689 len
= strlen(dprompt
);
690 len
+= strcount(dprompt
, "\\n") * 5; /* +5 chars per count */
691 if (len
> PROMPT_MAX
)
692 errx(EXIT_FAILURE
, "%s: Oops, dprompt buffer overflow "
693 "(%zu > %i)", __func__
, len
, PROMPT_MAX
);
694 if (replaceall(dprompt
, "\\n", "\n\\n\n") < 0)
695 err(EXIT_FAILURE
, "%s: replaceall()", __func__
);
697 else if (use_libdialog
)
698 strexpandnl(dprompt
);
702 * Print the [X]dialog(1) `--gauge' prompt text to a buffer.
705 dprompt_sprint(char * restrict str
, const char *prefix
, const char *append
)
708 return (snprintf(str
, PROMPT_MAX
, "%s%s%s%s", use_color
? "\\Zn" : "",
709 prefix
? prefix
: "", dprompt
, append
? append
: ""));
713 * Print the [X]dialog(1) `--gauge' prompt text to file descriptor fd (could
714 * be STDOUT_FILENO or a pipe(2) file descriptor to actual [X]dialog(1)).
717 dprompt_dprint(int fd
, const char *prefix
, const char *append
, int overall
)
719 int percent
= gauge_percent
;
721 if (overall
>= 0 && overall
<= 100)
722 gauge_percent
= percent
= overall
;
723 dprintf(fd
, "XXX\n%s%s%s%s\nXXX\n%i\n", use_color
? "\\Zn" : "",
724 prefix
? prefix
: "", dprompt
, append
? append
: "", percent
);
729 * Print the dialog(3) `gauge' prompt text using libdialog.
732 dprompt_libprint(const char *prefix
, const char *append
, int overall
)
734 int percent
= gauge_percent
;
735 char buf
[DPV_PPROMPT_MAX
+ DPV_APROMPT_MAX
+ DPV_DISPLAY_LIMIT
* 1024];
737 dprompt_sprint(buf
, prefix
, append
);
739 if (overall
>= 0 && overall
<= 100)
740 gauge_percent
= percent
= overall
;
741 gauge
= dlg_reallocate_gauge(gauge
, title
== NULL
? "" : title
,
742 buf
, dheight
, dwidth
, percent
);
743 dlg_update_gauge(gauge
, percent
);
747 * Free allocated items initialized by dprompt_init()
752 if ((dprompt_free_mask
& FM_DONE
) != 0) {
753 dprompt_free_mask
^= FM_DONE
;
757 if ((dprompt_free_mask
& FM_FAIL
) != 0) {
758 dprompt_free_mask
^= FM_FAIL
;
762 if ((dprompt_free_mask
& FM_PEND
) != 0) {
763 dprompt_free_mask
^= FM_PEND
;