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