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