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