xref: /freebsd/contrib/dialog/guage.c (revision a96ef4501919d7ac08e94e98dc34b0bdd744802b)
14c8945a0SNathan Whitehorn /*
2*a96ef450SBaptiste Daroussin  *  $Id: guage.c,v 1.83 2020/03/27 20:54:43 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  guage.c -- implements the gauge dialog
54c8945a0SNathan Whitehorn  *
6*a96ef450SBaptiste Daroussin  *  Copyright 2000-2019,2020	Thomas E. Dickey
74c8945a0SNathan Whitehorn  *
84c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
94c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
104c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
114c8945a0SNathan Whitehorn  *
124c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
134c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
144c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
154c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
164c8945a0SNathan Whitehorn  *
174c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
184c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
194c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
204c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
214c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
224c8945a0SNathan Whitehorn  *
234c8945a0SNathan Whitehorn  *  An earlier version of this program lists as authors
244c8945a0SNathan Whitehorn  *	Marc Ewing, Red Hat Software
254c8945a0SNathan Whitehorn  */
264c8945a0SNathan Whitehorn 
274c8945a0SNathan Whitehorn #include <dialog.h>
284c8945a0SNathan Whitehorn 
294c8945a0SNathan Whitehorn #include <errno.h>
304c8945a0SNathan Whitehorn 
314c8945a0SNathan Whitehorn #define MY_LEN (MAX_LEN)/2
324c8945a0SNathan Whitehorn 
334c8945a0SNathan Whitehorn #define MIN_HIGH (4)
344c8945a0SNathan Whitehorn #define MIN_WIDE (10 + 2 * (2 + MARGIN))
354c8945a0SNathan Whitehorn 
367a1c0d96SNathan Whitehorn #define isMarker(buf) !strncmp(buf, "XXX", (size_t) 3)
374c8945a0SNathan Whitehorn 
38682c9e0fSNathan Whitehorn typedef struct _my_obj {
39682c9e0fSNathan Whitehorn     DIALOG_CALLBACK obj;	/* has to be first in struct */
40682c9e0fSNathan Whitehorn     struct _my_obj *next;
414c8945a0SNathan Whitehorn     WINDOW *text;
42febdb468SDevin Teske     char *title;
434c8945a0SNathan Whitehorn     char *prompt;
444c8945a0SNathan Whitehorn     char prompt_buf[MY_LEN];
454c8945a0SNathan Whitehorn     int percent;
464c8945a0SNathan Whitehorn     int height;
474c8945a0SNathan Whitehorn     int width;
484c8945a0SNathan Whitehorn     char line[MAX_LEN + 1];
494c8945a0SNathan Whitehorn } MY_OBJ;
504c8945a0SNathan Whitehorn 
51682c9e0fSNathan Whitehorn static MY_OBJ *all_objects;
52682c9e0fSNathan Whitehorn 
53682c9e0fSNathan Whitehorn static int
valid(MY_OBJ * obj)54682c9e0fSNathan Whitehorn valid(MY_OBJ * obj)
55682c9e0fSNathan Whitehorn {
56682c9e0fSNathan Whitehorn     MY_OBJ *list = all_objects;
57682c9e0fSNathan Whitehorn     int result = 0;
58682c9e0fSNathan Whitehorn 
59682c9e0fSNathan Whitehorn     while (list != 0) {
60682c9e0fSNathan Whitehorn 	if (list == obj) {
61682c9e0fSNathan Whitehorn 	    result = 1;
62682c9e0fSNathan Whitehorn 	    break;
63682c9e0fSNathan Whitehorn 	}
64682c9e0fSNathan Whitehorn 	list = list->next;
65682c9e0fSNathan Whitehorn     }
66682c9e0fSNathan Whitehorn     return result;
67682c9e0fSNathan Whitehorn }
68682c9e0fSNathan Whitehorn 
69682c9e0fSNathan Whitehorn static void
delink(MY_OBJ * obj)70682c9e0fSNathan Whitehorn delink(MY_OBJ * obj)
71682c9e0fSNathan Whitehorn {
72682c9e0fSNathan Whitehorn     MY_OBJ *p = all_objects;
73682c9e0fSNathan Whitehorn     MY_OBJ *q = 0;
74682c9e0fSNathan Whitehorn     while (p != 0) {
75682c9e0fSNathan Whitehorn 	if (p == obj) {
76682c9e0fSNathan Whitehorn 	    if (q != 0) {
77682c9e0fSNathan Whitehorn 		q->next = p->next;
78682c9e0fSNathan Whitehorn 	    } else {
79682c9e0fSNathan Whitehorn 		all_objects = p->next;
80682c9e0fSNathan Whitehorn 	    }
81682c9e0fSNathan Whitehorn 	    break;
82682c9e0fSNathan Whitehorn 	}
83682c9e0fSNathan Whitehorn 	q = p;
84682c9e0fSNathan Whitehorn 	p = p->next;
85682c9e0fSNathan Whitehorn     }
86682c9e0fSNathan Whitehorn }
87682c9e0fSNathan Whitehorn 
884c8945a0SNathan Whitehorn static int
read_data(char * buffer,FILE * fp)894c8945a0SNathan Whitehorn read_data(char *buffer, FILE *fp)
904c8945a0SNathan Whitehorn {
914c8945a0SNathan Whitehorn     int result;
924c8945a0SNathan Whitehorn 
934c8945a0SNathan Whitehorn     if (feof(fp)) {
944c8945a0SNathan Whitehorn 	result = 0;
954c8945a0SNathan Whitehorn     } else if (fgets(buffer, MY_LEN, fp) != 0) {
96682c9e0fSNathan Whitehorn 	DLG_TRACE(("read_data:%s", buffer));
972a3e3873SBaptiste Daroussin 	buffer[MY_LEN] = '\0';
984c8945a0SNathan Whitehorn 	dlg_trim_string(buffer);
994c8945a0SNathan Whitehorn 	result = 1;
1004c8945a0SNathan Whitehorn     } else {
1014c8945a0SNathan Whitehorn 	result = -1;
1024c8945a0SNathan Whitehorn     }
1034c8945a0SNathan Whitehorn     return result;
1044c8945a0SNathan Whitehorn }
1054c8945a0SNathan Whitehorn 
1064c8945a0SNathan Whitehorn static int
decode_percent(char * buffer)1074c8945a0SNathan Whitehorn decode_percent(char *buffer)
1084c8945a0SNathan Whitehorn {
1094c8945a0SNathan Whitehorn     char *tmp = 0;
1104c8945a0SNathan Whitehorn     long value = strtol(buffer, &tmp, 10);
1114c8945a0SNathan Whitehorn 
1124c8945a0SNathan Whitehorn     if (tmp != 0 && (*tmp == 0 || isspace(UCH(*tmp))) && value >= 0) {
1134c8945a0SNathan Whitehorn 	return TRUE;
1144c8945a0SNathan Whitehorn     }
1154c8945a0SNathan Whitehorn     return FALSE;
1164c8945a0SNathan Whitehorn }
1174c8945a0SNathan Whitehorn 
1184c8945a0SNathan Whitehorn static void
repaint_text(MY_OBJ * obj)1194c8945a0SNathan Whitehorn repaint_text(MY_OBJ * obj)
1204c8945a0SNathan Whitehorn {
1214c8945a0SNathan Whitehorn     WINDOW *dialog = obj->obj.win;
1224c8945a0SNathan Whitehorn 
123f4f33ea0SBaptiste Daroussin     if (dialog != 0) {
124*a96ef450SBaptiste Daroussin 	int i, x;
125*a96ef450SBaptiste Daroussin 
1264c8945a0SNathan Whitehorn 	(void) werase(dialog);
1272a3e3873SBaptiste Daroussin 	dlg_draw_box2(dialog, 0, 0, obj->height, obj->width, dialog_attr,
1282a3e3873SBaptiste Daroussin 		      border_attr, border2_attr);
1294c8945a0SNathan Whitehorn 
1304c8945a0SNathan Whitehorn 	dlg_draw_title(dialog, obj->title);
1314c8945a0SNathan Whitehorn 
132f4f33ea0SBaptiste Daroussin 	dlg_attrset(dialog, dialog_attr);
133682c9e0fSNathan Whitehorn 	dlg_draw_helpline(dialog, FALSE);
1344c8945a0SNathan Whitehorn 	dlg_print_autowrap(dialog, obj->prompt, obj->height, obj->width);
1354c8945a0SNathan Whitehorn 
1362a3e3873SBaptiste Daroussin 	dlg_draw_box2(dialog,
1374c8945a0SNathan Whitehorn 		      obj->height - 4, 2 + MARGIN,
1384c8945a0SNathan Whitehorn 		      2 + MARGIN, obj->width - 2 * (2 + MARGIN),
1394c8945a0SNathan Whitehorn 		      dialog_attr,
1402a3e3873SBaptiste Daroussin 		      border_attr,
1412a3e3873SBaptiste Daroussin 		      border2_attr);
1424c8945a0SNathan Whitehorn 
1434c8945a0SNathan Whitehorn 	/*
1444c8945a0SNathan Whitehorn 	 * Clear the area for the progress bar by filling it with spaces
1452a3e3873SBaptiste Daroussin 	 * in the gauge-attribute, and write the percentage with that
1464c8945a0SNathan Whitehorn 	 * attribute.
1474c8945a0SNathan Whitehorn 	 */
1484c8945a0SNathan Whitehorn 	(void) wmove(dialog, obj->height - 3, 4);
149f4f33ea0SBaptiste Daroussin 	dlg_attrset(dialog, gauge_attr);
1504c8945a0SNathan Whitehorn 
1514c8945a0SNathan Whitehorn 	for (i = 0; i < (obj->width - 2 * (3 + MARGIN)); i++)
1524c8945a0SNathan Whitehorn 	    (void) waddch(dialog, ' ');
1534c8945a0SNathan Whitehorn 
1544c8945a0SNathan Whitehorn 	(void) wmove(dialog, obj->height - 3, (obj->width / 2) - 2);
1554c8945a0SNathan Whitehorn 	(void) wprintw(dialog, "%3d%%", obj->percent);
1564c8945a0SNathan Whitehorn 
1574c8945a0SNathan Whitehorn 	/*
1584c8945a0SNathan Whitehorn 	 * Now draw a bar in reverse, relative to the background.
1594c8945a0SNathan Whitehorn 	 * The window attribute was useful for painting the background,
1604c8945a0SNathan Whitehorn 	 * but requires some tweaks to reverse it.
1614c8945a0SNathan Whitehorn 	 */
1624c8945a0SNathan Whitehorn 	x = (obj->percent * (obj->width - 2 * (3 + MARGIN))) / 100;
1632a3e3873SBaptiste Daroussin 	if ((gauge_attr & A_REVERSE) != 0) {
164f4f33ea0SBaptiste Daroussin 	    dlg_attroff(dialog, A_REVERSE);
1654c8945a0SNathan Whitehorn 	} else {
166f4f33ea0SBaptiste Daroussin 	    dlg_attrset(dialog, A_REVERSE);
1674c8945a0SNathan Whitehorn 	}
1684c8945a0SNathan Whitehorn 	(void) wmove(dialog, obj->height - 3, 4);
1694c8945a0SNathan Whitehorn 	for (i = 0; i < x; i++) {
1704c8945a0SNathan Whitehorn 	    chtype ch2 = winch(dialog);
1712a3e3873SBaptiste Daroussin 	    if (gauge_attr & A_REVERSE) {
1724c8945a0SNathan Whitehorn 		ch2 &= ~A_REVERSE;
1734c8945a0SNathan Whitehorn 	    }
1744c8945a0SNathan Whitehorn 	    (void) waddch(dialog, ch2);
1754c8945a0SNathan Whitehorn 	}
1764c8945a0SNathan Whitehorn 
1774c8945a0SNathan Whitehorn 	(void) wrefresh(dialog);
1784c8945a0SNathan Whitehorn     }
1797a1c0d96SNathan Whitehorn }
1804c8945a0SNathan Whitehorn 
1817a1c0d96SNathan Whitehorn static bool
handle_input(DIALOG_CALLBACK * cb)1827a1c0d96SNathan Whitehorn handle_input(DIALOG_CALLBACK * cb)
1834c8945a0SNathan Whitehorn {
1847a1c0d96SNathan Whitehorn     MY_OBJ *obj = (MY_OBJ *) cb;
1857a1c0d96SNathan Whitehorn     bool result;
186f4f33ea0SBaptiste Daroussin     bool cleanup = FALSE;
1874c8945a0SNathan Whitehorn     int status;
1882a3e3873SBaptiste Daroussin     char buf[MY_LEN + 1];
1894c8945a0SNathan Whitehorn 
1907a1c0d96SNathan Whitehorn     if (dialog_state.pipe_input == 0) {
1917a1c0d96SNathan Whitehorn 	status = -1;
192f4f33ea0SBaptiste Daroussin 	cleanup = TRUE;
1937a1c0d96SNathan Whitehorn     } else if ((status = read_data(buf, dialog_state.pipe_input)) > 0) {
1944c8945a0SNathan Whitehorn 
1954c8945a0SNathan Whitehorn 	if (isMarker(buf)) {
1964c8945a0SNathan Whitehorn 	    /*
1974c8945a0SNathan Whitehorn 	     * Historically, next line should be percentage, but one of the
1984c8945a0SNathan Whitehorn 	     * worse-written clones of 'dialog' assumes the number is missing.
1994c8945a0SNathan Whitehorn 	     * (Gresham's Law applied to software).
2004c8945a0SNathan Whitehorn 	     */
2014c8945a0SNathan Whitehorn 	    if ((status = read_data(buf, dialog_state.pipe_input)) > 0) {
2024c8945a0SNathan Whitehorn 
2034c8945a0SNathan Whitehorn 		obj->prompt_buf[0] = '\0';
2044c8945a0SNathan Whitehorn 		if (decode_percent(buf))
2054c8945a0SNathan Whitehorn 		    obj->percent = atoi(buf);
2064c8945a0SNathan Whitehorn 		else
2074c8945a0SNathan Whitehorn 		    strcpy(obj->prompt_buf, buf);
2084c8945a0SNathan Whitehorn 
2094c8945a0SNathan Whitehorn 		/* Rest is message text */
2104c8945a0SNathan Whitehorn 		while ((status = read_data(buf, dialog_state.pipe_input)) > 0
2114c8945a0SNathan Whitehorn 		       && !isMarker(buf)) {
2124c8945a0SNathan Whitehorn 		    if (strlen(obj->prompt_buf) + strlen(buf) <
2134c8945a0SNathan Whitehorn 			sizeof(obj->prompt_buf) - 1) {
2144c8945a0SNathan Whitehorn 			strcat(obj->prompt_buf, buf);
2154c8945a0SNathan Whitehorn 		    }
2164c8945a0SNathan Whitehorn 		}
2174c8945a0SNathan Whitehorn 
2184c8945a0SNathan Whitehorn 		if (obj->prompt != obj->prompt_buf)
2194c8945a0SNathan Whitehorn 		    free(obj->prompt);
2204c8945a0SNathan Whitehorn 		obj->prompt = obj->prompt_buf;
2214c8945a0SNathan Whitehorn 	    }
2224c8945a0SNathan Whitehorn 	} else if (decode_percent(buf)) {
2234c8945a0SNathan Whitehorn 	    obj->percent = atoi(buf);
2244c8945a0SNathan Whitehorn 	}
2254c8945a0SNathan Whitehorn     } else {
2267a1c0d96SNathan Whitehorn 	if (feof(dialog_state.pipe_input) ||
2277a1c0d96SNathan Whitehorn 	    (ferror(dialog_state.pipe_input) && errno != EINTR)) {
228f4f33ea0SBaptiste Daroussin 	    cleanup = TRUE;
2297a1c0d96SNathan Whitehorn 	}
2304c8945a0SNathan Whitehorn     }
2314c8945a0SNathan Whitehorn 
232f4f33ea0SBaptiste Daroussin     repaint_text(obj);
2337a1c0d96SNathan Whitehorn     if (status > 0) {
2347a1c0d96SNathan Whitehorn 	result = TRUE;
2357a1c0d96SNathan Whitehorn     } else {
2367a1c0d96SNathan Whitehorn 	result = FALSE;
237f4f33ea0SBaptiste Daroussin 	if (cleanup) {
238f4f33ea0SBaptiste Daroussin 	    dlg_remove_callback(cb);
239f4f33ea0SBaptiste Daroussin 	    delink(obj);
240f4f33ea0SBaptiste Daroussin 	}
2417a1c0d96SNathan Whitehorn     }
2427a1c0d96SNathan Whitehorn 
2437a1c0d96SNathan Whitehorn     return result;
2444c8945a0SNathan Whitehorn }
2454c8945a0SNathan Whitehorn 
2464c8945a0SNathan Whitehorn static bool
handle_my_getc(DIALOG_CALLBACK * cb,int ch,int fkey,int * result)2474c8945a0SNathan Whitehorn handle_my_getc(DIALOG_CALLBACK * cb, int ch, int fkey, int *result)
2484c8945a0SNathan Whitehorn {
249f4f33ea0SBaptiste Daroussin     bool status = TRUE;
2504c8945a0SNathan Whitehorn 
2514c8945a0SNathan Whitehorn     *result = DLG_EXIT_OK;
2527a1c0d96SNathan Whitehorn     if (cb != 0) {
2534c8945a0SNathan Whitehorn 	if (!fkey && (ch == ERR)) {
2547a1c0d96SNathan Whitehorn 	    (void) handle_input(cb);
255682c9e0fSNathan Whitehorn 	    /* cb might be freed in handle_input */
256682c9e0fSNathan Whitehorn 	    status = (valid((MY_OBJ *) cb) && (cb->input != 0));
2574c8945a0SNathan Whitehorn 	}
2584c8945a0SNathan Whitehorn     } else {
2594c8945a0SNathan Whitehorn 	status = FALSE;
2604c8945a0SNathan Whitehorn     }
2614c8945a0SNathan Whitehorn     return status;
2624c8945a0SNathan Whitehorn }
2634c8945a0SNathan Whitehorn 
2644c8945a0SNathan Whitehorn static void
my_cleanup(DIALOG_CALLBACK * cb)2654c8945a0SNathan Whitehorn my_cleanup(DIALOG_CALLBACK * cb)
2664c8945a0SNathan Whitehorn {
2674c8945a0SNathan Whitehorn     MY_OBJ *obj = (MY_OBJ *) cb;
2684c8945a0SNathan Whitehorn 
269682c9e0fSNathan Whitehorn     if (valid(obj)) {
270682c9e0fSNathan Whitehorn 	if (obj->prompt != obj->prompt_buf) {
2714c8945a0SNathan Whitehorn 	    free(obj->prompt);
272682c9e0fSNathan Whitehorn 	    obj->prompt = obj->prompt_buf;
273682c9e0fSNathan Whitehorn 	}
274f4f33ea0SBaptiste Daroussin 	free(obj->title);
275f4f33ea0SBaptiste Daroussin 	dlg_del_window(obj->obj.win);
276682c9e0fSNathan Whitehorn 	delink(obj);
277682c9e0fSNathan Whitehorn     }
278682c9e0fSNathan Whitehorn }
279682c9e0fSNathan Whitehorn 
280682c9e0fSNathan Whitehorn void
dlg_update_gauge(void * objptr,int percent)281682c9e0fSNathan Whitehorn dlg_update_gauge(void *objptr, int percent)
282682c9e0fSNathan Whitehorn {
283682c9e0fSNathan Whitehorn     MY_OBJ *obj = (MY_OBJ *) objptr;
284febdb468SDevin Teske     bool save_finish_string = dialog_state.finish_string;
285682c9e0fSNathan Whitehorn 
286febdb468SDevin Teske     dialog_state.finish_string = TRUE;
287682c9e0fSNathan Whitehorn     curs_set(0);
288682c9e0fSNathan Whitehorn     obj->percent = percent;
289682c9e0fSNathan Whitehorn     repaint_text(obj);
290febdb468SDevin Teske     dialog_state.finish_string = save_finish_string;
291682c9e0fSNathan Whitehorn }
292682c9e0fSNathan Whitehorn 
293682c9e0fSNathan Whitehorn /*
294febdb468SDevin Teske  * (Re)Allocates an object and fills it as per the arguments
295682c9e0fSNathan Whitehorn  */
296682c9e0fSNathan Whitehorn void *
dlg_reallocate_gauge(void * objptr,const char * title,const char * cprompt,int height,int width,int percent)297febdb468SDevin Teske dlg_reallocate_gauge(void *objptr,
298febdb468SDevin Teske 		     const char *title,
299febdb468SDevin Teske 		     const char *cprompt,
300febdb468SDevin Teske 		     int height,
301febdb468SDevin Teske 		     int width,
302febdb468SDevin Teske 		     int percent)
303febdb468SDevin Teske {
304febdb468SDevin Teske     char *prompt = dlg_strclone(cprompt);
305*a96ef450SBaptiste Daroussin     MY_OBJ *obj;
306febdb468SDevin Teske     bool save_finish_string = dialog_state.finish_string;
307febdb468SDevin Teske 
308febdb468SDevin Teske     dialog_state.finish_string = TRUE;
309febdb468SDevin Teske     dlg_tab_correct_str(prompt);
310febdb468SDevin Teske 
311febdb468SDevin Teske     if (objptr == 0) {
312febdb468SDevin Teske 	/* create a new object */
313febdb468SDevin Teske 	obj = dlg_calloc(MY_OBJ, 1);
314febdb468SDevin Teske 	assert_ptr(obj, "dialog_gauge");
315febdb468SDevin Teske 
316febdb468SDevin Teske 	dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, MIN_WIDE);
317febdb468SDevin Teske 	dlg_print_size(height, width);
318febdb468SDevin Teske 	dlg_ctl_size(height, width);
319febdb468SDevin Teske 
320febdb468SDevin Teske     } else {
321febdb468SDevin Teske 	/* reuse an existing object */
322febdb468SDevin Teske 	obj = objptr;
323febdb468SDevin Teske 	height = obj->height;
324febdb468SDevin Teske 	width = obj->width;
325febdb468SDevin Teske     }
326febdb468SDevin Teske 
327febdb468SDevin Teske     if (obj->obj.win == 0) {
328febdb468SDevin Teske 	/* center dialog box on screen */
329febdb468SDevin Teske 	int x = dlg_box_x_ordinate(width);
330febdb468SDevin Teske 	int y = dlg_box_y_ordinate(height);
331febdb468SDevin Teske 	WINDOW *dialog = dlg_new_window(height, width, y, x);
332febdb468SDevin Teske 	obj->obj.win = dialog;
333febdb468SDevin Teske     }
334febdb468SDevin Teske 
335febdb468SDevin Teske     obj->obj.input = dialog_state.pipe_input;
336febdb468SDevin Teske     obj->obj.keep_win = TRUE;
337febdb468SDevin Teske     obj->obj.bg_task = TRUE;
338febdb468SDevin Teske     obj->obj.handle_getc = handle_my_getc;
339febdb468SDevin Teske     obj->obj.handle_input = handle_input;
340febdb468SDevin Teske 
341febdb468SDevin Teske     if (obj->title == 0 || strcmp(obj->title, title)) {
342febdb468SDevin Teske 	dlg_finish_string(obj->title);
343febdb468SDevin Teske 	free(obj->title);
344febdb468SDevin Teske 	obj->title = dlg_strclone(title);
345febdb468SDevin Teske     }
346febdb468SDevin Teske 
347febdb468SDevin Teske     dlg_finish_string(obj->prompt);
348febdb468SDevin Teske     free(obj->prompt);
349febdb468SDevin Teske 
350febdb468SDevin Teske     obj->prompt = prompt;
351febdb468SDevin Teske     obj->percent = percent;
352febdb468SDevin Teske     obj->height = height;
353febdb468SDevin Teske     obj->width = width;
354febdb468SDevin Teske 
355febdb468SDevin Teske     /* if this was a new object, link it into the list */
356febdb468SDevin Teske     if (objptr == 0) {
357febdb468SDevin Teske 	obj->next = all_objects;
358febdb468SDevin Teske 	all_objects = obj;
359febdb468SDevin Teske     }
360febdb468SDevin Teske 
361febdb468SDevin Teske     dialog_state.finish_string = save_finish_string;
362febdb468SDevin Teske     return (void *) obj;
363febdb468SDevin Teske }
364febdb468SDevin Teske 
365febdb468SDevin Teske void *
dlg_allocate_gauge(const char * title,const char * cprompt,int height,int width,int percent)366682c9e0fSNathan Whitehorn dlg_allocate_gauge(const char *title,
367682c9e0fSNathan Whitehorn 		   const char *cprompt,
368682c9e0fSNathan Whitehorn 		   int height,
369682c9e0fSNathan Whitehorn 		   int width,
370682c9e0fSNathan Whitehorn 		   int percent)
371682c9e0fSNathan Whitehorn {
372febdb468SDevin Teske     return dlg_reallocate_gauge(NULL, title, cprompt, height, width, percent);
373682c9e0fSNathan Whitehorn }
374682c9e0fSNathan Whitehorn 
375682c9e0fSNathan Whitehorn void
dlg_free_gauge(void * objptr)376682c9e0fSNathan Whitehorn dlg_free_gauge(void *objptr)
377682c9e0fSNathan Whitehorn {
378682c9e0fSNathan Whitehorn     MY_OBJ *obj = (MY_OBJ *) objptr;
379682c9e0fSNathan Whitehorn 
380682c9e0fSNathan Whitehorn     if (valid(obj)) {
381*a96ef450SBaptiste Daroussin 	if (obj->title)
382*a96ef450SBaptiste Daroussin 	    free(obj->title);
383*a96ef450SBaptiste Daroussin 	if (obj->prompt)
384*a96ef450SBaptiste Daroussin 	    free(obj->prompt);
385682c9e0fSNathan Whitehorn 	obj->obj.keep_win = FALSE;
386682c9e0fSNathan Whitehorn 	dlg_remove_callback(&(obj->obj));
387f4f33ea0SBaptiste Daroussin 	delink(obj);
3884c8945a0SNathan Whitehorn     }
389f4f33ea0SBaptiste Daroussin     curs_set(1);
3904c8945a0SNathan Whitehorn }
3914c8945a0SNathan Whitehorn 
3924c8945a0SNathan Whitehorn /*
3934c8945a0SNathan Whitehorn  * Display a gauge, or progress meter.  Starts at percent% and reads stdin.  If
3944c8945a0SNathan Whitehorn  * stdin is not XXX, then it is interpreted as a percentage, and the display is
3954c8945a0SNathan Whitehorn  * updated accordingly.  Otherwise the next line is the percentage, and
3964c8945a0SNathan Whitehorn  * subsequent lines up to another XXX are used for the new prompt.  Note that
3974c8945a0SNathan Whitehorn  * the size of the window never changes, so the prompt can not get any larger
3984c8945a0SNathan Whitehorn  * than the height and width specified.
3994c8945a0SNathan Whitehorn  */
4004c8945a0SNathan Whitehorn int
dialog_gauge(const char * title,const char * cprompt,int height,int width,int percent)4014c8945a0SNathan Whitehorn dialog_gauge(const char *title,
4024c8945a0SNathan Whitehorn 	     const char *cprompt,
4034c8945a0SNathan Whitehorn 	     int height,
4044c8945a0SNathan Whitehorn 	     int width,
4054c8945a0SNathan Whitehorn 	     int percent)
4064c8945a0SNathan Whitehorn {
4074c8945a0SNathan Whitehorn     int fkey;
4084c8945a0SNathan Whitehorn     int ch, result;
409682c9e0fSNathan Whitehorn     void *objptr = dlg_allocate_gauge(title, cprompt, height, width, percent);
410682c9e0fSNathan Whitehorn     MY_OBJ *obj = (MY_OBJ *) objptr;
4114c8945a0SNathan Whitehorn 
412f4f33ea0SBaptiste Daroussin     DLG_TRACE(("# gauge args:\n"));
413f4f33ea0SBaptiste Daroussin     DLG_TRACE2S("title", title);
414f4f33ea0SBaptiste Daroussin     DLG_TRACE2S("message", cprompt);
415f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("height", height);
416f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("width", width);
417f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("percent", percent);
418f4f33ea0SBaptiste Daroussin 
419682c9e0fSNathan Whitehorn     dlg_add_callback_ref((DIALOG_CALLBACK **) & obj, my_cleanup);
420682c9e0fSNathan Whitehorn     dlg_update_gauge(obj, percent);
4214c8945a0SNathan Whitehorn 
4222a3e3873SBaptiste Daroussin     dlg_trace_win(obj->obj.win);
4234c8945a0SNathan Whitehorn     do {
424682c9e0fSNathan Whitehorn 	ch = dlg_getc(obj->obj.win, &fkey);
4254c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
4264c8945a0SNathan Whitehorn 	if (fkey && ch == KEY_RESIZE) {
427682c9e0fSNathan Whitehorn 	    MY_OBJ *oldobj = obj;
428682c9e0fSNathan Whitehorn 
429f4f33ea0SBaptiste Daroussin 	    dlg_will_resize(obj->obj.win);
430682c9e0fSNathan Whitehorn 
431682c9e0fSNathan Whitehorn 	    obj = dlg_allocate_gauge(title,
432682c9e0fSNathan Whitehorn 				     cprompt,
433682c9e0fSNathan Whitehorn 				     height,
434682c9e0fSNathan Whitehorn 				     width,
435682c9e0fSNathan Whitehorn 				     oldobj->percent);
436682c9e0fSNathan Whitehorn 
437682c9e0fSNathan Whitehorn 	    /* avoid breaking new window in dlg_remove_callback */
438682c9e0fSNathan Whitehorn 	    oldobj->obj.caller = 0;
439682c9e0fSNathan Whitehorn 	    oldobj->obj.input = 0;
440682c9e0fSNathan Whitehorn 	    oldobj->obj.keep_win = FALSE;
441682c9e0fSNathan Whitehorn 
442682c9e0fSNathan Whitehorn 	    /* remove the old version of the gauge */
443*a96ef450SBaptiste Daroussin 	    _dlg_resize_cleanup(oldobj->obj.win);
444682c9e0fSNathan Whitehorn 	    dlg_remove_callback(&(oldobj->obj));
445682c9e0fSNathan Whitehorn 
446682c9e0fSNathan Whitehorn 	    dlg_add_callback_ref((DIALOG_CALLBACK **) & obj, my_cleanup);
447682c9e0fSNathan Whitehorn 	    dlg_update_gauge(obj, obj->percent);
4484c8945a0SNathan Whitehorn 	}
4494c8945a0SNathan Whitehorn #endif
4504c8945a0SNathan Whitehorn     }
451682c9e0fSNathan Whitehorn     while (valid(obj) && handle_my_getc(&(obj->obj), ch, fkey, &result));
4524c8945a0SNathan Whitehorn 
453682c9e0fSNathan Whitehorn     dlg_free_gauge(obj);
4544c8945a0SNathan Whitehorn 
4554c8945a0SNathan Whitehorn     return (DLG_EXIT_OK);
4564c8945a0SNathan Whitehorn }
457