progressbox.c revision 217309
1/*
2 *  $Id: progressbox.c,v 1.8 2010/01/12 10:46:24 tom Exp $
3 *
4 *  progressbox.c -- implements the progress box
5 *
6 *  Copyright 2005	Valery Reznic
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU Lesser General Public License as
10 *  published by the Free Software Foundation; either version 2.1 of the
11 *  License, or (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful, but
14 *  WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *  Lesser General Public License for more details.
17 *
18 *  You should have received a copy of the GNU Lesser General Public
19 *  License along with this program; if not, write to
20 *	Free Software Foundation, Inc.
21 *	51 Franklin St., Fifth Floor
22 *	Boston, MA 02110, USA.
23 */
24
25#include <dialog.h>
26#include <dlg_keys.h>
27
28#define MIN_HIGH (4)
29#define MIN_WIDE (10 + 2 * (2 + MARGIN))
30
31typedef struct {
32    DIALOG_CALLBACK obj;
33    WINDOW *text;
34    char line[MAX_LEN + 1];
35    int is_eof;
36} MY_OBJ;
37
38/*
39 * Return current line of text.
40 */
41static char *
42get_line(MY_OBJ * obj)
43{
44    FILE *fp = obj->obj.input;
45    int col = 0;
46    int j, tmpint, ch;
47
48    while (1) {
49	if ((ch = getc(fp)) == EOF) {
50	    obj->is_eof = 1;
51	    if (col) {
52		break;
53	    } else {
54		return NULL;
55	    }
56	}
57	if (ch == '\n')
58	    break;
59	if (ch == '\r')
60	    break;
61	if ((ch == TAB) && (dialog_vars.tab_correct)) {
62	    tmpint = dialog_state.tab_len
63		- (col % dialog_state.tab_len);
64	    for (j = 0; j < tmpint; j++) {
65		if (col < MAX_LEN)
66		    obj->line[col] = ' ';
67		++col;
68	    }
69	} else {
70	    obj->line[col] = (char) ch;
71	    ++col;
72	}
73	if (col >= MAX_LEN)
74	    break;
75    }
76
77    obj->line[col] = '\0';
78
79    return obj->line;
80}
81
82/*
83 * Print a new line of text.
84 */
85static void
86print_line(MY_OBJ * obj, WINDOW *win, int row, int width)
87{
88    int i, y, x;
89    char *line = obj->line;
90
91    (void) wmove(win, row, 0);	/* move cursor to correct line */
92    (void) waddch(win, ' ');
93#ifdef NCURSES_VERSION
94    (void) waddnstr(win, line, MIN((int) strlen(line), width - 2));
95#else
96    line[MIN((int) strlen(line), width - 2)] = '\0';
97    waddstr(win, line);
98#endif
99
100    getyx(win, y, x);
101    /* Clear 'residue' of previous line */
102    for (i = 0; i < width - x; i++)
103	(void) waddch(win, ' ');
104}
105
106/*
107 * Display text from a stdin in a scrolling window.
108 */
109int
110dialog_progressbox(const char *title, const char *cprompt, int height, int width)
111{
112    int i;
113    int x, y, thigh;
114    WINDOW *dialog, *text;
115    MY_OBJ *obj;
116    FILE *fd = dialog_state.pipe_input;
117    char *prompt = dlg_strclone(cprompt);
118
119    dlg_tab_correct_str(prompt);
120    dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, MIN_WIDE);
121    dlg_print_size(height, width);
122    dlg_ctl_size(height, width);
123
124    x = dlg_box_x_ordinate(width);
125    y = dlg_box_y_ordinate(height);
126    thigh = height - (2 * MARGIN);
127
128    dialog = dlg_new_window(height, width, y, x);
129
130    dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
131    dlg_draw_title(dialog, title);
132
133    if (*prompt != '\0') {
134	int y2, x2;
135
136	wattrset(dialog, dialog_attr);
137	dlg_print_autowrap(dialog, prompt, height, width);
138	getyx(dialog, y2, x2);
139	++y2;
140	wmove(dialog, y2, MARGIN);
141	for (i = 0; i < getmaxx(dialog) - 2 * MARGIN; i++)
142	    (void) waddch(dialog, dlg_boxchar(ACS_HLINE));
143	y += y2;
144	thigh -= y2;
145    }
146
147    /* Create window for text region, used for scrolling text */
148    text = dlg_sub_window(dialog,
149			  thigh,
150			  width - (2 * MARGIN),
151			  y + MARGIN,
152			  x + MARGIN);
153
154    (void) wrefresh(dialog);
155
156    (void) wmove(dialog, thigh, (MARGIN + 1));
157    (void) wnoutrefresh(dialog);
158
159    obj = dlg_calloc(MY_OBJ, 1);
160    assert_ptr(obj, "dialog_progressbox");
161
162    obj->obj.input = fd;
163    obj->obj.win = dialog;
164    obj->text = text;
165
166    dlg_attr_clear(text, thigh, getmaxx(text), dialog_attr);
167    for (i = 0; get_line(obj); i++) {
168	if (i < thigh) {
169	    print_line(obj, text, i, width - (2 * MARGIN));
170	} else {
171	    scrollok(text, TRUE);
172	    scroll(text);
173	    scrollok(text, FALSE);
174	    print_line(obj, text, thigh - 1, width - (2 * MARGIN));
175	}
176	(void) wnoutrefresh(text);
177	(void) wrefresh(text);
178	if (obj->is_eof)
179	    break;
180    }
181    dlg_unregister_window(text);
182    dlg_del_window(dialog);
183    free(prompt);
184    free(obj);
185
186    return DLG_EXIT_OK;
187}
188