summaryrefslogtreecommitdiffstats
path: root/contrib/dialog/guage.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/dialog/guage.c')
-rw-r--r--contrib/dialog/guage.c210
1 files changed, 147 insertions, 63 deletions
diff --git a/contrib/dialog/guage.c b/contrib/dialog/guage.c
index d12bc21..b25052f 100644
--- a/contrib/dialog/guage.c
+++ b/contrib/dialog/guage.c
@@ -1,5 +1,5 @@
/*
- * $Id: guage.c,v 1.52 2011/01/17 10:39:28 tom Exp $
+ * $Id: guage.c,v 1.60 2011/06/27 00:52:28 tom Exp $
*
* guage.c -- implements the gauge dialog
*
@@ -35,8 +35,9 @@
#define isMarker(buf) !strncmp(buf, "XXX", (size_t) 3)
-typedef struct {
- DIALOG_CALLBACK obj;
+typedef struct _my_obj {
+ DIALOG_CALLBACK obj; /* has to be first in struct */
+ struct _my_obj *next;
WINDOW *text;
const char *title;
char *prompt;
@@ -47,6 +48,43 @@ typedef struct {
char line[MAX_LEN + 1];
} MY_OBJ;
+static MY_OBJ *all_objects;
+
+static int
+valid(MY_OBJ * obj)
+{
+ MY_OBJ *list = all_objects;
+ int result = 0;
+
+ while (list != 0) {
+ if (list == obj) {
+ result = 1;
+ break;
+ }
+ list = list->next;
+ }
+ return result;
+}
+
+static void
+delink(MY_OBJ * obj)
+{
+ MY_OBJ *p = all_objects;
+ MY_OBJ *q = 0;
+ while (p != 0) {
+ if (p == obj) {
+ if (q != 0) {
+ q->next = p->next;
+ } else {
+ all_objects = p->next;
+ }
+ break;
+ }
+ q = p;
+ p = p->next;
+ }
+}
+
static int
read_data(char *buffer, FILE *fp)
{
@@ -55,6 +93,7 @@ read_data(char *buffer, FILE *fp)
if (feof(fp)) {
result = 0;
} else if (fgets(buffer, MY_LEN, fp) != 0) {
+ DLG_TRACE(("read_data:%s", buffer));
dlg_trim_string(buffer);
result = 1;
} else {
@@ -88,6 +127,7 @@ repaint_text(MY_OBJ * obj)
dlg_draw_title(dialog, obj->title);
wattrset(dialog, dialog_attr);
+ dlg_draw_helpline(dialog, FALSE);
dlg_print_autowrap(dialog, obj->prompt, obj->height, obj->width);
dlg_draw_box(dialog,
@@ -179,6 +219,7 @@ handle_input(DIALOG_CALLBACK * cb)
} else {
if (feof(dialog_state.pipe_input) ||
(ferror(dialog_state.pipe_input) && errno != EINTR)) {
+ delink(obj);
dlg_remove_callback(cb);
}
}
@@ -202,7 +243,8 @@ handle_my_getc(DIALOG_CALLBACK * cb, int ch, int fkey, int *result)
if (cb != 0) {
if (!fkey && (ch == ERR)) {
(void) handle_input(cb);
- status = (cb->input != 0);
+ /* cb might be freed in handle_input */
+ status = (valid((MY_OBJ *) cb) && (cb->input != 0));
}
} else {
status = FALSE;
@@ -215,46 +257,42 @@ my_cleanup(DIALOG_CALLBACK * cb)
{
MY_OBJ *obj = (MY_OBJ *) cb;
- if (obj != 0) {
- if (obj->prompt != obj->prompt_buf)
+ if (valid(obj)) {
+ if (obj->prompt != obj->prompt_buf) {
free(obj->prompt);
+ obj->prompt = obj->prompt_buf;
+ }
+ delink(obj);
}
}
+void
+dlg_update_gauge(void *objptr, int percent)
+{
+ MY_OBJ *obj = (MY_OBJ *) objptr;
+
+ curs_set(0);
+ obj->percent = percent;
+ repaint_text(obj);
+}
+
/*
- * Display a gauge, or progress meter. Starts at percent% and reads stdin. If
- * stdin is not XXX, then it is interpreted as a percentage, and the display is
- * updated accordingly. Otherwise the next line is the percentage, and
- * subsequent lines up to another XXX are used for the new prompt. Note that
- * the size of the window never changes, so the prompt can not get any larger
- * than the height and width specified.
+ * Allocates a new object and fills it as per the arguments
*/
-int
-dialog_gauge(const char *title,
- const char *cprompt,
- int height,
- int width,
- int percent)
+void *
+dlg_allocate_gauge(const char *title,
+ const char *cprompt,
+ int height,
+ int width,
+ int percent)
{
-#ifdef KEY_RESIZE
- int old_height = height;
- int old_width = width;
-#endif
- int fkey;
- int ch, result;
int x, y;
char *prompt = dlg_strclone(cprompt);
WINDOW *dialog;
MY_OBJ *obj = 0;
- curs_set(0);
-
dlg_tab_correct_str(prompt);
-#ifdef KEY_RESIZE
- retry:
-#endif
-
dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, MIN_WIDE);
dlg_print_size(height, width);
dlg_ctl_size(height, width);
@@ -265,51 +303,97 @@ dialog_gauge(const char *title,
dialog = dlg_new_window(height, width, y, x);
- if (obj == 0) {
- MY_OBJ **objref;
-
- obj = dlg_calloc(MY_OBJ, 1);
- assert_ptr(obj, "dialog_gauge");
-
- objref = &obj;
- obj->obj.input = dialog_state.pipe_input;
- obj->obj.win = dialog;
- obj->obj.keep_win = TRUE;
- obj->obj.bg_task = TRUE;
- obj->obj.handle_getc = handle_my_getc;
- obj->obj.handle_input = handle_input;
- obj->title = title;
- obj->prompt = prompt;
- obj->percent = percent;
- obj->height = height;
- obj->width = width;
- dlg_add_callback_ref((DIALOG_CALLBACK **) objref, my_cleanup);
- } else {
- obj->obj.win = dialog;
+ obj = dlg_calloc(MY_OBJ, 1);
+ assert_ptr(obj, "dialog_gauge");
+
+ obj->obj.input = dialog_state.pipe_input;
+ obj->obj.win = dialog;
+ obj->obj.keep_win = TRUE;
+ obj->obj.bg_task = TRUE;
+ obj->obj.handle_getc = handle_my_getc;
+ obj->obj.handle_input = handle_input;
+
+ obj->title = title;
+ obj->prompt = prompt;
+ obj->percent = percent;
+ obj->height = height;
+ obj->width = width;
+
+ obj->next = all_objects;
+ all_objects = obj;
+
+ return (void *) obj;
+}
+
+void
+dlg_free_gauge(void *objptr)
+{
+ MY_OBJ *obj = (MY_OBJ *) objptr;
+
+ curs_set(1);
+ if (valid(obj)) {
+ delink(obj);
+ obj->obj.keep_win = FALSE;
+ dlg_remove_callback(&(obj->obj));
+ free(obj);
}
+}
- repaint_text(obj);
+/*
+ * Display a gauge, or progress meter. Starts at percent% and reads stdin. If
+ * stdin is not XXX, then it is interpreted as a percentage, and the display is
+ * updated accordingly. Otherwise the next line is the percentage, and
+ * subsequent lines up to another XXX are used for the new prompt. Note that
+ * the size of the window never changes, so the prompt can not get any larger
+ * than the height and width specified.
+ */
+int
+dialog_gauge(const char *title,
+ const char *cprompt,
+ int height,
+ int width,
+ int percent)
+{
+ int fkey;
+ int ch, result;
+ void *objptr = dlg_allocate_gauge(title, cprompt, height, width, percent);
+ MY_OBJ *obj = (MY_OBJ *) objptr;
+
+ dlg_add_callback_ref((DIALOG_CALLBACK **) & obj, my_cleanup);
+ dlg_update_gauge(obj, percent);
do {
- ch = dlg_getc(dialog, &fkey);
+ ch = dlg_getc(obj->obj.win, &fkey);
#ifdef KEY_RESIZE
if (fkey && ch == KEY_RESIZE) {
- /* reset data */
- height = old_height;
- width = old_width;
- /* repaint */
+ MY_OBJ *oldobj = obj;
+
+ dlg_mouse_free_regions();
+
+ obj = dlg_allocate_gauge(title,
+ cprompt,
+ height,
+ width,
+ oldobj->percent);
+
+ /* avoid breaking new window in dlg_remove_callback */
+ oldobj->obj.caller = 0;
+ oldobj->obj.input = 0;
+ oldobj->obj.keep_win = FALSE;
+
+ /* remove the old version of the gauge */
dlg_clear();
- dlg_del_window(dialog);
+ dlg_remove_callback(&(oldobj->obj));
refresh();
- dlg_mouse_free_regions();
- goto retry;
+
+ dlg_add_callback_ref((DIALOG_CALLBACK **) & obj, my_cleanup);
+ dlg_update_gauge(obj, obj->percent);
}
#endif
}
- while (handle_my_getc(&(obj->obj), ch, fkey, &result));
+ while (valid(obj) && handle_my_getc(&(obj->obj), ch, fkey, &result));
- curs_set(1);
- dlg_del_window(dialog);
+ dlg_free_gauge(obj);
return (DLG_EXIT_OK);
}
OpenPOWER on IntegriCloud