xref: /freebsd/lib/libdpv/dprompt.c (revision a0d7de3b114c0819ce0921c10fb5bdaf2ee9976a)
1041394f3SDevin Teske /*-
2041394f3SDevin Teske  * Copyright (c) 2013-2014 Devin Teske <dteske@FreeBSD.org>
3041394f3SDevin Teske  * All rights reserved.
4041394f3SDevin Teske  *
5041394f3SDevin Teske  * Redistribution and use in source and binary forms, with or without
6041394f3SDevin Teske  * modification, are permitted provided that the following conditions
7041394f3SDevin Teske  * are met:
8041394f3SDevin Teske  * 1. Redistributions of source code must retain the above copyright
9041394f3SDevin Teske  *    notice, this list of conditions and the following disclaimer.
10041394f3SDevin Teske  * 2. Redistributions in binary form must reproduce the above copyright
11041394f3SDevin Teske  *    notice, this list of conditions and the following disclaimer in the
12041394f3SDevin Teske  *    documentation and/or other materials provided with the distribution.
13041394f3SDevin Teske  *
14041394f3SDevin Teske  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15041394f3SDevin Teske  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16041394f3SDevin Teske  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17041394f3SDevin Teske  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18041394f3SDevin Teske  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19041394f3SDevin Teske  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20041394f3SDevin Teske  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21041394f3SDevin Teske  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22041394f3SDevin Teske  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23041394f3SDevin Teske  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24041394f3SDevin Teske  * SUCH DAMAGE.
25041394f3SDevin Teske  */
26041394f3SDevin Teske 
27041394f3SDevin Teske #include <sys/cdefs.h>
28041394f3SDevin Teske __FBSDID("$FreeBSD$");
29041394f3SDevin Teske 
30041394f3SDevin Teske #include <sys/types.h>
31041394f3SDevin Teske 
32041394f3SDevin Teske #define _BSD_SOURCE /* to get dprintf() prototype in stdio.h below */
33041394f3SDevin Teske #include <dialog.h>
34041394f3SDevin Teske #include <err.h>
35041394f3SDevin Teske #include <libutil.h>
36041394f3SDevin Teske #include <stdarg.h>
37041394f3SDevin Teske #include <stdio.h>
38041394f3SDevin Teske #include <stdlib.h>
39041394f3SDevin Teske #include <string.h>
40041394f3SDevin Teske #include <string_m.h>
41041394f3SDevin Teske #include <unistd.h>
42041394f3SDevin Teske 
43041394f3SDevin Teske #include "dialog_util.h"
44041394f3SDevin Teske #include "dialogrc.h"
45041394f3SDevin Teske #include "dprompt.h"
46041394f3SDevin Teske #include "dpv.h"
47041394f3SDevin Teske #include "dpv_private.h"
48041394f3SDevin Teske 
49041394f3SDevin Teske #define FLABEL_MAX 1024
50041394f3SDevin Teske 
51041394f3SDevin Teske static int fheight = 0; /* initialized by dprompt_init() */
52041394f3SDevin Teske static char dprompt[PROMPT_MAX + 1] = "";
53041394f3SDevin Teske static char *dprompt_pos = (char *)(0); /* treated numerically */
54041394f3SDevin Teske 
55041394f3SDevin Teske /* Display characteristics */
56041394f3SDevin Teske #define FM_DONE 0x01
57041394f3SDevin Teske #define FM_FAIL 0x02
58041394f3SDevin Teske #define FM_PEND 0x04
59041394f3SDevin Teske static uint8_t dprompt_free_mask;
60041394f3SDevin Teske static char *done = NULL;
61041394f3SDevin Teske static char *fail = NULL;
62041394f3SDevin Teske static char *pend = NULL;
63041394f3SDevin Teske int display_limit = DISPLAY_LIMIT_DEFAULT;	/* Max entries to show */
64041394f3SDevin Teske int label_size    = LABEL_SIZE_DEFAULT;		/* Max width for labels */
65041394f3SDevin Teske int pbar_size     = PBAR_SIZE_DEFAULT;		/* Mini-progressbar size */
66041394f3SDevin Teske static int gauge_percent = 0;
67041394f3SDevin Teske static int done_size, done_lsize, done_rsize;
68041394f3SDevin Teske static int fail_size, fail_lsize, fail_rsize;
69041394f3SDevin Teske static int mesg_size, mesg_lsize, mesg_rsize;
70041394f3SDevin Teske static int pend_size, pend_lsize, pend_rsize;
71041394f3SDevin Teske static int pct_lsize, pct_rsize;
72041394f3SDevin Teske static void *gauge = NULL;
73041394f3SDevin Teske #define SPIN_SIZE 4
74041394f3SDevin Teske static char spin[SPIN_SIZE + 1] = "/-\\|";
75041394f3SDevin Teske static char msg[PROMPT_MAX + 1];
76041394f3SDevin Teske static char *spin_cp = spin;
77041394f3SDevin Teske 
78041394f3SDevin Teske /* Function prototypes */
79041394f3SDevin Teske static char	spin_char(void);
80041394f3SDevin Teske static int	dprompt_add_files(struct dpv_file_node *file_list,
81041394f3SDevin Teske 		    struct dpv_file_node *curfile, int pct);
82041394f3SDevin Teske 
83041394f3SDevin Teske /*
84041394f3SDevin Teske  * Returns a pointer to the current spin character in the spin string and
85041394f3SDevin Teske  * advances the global position to the next character for the next call.
86041394f3SDevin Teske  */
87041394f3SDevin Teske static char
88041394f3SDevin Teske spin_char(void)
89041394f3SDevin Teske {
90041394f3SDevin Teske 	char ch;
91041394f3SDevin Teske 
92*a0d7de3bSDevin Teske 	if (*spin_cp == '\0')
93041394f3SDevin Teske 		spin_cp = spin;
94041394f3SDevin Teske 	ch = *spin_cp;
95041394f3SDevin Teske 
96041394f3SDevin Teske 	/* Advance the spinner to the next char */
97041394f3SDevin Teske 	if (++spin_cp >= (spin + SPIN_SIZE))
98041394f3SDevin Teske 		spin_cp = spin;
99041394f3SDevin Teske 
100041394f3SDevin Teske 	return (ch);
101041394f3SDevin Teske }
102041394f3SDevin Teske 
103041394f3SDevin Teske /*
104041394f3SDevin Teske  * Initialize heights and widths based on various strings and environment
105041394f3SDevin Teske  * variables (such as ENV_USE_COLOR).
106041394f3SDevin Teske  */
107041394f3SDevin Teske void
108041394f3SDevin Teske dprompt_init(struct dpv_file_node *file_list)
109041394f3SDevin Teske {
110041394f3SDevin Teske 	uint8_t nls = 0;
111041394f3SDevin Teske 	int len;
112041394f3SDevin Teske 	int max_cols;
113041394f3SDevin Teske 	int max_rows;
114041394f3SDevin Teske 	int nthfile;
115041394f3SDevin Teske 	int numlines;
116041394f3SDevin Teske 	struct dpv_file_node *curfile;
117041394f3SDevin Teske 
118041394f3SDevin Teske 	/*
119041394f3SDevin Teske 	 * Initialize dialog(3) `colors' support and draw backtitle
120041394f3SDevin Teske 	 */
121041394f3SDevin Teske 	if (use_libdialog && !debug) {
122041394f3SDevin Teske 		init_dialog(stdin, stdout);
123041394f3SDevin Teske 		dialog_vars.colors = 1;
124041394f3SDevin Teske 		if (backtitle != NULL) {
125041394f3SDevin Teske 			dialog_vars.backtitle = (char *)backtitle;
126041394f3SDevin Teske 			dlg_put_backtitle();
127041394f3SDevin Teske 		}
128041394f3SDevin Teske 	}
129041394f3SDevin Teske 
130041394f3SDevin Teske 	/* Calculate width of dialog(3) or [X]dialog(1) --gauge box */
131041394f3SDevin Teske 	dwidth = label_size + pbar_size + 9;
132041394f3SDevin Teske 
133041394f3SDevin Teske 	/*
134041394f3SDevin Teske 	 * Calculate height of dialog(3) or [X]dialog(1) --gauge box
135041394f3SDevin Teske 	 */
136041394f3SDevin Teske 	dheight = 5;
137041394f3SDevin Teske 	max_rows = dialog_maxrows();
138041394f3SDevin Teske 	/* adjust max_rows for backtitle and/or dialog(3) statusLine */
139041394f3SDevin Teske 	if (backtitle != NULL)
140041394f3SDevin Teske 		max_rows -= use_shadow ? 3 : 2;
141041394f3SDevin Teske 	if (use_libdialog && use_shadow)
142041394f3SDevin Teske 		max_rows -= 2;
143041394f3SDevin Teske 	/* add lines for `-p text' */
144041394f3SDevin Teske 	numlines = dialog_prompt_numlines(pprompt, 0);
145041394f3SDevin Teske 	if (debug)
146041394f3SDevin Teske 		warnx("`-p text' is %i line%s long", numlines,
147041394f3SDevin Teske 		    numlines == 1 ? "" : "s");
148041394f3SDevin Teske 	dheight += numlines;
149041394f3SDevin Teske 	/* adjust dheight for various implementations */
150041394f3SDevin Teske 	if (use_dialog) {
151041394f3SDevin Teske 		dheight -= dialog_prompt_nlstate(pprompt);
152041394f3SDevin Teske 		nls = dialog_prompt_nlstate(pprompt);
153041394f3SDevin Teske 	} else if (use_xdialog) {
154041394f3SDevin Teske 		if (pprompt == NULL || *pprompt == '\0')
155041394f3SDevin Teske 			dheight++;
156041394f3SDevin Teske 	} else if (use_libdialog) {
157041394f3SDevin Teske 		if (pprompt != NULL && *pprompt != '\0')
158041394f3SDevin Teske 			dheight--;
159041394f3SDevin Teske 	}
160041394f3SDevin Teske 	/* limit the number of display items (necessary per dialog(1,3)) */
161041394f3SDevin Teske 	if (display_limit == 0 || display_limit > DPV_DISPLAY_LIMIT)
162041394f3SDevin Teske 		display_limit = DPV_DISPLAY_LIMIT;
163041394f3SDevin Teske 	/* verify fheight will fit (stop if we hit 1) */
164041394f3SDevin Teske 	for (; display_limit > 0; display_limit--) {
165041394f3SDevin Teske 		nthfile = numlines = 0;
166041394f3SDevin Teske 		fheight = (int)dpv_nfiles > display_limit ?
167041394f3SDevin Teske 		    (unsigned int)display_limit : dpv_nfiles;
168041394f3SDevin Teske 		for (curfile = file_list; curfile != NULL;
169041394f3SDevin Teske 		    curfile = curfile->next) {
170041394f3SDevin Teske 			nthfile++;
171041394f3SDevin Teske 			numlines += dialog_prompt_numlines(curfile->name, nls);
172041394f3SDevin Teske 			if ((nthfile % display_limit) == 0) {
173041394f3SDevin Teske 				if (numlines > fheight)
174041394f3SDevin Teske 					fheight = numlines;
175041394f3SDevin Teske 				numlines = nthfile = 0;
176041394f3SDevin Teske 			}
177041394f3SDevin Teske 		}
178041394f3SDevin Teske 		if (numlines > fheight)
179041394f3SDevin Teske 			fheight = numlines;
180041394f3SDevin Teske 		if ((dheight + fheight +
181041394f3SDevin Teske 		    (int)dialog_prompt_numlines(aprompt, use_dialog) -
182041394f3SDevin Teske 		    (use_dialog ? (int)dialog_prompt_nlstate(aprompt) : 0))
183041394f3SDevin Teske 		    <= max_rows)
184041394f3SDevin Teske 			break;
185041394f3SDevin Teske 	}
186041394f3SDevin Teske 	/* don't show any items if we run the risk of hitting a blank set */
187041394f3SDevin Teske 	if ((max_rows - (use_shadow ? 5 : 4)) >= fheight)
188041394f3SDevin Teske 		dheight += fheight;
189041394f3SDevin Teske 	else
190041394f3SDevin Teske 		fheight = 0;
191041394f3SDevin Teske 	/* add lines for `-a text' */
192041394f3SDevin Teske 	numlines = dialog_prompt_numlines(aprompt, use_dialog);
193041394f3SDevin Teske 	if (debug)
194041394f3SDevin Teske 		warnx("`-a text' is %i line%s long", numlines,
195041394f3SDevin Teske 		    numlines == 1 ? "" : "s");
196041394f3SDevin Teske 	dheight += numlines;
197041394f3SDevin Teske 
198041394f3SDevin Teske 	/* If using Xdialog(1), adjust accordingly (based on testing) */
199041394f3SDevin Teske 	if (use_xdialog)
200041394f3SDevin Teske 		dheight += dheight / 4;
201041394f3SDevin Teske 
202041394f3SDevin Teske 	/* For wide mode, long prefix (`pprompt') or append (`aprompt')
203041394f3SDevin Teske 	 * strings will bump width */
204041394f3SDevin Teske 	if (wide) {
205041394f3SDevin Teske 		len = (int)dialog_prompt_longestline(pprompt, 0); /* !nls */
206041394f3SDevin Teske 		if ((len + 4) > dwidth)
207041394f3SDevin Teske 			dwidth = len + 4;
208041394f3SDevin Teske 		len = (int)dialog_prompt_longestline(aprompt, 1); /* nls */
209041394f3SDevin Teske 		if ((len + 4) > dwidth)
210041394f3SDevin Teske 			dwidth = len + 4;
211041394f3SDevin Teske 	}
212041394f3SDevin Teske 
213041394f3SDevin Teske 	/* Enforce width constraints to maximum values */
214041394f3SDevin Teske 	max_cols = dialog_maxcols();
215041394f3SDevin Teske 	if (max_cols > 0 && dwidth > max_cols)
216041394f3SDevin Teske 		dwidth = max_cols;
217041394f3SDevin Teske 
218041394f3SDevin Teske 	/* Optimize widths to sane values*/
219041394f3SDevin Teske 	if (pbar_size > dwidth - 9) {
220041394f3SDevin Teske 		pbar_size = dwidth - 9;
221041394f3SDevin Teske 		label_size = 0;
222041394f3SDevin Teske 		/* -9 = "|  - [" ... "] |" */
223041394f3SDevin Teske 	}
224041394f3SDevin Teske 	if (pbar_size < 0)
225041394f3SDevin Teske 		label_size = dwidth - 8;
226041394f3SDevin Teske 		/* -8 = "|  " ... " -  |" */
227041394f3SDevin Teske 	else if (label_size > (dwidth - pbar_size - 9) || wide)
228041394f3SDevin Teske 		label_size = no_labels ? 0 : dwidth - pbar_size - 9;
229041394f3SDevin Teske 		/* -9 = "| " ... " - [" ... "] |" */
230041394f3SDevin Teske 
231041394f3SDevin Teske 	/* Hide labels if requested */
232041394f3SDevin Teske 	if (no_labels)
233041394f3SDevin Teske 		label_size = 0;
234041394f3SDevin Teske 
235041394f3SDevin Teske 	/* Touch up the height (now that we know dwidth) */
236041394f3SDevin Teske 	dheight += dialog_prompt_wrappedlines(pprompt, dwidth - 4, 0);
237041394f3SDevin Teske 	dheight += dialog_prompt_wrappedlines(aprompt, dwidth - 4, 1);
238041394f3SDevin Teske 
239041394f3SDevin Teske 	if (debug)
240041394f3SDevin Teske 		warnx("dheight = %i dwidth = %i fheight = %i",
241041394f3SDevin Teske 		    dheight, dwidth, fheight);
242041394f3SDevin Teske 
243041394f3SDevin Teske 	/* Calculate left/right portions of % */
244041394f3SDevin Teske 	pct_lsize = (pbar_size - 4) / 2; /* -4 == printf("%-3s%%", pct) */
245041394f3SDevin Teske 	pct_rsize = pct_lsize;
246041394f3SDevin Teske 	/* If not evenly divisible by 2, increment the right-side */
247041394f3SDevin Teske 	if ((pct_rsize + pct_rsize + 4) != pbar_size)
248041394f3SDevin Teske 		pct_rsize++;
249041394f3SDevin Teske 
250041394f3SDevin Teske 	/* Initialize "Done" text */
251041394f3SDevin Teske 	if (done == NULL && (done = msg_done) == NULL) {
252041394f3SDevin Teske 		if ((done = getenv(ENV_MSG_DONE)) != NULL)
253041394f3SDevin Teske 			done_size = strlen(done);
254041394f3SDevin Teske 		else {
255041394f3SDevin Teske 			done_size = strlen(DPV_DONE_DEFAULT);
256041394f3SDevin Teske 			if ((done = malloc(done_size + 1)) == NULL)
257041394f3SDevin Teske 				errx(EXIT_FAILURE, "Out of memory?!");
258041394f3SDevin Teske 			dprompt_free_mask |= FM_DONE;
259041394f3SDevin Teske 			snprintf(done, done_size + 1, DPV_DONE_DEFAULT);
260041394f3SDevin Teske 		}
261041394f3SDevin Teske 	}
262041394f3SDevin Teske 	if (pbar_size < done_size) {
263041394f3SDevin Teske 		done_lsize = done_rsize = 0;
264041394f3SDevin Teske 		*(done + pbar_size) = '\0';
265041394f3SDevin Teske 		done_size = pbar_size;
266041394f3SDevin Teske 	} else {
267041394f3SDevin Teske 		/* Calculate left/right portions for mini-progressbar */
268041394f3SDevin Teske 		done_lsize = (pbar_size - done_size) / 2;
269041394f3SDevin Teske 		done_rsize = done_lsize;
270041394f3SDevin Teske 		/* If not evenly divisible by 2, increment the right-side */
271041394f3SDevin Teske 		if ((done_rsize + done_size + done_lsize) != pbar_size)
272041394f3SDevin Teske 			done_rsize++;
273041394f3SDevin Teske 	}
274041394f3SDevin Teske 
275041394f3SDevin Teske 	/* Initialize "Fail" text */
276041394f3SDevin Teske 	if (fail == NULL && (fail = msg_fail) == NULL) {
277041394f3SDevin Teske 		if ((fail = getenv(ENV_MSG_FAIL)) != NULL)
278041394f3SDevin Teske 			fail_size = strlen(fail);
279041394f3SDevin Teske 		else {
280041394f3SDevin Teske 			fail_size = strlen(DPV_FAIL_DEFAULT);
281041394f3SDevin Teske 			if ((fail = malloc(fail_size + 1)) == NULL)
282041394f3SDevin Teske 				errx(EXIT_FAILURE, "Out of memory?!");
283041394f3SDevin Teske 			dprompt_free_mask |= FM_FAIL;
284041394f3SDevin Teske 			snprintf(fail, fail_size + 1, DPV_FAIL_DEFAULT);
285041394f3SDevin Teske 		}
286041394f3SDevin Teske 	}
287041394f3SDevin Teske 	if (pbar_size < fail_size) {
288041394f3SDevin Teske 		fail_lsize = fail_rsize = 0;
289041394f3SDevin Teske 		*(fail + pbar_size) = '\0';
290041394f3SDevin Teske 		fail_size = pbar_size;
291041394f3SDevin Teske 	} else {
292041394f3SDevin Teske 		/* Calculate left/right portions for mini-progressbar */
293041394f3SDevin Teske 		fail_lsize = (pbar_size - fail_size) / 2;
294041394f3SDevin Teske 		fail_rsize = fail_lsize;
295041394f3SDevin Teske 		/* If not evenly divisible by 2, increment the right-side */
296041394f3SDevin Teske 		if ((fail_rsize + fail_size + fail_lsize) != pbar_size)
297041394f3SDevin Teske 			fail_rsize++;
298041394f3SDevin Teske 	}
299041394f3SDevin Teske 
300041394f3SDevin Teske 	/* Initialize "Pending" text */
301041394f3SDevin Teske 	if (pend == NULL && (pend = msg_pending) == NULL) {
302041394f3SDevin Teske 		if ((pend = getenv(ENV_MSG_PENDING)) != NULL)
303041394f3SDevin Teske 			pend_size = strlen(pend);
304041394f3SDevin Teske 		else {
305041394f3SDevin Teske 			pend_size = strlen(DPV_PENDING_DEFAULT);
306041394f3SDevin Teske 			if ((pend = malloc(pend_size + 1)) == NULL)
307041394f3SDevin Teske 				errx(EXIT_FAILURE, "Out of memory?!");
308041394f3SDevin Teske 			dprompt_free_mask |= FM_PEND;
309041394f3SDevin Teske 			snprintf(pend, pend_size + 1, DPV_PENDING_DEFAULT);
310041394f3SDevin Teske 		}
311041394f3SDevin Teske 	}
312041394f3SDevin Teske 	if (pbar_size < pend_size) {
313041394f3SDevin Teske 		pend_lsize = pend_rsize = 0;
314041394f3SDevin Teske 		*(pend + pbar_size) = '\0';
315041394f3SDevin Teske 		pend_size = pbar_size;
316041394f3SDevin Teske 	} else {
317041394f3SDevin Teske 		/* Calculate left/right portions for mini-progressbar */
318041394f3SDevin Teske 		pend_lsize = (pbar_size - pend_size) / 2;
319041394f3SDevin Teske 		pend_rsize = pend_lsize;
320041394f3SDevin Teske 		/* If not evenly divisible by 2, increment the right-side */
321041394f3SDevin Teske 		if ((pend_rsize + pend_lsize + pend_size) != pbar_size)
322041394f3SDevin Teske 			pend_rsize++;
323041394f3SDevin Teske 	}
324041394f3SDevin Teske 
325041394f3SDevin Teske 	if (debug)
326041394f3SDevin Teske 		warnx("label_size = %i pbar_size = %i", label_size, pbar_size);
327041394f3SDevin Teske 
328041394f3SDevin Teske 	dprompt_clear();
329041394f3SDevin Teske }
330041394f3SDevin Teske 
331041394f3SDevin Teske /*
332041394f3SDevin Teske  * Clear the [X]dialog(1) `--gauge' prompt buffer.
333041394f3SDevin Teske  */
334041394f3SDevin Teske void
335041394f3SDevin Teske dprompt_clear(void)
336041394f3SDevin Teske {
337041394f3SDevin Teske 
338041394f3SDevin Teske 	*dprompt = '\0';
339041394f3SDevin Teske 	dprompt_pos = dprompt;
340041394f3SDevin Teske }
341041394f3SDevin Teske 
342041394f3SDevin Teske /*
343041394f3SDevin Teske  * Append to the [X]dialog(1) `--gauge' prompt buffer. Syntax is like printf(3)
344041394f3SDevin Teske  * and returns the number of bytes appended to the buffer.
345041394f3SDevin Teske  */
346041394f3SDevin Teske int
347041394f3SDevin Teske dprompt_add(const char *format, ...)
348041394f3SDevin Teske {
349041394f3SDevin Teske 	int len;
350041394f3SDevin Teske 	va_list ap;
351041394f3SDevin Teske 
352041394f3SDevin Teske 	if (dprompt_pos >= (dprompt + PROMPT_MAX))
353041394f3SDevin Teske 		return (0);
354041394f3SDevin Teske 
355041394f3SDevin Teske 	va_start(ap, format);
356041394f3SDevin Teske 	len = vsnprintf(dprompt_pos, (size_t)(PROMPT_MAX -
357041394f3SDevin Teske 	    (dprompt_pos - dprompt)), format, ap);
358041394f3SDevin Teske 	va_end(ap);
359041394f3SDevin Teske 	if (len == -1)
360041394f3SDevin Teske 		errx(EXIT_FAILURE, "%s: Oops, dprompt buffer overflow",
361041394f3SDevin Teske 		    __func__);
362041394f3SDevin Teske 
363041394f3SDevin Teske 	if ((dprompt_pos + len) < (dprompt + PROMPT_MAX))
364041394f3SDevin Teske 		dprompt_pos += len;
365041394f3SDevin Teske 	else
366041394f3SDevin Teske 		dprompt_pos = dprompt + PROMPT_MAX;
367041394f3SDevin Teske 
368041394f3SDevin Teske 	return (len);
369041394f3SDevin Teske }
370041394f3SDevin Teske 
371041394f3SDevin Teske /*
372041394f3SDevin Teske  * Append active files to the [X]dialog(1) `--gauge' prompt buffer. Syntax
373041394f3SDevin Teske  * requires a pointer to the head of the dpv_file_node linked-list. Returns the
374041394f3SDevin Teske  * number of files processed successfully.
375041394f3SDevin Teske  */
376041394f3SDevin Teske static int
377041394f3SDevin Teske dprompt_add_files(struct dpv_file_node *file_list,
378041394f3SDevin Teske     struct dpv_file_node *curfile, int pct)
379041394f3SDevin Teske {
380041394f3SDevin Teske 	char c;
381041394f3SDevin Teske 	char bold_code = 'b'; /* default: enabled */
382041394f3SDevin Teske 	char color_code = '4'; /* default: blue */
383041394f3SDevin Teske 	uint8_t after_curfile = curfile != NULL ? FALSE : TRUE;
384041394f3SDevin Teske 	uint8_t nls = 0;
385041394f3SDevin Teske 	char *cp;
386041394f3SDevin Teske 	char *lastline;
387041394f3SDevin Teske 	char *name;
388041394f3SDevin Teske 	const char *bg_code;
389041394f3SDevin Teske 	const char *estext;
390041394f3SDevin Teske 	const char *format;
391041394f3SDevin Teske 	enum dprompt_state dstate;
392041394f3SDevin Teske 	int estext_lsize;
393041394f3SDevin Teske 	int estext_rsize;
394041394f3SDevin Teske 	int flabel_size;
395041394f3SDevin Teske 	int hlen;
396041394f3SDevin Teske 	int lsize;
397041394f3SDevin Teske 	int nlines = 0;
398041394f3SDevin Teske 	int nthfile = 0;
399041394f3SDevin Teske 	int pwidth;
400041394f3SDevin Teske 	int rsize;
401041394f3SDevin Teske 	struct dpv_file_node *fp;
402041394f3SDevin Teske 	char flabel[FLABEL_MAX + 1];
403041394f3SDevin Teske 	char human[32];
404041394f3SDevin Teske 	char pbar[pbar_size + 16]; /* +15 for optional color */
405041394f3SDevin Teske 	char pbar_cap[sizeof(pbar)];
406041394f3SDevin Teske 	char pbar_fill[sizeof(pbar)];
407041394f3SDevin Teske 
408041394f3SDevin Teske 
409041394f3SDevin Teske 	/* Override color defaults with that of main progress bar */
410041394f3SDevin Teske 	if (use_colors || use_shadow) { /* NB: shadow enables color */
411041394f3SDevin Teske 		color_code = gauge_color[0];
412041394f3SDevin Teske 		/* NB: str[1] aka bg is unused */
413041394f3SDevin Teske 		bold_code = gauge_color[2];
414041394f3SDevin Teske 	}
415041394f3SDevin Teske 
416041394f3SDevin Teske 	/*
417041394f3SDevin Teske 	 * Create mini-progressbar for current file (if applicable)
418041394f3SDevin Teske 	 */
419041394f3SDevin Teske 	*pbar = '\0';
420041394f3SDevin Teske 	if (pbar_size >= 0 && pct >= 0 && curfile != NULL &&
421041394f3SDevin Teske 	    (curfile->length >= 0 || dialog_test)) {
422041394f3SDevin Teske 		snprintf(pbar, pbar_size + 1, "%*s%3u%%%*s", pct_lsize, "",
423041394f3SDevin Teske 		    pct, pct_rsize, "");
424041394f3SDevin Teske 		if (use_color) {
425041394f3SDevin Teske 			/* Calculate the fill-width of progressbar */
426041394f3SDevin Teske 			pwidth = pct * pbar_size / 100;
427041394f3SDevin Teske 			/* Round up based on one-tenth of a percent */
428041394f3SDevin Teske 			if ((pct * pbar_size % 100) > 50)
429041394f3SDevin Teske 				pwidth++;
430041394f3SDevin Teske 
431041394f3SDevin Teske 			/*
432041394f3SDevin Teske 			 * Make two copies of pbar. Make one represent the fill
433041394f3SDevin Teske 			 * and the other the remainder (cap). We'll insert the
434041394f3SDevin Teske 			 * ANSI delimiter in between.
435041394f3SDevin Teske 			 */
436041394f3SDevin Teske 			*pbar_fill = '\0';
437041394f3SDevin Teske 			*pbar_cap = '\0';
438041394f3SDevin Teske 			strncat(pbar_fill, (const char *)(pbar), dwidth);
439041394f3SDevin Teske 			*(pbar_fill + pwidth) = '\0';
440041394f3SDevin Teske 			strncat(pbar_cap, (const char *)(pbar+pwidth), dwidth);
441041394f3SDevin Teske 
442041394f3SDevin Teske 			/* Finalize the mini [color] progressbar */
443041394f3SDevin Teske 			snprintf(pbar, sizeof(pbar),
444041394f3SDevin Teske 			    "\\Z%c\\Zr\\Z%c%s%s%s\\Zn", bold_code, color_code,
445041394f3SDevin Teske 			    pbar_fill, "\\ZR", pbar_cap);
446041394f3SDevin Teske 		}
447041394f3SDevin Teske 	}
448041394f3SDevin Teske 
449041394f3SDevin Teske 	for (fp = file_list; fp != NULL; fp = fp->next) {
450041394f3SDevin Teske 		flabel_size = label_size;
451041394f3SDevin Teske 		name = fp->name;
452041394f3SDevin Teske 		nthfile++;
453041394f3SDevin Teske 
454041394f3SDevin Teske 		/*
455041394f3SDevin Teske 		 * Support multiline filenames (where the filename is taken as
456041394f3SDevin Teske 		 * the last line and the text leading up to the last line can
457041394f3SDevin Teske 		 * be used as (for example) a heading/separator between files.
458041394f3SDevin Teske 		 */
459041394f3SDevin Teske 		if (use_dialog)
460041394f3SDevin Teske 			nls = dialog_prompt_nlstate(pprompt);
461041394f3SDevin Teske 		nlines += dialog_prompt_numlines(name, nls);
462041394f3SDevin Teske 		lastline = dialog_prompt_lastline(name, 1);
463041394f3SDevin Teske 		if (name != lastline) {
464041394f3SDevin Teske 			c = *lastline;
465041394f3SDevin Teske 			*lastline = '\0';
466041394f3SDevin Teske 			dprompt_add("%s", name);
467041394f3SDevin Teske 			*lastline = c;
468041394f3SDevin Teske 			name = lastline;
469041394f3SDevin Teske 		}
470041394f3SDevin Teske 
471041394f3SDevin Teske 		/* Support color codes (for dialog(1,3)) in file names */
472041394f3SDevin Teske 		if ((use_dialog || use_libdialog) && use_color) {
473041394f3SDevin Teske 			cp = name;
474041394f3SDevin Teske 			while (*cp != '\0') {
475041394f3SDevin Teske 				if (*cp == '\\' && *(cp + 1) != '\0' &&
476041394f3SDevin Teske 				    *(++cp) == 'Z' && *(cp + 1) != '\0') {
477041394f3SDevin Teske 					cp++;
478041394f3SDevin Teske 					flabel_size += 3;
479041394f3SDevin Teske 				}
480041394f3SDevin Teske 				cp++;
481041394f3SDevin Teske 			}
482041394f3SDevin Teske 			if (flabel_size > FLABEL_MAX)
483041394f3SDevin Teske 				flabel_size = FLABEL_MAX;
484041394f3SDevin Teske 		}
485041394f3SDevin Teske 
486041394f3SDevin Teske 		/* If no mini-progressbar, increase label width */
487041394f3SDevin Teske 		if (pbar_size < 0 && flabel_size <= FLABEL_MAX - 2 &&
488041394f3SDevin Teske 		    no_labels == FALSE)
489041394f3SDevin Teske 			flabel_size += 2;
490041394f3SDevin Teske 
491041394f3SDevin Teske 		/* If name is too long, add an ellipsis */
492041394f3SDevin Teske 		if (snprintf(flabel, flabel_size + 1, "%s", name) >
493041394f3SDevin Teske 		    flabel_size) sprintf(flabel + flabel_size - 3, "...");
494041394f3SDevin Teske 
495041394f3SDevin Teske 		/*
496041394f3SDevin Teske 		 * Append the label (processing the current file differently)
497041394f3SDevin Teske 		 */
498041394f3SDevin Teske 		if (fp == curfile && pct < 100) {
499041394f3SDevin Teske 			/*
500041394f3SDevin Teske 			 * Add an ellipsis to current file name if it will fit.
501041394f3SDevin Teske 			 * There may be an ellipsis already from truncating the
502041394f3SDevin Teske 			 * label (in which case, we already have one).
503041394f3SDevin Teske 			 */
504041394f3SDevin Teske 			cp = flabel + strlen(flabel);
505041394f3SDevin Teske 			if (cp < (flabel + flabel_size))
506041394f3SDevin Teske 				snprintf(cp, flabel_size -
507041394f3SDevin Teske 				    (cp - flabel) + 1, "...");
508041394f3SDevin Teske 
509041394f3SDevin Teske 			/* Append label (with spinner and optional color) */
510041394f3SDevin Teske 			dprompt_add("%s%-*s%s %c", use_color ? "\\Zb" : "",
511041394f3SDevin Teske 			    flabel_size, flabel, use_color ? "\\Zn" : "",
512041394f3SDevin Teske 			    spin_char());
513041394f3SDevin Teske 		} else
514041394f3SDevin Teske 			dprompt_add("%-*s%s %s", flabel_size,
515041394f3SDevin Teske 			    flabel, use_color ? "\\Zn" : "", " ");
516041394f3SDevin Teske 
517041394f3SDevin Teske 		/*
518041394f3SDevin Teske 		 * Append pbar/status (processing the current file differently)
519041394f3SDevin Teske 		 */
520041394f3SDevin Teske 		dstate = DPROMPT_NONE;
521041394f3SDevin Teske 		if (fp->msg != NULL)
522041394f3SDevin Teske 			dstate = DPROMPT_CUSTOM_MSG;
523041394f3SDevin Teske 		else if (pbar_size < 0)
524041394f3SDevin Teske 			dstate = DPROMPT_NONE;
525041394f3SDevin Teske 		else if (pbar_size < 4)
526041394f3SDevin Teske 			dstate = DPROMPT_MINIMAL;
527041394f3SDevin Teske 		else if (after_curfile)
528041394f3SDevin Teske 			dstate = DPROMPT_PENDING;
529041394f3SDevin Teske 		else if (fp == curfile) {
530041394f3SDevin Teske 			if (*pbar == '\0') {
531041394f3SDevin Teske 				if (fp->length < 0)
532041394f3SDevin Teske 					dstate = DPROMPT_DETAILS;
533041394f3SDevin Teske 				else if (fp->status == DPV_STATUS_RUNNING)
534041394f3SDevin Teske 					dstate = DPROMPT_DETAILS;
535041394f3SDevin Teske 				else
536041394f3SDevin Teske 					dstate = DPROMPT_END_STATE;
537041394f3SDevin Teske 			}
538041394f3SDevin Teske 			else if (dialog_test) /* status/length ignored */
539041394f3SDevin Teske 				dstate = pct < 100 ?
540041394f3SDevin Teske 				    DPROMPT_PBAR : DPROMPT_END_STATE;
541041394f3SDevin Teske 			else if (fp->status == DPV_STATUS_RUNNING)
542041394f3SDevin Teske 				dstate = fp->length < 0 ?
543041394f3SDevin Teske 				    DPROMPT_DETAILS : DPROMPT_PBAR;
544041394f3SDevin Teske 			else /* not running */
545041394f3SDevin Teske 				dstate = fp->length < 0 ?
546041394f3SDevin Teske 				    DPROMPT_DETAILS : DPROMPT_END_STATE;
547041394f3SDevin Teske 		} else { /* before curfile */
548041394f3SDevin Teske 			if (dialog_test)
549041394f3SDevin Teske 				dstate = DPROMPT_END_STATE;
550041394f3SDevin Teske 			else
551041394f3SDevin Teske 				dstate = fp->length < 0 ?
552041394f3SDevin Teske 				    DPROMPT_DETAILS : DPROMPT_END_STATE;
553041394f3SDevin Teske 		}
554041394f3SDevin Teske 		format = use_color ?
555041394f3SDevin Teske 		    " [\\Z%c%s%-*s%s%-*s\\Zn]\\n" :
556041394f3SDevin Teske 		    " [%-*s%s%-*s]\\n";
557041394f3SDevin Teske 		if (fp->status == DPV_STATUS_FAILED) {
558041394f3SDevin Teske 			bg_code = "\\Zr\\Z1"; /* Red */
559041394f3SDevin Teske 			estext_lsize = fail_lsize;
560041394f3SDevin Teske 			estext_rsize = fail_rsize;
561041394f3SDevin Teske 			estext = fail;
562041394f3SDevin Teske 		} else { /* e.g., DPV_STATUS_DONE */
563041394f3SDevin Teske 			bg_code = "\\Zr\\Z2"; /* Green */
564041394f3SDevin Teske 			estext_lsize = done_lsize;
565041394f3SDevin Teske 			estext_rsize = done_rsize;
566041394f3SDevin Teske 			estext = done;
567041394f3SDevin Teske 		}
568041394f3SDevin Teske 		switch (dstate) {
569041394f3SDevin Teske 		case DPROMPT_PENDING: /* Future file(s) */
570041394f3SDevin Teske 			dprompt_add(" [%-*s%s%-*s]\\n",
571041394f3SDevin Teske 			    pend_lsize, "", pend, pend_rsize, "");
572041394f3SDevin Teske 			break;
573041394f3SDevin Teske 		case DPROMPT_PBAR: /* Current file */
574041394f3SDevin Teske 			dprompt_add(" [%s]\\n", pbar);
575041394f3SDevin Teske 			break;
576041394f3SDevin Teske 		case DPROMPT_END_STATE: /* Past/Current file(s) */
577041394f3SDevin Teske 			if (use_color)
578041394f3SDevin Teske 				dprompt_add(format, bold_code, bg_code,
579041394f3SDevin Teske 				    estext_lsize, "", estext,
580041394f3SDevin Teske 				    estext_rsize, "");
581041394f3SDevin Teske 			else
582041394f3SDevin Teske 				dprompt_add(format,
583041394f3SDevin Teske 				    estext_lsize, "", estext,
584041394f3SDevin Teske 				    estext_rsize, "");
585041394f3SDevin Teske 			break;
586041394f3SDevin Teske 		case DPROMPT_DETAILS: /* Past/Current file(s) */
587041394f3SDevin Teske 			humanize_number(human, pbar_size + 2, fp->read, "",
588041394f3SDevin Teske 			    HN_AUTOSCALE, HN_NOSPACE | HN_DIVISOR_1000);
589041394f3SDevin Teske 
590041394f3SDevin Teske 			/* Calculate center alignment */
591041394f3SDevin Teske 			hlen = (int)strlen(human);
592041394f3SDevin Teske 			lsize = (pbar_size - hlen) / 2;
593041394f3SDevin Teske 			rsize = lsize;
594041394f3SDevin Teske 			if ((lsize+hlen+rsize) != pbar_size)
595041394f3SDevin Teske 				rsize++;
596041394f3SDevin Teske 
597041394f3SDevin Teske 			if (use_color)
598041394f3SDevin Teske 				dprompt_add(format, bold_code, bg_code,
599041394f3SDevin Teske 				    lsize, "", human, rsize, "");
600041394f3SDevin Teske 			else
601041394f3SDevin Teske 				dprompt_add(format,
602041394f3SDevin Teske 				    lsize, "", human, rsize, "");
603041394f3SDevin Teske 			break;
604041394f3SDevin Teske 		case DPROMPT_CUSTOM_MSG: /* File-specific message override */
605041394f3SDevin Teske 			snprintf(msg, PROMPT_MAX + 1, "%s", fp->msg);
606041394f3SDevin Teske 			if (pbar_size < (mesg_size = strlen(msg))) {
607041394f3SDevin Teske 				mesg_lsize = mesg_rsize = 0;
608041394f3SDevin Teske 				*(msg + pbar_size) = '\0';
609041394f3SDevin Teske 				mesg_size = pbar_size;
610041394f3SDevin Teske 			} else {
611041394f3SDevin Teske 				mesg_lsize = (pbar_size - mesg_size) / 2;
612041394f3SDevin Teske 				mesg_rsize = mesg_lsize;
613041394f3SDevin Teske 				if ((mesg_rsize + mesg_size + mesg_lsize)
614041394f3SDevin Teske 				    != pbar_size)
615041394f3SDevin Teske 					mesg_rsize++;
616041394f3SDevin Teske 			}
617041394f3SDevin Teske 			if (use_color)
618041394f3SDevin Teske 				dprompt_add(format, bold_code, bg_code,
619041394f3SDevin Teske 				    mesg_lsize, "", msg, mesg_rsize, "");
620041394f3SDevin Teske 			else
621041394f3SDevin Teske 				dprompt_add(format, mesg_lsize, "", msg,
622041394f3SDevin Teske 				    mesg_rsize, "");
623041394f3SDevin Teske 			break;
624041394f3SDevin Teske 		case DPROMPT_MINIMAL: /* Short progress bar, minimal room */
625041394f3SDevin Teske 			if (use_color)
626041394f3SDevin Teske 				dprompt_add(format, bold_code, bg_code,
627041394f3SDevin Teske 				    pbar_size, "", "", 0, "");
628041394f3SDevin Teske 			else
629041394f3SDevin Teske 				dprompt_add(format, pbar_size, "", "", 0, "");
630041394f3SDevin Teske 			break;
631041394f3SDevin Teske 		case DPROMPT_NONE: /* pbar_size < 0 */
632041394f3SDevin Teske 			/* FALLTHROUGH */
633041394f3SDevin Teske 		default:
634041394f3SDevin Teske 			dprompt_add(" \\n");
635041394f3SDevin Teske 			/*
636041394f3SDevin Teske 			 * NB: Leading space required for the case when
637041394f3SDevin Teske 			 * spin_char() returns a single backslash [\] which
638041394f3SDevin Teske 			 * without the space, changes the meaning of `\n'
639041394f3SDevin Teske 			 */
640041394f3SDevin Teske 		}
641041394f3SDevin Teske 
642041394f3SDevin Teske 		/* Stop building if we've hit the internal limit */
643041394f3SDevin Teske 		if (nthfile >= display_limit)
644041394f3SDevin Teske 			break;
645041394f3SDevin Teske 
646041394f3SDevin Teske 		/* If this is the current file, all others are pending */
647041394f3SDevin Teske 		if (fp == curfile)
648041394f3SDevin Teske 			after_curfile = TRUE;
649041394f3SDevin Teske 	}
650041394f3SDevin Teske 
651041394f3SDevin Teske 	/*
652041394f3SDevin Teske 	 * Since we cannot change the height/width of the [X]dialog(1) widget
653041394f3SDevin Teske 	 * after spawn, to make things look nice let's pad the height so that
654041394f3SDevin Teske 	 * the `-a text' always appears in the same spot.
655041394f3SDevin Teske 	 *
656041394f3SDevin Teske 	 * NOTE: fheight is calculated in dprompt_init(). It represents the
657041394f3SDevin Teske 	 * maximum height required to display the set of items (broken up into
658041394f3SDevin Teske 	 * pieces of display_limit chunks) whose names contain the most
659041394f3SDevin Teske 	 * newlines for any given set.
660041394f3SDevin Teske 	 */
661041394f3SDevin Teske 	while (nlines < fheight) {
662041394f3SDevin Teske 		dprompt_add("\n");
663041394f3SDevin Teske 		nlines++;
664041394f3SDevin Teske 	}
665041394f3SDevin Teske 
666041394f3SDevin Teske 	return (nthfile);
667041394f3SDevin Teske }
668041394f3SDevin Teske 
669041394f3SDevin Teske /*
670041394f3SDevin Teske  * Process the dpv_file_node linked-list of named files, re-generating the
671041394f3SDevin Teske  * [X]dialog(1) `--gauge' prompt text for the current state of transfers.
672041394f3SDevin Teske  */
673041394f3SDevin Teske void
674041394f3SDevin Teske dprompt_recreate(struct dpv_file_node *file_list,
675041394f3SDevin Teske     struct dpv_file_node *curfile, int pct)
676041394f3SDevin Teske {
677041394f3SDevin Teske 	size_t len;
678041394f3SDevin Teske 
679041394f3SDevin Teske 	/*
680041394f3SDevin Teske 	 * Re-Build the prompt text
681041394f3SDevin Teske 	 */
682041394f3SDevin Teske 	dprompt_clear();
683041394f3SDevin Teske 	if (display_limit > 0)
684041394f3SDevin Teske 		dprompt_add_files(file_list, curfile, pct);
685041394f3SDevin Teske 
686041394f3SDevin Teske 	/* Xdialog(1) requires newlines (a) escaped and (b) in triplicate */
687041394f3SDevin Teske 	if (use_xdialog) {
688041394f3SDevin Teske 		/* Replace `\n' with `\n\\n\n' in dprompt */
689041394f3SDevin Teske 		len = strlen(dprompt);
690041394f3SDevin Teske 		len += strcount(dprompt, "\\n") * 5; /* +5 chars per count */
691041394f3SDevin Teske 		if (len > PROMPT_MAX)
692041394f3SDevin Teske 			errx(EXIT_FAILURE, "%s: Oops, dprompt buffer overflow "
693041394f3SDevin Teske 			    "(%zu > %i)", __func__, len, PROMPT_MAX);
694041394f3SDevin Teske 		if (replaceall(dprompt, "\\n", "\n\\n\n") < 0)
695041394f3SDevin Teske 			err(EXIT_FAILURE, "%s: replaceall()", __func__);
696041394f3SDevin Teske 	}
697041394f3SDevin Teske 	else if (use_libdialog)
698041394f3SDevin Teske 		strexpandnl(dprompt);
699041394f3SDevin Teske }
700041394f3SDevin Teske 
701041394f3SDevin Teske /*
702041394f3SDevin Teske  * Print the [X]dialog(1) `--gauge' prompt text to a buffer.
703041394f3SDevin Teske  */
704041394f3SDevin Teske int
705041394f3SDevin Teske dprompt_sprint(char * restrict str, const char *prefix, const char *append)
706041394f3SDevin Teske {
707041394f3SDevin Teske 
708041394f3SDevin Teske 	return (snprintf(str, PROMPT_MAX, "%s%s%s%s", use_color ? "\\Zn" : "",
709041394f3SDevin Teske 	    prefix ? prefix : "", dprompt, append ? append : ""));
710041394f3SDevin Teske }
711041394f3SDevin Teske 
712041394f3SDevin Teske /*
713041394f3SDevin Teske  * Print the [X]dialog(1) `--gauge' prompt text to file descriptor fd (could
714041394f3SDevin Teske  * be STDOUT_FILENO or a pipe(2) file descriptor to actual [X]dialog(1)).
715041394f3SDevin Teske  */
716041394f3SDevin Teske void
717041394f3SDevin Teske dprompt_dprint(int fd, const char *prefix, const char *append, int overall)
718041394f3SDevin Teske {
719041394f3SDevin Teske 	int percent = gauge_percent;
720041394f3SDevin Teske 
721041394f3SDevin Teske 	if (overall >= 0 && overall <= 100)
722041394f3SDevin Teske 		gauge_percent = percent = overall;
723041394f3SDevin Teske 	dprintf(fd, "XXX\n%s%s%s%s\nXXX\n%i\n", use_color ? "\\Zn" : "",
724041394f3SDevin Teske 	    prefix ? prefix : "", dprompt, append ? append : "", percent);
725041394f3SDevin Teske 	fsync(fd);
726041394f3SDevin Teske }
727041394f3SDevin Teske 
728041394f3SDevin Teske /*
729041394f3SDevin Teske  * Print the dialog(3) `gauge' prompt text using libdialog.
730041394f3SDevin Teske  */
731041394f3SDevin Teske void
732041394f3SDevin Teske dprompt_libprint(const char *prefix, const char *append, int overall)
733041394f3SDevin Teske {
734041394f3SDevin Teske 	int percent = gauge_percent;
735041394f3SDevin Teske 	char buf[DPV_PPROMPT_MAX + DPV_APROMPT_MAX + DPV_DISPLAY_LIMIT * 1024];
736041394f3SDevin Teske 
737041394f3SDevin Teske 	dprompt_sprint(buf, prefix, append);
738041394f3SDevin Teske 
739041394f3SDevin Teske 	if (overall >= 0 && overall <= 100)
740041394f3SDevin Teske 		gauge_percent = percent = overall;
741041394f3SDevin Teske 	gauge = dlg_reallocate_gauge(gauge, title == NULL ? "" : title,
742041394f3SDevin Teske 	    buf, dheight, dwidth, percent);
743041394f3SDevin Teske 	dlg_update_gauge(gauge, percent);
744041394f3SDevin Teske }
745041394f3SDevin Teske 
746041394f3SDevin Teske /*
747041394f3SDevin Teske  * Free allocated items initialized by dprompt_init()
748041394f3SDevin Teske  */
749041394f3SDevin Teske void
750041394f3SDevin Teske dprompt_free(void)
751041394f3SDevin Teske {
752041394f3SDevin Teske 	if ((dprompt_free_mask & FM_DONE) != 0) {
753041394f3SDevin Teske 		dprompt_free_mask ^= FM_DONE;
754041394f3SDevin Teske 		free(done);
755041394f3SDevin Teske 		done = NULL;
756041394f3SDevin Teske 	}
757041394f3SDevin Teske 	if ((dprompt_free_mask & FM_FAIL) != 0) {
758041394f3SDevin Teske 		dprompt_free_mask ^= FM_FAIL;
759041394f3SDevin Teske 		free(fail);
760041394f3SDevin Teske 		fail = NULL;
761041394f3SDevin Teske 	}
762041394f3SDevin Teske 	if ((dprompt_free_mask & FM_PEND) != 0) {
763041394f3SDevin Teske 		dprompt_free_mask ^= FM_PEND;
764041394f3SDevin Teske 		free(pend);
765041394f3SDevin Teske 		pend = NULL;
766041394f3SDevin Teske 	}
767041394f3SDevin Teske }
768