diff options
Diffstat (limited to 'lib/libdpv/dprompt.c')
-rw-r--r-- | lib/libdpv/dprompt.c | 764 |
1 files changed, 764 insertions, 0 deletions
diff --git a/lib/libdpv/dprompt.c b/lib/libdpv/dprompt.c new file mode 100644 index 000000000000..66f785ac86a1 --- /dev/null +++ b/lib/libdpv/dprompt.c @@ -0,0 +1,764 @@ +/*- + * Copyright (c) 2013-2014 Devin Teske <dteske@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> + +#define _BSD_SOURCE /* to get dprintf() prototype in stdio.h below */ +#include <dialog.h> +#include <err.h> +#include <libutil.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <string_m.h> +#include <unistd.h> + +#include "dialog_util.h" +#include "dialogrc.h" +#include "dprompt.h" +#include "dpv.h" +#include "dpv_private.h" + +#define FLABEL_MAX 1024 + +static int fheight = 0; /* initialized by dprompt_init() */ +static char dprompt[PROMPT_MAX + 1] = ""; +static char *dprompt_pos = (char *)(0); /* treated numerically */ + +/* Display characteristics */ +#define FM_DONE 0x01 +#define FM_FAIL 0x02 +#define FM_PEND 0x04 +static uint8_t dprompt_free_mask; +static char *done = NULL; +static char *fail = NULL; +static char *pend = NULL; +int display_limit = DISPLAY_LIMIT_DEFAULT; /* Max entries to show */ +int label_size = LABEL_SIZE_DEFAULT; /* Max width for labels */ +int pbar_size = PBAR_SIZE_DEFAULT; /* Mini-progressbar size */ +static int gauge_percent = 0; +static int done_size, done_lsize, done_rsize; +static int fail_size, fail_lsize, fail_rsize; +static int mesg_size, mesg_lsize, mesg_rsize; +static int pend_size, pend_lsize, pend_rsize; +static int pct_lsize, pct_rsize; +static void *gauge = NULL; +#define SPIN_SIZE 4 +static char spin[SPIN_SIZE + 1] = "/-\\|"; +static char msg[PROMPT_MAX + 1]; +static char *spin_cp = spin; + +/* Function prototypes */ +static char spin_char(void); +static int dprompt_add_files(struct dpv_file_node *file_list, + struct dpv_file_node *curfile, int pct); + +/* + * Returns a pointer to the current spin character in the spin string and + * advances the global position to the next character for the next call. + */ +static char +spin_char(void) +{ + char ch; + + if (*spin_cp == '\0') + spin_cp = spin; + ch = *spin_cp; + + /* Advance the spinner to the next char */ + if (++spin_cp >= (spin + SPIN_SIZE)) + spin_cp = spin; + + return (ch); +} + +/* + * Initialize heights and widths based on various strings and environment + * variables (such as ENV_USE_COLOR). + */ +void +dprompt_init(struct dpv_file_node *file_list) +{ + uint8_t nls = 0; + int len; + int max_cols; + int max_rows; + int nthfile; + int numlines; + struct dpv_file_node *curfile; + + /* + * Initialize dialog(3) `colors' support and draw backtitle + */ + if (use_libdialog && !debug) { + init_dialog(stdin, stdout); + dialog_vars.colors = 1; + if (backtitle != NULL) { + dialog_vars.backtitle = (char *)backtitle; + dlg_put_backtitle(); + } + } + + /* Calculate width of dialog(3) or [X]dialog(1) --gauge box */ + dwidth = label_size + pbar_size + 9; + + /* + * Calculate height of dialog(3) or [X]dialog(1) --gauge box + */ + dheight = 5; + max_rows = dialog_maxrows(); + /* adjust max_rows for backtitle and/or dialog(3) statusLine */ + if (backtitle != NULL) + max_rows -= use_shadow ? 3 : 2; + if (use_libdialog && use_shadow) + max_rows -= 2; + /* add lines for `-p text' */ + numlines = dialog_prompt_numlines(pprompt, 0); + if (debug) + warnx("`-p text' is %i line%s long", numlines, + numlines == 1 ? "" : "s"); + dheight += numlines; + /* adjust dheight for various implementations */ + if (use_dialog) { + dheight -= dialog_prompt_nlstate(pprompt); + nls = dialog_prompt_nlstate(pprompt); + } else if (use_xdialog) { + if (pprompt == NULL || *pprompt == '\0') + dheight++; + } else if (use_libdialog) { + if (pprompt != NULL && *pprompt != '\0') + dheight--; + } + /* limit the number of display items (necessary per dialog(1,3)) */ + if (display_limit == 0 || display_limit > DPV_DISPLAY_LIMIT) + display_limit = DPV_DISPLAY_LIMIT; + /* verify fheight will fit (stop if we hit 1) */ + for (; display_limit > 0; display_limit--) { + nthfile = numlines = 0; + fheight = (int)dpv_nfiles > display_limit ? + (unsigned int)display_limit : dpv_nfiles; + for (curfile = file_list; curfile != NULL; + curfile = curfile->next) { + nthfile++; + numlines += dialog_prompt_numlines(curfile->name, nls); + if ((nthfile % display_limit) == 0) { + if (numlines > fheight) + fheight = numlines; + numlines = nthfile = 0; + } + } + if (numlines > fheight) + fheight = numlines; + if ((dheight + fheight + + (int)dialog_prompt_numlines(aprompt, use_dialog) - + (use_dialog ? (int)dialog_prompt_nlstate(aprompt) : 0)) + <= max_rows) + break; + } + /* don't show any items if we run the risk of hitting a blank set */ + if ((max_rows - (use_shadow ? 5 : 4)) >= fheight) + dheight += fheight; + else + fheight = 0; + /* add lines for `-a text' */ + numlines = dialog_prompt_numlines(aprompt, use_dialog); + if (debug) + warnx("`-a text' is %i line%s long", numlines, + numlines == 1 ? "" : "s"); + dheight += numlines; + + /* If using Xdialog(1), adjust accordingly (based on testing) */ + if (use_xdialog) + dheight += dheight / 4; + + /* For wide mode, long prefix (`pprompt') or append (`aprompt') + * strings will bump width */ + if (wide) { + len = (int)dialog_prompt_longestline(pprompt, 0); /* !nls */ + if ((len + 4) > dwidth) + dwidth = len + 4; + len = (int)dialog_prompt_longestline(aprompt, 1); /* nls */ + if ((len + 4) > dwidth) + dwidth = len + 4; + } + + /* Enforce width constraints to maximum values */ + max_cols = dialog_maxcols(); + if (max_cols > 0 && dwidth > max_cols) + dwidth = max_cols; + + /* Optimize widths to sane values*/ + if (pbar_size > dwidth - 9) { + pbar_size = dwidth - 9; + label_size = 0; + /* -9 = "| - [" ... "] |" */ + } + if (pbar_size < 0) + label_size = dwidth - 8; + /* -8 = "| " ... " - |" */ + else if (label_size > (dwidth - pbar_size - 9) || wide) + label_size = no_labels ? 0 : dwidth - pbar_size - 9; + /* -9 = "| " ... " - [" ... "] |" */ + + /* Hide labels if requested */ + if (no_labels) + label_size = 0; + + /* Touch up the height (now that we know dwidth) */ + dheight += dialog_prompt_wrappedlines(pprompt, dwidth - 4, 0); + dheight += dialog_prompt_wrappedlines(aprompt, dwidth - 4, 1); + + if (debug) + warnx("dheight = %i dwidth = %i fheight = %i", + dheight, dwidth, fheight); + + /* Calculate left/right portions of % */ + pct_lsize = (pbar_size - 4) / 2; /* -4 == printf("%-3s%%", pct) */ + pct_rsize = pct_lsize; + /* If not evenly divisible by 2, increment the right-side */ + if ((pct_rsize + pct_rsize + 4) != pbar_size) + pct_rsize++; + + /* Initialize "Done" text */ + if (done == NULL && (done = msg_done) == NULL) { + if ((done = getenv(ENV_MSG_DONE)) != NULL) + done_size = strlen(done); + else { + done_size = strlen(DPV_DONE_DEFAULT); + if ((done = malloc(done_size + 1)) == NULL) + errx(EXIT_FAILURE, "Out of memory?!"); + dprompt_free_mask |= FM_DONE; + snprintf(done, done_size + 1, DPV_DONE_DEFAULT); + } + } + if (pbar_size < done_size) { + done_lsize = done_rsize = 0; + *(done + pbar_size) = '\0'; + done_size = pbar_size; + } else { + /* Calculate left/right portions for mini-progressbar */ + done_lsize = (pbar_size - done_size) / 2; + done_rsize = done_lsize; + /* If not evenly divisible by 2, increment the right-side */ + if ((done_rsize + done_size + done_lsize) != pbar_size) + done_rsize++; + } + + /* Initialize "Fail" text */ + if (fail == NULL && (fail = msg_fail) == NULL) { + if ((fail = getenv(ENV_MSG_FAIL)) != NULL) + fail_size = strlen(fail); + else { + fail_size = strlen(DPV_FAIL_DEFAULT); + if ((fail = malloc(fail_size + 1)) == NULL) + errx(EXIT_FAILURE, "Out of memory?!"); + dprompt_free_mask |= FM_FAIL; + snprintf(fail, fail_size + 1, DPV_FAIL_DEFAULT); + } + } + if (pbar_size < fail_size) { + fail_lsize = fail_rsize = 0; + *(fail + pbar_size) = '\0'; + fail_size = pbar_size; + } else { + /* Calculate left/right portions for mini-progressbar */ + fail_lsize = (pbar_size - fail_size) / 2; + fail_rsize = fail_lsize; + /* If not evenly divisible by 2, increment the right-side */ + if ((fail_rsize + fail_size + fail_lsize) != pbar_size) + fail_rsize++; + } + + /* Initialize "Pending" text */ + if (pend == NULL && (pend = msg_pending) == NULL) { + if ((pend = getenv(ENV_MSG_PENDING)) != NULL) + pend_size = strlen(pend); + else { + pend_size = strlen(DPV_PENDING_DEFAULT); + if ((pend = malloc(pend_size + 1)) == NULL) + errx(EXIT_FAILURE, "Out of memory?!"); + dprompt_free_mask |= FM_PEND; + snprintf(pend, pend_size + 1, DPV_PENDING_DEFAULT); + } + } + if (pbar_size < pend_size) { + pend_lsize = pend_rsize = 0; + *(pend + pbar_size) = '\0'; + pend_size = pbar_size; + } else { + /* Calculate left/right portions for mini-progressbar */ + pend_lsize = (pbar_size - pend_size) / 2; + pend_rsize = pend_lsize; + /* If not evenly divisible by 2, increment the right-side */ + if ((pend_rsize + pend_lsize + pend_size) != pbar_size) + pend_rsize++; + } + + if (debug) + warnx("label_size = %i pbar_size = %i", label_size, pbar_size); + + dprompt_clear(); +} + +/* + * Clear the [X]dialog(1) `--gauge' prompt buffer. + */ +void +dprompt_clear(void) +{ + + *dprompt = '\0'; + dprompt_pos = dprompt; +} + +/* + * Append to the [X]dialog(1) `--gauge' prompt buffer. Syntax is like printf(3) + * and returns the number of bytes appended to the buffer. + */ +int +dprompt_add(const char *format, ...) +{ + int len; + va_list ap; + + if (dprompt_pos >= (dprompt + PROMPT_MAX)) + return (0); + + va_start(ap, format); + len = vsnprintf(dprompt_pos, (size_t)(PROMPT_MAX - + (dprompt_pos - dprompt)), format, ap); + va_end(ap); + if (len == -1) + errx(EXIT_FAILURE, "%s: Oops, dprompt buffer overflow", + __func__); + + if ((dprompt_pos + len) < (dprompt + PROMPT_MAX)) + dprompt_pos += len; + else + dprompt_pos = dprompt + PROMPT_MAX; + + return (len); +} + +/* + * Append active files to the [X]dialog(1) `--gauge' prompt buffer. Syntax + * requires a pointer to the head of the dpv_file_node linked-list. Returns the + * number of files processed successfully. + */ +static int +dprompt_add_files(struct dpv_file_node *file_list, + struct dpv_file_node *curfile, int pct) +{ + char c; + char bold_code = 'b'; /* default: enabled */ + char color_code = '4'; /* default: blue */ + uint8_t after_curfile = curfile != NULL ? FALSE : TRUE; + uint8_t nls = 0; + char *cp; + char *lastline; + char *name; + const char *bg_code; + const char *estext; + const char *format; + enum dprompt_state dstate; + int estext_lsize; + int estext_rsize; + int flabel_size; + int hlen; + int lsize; + int nlines = 0; + int nthfile = 0; + int pwidth; + int rsize; + struct dpv_file_node *fp; + char flabel[FLABEL_MAX + 1]; + char human[32]; + char pbar[pbar_size + 16]; /* +15 for optional color */ + char pbar_cap[sizeof(pbar)]; + char pbar_fill[sizeof(pbar)]; + + + /* Override color defaults with that of main progress bar */ + if (use_colors || use_shadow) { /* NB: shadow enables color */ + color_code = gauge_color[0]; + /* NB: str[1] aka bg is unused */ + bold_code = gauge_color[2]; + } + + /* + * Create mini-progressbar for current file (if applicable) + */ + *pbar = '\0'; + if (pbar_size >= 0 && pct >= 0 && curfile != NULL && + (curfile->length >= 0 || dialog_test)) { + snprintf(pbar, pbar_size + 1, "%*s%3u%%%*s", pct_lsize, "", + pct, pct_rsize, ""); + if (use_color) { + /* Calculate the fill-width of progressbar */ + pwidth = pct * pbar_size / 100; + /* Round up based on one-tenth of a percent */ + if ((pct * pbar_size % 100) > 50) + pwidth++; + + /* + * Make two copies of pbar. Make one represent the fill + * and the other the remainder (cap). We'll insert the + * ANSI delimiter in between. + */ + *pbar_fill = '\0'; + *pbar_cap = '\0'; + strncat(pbar_fill, (const char *)(pbar), dwidth); + *(pbar_fill + pwidth) = '\0'; + strncat(pbar_cap, (const char *)(pbar+pwidth), dwidth); + + /* Finalize the mini [color] progressbar */ + snprintf(pbar, sizeof(pbar), + "\\Z%c\\Zr\\Z%c%s%s%s\\Zn", bold_code, color_code, + pbar_fill, "\\ZR", pbar_cap); + } + } + + for (fp = file_list; fp != NULL; fp = fp->next) { + flabel_size = label_size; + name = fp->name; + nthfile++; + + /* + * Support multiline filenames (where the filename is taken as + * the last line and the text leading up to the last line can + * be used as (for example) a heading/separator between files. + */ + if (use_dialog) + nls = dialog_prompt_nlstate(pprompt); + nlines += dialog_prompt_numlines(name, nls); + lastline = dialog_prompt_lastline(name, 1); + if (name != lastline) { + c = *lastline; + *lastline = '\0'; + dprompt_add("%s", name); + *lastline = c; + name = lastline; + } + + /* Support color codes (for dialog(1,3)) in file names */ + if ((use_dialog || use_libdialog) && use_color) { + cp = name; + while (*cp != '\0') { + if (*cp == '\\' && *(cp + 1) != '\0' && + *(++cp) == 'Z' && *(cp + 1) != '\0') { + cp++; + flabel_size += 3; + } + cp++; + } + if (flabel_size > FLABEL_MAX) + flabel_size = FLABEL_MAX; + } + + /* If no mini-progressbar, increase label width */ + if (pbar_size < 0 && flabel_size <= FLABEL_MAX - 2 && + no_labels == FALSE) + flabel_size += 2; + + /* If name is too long, add an ellipsis */ + if (snprintf(flabel, flabel_size + 1, "%s", name) > + flabel_size) sprintf(flabel + flabel_size - 3, "..."); + + /* + * Append the label (processing the current file differently) + */ + if (fp == curfile && pct < 100) { + /* + * Add an ellipsis to current file name if it will fit. + * There may be an ellipsis already from truncating the + * label (in which case, we already have one). + */ + cp = flabel + strlen(flabel); + if (cp < (flabel + flabel_size)) + snprintf(cp, flabel_size - + (cp - flabel) + 1, "..."); + + /* Append label (with spinner and optional color) */ + dprompt_add("%s%-*s%s %c", use_color ? "\\Zb" : "", + flabel_size, flabel, use_color ? "\\Zn" : "", + spin_char()); + } else + dprompt_add("%-*s%s %s", flabel_size, + flabel, use_color ? "\\Zn" : "", " "); + + /* + * Append pbar/status (processing the current file differently) + */ + dstate = DPROMPT_NONE; + if (fp->msg != NULL) + dstate = DPROMPT_CUSTOM_MSG; + else if (pbar_size < 0) + dstate = DPROMPT_NONE; + else if (pbar_size < 4) + dstate = DPROMPT_MINIMAL; + else if (after_curfile) + dstate = DPROMPT_PENDING; + else if (fp == curfile) { + if (*pbar == '\0') { + if (fp->length < 0) + dstate = DPROMPT_DETAILS; + else if (fp->status == DPV_STATUS_RUNNING) + dstate = DPROMPT_DETAILS; + else + dstate = DPROMPT_END_STATE; + } + else if (dialog_test) /* status/length ignored */ + dstate = pct < 100 ? + DPROMPT_PBAR : DPROMPT_END_STATE; + else if (fp->status == DPV_STATUS_RUNNING) + dstate = fp->length < 0 ? + DPROMPT_DETAILS : DPROMPT_PBAR; + else /* not running */ + dstate = fp->length < 0 ? + DPROMPT_DETAILS : DPROMPT_END_STATE; + } else { /* before curfile */ + if (dialog_test) + dstate = DPROMPT_END_STATE; + else + dstate = fp->length < 0 ? + DPROMPT_DETAILS : DPROMPT_END_STATE; + } + format = use_color ? + " [\\Z%c%s%-*s%s%-*s\\Zn]\\n" : + " [%-*s%s%-*s]\\n"; + if (fp->status == DPV_STATUS_FAILED) { + bg_code = "\\Zr\\Z1"; /* Red */ + estext_lsize = fail_lsize; + estext_rsize = fail_rsize; + estext = fail; + } else { /* e.g., DPV_STATUS_DONE */ + bg_code = "\\Zr\\Z2"; /* Green */ + estext_lsize = done_lsize; + estext_rsize = done_rsize; + estext = done; + } + switch (dstate) { + case DPROMPT_PENDING: /* Future file(s) */ + dprompt_add(" [%-*s%s%-*s]\\n", + pend_lsize, "", pend, pend_rsize, ""); + break; + case DPROMPT_PBAR: /* Current file */ + dprompt_add(" [%s]\\n", pbar); + break; + case DPROMPT_END_STATE: /* Past/Current file(s) */ + if (use_color) + dprompt_add(format, bold_code, bg_code, + estext_lsize, "", estext, + estext_rsize, ""); + else + dprompt_add(format, + estext_lsize, "", estext, + estext_rsize, ""); + break; + case DPROMPT_DETAILS: /* Past/Current file(s) */ + humanize_number(human, pbar_size + 2, fp->read, "", + HN_AUTOSCALE, HN_NOSPACE | HN_DIVISOR_1000); + + /* Calculate center alignment */ + hlen = (int)strlen(human); + lsize = (pbar_size - hlen) / 2; + rsize = lsize; + if ((lsize+hlen+rsize) != pbar_size) + rsize++; + + if (use_color) + dprompt_add(format, bold_code, bg_code, + lsize, "", human, rsize, ""); + else + dprompt_add(format, + lsize, "", human, rsize, ""); + break; + case DPROMPT_CUSTOM_MSG: /* File-specific message override */ + snprintf(msg, PROMPT_MAX + 1, "%s", fp->msg); + if (pbar_size < (mesg_size = strlen(msg))) { + mesg_lsize = mesg_rsize = 0; + *(msg + pbar_size) = '\0'; + mesg_size = pbar_size; + } else { + mesg_lsize = (pbar_size - mesg_size) / 2; + mesg_rsize = mesg_lsize; + if ((mesg_rsize + mesg_size + mesg_lsize) + != pbar_size) + mesg_rsize++; + } + if (use_color) + dprompt_add(format, bold_code, bg_code, + mesg_lsize, "", msg, mesg_rsize, ""); + else + dprompt_add(format, mesg_lsize, "", msg, + mesg_rsize, ""); + break; + case DPROMPT_MINIMAL: /* Short progress bar, minimal room */ + if (use_color) + dprompt_add(format, bold_code, bg_code, + pbar_size, "", "", 0, ""); + else + dprompt_add(format, pbar_size, "", "", 0, ""); + break; + case DPROMPT_NONE: /* pbar_size < 0 */ + /* FALLTHROUGH */ + default: + dprompt_add(" \\n"); + /* + * NB: Leading space required for the case when + * spin_char() returns a single backslash [\] which + * without the space, changes the meaning of `\n' + */ + } + + /* Stop building if we've hit the internal limit */ + if (nthfile >= display_limit) + break; + + /* If this is the current file, all others are pending */ + if (fp == curfile) + after_curfile = TRUE; + } + + /* + * Since we cannot change the height/width of the [X]dialog(1) widget + * after spawn, to make things look nice let's pad the height so that + * the `-a text' always appears in the same spot. + * + * NOTE: fheight is calculated in dprompt_init(). It represents the + * maximum height required to display the set of items (broken up into + * pieces of display_limit chunks) whose names contain the most + * newlines for any given set. + */ + while (nlines < fheight) { + dprompt_add("\n"); + nlines++; + } + + return (nthfile); +} + +/* + * Process the dpv_file_node linked-list of named files, re-generating the + * [X]dialog(1) `--gauge' prompt text for the current state of transfers. + */ +void +dprompt_recreate(struct dpv_file_node *file_list, + struct dpv_file_node *curfile, int pct) +{ + size_t len; + + /* + * Re-Build the prompt text + */ + dprompt_clear(); + if (display_limit > 0) + dprompt_add_files(file_list, curfile, pct); + + /* Xdialog(1) requires newlines (a) escaped and (b) in triplicate */ + if (use_xdialog) { + /* Replace `\n' with `\n\\n\n' in dprompt */ + len = strlen(dprompt); + len += strcount(dprompt, "\\n") * 5; /* +5 chars per count */ + if (len > PROMPT_MAX) + errx(EXIT_FAILURE, "%s: Oops, dprompt buffer overflow " + "(%zu > %i)", __func__, len, PROMPT_MAX); + if (replaceall(dprompt, "\\n", "\n\\n\n") < 0) + err(EXIT_FAILURE, "%s: replaceall()", __func__); + } + else if (use_libdialog) + strexpandnl(dprompt); +} + +/* + * Print the [X]dialog(1) `--gauge' prompt text to a buffer. + */ +int +dprompt_sprint(char * restrict str, const char *prefix, const char *append) +{ + + return (snprintf(str, PROMPT_MAX, "%s%s%s%s", use_color ? "\\Zn" : "", + prefix ? prefix : "", dprompt, append ? append : "")); +} + +/* + * Print the [X]dialog(1) `--gauge' prompt text to file descriptor fd (could + * be STDOUT_FILENO or a pipe(2) file descriptor to actual [X]dialog(1)). + */ +void +dprompt_dprint(int fd, const char *prefix, const char *append, int overall) +{ + int percent = gauge_percent; + + if (overall >= 0 && overall <= 100) + gauge_percent = percent = overall; + dprintf(fd, "XXX\n%s%s%s%s\nXXX\n%i\n", use_color ? "\\Zn" : "", + prefix ? prefix : "", dprompt, append ? append : "", percent); + fsync(fd); +} + +/* + * Print the dialog(3) `gauge' prompt text using libdialog. + */ +void +dprompt_libprint(const char *prefix, const char *append, int overall) +{ + int percent = gauge_percent; + char buf[DPV_PPROMPT_MAX + DPV_APROMPT_MAX + DPV_DISPLAY_LIMIT * 1024]; + + dprompt_sprint(buf, prefix, append); + + if (overall >= 0 && overall <= 100) + gauge_percent = percent = overall; + gauge = dlg_reallocate_gauge(gauge, title == NULL ? "" : title, + buf, dheight, dwidth, percent); + dlg_update_gauge(gauge, percent); +} + +/* + * Free allocated items initialized by dprompt_init() + */ +void +dprompt_free(void) +{ + if ((dprompt_free_mask & FM_DONE) != 0) { + dprompt_free_mask ^= FM_DONE; + free(done); + done = NULL; + } + if ((dprompt_free_mask & FM_FAIL) != 0) { + dprompt_free_mask ^= FM_FAIL; + free(fail); + fail = NULL; + } + if ((dprompt_free_mask & FM_PEND) != 0) { + dprompt_free_mask ^= FM_PEND; + free(pend); + pend = NULL; + } +} |