ncurses 6.0 - patch 20170401
[ncurses.git] / test / sp_tinfo.c
1 /****************************************************************************
2  * Copyright (c) 2017 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 /*
30  * $Id: sp_tinfo.c,v 1.17 2017/04/02 01:03:30 tom Exp $
31  *
32  * TOTO: add option for non-sp-funcs interface
33  */
34
35 #define USE_TINFO
36 #include <test.priv.h>
37
38 #if HAVE_TPUTS_SP
39 /*
40  * The higher-level curses library stores a TERMINAL* inside SCREEN, but the
41  * latter is opaque.  This structure helps us keep the two associated.
42  */
43 typedef struct {
44     const char *name;
45     FILE *fp;
46     SCREEN *sp;
47     TERMINAL *term;
48     int (*outc) (SCREEN *, int);
49 } MYDATA;
50
51 static bool opt_n = FALSE;      /* true to suppress new_prescr */
52 static bool opt_t = FALSE;      /* true to use termcap */
53
54 static int
55 my_outc(SCREEN *sp, int ch)
56 {
57     (void) sp;
58     return fputc(ch, stdout);
59 }
60
61 static int
62 my_errc(SCREEN *sp, int ch)
63 {
64     (void) sp;
65     return fputc(ch, stderr);
66 }
67
68 static MYDATA *
69 initialize(const char *name, FILE *output)
70 {
71     MYDATA *result = typeCalloc(MYDATA, 1);
72     int error;
73
74     result->fp = output;
75     result->name = name;
76     result->outc = (fileno(output) == 1) ? my_outc : my_errc;
77     result->sp = opt_n ? 0 : new_prescr();
78
79     if (opt_t) {
80         char *temp = strdup(name);
81         tgetent_sp(result->sp, temp, name);
82         free(temp);
83     } else {
84         setupterm(name, fileno(output), &error);
85     }
86     result->term = cur_term;
87
88     return result;
89 }
90
91 static void
92 show_flag(MYDATA * data, const char *name, int value)
93 {
94     if (value < 0) {
95         fprintf(data->fp, " %s = (unknown)\n", name);
96     } else if (value == 0) {
97         fprintf(data->fp, " %s = false\n", name);
98     } else {
99         fprintf(data->fp, " %s = true\n", name);
100     }
101 }
102
103 static void
104 show_cap_flag(MYDATA * data, const char *ti, const char *tc)
105 {
106     const char *name = (opt_t ? tc : ti);
107     show_flag(data, name, (opt_t
108                            ? tgetflag_sp(data->sp, tc)
109                            : tigetflag_sp(data->sp, ti)));
110 }
111
112 static void
113 show_number(MYDATA * data, const char *name, int value)
114 {
115     if (value <= -2) {
116         fprintf(data->fp, " %s = (unknown)\n", name);
117     } else if (value <= -1) {
118         fprintf(data->fp, " %s = (missing)\n", name);
119     } else {
120         fprintf(data->fp, " %s = %d\n", name, value);
121     }
122 }
123
124 static void
125 show_cap_number(MYDATA * data, const char *ti, const char *tc)
126 {
127     const char *name = (opt_t ? tc : ti);
128     show_number(data, name, (opt_t
129                              ? tgetnum_sp(data->sp, tc)
130                              : tigetnum_sp(data->sp, ti)));
131 }
132
133 static void
134 show_string(MYDATA * data, const char *name, const char *value)
135 {
136     fprintf(data->fp, " %s = ", name);
137     if (value == 0) {
138         fprintf(data->fp, "(missing)");
139     } else if (value == (char *) -1) {
140         fprintf(data->fp, "(canceled)");
141     } else {
142         int ch;
143         while ((ch = UChar(*value++)) != '\0') {
144             if (ch < 32) {
145                 fprintf(data->fp, "^%c", ch | '@');
146             } else if (ch == 127) {
147                 fprintf(data->fp, "^?");
148             } else if (ch > 127) {
149                 fprintf(data->fp, "\\%03o", ch);
150             } else {
151                 fprintf(data->fp, "%c", ch);
152             }
153         }
154     }
155     fprintf(data->fp, "\n");
156 }
157
158 static void
159 show_cap_string(MYDATA * data, const char *ti, const char *tc)
160 {
161     const char *name = (opt_t ? tc : ti);
162     char tcapjunk[1024];
163     char *tcap_ptr = tcapjunk;
164     show_string(data, name, (opt_t
165                              ? tgetstr_sp(data->sp, tc, &tcap_ptr)
166                              : tigetstr_sp(data->sp, ti)));
167 }
168
169 static void
170 show_char(MYDATA * data, const char *name, int value)
171 {
172     if (value < 0) {
173         show_string(data, name, "(missing)");
174     } else {
175         char temp[2];
176         temp[0] = (char) value;
177         temp[1] = '\0';
178         show_string(data, name, temp);
179     }
180 }
181
182 static void
183 do_stuff(MYDATA * data)
184 {
185     char *s;
186     SCREEN *sp = data->sp;
187     int my_code = 1234;
188     const char *my_text = "\033[?m";
189
190     set_curterm_sp(sp, data->term);
191
192     /* putp always goes to standard output */
193     putp_sp(sp, "Hello ");
194     putp_sp(sp, data->name);
195     putp_sp(sp, "!\n");
196
197     fprintf(data->fp, "Term: %s\n", termname_sp(sp));
198     fprintf(data->fp, "Long: %s\n", longname_sp(sp));
199     show_cap_flag(data, "am", "am");
200     show_cap_number(data, "lines", "li");
201     show_cap_string(data, "clear", "cl");
202     show_cap_string(data, "tbc", "ct");
203     show_flag(data, "has_ic", has_ic_sp(sp));
204     show_flag(data, "has_il", has_il_sp(sp));
205     show_number(data, "baudrate", baudrate_sp(sp));
206     show_char(data, "erase ch", erasechar_sp(sp));
207     show_char(data, "kill ch", killchar_sp(sp));
208     show_string(data, "unctrl", unctrl_sp(sp, 033));
209     fflush(data->fp);
210
211     define_key_sp(sp, my_text, my_code);
212     has_key_sp(sp, 0);
213     key_defined_sp(sp, my_text);
214     if ((s = keybound_sp(sp, my_code, 0)) != 0)
215         free(s);
216     keyname_sp(sp, '?');
217     keyok_sp(sp, my_code, FALSE);
218     keyok_sp(sp, my_code, TRUE);
219
220     savetty_sp(sp);
221
222     def_shell_mode_sp(sp);
223
224     /*
225      * These functions are low-level settings for ncurses.
226      */
227     set_tabsize_sp(sp, 5);      /* waddch */
228     typeahead_sp(sp, FALSE);    /* waddch */
229     use_env_sp(sp, FALSE);      /* newterm */
230     use_tioctl_sp(sp, FALSE);   /* newterm */
231     intrflush_sp(sp, 0, 0);     /* wgetch */
232     flushinp_sp(sp);            /* waddch */
233     halfdelay_sp(sp, 5);        /* wgetch */
234
235     /*
236      * These manipulate the terminal modes, mainly for wgetch.
237      */
238     cbreak_sp(sp);
239     raw_sp(sp);
240     def_prog_mode_sp(sp);
241
242     delay_output_sp(sp, 200);
243
244     napms_sp(sp, 10);
245
246     nocbreak_sp(sp);
247     noqiflush_sp(sp);
248     noraw_sp(sp);
249     qiflush_sp(sp);
250
251     resetty_sp(sp);
252
253     tputs_sp(sp, "{reset-mode}\n", 0, data->outc);
254
255     reset_prog_mode_sp(sp);
256
257     curs_set_sp(sp, 0);
258     tputs_sp(sp, "{prog-mode}\n", 0, data->outc);
259
260     reset_shell_mode_sp(sp);
261
262     tputs_sp(sp, "{shell-mode}\n", 0, data->outc);
263 }
264
265 static void
266 cleanup(MYDATA * data)
267 {
268     set_curterm(data->term);
269     del_curterm(data->term);
270     free(data->sp);             /* cannot use delscreen in tinfo */
271     free(data);
272 }
273
274 static void
275 usage(void)
276 {
277     static const char *tbl[] =
278     {
279         "Usage: sp_tinfo [output] [error]",
280         "",
281         "Options:",
282         " -n   suppress call to new_prescr()",
283         " -t   use termcap functions rather than terminfo",
284         NULL
285     };
286     size_t n;
287     for (n = 0; n < SIZEOF(tbl); ++n) {
288         fprintf(stderr, "%s\n", tbl[n]);
289     }
290     ExitProgram(EXIT_FAILURE);
291 }
292
293 int
294 main(int argc, char *argv[])
295 {
296     MYDATA *my_out;
297     MYDATA *my_err;
298     int n;
299
300     while ((n = getopt(argc, argv, "nt")) != -1) {
301         switch (n) {
302         case 'n':
303             opt_n = TRUE;
304             break;
305         case 't':
306             opt_t = TRUE;
307             break;
308         default:
309             usage();
310             /* NOTREACHED */
311         }
312     }
313     argv += (optind - 1);
314     argc -= (optind - 1);
315
316     if (argc > 3)
317         usage();
318
319     my_out = initialize((argc > 1) ? argv[1] : "vt100", stdout);
320     my_err = initialize((argc > 2) ? argv[2] : "ansi", stderr);
321
322     do_stuff(my_out);
323     do_stuff(my_err);
324
325     cleanup(my_out);
326     cleanup(my_err);
327
328     ExitProgram(EXIT_SUCCESS);
329 }
330 #else
331 int
332 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
333 {
334     fprintf(stderr,
335             "This program requires the low-level ncurses sp-funcs tputs_sp\n");
336     ExitProgram(EXIT_FAILURE);
337 }
338 #endif