ncurses 5.6
[ncurses.git] / test / demo_forms.c
1 /****************************************************************************
2  * Copyright (c) 2003-2005,2006 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.22 2006/12/10 00:30:24 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     help_edit_field();
326
327     mvaddstr(4, 57, "Forms Entry Test");
328     show_insert_mode(TRUE);
329
330     refresh();
331
332     /* describe the form */
333     for (pg = 0; pg < 4; ++pg) {
334         char label[80];
335         sprintf(label, "Sample Form Page %d", pg + 1);
336         f[n++] = make_label(0, 15, label);
337         set_new_page(f[n - 1], TRUE);
338
339         switch (pg) {
340         default:
341             f[n++] = make_label(2, 0, "Last Name");
342             f[n++] = make_field(3, 0, 1, 18);
343             set_field_type(f[n - 1], TYPE_ALPHA, 1);
344
345             f[n++] = make_label(2, 20, "First Name");
346             f[n++] = make_field(3, 20, 1, 12);
347             set_field_type(f[n - 1], TYPE_ALPHA, 1);
348
349             f[n++] = make_label(2, 34, "Middle Name");
350             f[n++] = make_field(3, 34, 1, 12);
351             set_field_type(f[n - 1], TYPE_ALPHA, 1);
352             break;
353         case 1:
354             f[n++] = make_label(2, 0, "Last Name");
355             f[n++] = make_field(3, 0, 1, 18);
356             set_field_type(f[n - 1], TYPE_ALPHA, 1);
357
358             f[n++] = make_label(2, 20, "First Name");
359             f[n++] = make_field(3, 20, 1, 12);
360             set_field_type(f[n - 1], TYPE_ALPHA, 1);
361
362             f[n++] = make_label(2, 34, "MI");
363             f[n++] = make_field(3, 34, 1, 1);
364             set_field_type(f[n - 1], TYPE_ALPHA, 1);
365             break;
366         case 2:
367             f[n++] = make_label(2, 0, "Host Name");
368             f[n++] = make_field(3, 0, 1, 18);
369             set_field_type(f[n - 1], TYPE_ALNUM, 1);
370
371 #ifdef NCURSES_VERSION
372             f[n++] = make_label(2, 20, "IP Address");
373             f[n++] = make_field(3, 20, 1, 12);
374             set_field_type(f[n - 1], TYPE_IPV4, 1);
375 #endif
376
377             break;
378
379         case 3:
380             f[n++] = make_label(2, 0, "Four digits");
381             f[n++] = make_field(3, 0, 1, 18);
382             set_field_type(f[n - 1], TYPE_INTEGER, 4, 0, 0);
383
384             f[n++] = make_label(2, 20, "Numeric");
385             f[n++] = make_field(3, 20, 1, 12);
386             set_field_type(f[n - 1], TYPE_NUMERIC, 3, -10000.0, 100000000.0);
387
388             break;
389         }
390
391         f[n++] = make_label(5, 0, "Comments");
392         f[n++] = make_field(6, 0, 4, 46);
393     }
394
395     f[n++] = (FIELD *) 0;
396
397     form = new_form(f);
398
399     display_form(form);
400
401     w = form_win(form);
402     also = newwin(getmaxy(stdscr) - getmaxy(w), COLS, getmaxy(w), 0);
403     show_current_field(also, form);
404
405     while (!finished) {
406         switch (edit_field(form, &c)) {
407         case E_OK:
408             break;
409         case E_UNKNOWN_COMMAND:
410             finished = my_form_driver(form, c);
411             break;
412         default:
413             beep();
414             break;
415         }
416         show_current_field(also, form);
417     }
418
419     erase_form(form);
420
421     free_form(form);
422     for (c = 0; f[c] != 0; c++)
423         free_field(f[c]);
424     noraw();
425     nl();
426 }
427
428 static void
429 usage(void)
430 {
431     static const char *tbl[] =
432     {
433         "Usage: demo_forms [options]"
434         ,""
435         ," -d        make fields dynamic"
436         ," -j value  justify (1=left, 2=center, 3=right)"
437         ," -m value  set maximum size of dynamic fields"
438         ," -o value  specify number of offscreen rows in new_field()"
439         ," -t value  specify text to fill fields initially"
440     };
441     unsigned int j;
442     for (j = 0; j < SIZEOF(tbl); ++j)
443         fprintf(stderr, "%s\n", tbl[j]);
444     exit(EXIT_FAILURE);
445 }
446
447 int
448 main(int argc, char *argv[])
449 {
450     int ch;
451
452     setlocale(LC_ALL, "");
453
454     while ((ch = getopt(argc, argv, "dj:m:o:t:")) != EOF) {
455         switch (ch) {
456         case 'd':
457             d_option = TRUE;
458             break;
459         case 'j':
460             j_value = atoi(optarg);
461             if (j_value < NO_JUSTIFICATION
462                 || j_value > JUSTIFY_RIGHT)
463                 usage();
464             break;
465         case 'm':
466             m_value = atoi(optarg);
467             break;
468         case 'o':
469             o_value = atoi(optarg);
470             break;
471         case 't':
472             t_value = optarg;
473             break;
474         default:
475             usage();
476
477         }
478     }
479
480     initscr();
481     cbreak();
482     noecho();
483     raw();
484     nonl();                     /* lets us read ^M's */
485     intrflush(stdscr, FALSE);
486     keypad(stdscr, TRUE);
487
488     if (has_colors()) {
489         start_color();
490         init_pair(1, COLOR_WHITE, COLOR_BLUE);
491         init_pair(2, COLOR_GREEN, COLOR_BLACK);
492         bkgd(COLOR_PAIR(1));
493         refresh();
494     }
495
496     demo_forms();
497
498     endwin();
499     ExitProgram(EXIT_SUCCESS);
500 }
501 #else
502 int
503 main(void)
504 {
505     printf("This program requires the curses form library\n");
506     ExitProgram(EXIT_FAILURE);
507 }
508 #endif