ncurses 5.7 - patch 20081206
[ncurses.git] / test / demo_forms.c
1 /****************************************************************************
2  * Copyright (c) 2003-2007,2008 Free Software Foundation, Inc.              *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28 /*
29  * $Id: demo_forms.c,v 1.30 2008/10/18 20:38:20 tom Exp $
30  *
31  * Demonstrate a variety of functions from the form library.
32  * Thomas Dickey - 2003/4/26
33  */
34 /*
35 TYPE_ENUM                       -
36 TYPE_REGEXP                     -
37 dup_field                       -
38 field_init                      -
39 field_just                      -
40 field_term                      -
41 form_init                       -
42 form_opts                       -
43 form_opts_off                   -
44 form_opts_on                    -
45 form_request_by_name            -
46 form_term                       -
47 form_userptr                    -
48 free_fieldtype                  -
49 link_field                      -
50 link_fieldtype                  -
51 move_field                      -
52 new_page                        -
53 pos_form_cursor                 -
54 set_field_init                  -
55 set_field_term                  -
56 set_fieldtype_arg               -
57 set_fieldtype_choice            -
58 set_form_fields                 -
59 set_form_init                   -
60 set_form_opts                   -
61 set_form_page                   -
62 set_form_term                   -
63 set_form_userptr                -
64 set_max_field                   -
65 */
66
67 #include <test.priv.h>
68
69 #if USE_LIBFORM
70
71 #include <edit_field.h>
72
73 static int d_option = 0;
74 static int j_value = 0;
75 static int m_value = 0;
76 static int o_value = 0;
77 static char *t_value = 0;
78
79 static FIELD *
80 make_label(int frow, int fcol, NCURSES_CONST char *label)
81 {
82     FIELD *f = new_field(1, (int) strlen(label), frow, fcol, 0, 0);
83
84     if (f) {
85         set_field_buffer(f, 0, label);
86         set_field_opts(f, (int) (field_opts(f) & ~O_ACTIVE));
87     }
88     return (f);
89 }
90
91 /*
92  * Define each field with an extra one, for reflecting "actual" text.
93  */
94 static FIELD *
95 make_field(int frow, int fcol, int rows, int cols)
96 {
97     FIELD *f = new_field(rows, cols, frow, fcol, o_value, 1);
98
99     if (f) {
100         set_field_back(f, A_UNDERLINE);
101         /*
102          * If -j and -d options are combined, -j loses.  It is documented in
103          * "Character User Interface Programming", page 12-15 that setting
104          * O_STATIC off makes the form library ignore justification.
105          */
106         set_field_just(f, j_value);
107         if (d_option) {
108             if (has_colors()) {
109                 set_field_fore(f, COLOR_PAIR(2));
110                 set_field_back(f, A_UNDERLINE | COLOR_PAIR(3));
111             } else {
112                 set_field_fore(f, A_BOLD);
113             }
114             /*
115              * The field_opts_off() call dumps core with Solaris curses,
116              * but that is a known bug in Solaris' form library -TD
117              */
118             field_opts_off(f, O_STATIC);
119             set_max_field(f, m_value);
120         }
121
122         /*
123          * The userptr is used in edit_field.c's inactive_field().
124          */
125         set_field_userptr(f, (void *) (long) field_back(f));
126         if (t_value)
127             set_field_buffer(f, 0, t_value);
128     }
129     return (f);
130 }
131
132 static void
133 display_form(FORM * f)
134 {
135     WINDOW *w;
136     int rows, cols;
137
138     scale_form(f, &rows, &cols);
139
140     /*
141      * Put the form at the upper-left corner of the display, with just a box
142      * around it.
143      */
144     if ((w = newwin(rows + 2, cols + 4, 0, 0)) != (WINDOW *) 0) {
145         set_form_win(f, w);
146         set_form_sub(f, derwin(w, rows, cols, 1, 2));
147         box(w, 0, 0);
148         keypad(w, TRUE);
149     }
150
151     if (post_form(f) != E_OK)
152         wrefresh(w);
153 }
154
155 static void
156 erase_form(FORM * f)
157 {
158     WINDOW *w = form_win(f);
159     WINDOW *s = form_sub(f);
160
161     unpost_form(f);
162     werase(w);
163     wrefresh(w);
164     delwin(s);
165     delwin(w);
166 }
167
168 static void
169 show_insert_mode(bool insert_mode)
170 {
171     mvaddstr(5, 57, (insert_mode
172                      ? "form_status: insert "
173                      : "form_status: overlay"));
174 }
175
176 #define O_SELECTABLE (O_ACTIVE | O_VISIBLE)
177
178 static FIELD *
179 another_field(FORM * form, FIELD * field)
180 {
181     FIELD **f = form_fields(form);
182     FIELD *result = 0;
183     int n;
184
185     for (n = 0; f[n] != 0; ++n) {
186         if (f[n] != field) {
187             result = f[n];
188             field_opts_on(result, O_SELECTABLE);
189             break;
190         }
191     }
192     return result;
193 }
194
195 static int
196 my_form_driver(FORM * form, int c)
197 {
198     static bool insert_mode = TRUE;
199     FIELD *field;
200
201     switch (c) {
202     case MY_QUIT:
203         if (form_driver(form, REQ_VALIDATION) == E_OK)
204             return (TRUE);
205         break;
206     case MY_HELP:
207         help_edit_field();
208         break;
209     case MY_EDT_MODE:
210         if ((field = current_field(form)) != 0) {
211             set_current_field(form, another_field(form, field));
212             if (field_opts(field) & O_EDIT) {
213                 field_opts_off(field, O_EDIT);
214                 set_field_status(field, 0);
215             } else {
216                 field_opts_on(field, O_EDIT);
217             }
218             set_current_field(form, field);
219         }
220         break;
221     case MY_INS_MODE:
222         /* there should be a form_status() function, but there is none */
223         if (!insert_mode) {
224             if (form_driver(form, REQ_INS_MODE) == E_OK) {
225                 insert_mode = TRUE;
226             }
227         } else {
228             if (form_driver(form, REQ_OVL_MODE) == E_OK) {
229                 insert_mode = FALSE;
230             }
231         }
232         show_insert_mode(insert_mode);
233         refresh();
234         break;
235     default:
236         beep();
237         break;
238     }
239     return (FALSE);
240 }
241
242 static void
243 show_current_field(WINDOW *win, FORM * form)
244 {
245     FIELD *field;
246     FIELDTYPE *type;
247     char *buffer;
248     int nbuf;
249     int field_rows, field_cols, field_max;
250
251     if (has_colors()) {
252         wbkgd(win, COLOR_PAIR(1));
253     }
254     werase(win);
255     wprintw(win, "Cursor: %d,%d", form->currow, form->curcol);
256     if (data_ahead(form))
257         waddstr(win, " ahead");
258     if (data_behind(form))
259         waddstr(win, " behind");
260     waddch(win, '\n');
261     if ((field = current_field(form)) != 0) {
262         wprintw(win, "Page %d%s, Field %d/%d%s:",
263                 form_page(form),
264                 new_page(field) ? "*" : "",
265                 field_index(field), field_count(form),
266                 field_arg(field) ? "(arg)" : "");
267         if ((type = field_type(field)) != 0) {
268             if (type == TYPE_ALNUM)
269                 waddstr(win, "ALNUM");
270             else if (type == TYPE_ALPHA)
271                 waddstr(win, "ALPHA");
272             else if (type == TYPE_ENUM)
273                 waddstr(win, "ENUM");
274             else if (type == TYPE_INTEGER)
275                 waddstr(win, "INTEGER");
276 #ifdef NCURSES_VERSION
277             else if (type == TYPE_IPV4)
278                 waddstr(win, "IPV4");
279 #endif
280             else if (type == TYPE_NUMERIC)
281                 waddstr(win, "NUMERIC");
282             else if (type == TYPE_REGEXP)
283                 waddstr(win, "REGEXP");
284             else
285                 waddstr(win, "other");
286         }
287
288         if (field_opts(field) & O_EDIT)
289             waddstr(win, " editable");
290         else
291             waddstr(win, " readonly");
292
293         if (field_status(field))
294             waddstr(win, " modified");
295
296         if (dynamic_field_info(field, &field_rows, &field_cols, &field_max)
297             != ERR) {
298             wprintw(win, " size %dx%d (max %d)",
299                     field_rows, field_cols, field_max);
300         }
301
302         waddch(win, ' ');
303         wattrset(win, field_fore(field));
304         waddstr(win, "fore");
305         wattroff(win, field_fore(field));
306
307         waddch(win, '/');
308
309         wattrset(win, field_back(field));
310         waddstr(win, "back");
311         wattroff(win, field_back(field));
312
313         wprintw(win, ", pad '%c'",
314                 field_pad(field));
315
316         waddstr(win, "\n");
317         for (nbuf = 0; nbuf <= 2; ++nbuf) {
318             if ((buffer = field_buffer(field, nbuf)) != 0) {
319                 wprintw(win, "buffer %d:", nbuf);
320                 wattrset(win, A_REVERSE);
321                 waddstr(win, buffer);
322                 wattroff(win, A_REVERSE);
323                 waddstr(win, "\n");
324             }
325         }
326     }
327     wrefresh(win);
328 }
329
330 static void
331 demo_forms(void)
332 {
333     WINDOW *w;
334     FORM *form;
335     FIELD *f[100];              /* FIXME memset to zero */
336     int finished = 0, c;
337     unsigned n = 0;
338     int pg;
339     WINDOW *also;
340
341 #ifdef NCURSES_MOUSE_VERSION
342     mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
343 #endif
344
345     help_edit_field();
346
347     mvaddstr(4, 57, "Forms Entry Test");
348     show_insert_mode(TRUE);
349
350     refresh();
351
352     /* describe the form */
353     memset(f, 0, sizeof(f));
354     for (pg = 0; pg < 4; ++pg) {
355         char label[80];
356         sprintf(label, "Sample Form Page %d", pg + 1);
357         f[n++] = make_label(0, 15, label);
358         set_new_page(f[n - 1], TRUE);
359
360         switch (pg) {
361         default:
362             f[n++] = make_label(2, 0, "Last Name");
363             f[n++] = make_field(3, 0, 1, 18);
364             set_field_type(f[n - 1], TYPE_ALPHA, 1);
365
366             f[n++] = make_label(2, 20, "First Name");
367             f[n++] = make_field(3, 20, 1, 12);
368             set_field_type(f[n - 1], TYPE_ALPHA, 1);
369
370             f[n++] = make_label(2, 34, "Middle Name");
371             f[n++] = make_field(3, 34, 1, 12);
372             set_field_type(f[n - 1], TYPE_ALPHA, 1);
373             break;
374         case 1:
375             f[n++] = make_label(2, 0, "Last Name");
376             f[n++] = make_field(3, 0, 1, 18);
377             set_field_type(f[n - 1], TYPE_ALPHA, 1);
378
379             f[n++] = make_label(2, 20, "First Name");
380             f[n++] = make_field(3, 20, 1, 12);
381             set_field_type(f[n - 1], TYPE_ALPHA, 1);
382
383             f[n++] = make_label(2, 34, "MI");
384             f[n++] = make_field(3, 34, 1, 1);
385             set_field_pad(f[n - 1], '?');
386             set_field_type(f[n - 1], TYPE_ALPHA, 1);
387             break;
388         case 2:
389             f[n++] = make_label(2, 0, "Host Name");
390             f[n++] = make_field(3, 0, 1, 18);
391             set_field_type(f[n - 1], TYPE_ALNUM, 1);
392
393 #ifdef NCURSES_VERSION
394             f[n++] = make_label(2, 20, "IP Address");
395             f[n++] = make_field(3, 20, 1, 12);
396             set_field_type(f[n - 1], TYPE_IPV4, 1);
397 #endif
398
399             break;
400
401         case 3:
402             f[n++] = make_label(2, 0, "Four digits");
403             f[n++] = make_field(3, 0, 1, 18);
404             set_field_type(f[n - 1], TYPE_INTEGER, 4, 0, 0);
405
406             f[n++] = make_label(2, 20, "Numeric");
407             f[n++] = make_field(3, 20, 1, 12);
408             set_field_type(f[n - 1], TYPE_NUMERIC, 3, -10000.0, 100000000.0);
409
410             break;
411         }
412
413         f[n++] = make_label(5, 0, "Comments");
414         f[n++] = make_field(6, 0, 4, 46);
415         set_field_buffer(f[n - 1], 0, "HELLO\nWORLD!");
416         set_field_buffer(f[n - 1], 1, "Hello\nWorld!");
417     }
418
419     f[n++] = (FIELD *) 0;
420
421     if ((form = new_form(f)) != 0) {
422
423         display_form(form);
424
425         w = form_win(form);
426         also = newwin(getmaxy(stdscr) - getmaxy(w), COLS, getmaxy(w), 0);
427         show_current_field(also, form);
428
429         while (!finished) {
430             switch (edit_field(form, &c)) {
431             case E_OK:
432                 break;
433             case E_UNKNOWN_COMMAND:
434                 finished = my_form_driver(form, c);
435                 break;
436             default:
437                 beep();
438                 break;
439             }
440             show_current_field(also, form);
441         }
442
443         erase_form(form);
444
445         free_form(form);
446     }
447     for (c = 0; f[c] != 0; c++)
448         free_field(f[c]);
449     noraw();
450     nl();
451
452 #ifdef NCURSES_MOUSE_VERSION
453     mousemask(0, (mmask_t *) 0);
454 #endif
455 }
456
457 static void
458 usage(void)
459 {
460     static const char *tbl[] =
461     {
462         "Usage: demo_forms [options]"
463         ,""
464         ," -d        make fields dynamic"
465         ," -j value  justify (1=left, 2=center, 3=right)"
466         ," -m value  set maximum size of dynamic fields"
467         ," -o value  specify number of offscreen rows in new_field()"
468         ," -t value  specify text to fill fields initially"
469     };
470     unsigned int j;
471     for (j = 0; j < SIZEOF(tbl); ++j)
472         fprintf(stderr, "%s\n", tbl[j]);
473     exit(EXIT_FAILURE);
474 }
475
476 int
477 main(int argc, char *argv[])
478 {
479     int ch;
480
481     setlocale(LC_ALL, "");
482
483     while ((ch = getopt(argc, argv, "dj:m:o:t:")) != -1) {
484         switch (ch) {
485         case 'd':
486             d_option = TRUE;
487             break;
488         case 'j':
489             j_value = atoi(optarg);
490             if (j_value < NO_JUSTIFICATION
491                 || j_value > JUSTIFY_RIGHT)
492                 usage();
493             break;
494         case 'm':
495             m_value = atoi(optarg);
496             break;
497         case 'o':
498             o_value = atoi(optarg);
499             break;
500         case 't':
501             t_value = optarg;
502             break;
503         default:
504             usage();
505
506         }
507     }
508
509     initscr();
510     cbreak();
511     noecho();
512     raw();
513     nonl();                     /* lets us read ^M's */
514     intrflush(stdscr, FALSE);
515     keypad(stdscr, TRUE);
516
517     if (has_colors()) {
518         start_color();
519         init_pair(1, COLOR_WHITE, COLOR_BLUE);
520         init_pair(2, COLOR_GREEN, COLOR_BLACK);
521         init_pair(3, COLOR_CYAN, COLOR_BLACK);
522         bkgd(COLOR_PAIR(1));
523         refresh();
524     }
525
526     demo_forms();
527
528     endwin();
529     ExitProgram(EXIT_SUCCESS);
530 }
531 #else
532 int
533 main(void)
534 {
535     printf("This program requires the curses form library\n");
536     ExitProgram(EXIT_FAILURE);
537 }
538 #endif