455b7bb7f3dfe7afcaa731d853945045a9912a61
[ncurses.git] / test / demo_forms.c
1 /****************************************************************************
2  * Copyright (c) 2003-2011,2012 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.39 2012/06/09 20:30:32 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) ((unsigned) 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         FieldAttrs *ptr;
101
102         set_field_back(f, A_UNDERLINE);
103         /*
104          * If -j and -d options are combined, -j loses.  It is documented in
105          * "Character User Interface Programming", page 12-15 that setting
106          * O_STATIC off makes the form library ignore justification.
107          */
108         set_field_just(f, j_value);
109         if (d_option) {
110             if (has_colors()) {
111                 set_field_fore(f, (chtype) COLOR_PAIR(2));
112                 set_field_back(f, A_UNDERLINE | COLOR_PAIR(3));
113             } else {
114                 set_field_fore(f, A_BOLD);
115             }
116             /*
117              * The field_opts_off() call dumps core with Solaris curses,
118              * but that is a known bug in Solaris' form library -TD
119              */
120             field_opts_off(f, O_STATIC);
121             set_max_field(f, m_value);
122         }
123
124         /*
125          * The userptr is used in edit_field.c's inactive_field().
126          */
127         ptr = (FieldAttrs *) field_userptr(f);
128         if (ptr == 0) {
129             ptr = typeCalloc(FieldAttrs, 1);
130             ptr->background = field_back(f);
131         }
132         set_field_userptr(f, (void *) ptr);
133         if (t_value)
134             set_field_buffer(f, 0, t_value);
135     }
136     return (f);
137 }
138
139 static void
140 display_form(FORM * f)
141 {
142     WINDOW *w;
143     int rows, cols;
144
145     scale_form(f, &rows, &cols);
146
147     /*
148      * Put the form at the upper-left corner of the display, with just a box
149      * around it.
150      */
151     if ((w = newwin(rows + 2, cols + 4, 0, 0)) != (WINDOW *) 0) {
152         set_form_win(f, w);
153         set_form_sub(f, derwin(w, rows, cols, 1, 2));
154         box(w, 0, 0);
155         keypad(w, TRUE);
156     }
157
158     if (post_form(f) != E_OK)
159         wrefresh(w);
160 }
161
162 static void
163 erase_form(FORM * f)
164 {
165     WINDOW *w = form_win(f);
166     WINDOW *s = form_sub(f);
167
168     unpost_form(f);
169     werase(w);
170     wrefresh(w);
171     delwin(s);
172     delwin(w);
173 }
174
175 static void
176 show_insert_mode(bool insert_mode)
177 {
178     MvAddStr(5, 57, (insert_mode
179                      ? "form_status: insert "
180                      : "form_status: overlay"));
181 }
182
183 #define O_SELECTABLE (O_ACTIVE | O_VISIBLE)
184
185 static FIELD *
186 another_field(FORM * form, FIELD * field)
187 {
188     FIELD **f = form_fields(form);
189     FIELD *result = 0;
190     int n;
191
192     for (n = 0; f[n] != 0; ++n) {
193         if (f[n] != field) {
194             result = f[n];
195             field_opts_on(result, O_SELECTABLE);
196             break;
197         }
198     }
199     return result;
200 }
201
202 static int
203 my_form_driver(FORM * form, int c)
204 {
205     static bool insert_mode = TRUE;
206     FIELD *field;
207
208     switch (c) {
209     case MY_QUIT:
210         if (form_driver(form, REQ_VALIDATION) == E_OK)
211             return (TRUE);
212         break;
213     case MY_HELP:
214         help_edit_field();
215         break;
216     case MY_EDT_MODE:
217         if ((field = current_field(form)) != 0) {
218             set_current_field(form, another_field(form, field));
219             if ((unsigned) field_opts(field) & O_EDIT) {
220                 field_opts_off(field, O_EDIT);
221                 set_field_status(field, 0);
222             } else {
223                 field_opts_on(field, O_EDIT);
224             }
225             set_current_field(form, field);
226         }
227         break;
228     case MY_INS_MODE:
229         /* there should be a form_status() function, but there is none */
230         if (!insert_mode) {
231             if (form_driver(form, REQ_INS_MODE) == E_OK) {
232                 insert_mode = TRUE;
233             }
234         } else {
235             if (form_driver(form, REQ_OVL_MODE) == E_OK) {
236                 insert_mode = FALSE;
237             }
238         }
239         show_insert_mode(insert_mode);
240         refresh();
241         break;
242     default:
243         beep();
244         break;
245     }
246     return (FALSE);
247 }
248
249 static void
250 show_current_field(WINDOW *win, FORM * form)
251 {
252     FIELD *field;
253     FIELDTYPE *type;
254     char *buffer;
255     int nbuf;
256     int field_rows, field_cols, field_max;
257     int currow, curcol;
258
259     if (has_colors()) {
260         wbkgd(win, (chtype) COLOR_PAIR(1));
261     }
262     werase(win);
263     form_getyx(form, currow, curcol);
264     wprintw(win, "Cursor: %d,%d", currow, curcol);
265     if (data_ahead(form))
266         waddstr(win, " ahead");
267     if (data_behind(form))
268         waddstr(win, " behind");
269     waddch(win, '\n');
270     if ((field = current_field(form)) != 0) {
271         wprintw(win, "Page %d%s, Field %d/%d%s:",
272                 form_page(form),
273                 new_page(field) ? "*" : "",
274                 field_index(field), field_count(form),
275                 field_arg(field) ? "(arg)" : "");
276         if ((type = field_type(field)) != 0) {
277             if (type == TYPE_ALNUM)
278                 waddstr(win, "ALNUM");
279             else if (type == TYPE_ALPHA)
280                 waddstr(win, "ALPHA");
281             else if (type == TYPE_ENUM)
282                 waddstr(win, "ENUM");
283             else if (type == TYPE_INTEGER)
284                 waddstr(win, "INTEGER");
285 #ifdef NCURSES_VERSION
286             else if (type == TYPE_IPV4)
287                 waddstr(win, "IPV4");
288 #endif
289             else if (type == TYPE_NUMERIC)
290                 waddstr(win, "NUMERIC");
291             else if (type == TYPE_REGEXP)
292                 waddstr(win, "REGEXP");
293             else
294                 waddstr(win, "other");
295         }
296
297         if ((unsigned) field_opts(field) & O_EDIT)
298             waddstr(win, " editable");
299         else
300             waddstr(win, " readonly");
301
302         if (field_status(field))
303             waddstr(win, " modified");
304
305         if (dynamic_field_info(field, &field_rows, &field_cols, &field_max)
306             != ERR) {
307             wprintw(win, " size %dx%d (max %d)",
308                     field_rows, field_cols, field_max);
309         }
310
311         waddch(win, ' ');
312         (void) wattrset(win, (int) field_fore(field));
313         waddstr(win, "fore");
314         wattroff(win, (int) field_fore(field));
315
316         waddch(win, '/');
317
318         (void) wattrset(win, (int) field_back(field));
319         waddstr(win, "back");
320         wattroff(win, (int) field_back(field));
321
322         wprintw(win, ", pad '%c'",
323                 field_pad(field));
324
325         waddstr(win, "\n");
326         for (nbuf = 0; nbuf <= 2; ++nbuf) {
327             if ((buffer = field_buffer(field, nbuf)) != 0) {
328                 wprintw(win, "buffer %d:", nbuf);
329                 (void) wattrset(win, A_REVERSE);
330                 waddstr(win, buffer);
331                 wattroff(win, A_REVERSE);
332                 waddstr(win, "\n");
333             }
334         }
335     }
336     wrefresh(win);
337 }
338
339 static void
340 demo_forms(void)
341 {
342     WINDOW *w;
343     FORM *form;
344     FIELD *f[100];              /* FIXME memset to zero */
345     int finished = 0, c;
346     unsigned n = 0;
347     int pg;
348     WINDOW *also;
349
350 #ifdef NCURSES_MOUSE_VERSION
351     mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
352 #endif
353
354     help_edit_field();
355
356     MvAddStr(4, 57, "Forms Entry Test");
357     show_insert_mode(TRUE);
358
359     refresh();
360
361     /* describe the form */
362     memset(f, 0, sizeof(f));
363     for (pg = 0; pg < 4; ++pg) {
364         char label[80];
365         sprintf(label, "Sample Form Page %d", pg + 1);
366         f[n++] = make_label(0, 15, label);
367         set_new_page(f[n - 1], TRUE);
368
369         switch (pg) {
370         default:
371             f[n++] = make_label(2, 0, "Last Name");
372             f[n++] = make_field(3, 0, 1, 18);
373             set_field_type(f[n - 1], TYPE_ALPHA, 1);
374
375             f[n++] = make_label(2, 20, "First Name");
376             f[n++] = make_field(3, 20, 1, 12);
377             set_field_type(f[n - 1], TYPE_ALPHA, 1);
378
379             f[n++] = make_label(2, 34, "Middle Name");
380             f[n++] = make_field(3, 34, 1, 12);
381             set_field_type(f[n - 1], TYPE_ALPHA, 1);
382             break;
383         case 1:
384             f[n++] = make_label(2, 0, "Last Name");
385             f[n++] = make_field(3, 0, 1, 18);
386             set_field_type(f[n - 1], TYPE_ALPHA, 1);
387
388             f[n++] = make_label(2, 20, "First Name");
389             f[n++] = make_field(3, 20, 1, 12);
390             set_field_type(f[n - 1], TYPE_ALPHA, 1);
391
392             f[n++] = make_label(2, 34, "MI");
393             f[n++] = make_field(3, 34, 1, 1);
394             set_field_pad(f[n - 1], '?');
395             set_field_type(f[n - 1], TYPE_ALPHA, 1);
396             break;
397         case 2:
398             f[n++] = make_label(2, 0, "Host Name");
399             f[n++] = make_field(3, 0, 1, 18);
400             set_field_type(f[n - 1], TYPE_ALNUM, 1);
401
402 #ifdef NCURSES_VERSION
403             f[n++] = make_label(2, 20, "IP Address");
404             f[n++] = make_field(3, 20, 1, 12);
405             set_field_type(f[n - 1], TYPE_IPV4, 1);
406 #endif
407
408             break;
409
410         case 3:
411             f[n++] = make_label(2, 0, "Four digits");
412             f[n++] = make_field(3, 0, 1, 18);
413             set_field_type(f[n - 1], TYPE_INTEGER, 4, 0, 0);
414
415             f[n++] = make_label(2, 20, "Numeric");
416             f[n++] = make_field(3, 20, 1, 12);
417             set_field_type(f[n - 1], TYPE_NUMERIC, 3, -10000.0, 100000000.0);
418
419             break;
420         }
421
422         f[n++] = make_label(5, 0, "Comments");
423         f[n++] = make_field(6, 0, 4, 46);
424         set_field_buffer(f[n - 1], 0, "HELLO\nWORLD!");
425         set_field_buffer(f[n - 1], 1, "Hello\nWorld!");
426     }
427
428     f[n] = (FIELD *) 0;
429
430     if ((form = new_form(f)) != 0) {
431
432         display_form(form);
433
434         w = form_win(form);
435         also = newwin(getmaxy(stdscr) - getmaxy(w), COLS, getmaxy(w), 0);
436         show_current_field(also, form);
437
438         while (!finished) {
439             switch (edit_field(form, &c)) {
440             case E_OK:
441                 break;
442             case E_UNKNOWN_COMMAND:
443                 finished = my_form_driver(form, c);
444                 break;
445             default:
446                 beep();
447                 break;
448             }
449             show_current_field(also, form);
450         }
451
452         erase_form(form);
453
454         free_form(form);
455     }
456     for (c = 0; f[c] != 0; c++) {
457         void *ptr = field_userptr(f[c]);
458         free(ptr);
459         free_field(f[c]);
460     }
461     noraw();
462     nl();
463
464 #ifdef NCURSES_MOUSE_VERSION
465     mousemask(0, (mmask_t *) 0);
466 #endif
467 }
468
469 static void
470 usage(void)
471 {
472     static const char *tbl[] =
473     {
474         "Usage: demo_forms [options]"
475         ,""
476         ," -d        make fields dynamic"
477         ," -j value  justify (1=left, 2=center, 3=right)"
478         ," -m value  set maximum size of dynamic fields"
479         ," -o value  specify number of offscreen rows in new_field()"
480         ," -t value  specify text to fill fields initially"
481     };
482     unsigned int j;
483     for (j = 0; j < SIZEOF(tbl); ++j)
484         fprintf(stderr, "%s\n", tbl[j]);
485     exit(EXIT_FAILURE);
486 }
487
488 int
489 main(int argc, char *argv[])
490 {
491     int ch;
492
493     setlocale(LC_ALL, "");
494
495     while ((ch = getopt(argc, argv, "dj:m:o:t:")) != -1) {
496         switch (ch) {
497         case 'd':
498             d_option = TRUE;
499             break;
500         case 'j':
501             j_value = atoi(optarg);
502             if (j_value < NO_JUSTIFICATION
503                 || j_value > JUSTIFY_RIGHT)
504                 usage();
505             break;
506         case 'm':
507             m_value = atoi(optarg);
508             break;
509         case 'o':
510             o_value = atoi(optarg);
511             break;
512         case 't':
513             t_value = optarg;
514             break;
515         default:
516             usage();
517
518         }
519     }
520
521     initscr();
522     cbreak();
523     noecho();
524     raw();
525     nonl();                     /* lets us read ^M's */
526     intrflush(stdscr, FALSE);
527     keypad(stdscr, TRUE);
528
529     if (has_colors()) {
530         start_color();
531         init_pair(1, COLOR_WHITE, COLOR_BLUE);
532         init_pair(2, COLOR_GREEN, COLOR_BLACK);
533         init_pair(3, COLOR_CYAN, COLOR_BLACK);
534         bkgd((chtype) COLOR_PAIR(1));
535         refresh();
536     }
537
538     demo_forms();
539
540     endwin();
541     ExitProgram(EXIT_SUCCESS);
542 }
543
544 #else
545 int
546 main(void)
547 {
548     printf("This program requires the curses form library\n");
549     ExitProgram(EXIT_FAILURE);
550 }
551 #endif