ncurses 5.7 - patch 20100731
[ncurses.git] / test / demo_forms.c
1 /****************************************************************************
2  * Copyright (c) 2003-2009,2010 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.35 2010/05/01 21:56:10 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         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, 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 (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
258     if (has_colors()) {
259         wbkgd(win, COLOR_PAIR(1));
260     }
261     werase(win);
262     wprintw(win, "Cursor: %d,%d", form->currow, form->curcol);
263     if (data_ahead(form))
264         waddstr(win, " ahead");
265     if (data_behind(form))
266         waddstr(win, " behind");
267     waddch(win, '\n');
268     if ((field = current_field(form)) != 0) {
269         wprintw(win, "Page %d%s, Field %d/%d%s:",
270                 form_page(form),
271                 new_page(field) ? "*" : "",
272                 field_index(field), field_count(form),
273                 field_arg(field) ? "(arg)" : "");
274         if ((type = field_type(field)) != 0) {
275             if (type == TYPE_ALNUM)
276                 waddstr(win, "ALNUM");
277             else if (type == TYPE_ALPHA)
278                 waddstr(win, "ALPHA");
279             else if (type == TYPE_ENUM)
280                 waddstr(win, "ENUM");
281             else if (type == TYPE_INTEGER)
282                 waddstr(win, "INTEGER");
283 #ifdef NCURSES_VERSION
284             else if (type == TYPE_IPV4)
285                 waddstr(win, "IPV4");
286 #endif
287             else if (type == TYPE_NUMERIC)
288                 waddstr(win, "NUMERIC");
289             else if (type == TYPE_REGEXP)
290                 waddstr(win, "REGEXP");
291             else
292                 waddstr(win, "other");
293         }
294
295         if (field_opts(field) & O_EDIT)
296             waddstr(win, " editable");
297         else
298             waddstr(win, " readonly");
299
300         if (field_status(field))
301             waddstr(win, " modified");
302
303         if (dynamic_field_info(field, &field_rows, &field_cols, &field_max)
304             != ERR) {
305             wprintw(win, " size %dx%d (max %d)",
306                     field_rows, field_cols, field_max);
307         }
308
309         waddch(win, ' ');
310         (void) wattrset(win, field_fore(field));
311         waddstr(win, "fore");
312         wattroff(win, field_fore(field));
313
314         waddch(win, '/');
315
316         (void) wattrset(win, field_back(field));
317         waddstr(win, "back");
318         wattroff(win, field_back(field));
319
320         wprintw(win, ", pad '%c'",
321                 field_pad(field));
322
323         waddstr(win, "\n");
324         for (nbuf = 0; nbuf <= 2; ++nbuf) {
325             if ((buffer = field_buffer(field, nbuf)) != 0) {
326                 wprintw(win, "buffer %d:", nbuf);
327                 (void) wattrset(win, A_REVERSE);
328                 waddstr(win, buffer);
329                 wattroff(win, A_REVERSE);
330                 waddstr(win, "\n");
331             }
332         }
333     }
334     wrefresh(win);
335 }
336
337 static void
338 demo_forms(void)
339 {
340     WINDOW *w;
341     FORM *form;
342     FIELD *f[100];              /* FIXME memset to zero */
343     int finished = 0, c;
344     unsigned n = 0;
345     int pg;
346     WINDOW *also;
347
348 #ifdef NCURSES_MOUSE_VERSION
349     mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
350 #endif
351
352     help_edit_field();
353
354     MvAddStr(4, 57, "Forms Entry Test");
355     show_insert_mode(TRUE);
356
357     refresh();
358
359     /* describe the form */
360     memset(f, 0, sizeof(f));
361     for (pg = 0; pg < 4; ++pg) {
362         char label[80];
363         sprintf(label, "Sample Form Page %d", pg + 1);
364         f[n++] = make_label(0, 15, label);
365         set_new_page(f[n - 1], TRUE);
366
367         switch (pg) {
368         default:
369             f[n++] = make_label(2, 0, "Last Name");
370             f[n++] = make_field(3, 0, 1, 18);
371             set_field_type(f[n - 1], TYPE_ALPHA, 1);
372
373             f[n++] = make_label(2, 20, "First Name");
374             f[n++] = make_field(3, 20, 1, 12);
375             set_field_type(f[n - 1], TYPE_ALPHA, 1);
376
377             f[n++] = make_label(2, 34, "Middle Name");
378             f[n++] = make_field(3, 34, 1, 12);
379             set_field_type(f[n - 1], TYPE_ALPHA, 1);
380             break;
381         case 1:
382             f[n++] = make_label(2, 0, "Last Name");
383             f[n++] = make_field(3, 0, 1, 18);
384             set_field_type(f[n - 1], TYPE_ALPHA, 1);
385
386             f[n++] = make_label(2, 20, "First Name");
387             f[n++] = make_field(3, 20, 1, 12);
388             set_field_type(f[n - 1], TYPE_ALPHA, 1);
389
390             f[n++] = make_label(2, 34, "MI");
391             f[n++] = make_field(3, 34, 1, 1);
392             set_field_pad(f[n - 1], '?');
393             set_field_type(f[n - 1], TYPE_ALPHA, 1);
394             break;
395         case 2:
396             f[n++] = make_label(2, 0, "Host Name");
397             f[n++] = make_field(3, 0, 1, 18);
398             set_field_type(f[n - 1], TYPE_ALNUM, 1);
399
400 #ifdef NCURSES_VERSION
401             f[n++] = make_label(2, 20, "IP Address");
402             f[n++] = make_field(3, 20, 1, 12);
403             set_field_type(f[n - 1], TYPE_IPV4, 1);
404 #endif
405
406             break;
407
408         case 3:
409             f[n++] = make_label(2, 0, "Four digits");
410             f[n++] = make_field(3, 0, 1, 18);
411             set_field_type(f[n - 1], TYPE_INTEGER, 4, 0, 0);
412
413             f[n++] = make_label(2, 20, "Numeric");
414             f[n++] = make_field(3, 20, 1, 12);
415             set_field_type(f[n - 1], TYPE_NUMERIC, 3, -10000.0, 100000000.0);
416
417             break;
418         }
419
420         f[n++] = make_label(5, 0, "Comments");
421         f[n++] = make_field(6, 0, 4, 46);
422         set_field_buffer(f[n - 1], 0, "HELLO\nWORLD!");
423         set_field_buffer(f[n - 1], 1, "Hello\nWorld!");
424     }
425
426     f[n] = (FIELD *) 0;
427
428     if ((form = new_form(f)) != 0) {
429
430         display_form(form);
431
432         w = form_win(form);
433         also = newwin(getmaxy(stdscr) - getmaxy(w), COLS, getmaxy(w), 0);
434         show_current_field(also, form);
435
436         while (!finished) {
437             switch (edit_field(form, &c)) {
438             case E_OK:
439                 break;
440             case E_UNKNOWN_COMMAND:
441                 finished = my_form_driver(form, c);
442                 break;
443             default:
444                 beep();
445                 break;
446             }
447             show_current_field(also, form);
448         }
449
450         erase_form(form);
451
452         free_form(form);
453     }
454     for (c = 0; f[c] != 0; c++) {
455         void *ptr = field_userptr(f[c]);
456         free(ptr);
457         free_field(f[c]);
458     }
459     noraw();
460     nl();
461
462 #ifdef NCURSES_MOUSE_VERSION
463     mousemask(0, (mmask_t *) 0);
464 #endif
465 }
466
467 static void
468 usage(void)
469 {
470     static const char *tbl[] =
471     {
472         "Usage: demo_forms [options]"
473         ,""
474         ," -d        make fields dynamic"
475         ," -j value  justify (1=left, 2=center, 3=right)"
476         ," -m value  set maximum size of dynamic fields"
477         ," -o value  specify number of offscreen rows in new_field()"
478         ," -t value  specify text to fill fields initially"
479     };
480     unsigned int j;
481     for (j = 0; j < SIZEOF(tbl); ++j)
482         fprintf(stderr, "%s\n", tbl[j]);
483     exit(EXIT_FAILURE);
484 }
485
486 int
487 main(int argc, char *argv[])
488 {
489     int ch;
490
491     setlocale(LC_ALL, "");
492
493     while ((ch = getopt(argc, argv, "dj:m:o:t:")) != -1) {
494         switch (ch) {
495         case 'd':
496             d_option = TRUE;
497             break;
498         case 'j':
499             j_value = atoi(optarg);
500             if (j_value < NO_JUSTIFICATION
501                 || j_value > JUSTIFY_RIGHT)
502                 usage();
503             break;
504         case 'm':
505             m_value = atoi(optarg);
506             break;
507         case 'o':
508             o_value = atoi(optarg);
509             break;
510         case 't':
511             t_value = optarg;
512             break;
513         default:
514             usage();
515
516         }
517     }
518
519     initscr();
520     cbreak();
521     noecho();
522     raw();
523     nonl();                     /* lets us read ^M's */
524     intrflush(stdscr, FALSE);
525     keypad(stdscr, TRUE);
526
527     if (has_colors()) {
528         start_color();
529         init_pair(1, COLOR_WHITE, COLOR_BLUE);
530         init_pair(2, COLOR_GREEN, COLOR_BLACK);
531         init_pair(3, COLOR_CYAN, COLOR_BLACK);
532         bkgd(COLOR_PAIR(1));
533         refresh();
534     }
535
536     demo_forms();
537
538     endwin();
539     ExitProgram(EXIT_SUCCESS);
540 }
541 #else
542 int
543 main(void)
544 {
545     printf("This program requires the curses form library\n");
546     ExitProgram(EXIT_FAILURE);
547 }
548 #endif