ncurses 6.0 - patch 20170617
[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.21 2017/06/17 21:19:25 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 ? NULL : 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((NCURSES_CONST char *) 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 #define TC_PARMS data->sp, (NCURSES_CONST char *)tc
104 #define TI_PARMS data->sp, (NCURSES_CONST char *)ti
105
106 static void
107 show_cap_flag(MYDATA * data, const char *ti, const char *tc)
108 {
109     const char *name = (opt_t ? tc : ti);
110     show_flag(data, name, (opt_t
111                            ? tgetflag_sp(TC_PARMS)
112                            : tigetflag_sp(TI_PARMS)));
113 }
114
115 static void
116 show_number(MYDATA * data, const char *name, int value)
117 {
118     if (value <= -2) {
119         fprintf(data->fp, " %s = (unknown)\n", name);
120     } else if (value <= -1) {
121         fprintf(data->fp, " %s = (missing)\n", name);
122     } else {
123         fprintf(data->fp, " %s = %d\n", name, value);
124     }
125 }
126
127 static void
128 show_cap_number(MYDATA * data, const char *ti, const char *tc)
129 {
130     const char *name = (opt_t ? tc : ti);
131     show_number(data, name, (opt_t
132                              ? tgetnum_sp(TC_PARMS)
133                              : tigetnum_sp(TI_PARMS)));
134 }
135
136 static void
137 show_string(MYDATA * data, const char *name, const char *value)
138 {
139     fprintf(data->fp, " %s = ", name);
140     if (value == 0) {
141         fprintf(data->fp, "(missing)");
142     } else if (value == (char *) -1) {
143         fprintf(data->fp, "(canceled)");
144     } else {
145         int ch;
146         while ((ch = UChar(*value++)) != '\0') {
147             if (ch < 32) {
148                 fprintf(data->fp, "^%c", ch | '@');
149             } else if (ch == 127) {
150                 fprintf(data->fp, "^?");
151             } else if (ch > 127) {
152                 fprintf(data->fp, "\\%03o", ch);
153             } else {
154                 fprintf(data->fp, "%c", ch);
155             }
156         }
157     }
158     fprintf(data->fp, "\n");
159 }
160
161 static void
162 show_cap_string(MYDATA * data, const char *ti, const char *tc)
163 {
164     const char *name = (opt_t ? tc : ti);
165     char tcapjunk[1024];
166     char *tcap_ptr = tcapjunk;
167     show_string(data, name, (opt_t
168                              ? tgetstr_sp(TC_PARMS, &tcap_ptr)
169                              : tigetstr_sp(TI_PARMS)));
170 }
171
172 static void
173 show_char(MYDATA * data, const char *name, int value)
174 {
175     if (value < 0) {
176         show_string(data, name, "(missing)");
177     } else {
178         char temp[2];
179         temp[0] = (char) value;
180         temp[1] = '\0';
181         show_string(data, name, temp);
182     }
183 }
184
185 static void
186 do_stuff(MYDATA * data)
187 {
188     char *s;
189     SCREEN *sp = data->sp;
190     int my_code = 1234;
191     const char *my_text = "\033[?m";
192
193     set_curterm_sp(sp, data->term);
194
195     /* putp always goes to standard output */
196     putp_sp(sp, "Hello ");
197     putp_sp(sp, data->name);
198     putp_sp(sp, "!\n");
199
200     fprintf(data->fp, "Term: %s\n", termname_sp(sp));
201     fprintf(data->fp, "Long: %s\n", longname_sp(sp));
202     show_cap_flag(data, "am", "am");
203     show_cap_number(data, "lines", "li");
204     show_cap_string(data, "clear", "cl");
205     show_cap_string(data, "tbc", "ct");
206     show_flag(data, "has_ic", has_ic_sp(sp));
207     show_flag(data, "has_il", has_il_sp(sp));
208     show_number(data, "baudrate", baudrate_sp(sp));
209     show_char(data, "erase ch", erasechar_sp(sp));
210     show_char(data, "kill ch", killchar_sp(sp));
211     show_string(data, "unctrl", unctrl_sp(sp, 033));
212     fflush(data->fp);
213
214     define_key_sp(sp, my_text, my_code);
215     has_key_sp(sp, 0);
216     key_defined_sp(sp, my_text);
217     if ((s = keybound_sp(sp, my_code, 0)) != 0)
218         free(s);
219     keyname_sp(sp, '?');
220     keyok_sp(sp, my_code, FALSE);
221     keyok_sp(sp, my_code, TRUE);
222
223     savetty_sp(sp);
224
225     def_shell_mode_sp(sp);
226
227     /*
228      * These functions are low-level settings for ncurses.
229      */
230     set_tabsize_sp(sp, 5);      /* waddch */
231     typeahead_sp(sp, FALSE);    /* waddch */
232     use_env_sp(sp, FALSE);      /* newterm */
233     use_tioctl_sp(sp, FALSE);   /* newterm */
234     intrflush_sp(sp, 0, 0);     /* wgetch */
235     flushinp_sp(sp);            /* waddch */
236     halfdelay_sp(sp, 5);        /* wgetch */
237
238     /*
239      * These manipulate the terminal modes, mainly for wgetch.
240      */
241     cbreak_sp(sp);
242     raw_sp(sp);
243     def_prog_mode_sp(sp);
244
245     delay_output_sp(sp, 200);
246
247     napms_sp(sp, 10);
248
249     nocbreak_sp(sp);
250     noqiflush_sp(sp);
251     noraw_sp(sp);
252     qiflush_sp(sp);
253
254     resetty_sp(sp);
255
256     tputs_sp(sp, "{reset-mode}\n", 0, data->outc);
257
258     reset_prog_mode_sp(sp);
259
260     curs_set_sp(sp, 0);
261     tputs_sp(sp, "{prog-mode}\n", 0, data->outc);
262
263     reset_shell_mode_sp(sp);
264
265     tputs_sp(sp, "{shell-mode}\n", 0, data->outc);
266 }
267
268 static void
269 cleanup(MYDATA * data)
270 {
271     set_curterm(data->term);
272     del_curterm(data->term);
273 #if !NO_LEAKS
274     free(data->sp);             /* cannot use delscreen in tinfo */
275 #endif
276     free(data);
277 }
278
279 static void
280 usage(void)
281 {
282     static const char *tbl[] =
283     {
284         "Usage: sp_tinfo [output] [error]",
285         "",
286         "Options:",
287         " -n   suppress call to new_prescr()",
288         " -t   use termcap functions rather than terminfo",
289         NULL
290     };
291     size_t n;
292     for (n = 0; n < SIZEOF(tbl); ++n) {
293         fprintf(stderr, "%s\n", tbl[n]);
294     }
295     ExitProgram(EXIT_FAILURE);
296 }
297
298 int
299 main(int argc, char *argv[])
300 {
301     MYDATA *my_out;
302     MYDATA *my_err;
303     int n;
304
305     while ((n = getopt(argc, argv, "nt")) != -1) {
306         switch (n) {
307         case 'n':
308             opt_n = TRUE;
309             break;
310         case 't':
311             opt_t = TRUE;
312             break;
313         default:
314             usage();
315             /* NOTREACHED */
316         }
317     }
318     argv += (optind - 1);
319     argc -= (optind - 1);
320
321     if (argc > 3)
322         usage();
323
324     my_out = initialize((argc > 1) ? argv[1] : "vt100", stdout);
325     my_err = initialize((argc > 2) ? argv[2] : "ansi", stderr);
326
327     do_stuff(my_out);
328     do_stuff(my_err);
329
330     cleanup(my_out);
331     cleanup(my_err);
332
333     ExitProgram(EXIT_SUCCESS);
334 }
335 #else
336 int
337 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
338 {
339     fprintf(stderr,
340             "This program requires the low-level ncurses sp-funcs tputs_sp\n");
341     ExitProgram(EXIT_FAILURE);
342 }
343 #endif