1 /*
2 * Copyright (c)2004 Cat's Eye Technologies. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Cat's Eye Technologies nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * main.c
36 * Main program for dfuife_curses.
37 * $Id: main.c,v 1.21 2005/03/25 04:51:10 cpressey Exp $
38 */
39
40 #include <ctype.h>
41 #include <ncurses.h>
42 #include <signal.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <term.h>
46 #include <unistd.h>
47
48 #ifdef ENABLE_NLS
49 #include <libintl.h>
50 #include "libdfui/lang.h"
51 #define _(String) gettext (String)
52 extern int _nl_msg_cat_cntr;
53 #else
54 #define _(String) (String)
55 #endif
56
57 #include "libaura/mem.h"
58
59 #include "libdfui/dfui.h"
60 #ifdef DEBUG
61 #include "libdfui/dump.h"
62 #endif
63 #include "libdfui/system.h"
64
65 #include "curses_form.h"
66 #include "curses_widget.h"
67 #include "curses_bar.h"
68 #include "curses_util.h"
69 #include "curses_xlat.h"
70
71 /*** GLOBALS ***/
72
73 struct curses_bar *menubar, *statusbar;
74
75 /*** SIGNAL HANDLING ***/
76
77 #ifdef SIGNAL_HANDLING
78 volatile sig_atomic_t caught_signal;
79
signal_handler(int signo)80 void signal_handler(int signo)
81 {
82 caught_signal = signo;
83 }
84
85 void
abort_frontend(struct dfui_connection * c)86 abort_frontend(struct dfui_connection *c)
87 {
88 dfui_fe_abort(c);
89
90 clear();
91 refresh();
92 endwin();
93 exit(1);
94 }
95 #endif
96
97 static struct dfui_response *
98 #ifdef SIGNAL_HANDLING
present_form(struct dfui_connection * c,struct dfui_form * f)99 present_form(struct dfui_connection *c, struct dfui_form *f)
100 #else
101 present_form(struct dfui_connection *c __unused, struct dfui_form *f)
102 #endif
103 {
104 struct dfui_response *r = NULL;
105 struct curses_form *cf;
106 struct curses_widget *cw;
107
108 cf = curses_form_construct_from_dfui_form(f);
109 curses_form_draw(cf);
110 curses_form_refresh(cf);
111 cw = curses_form_frob(cf);
112 #ifdef SIGNAL_HANDLING
113 if (caught_signal) abort_frontend(c);
114 #endif
115 r = response_construct_from_curses_form(f, cf, cw);
116 curses_form_free(cf);
117 curses_form_refresh(NULL);
118 return(r);
119 }
120
121 static void
usage(char ** argv)122 usage(char **argv)
123 {
124 fprintf(stderr, _("Usage: %s "
125 "[-b backdrop] [-r rendezvous] [-t npipe|tcp]\n"),
126 argv[0]);
127 exit(1);
128 }
129
130 /*
131 * dfuife_curses
132 * DFUI Curses frontend.
133 */
134 int
main(int argc,char ** argv)135 main(int argc, char **argv)
136 {
137 struct dfui_connection *c;
138 struct dfui_form *f;
139 struct dfui_response *r;
140 struct dfui_progress *pr;
141 struct dfui_property *gp;
142
143 struct curses_form *pf = NULL;
144 struct curses_widget *pbar = NULL, *plab = NULL, *pcan = NULL;
145 struct curses_widget *w;
146
147 void *payload = NULL;
148 int done = 0;
149 char msgtype;
150 int opt;
151 char last_message[80];
152 int is_streaming = 0;
153 int ch;
154 char *bdropfn = NULL;
155 char *rendezvous = NULL;
156 int transport = 0;
157 int force_monochrome = 0;
158
159 /*
160 * Get command-line arguments.
161 */
162 while ((opt = getopt(argc, argv, "b:mr:t:")) != -1) {
163 switch(opt) {
164 case 'b':
165 bdropfn = aura_strdup(optarg);
166 break;
167 case 'm':
168 force_monochrome = 1;
169 break;
170 case 'r':
171 rendezvous = aura_strdup(optarg);
172 break;
173 case 't':
174 transport = user_get_transport(optarg);
175 break;
176 case '?':
177 default:
178 usage(argv);
179 }
180 }
181 argc -= optind;
182 argv += optind;
183
184 if (!transport)
185 transport = user_get_transport("tcp");
186
187 if (rendezvous == NULL) {
188 if (transport == DFUI_TRANSPORT_TCP) {
189 rendezvous = aura_strdup("9999");
190 } else {
191 rendezvous = aura_strdup("test");
192 }
193 }
194
195 #ifdef ENABLE_NLS
196 setlocale (LC_ALL, "");
197 bindtextdomain (PACKAGE, LOCALEDIR);
198 textdomain (PACKAGE);
199 #endif
200
201 /*
202 * Set up screen.
203 */
204
205 initscr();
206
207 #ifdef SIGNAL_HANDLING
208 signal(SIGINT, signal_handler);
209 signal(SIGTERM, signal_handler);
210 #endif
211
212 curses_colors_init(force_monochrome);
213 cbreak();
214 noecho();
215 nonl();
216 keypad(stdscr, TRUE);
217 curs_set(0);
218
219 getmaxyx(stdscr, ymax, xmax);
220
221 if (bdropfn == NULL) {
222 curses_colors_set(stdscr, CURSES_COLORS_BACKDROP);
223 curses_window_blank(stdscr);
224 } else {
225 curses_load_backdrop(stdscr, bdropfn);
226 }
227
228 menubar = curses_bar_new(0, 0, 0, 1, CURSES_COLORS_MENUBAR,
229 CURSES_BAR_WIDEN);
230 statusbar = curses_bar_new(0, 0, 0, 1, CURSES_COLORS_STATUSBAR,
231 CURSES_BAR_WIDEN | CURSES_BAR_BOTTOM);
232
233 curses_bar_set_text(menubar, _("F10=Refresh Display"));
234 curses_bar_set_text(statusbar, _("Waiting for backend..."));
235
236 update_panels();
237 doupdate();
238
239 #ifdef DEBUG
240 dfui_debug_file = fopen("/tmp/dfuife_curses_debug.log", "w");
241 #endif
242
243 c = dfui_connection_new(transport, rendezvous);
244 dfui_fe_connect(c);
245
246 curses_bar_set_text(statusbar, _("Connected"));
247
248 while (!done) {
249 dfui_fe_receive(c, &msgtype, &payload);
250 switch (msgtype) {
251 case DFUI_BE_MSG_PRESENT:
252 f = (struct dfui_form *)payload;
253 r = present_form(c, f);
254 #ifdef SIGNAL_HANDLING
255 if (caught_signal) abort_frontend(c);
256 #endif
257 dfui_fe_submit(c, r);
258 dfui_form_free(f);
259 dfui_response_free(r);
260 break;
261 case DFUI_BE_MSG_PROG_BEGIN:
262 pr = (struct dfui_progress *)payload;
263 if (pf != NULL)
264 curses_form_free(pf);
265 is_streaming = dfui_progress_get_streaming(pr);
266 strncpy(last_message, dfui_info_get_short_desc(
267 dfui_progress_get_info(pr)), 79);
268 pf = curses_form_construct_from_dfui_progress(pr,
269 &pbar, &plab, &pcan);
270 curses_form_draw(pf);
271 curses_form_refresh(pf);
272 dfui_progress_free(pr);
273 nodelay(stdscr, TRUE);
274 dfui_fe_progress_continue(c);
275 break;
276 case DFUI_BE_MSG_PROG_UPDATE:
277 pr = (struct dfui_progress *)payload;
278 if (pf != NULL) {
279 curses_widgets_update_from_dfui_progress(pr,
280 pbar, plab, pcan);
281 }
282 dfui_progress_free(pr);
283 ch = getch();
284 if (ch == ' ' || ch == '\n' || ch == '\r') {
285 dfui_fe_progress_cancel(c);
286 } else if (ch == KEY_F(10)) {
287 redrawwin(stdscr);
288 curses_form_refresh(NULL);
289 dfui_fe_progress_continue(c);
290 } else {
291 dfui_fe_progress_continue(c);
292 }
293 break;
294 case DFUI_BE_MSG_PROG_END:
295 if (pf != NULL) {
296 if (is_streaming) {
297 w = curses_form_widget_add(pf, 0, pf->int_height, 0,
298 CURSES_BUTTON, "OK", -1,
299 CURSES_WIDGET_CENTER | CURSES_WIDGET_WIDEN);
300 pf->int_height++;
301 curses_widget_set_click_cb(w, cb_click_close_form);
302 pf->widget_focus = w;
303 curses_form_widget_ensure_visible(w);
304 curses_widget_draw(w);
305 curses_form_refresh(pf);
306 curses_form_frob(pf);
307 }
308 curses_form_free(pf);
309 curses_form_refresh(NULL);
310 }
311 pf = NULL;
312 plab = pbar = pcan = NULL;
313 nodelay(stdscr, FALSE);
314 dfui_fe_progress_continue(c);
315 break;
316 case DFUI_BE_MSG_SET_GLOBAL:
317 gp = (struct dfui_property *)payload;
318
319 #ifdef ENABLE_NLS
320 /*
321 * Check for a change to the "lang" setting...
322 */
323 if (strcmp(dfui_property_get_name(gp), "lang") == 0) {
324 set_lang_envars(dfui_property_get_value(gp));
325
326 /* let gettext know about changes */
327 ++_nl_msg_cat_cntr;
328
329 /* BEGIN: reinit curses to use new TERM */
330 curses_bar_free(menubar);
331 curses_bar_free(statusbar);
332
333 endwin();
334 newterm(getenv("TERM"), stdout, stdin);
335
336 curses_colors_init(force_monochrome);
337 cbreak();
338 noecho();
339 nonl();
340 keypad(stdscr, TRUE);
341 curs_set(0);
342
343 update_panels();
344 doupdate();
345
346 if (bdropfn == NULL) {
347 curses_colors_set(stdscr,
348 CURSES_COLORS_BACKDROP);
349 curses_window_blank(stdscr);
350 } else {
351 curses_load_backdrop(stdscr, bdropfn);
352 }
353
354 menubar = curses_bar_new(0, 0, 0, 1,
355 CURSES_COLORS_MENUBAR, CURSES_BAR_WIDEN);
356 statusbar = curses_bar_new(0, 0, 0, 1,
357 CURSES_COLORS_STATUSBAR,
358 CURSES_BAR_WIDEN | CURSES_BAR_BOTTOM);
359 /* END: reinit curses to use new TERM */
360
361 curses_bar_set_text(menubar,
362 _("F1=Help F10=Refresh Display"));
363 }
364 #endif
365
366 dfui_fe_confirm_set_global(c);
367 dfui_property_free(gp);
368 break;
369 case DFUI_BE_MSG_STOP:
370 dfui_fe_confirm_stop(c);
371 done = 1;
372 break;
373 }
374 }
375
376 dfui_fe_disconnect(c);
377
378 #ifdef DEBUG
379 fclose(dfui_debug_file);
380 #endif
381
382 curses_bar_free(menubar);
383 curses_bar_free(statusbar);
384
385 clear();
386 refresh();
387 endwin();
388
389 if (rendezvous != NULL)
390 free(rendezvous);
391 if (bdropfn != NULL)
392 free(bdropfn);
393
394 exit(0);
395 }
396