ncurses 6.2 - patch 20200418
[ncurses.git] / test / sp_tinfo.c
1 /****************************************************************************
2  * Copyright 2019,2020 Thomas E. Dickey                                     *
3  * Copyright 2017 Free Software Foundation, Inc.                            *
4  *                                                                          *
5  * Permission is hereby granted, free of charge, to any person obtaining a  *
6  * copy of this software and associated documentation files (the            *
7  * "Software"), to deal in the Software without restriction, including      *
8  * without limitation the rights to use, copy, modify, merge, publish,      *
9  * distribute, distribute with modifications, sublicense, and/or sell       *
10  * copies of the Software, and to permit persons to whom the Software is    *
11  * furnished to do so, subject to the following conditions:                 *
12  *                                                                          *
13  * The above copyright notice and this permission notice shall be included  *
14  * in all copies or substantial portions of the Software.                   *
15  *                                                                          *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23  *                                                                          *
24  * Except as contained in this notice, the name(s) of the above copyright   *
25  * holders shall not be used in advertising or otherwise to promote the     *
26  * sale, use or other dealings in this Software without prior written       *
27  * authorization.                                                           *
28  ****************************************************************************/
29
30 /*
31  * $Id: sp_tinfo.c,v 1.23 2020/02/02 23:34:34 tom Exp $
32  *
33  * TOTO: add option for non-sp-funcs interface
34  */
35
36 #define USE_TINFO
37 #include <test.priv.h>
38
39 #if HAVE_TPUTS_SP
40 /*
41  * The higher-level curses library stores a TERMINAL* inside SCREEN, but the
42  * latter is opaque.  This structure helps us keep the two associated.
43  */
44 typedef struct {
45     const char *name;
46     FILE *fp;
47     SCREEN *sp;
48     TERMINAL *term;
49     int (*outc) (SCREEN *, int);
50 } MYDATA;
51
52 static bool opt_n = FALSE;      /* true to suppress new_prescr */
53 static bool opt_t = FALSE;      /* true to use termcap */
54
55 static int
56 my_outc(SCREEN *sp, int ch)
57 {
58     (void) sp;
59     return fputc(ch, stdout);
60 }
61
62 static int
63 my_errc(SCREEN *sp, int ch)
64 {
65     (void) sp;
66     return fputc(ch, stderr);
67 }
68
69 static MYDATA *
70 initialize(const char *name, FILE *output)
71 {
72     MYDATA *result = typeCalloc(MYDATA, 1);
73     int error;
74
75     result->fp = output;
76     result->name = name;
77     result->outc = (fileno(output) == 1) ? my_outc : my_errc;
78     result->sp = opt_n ? NULL : new_prescr();
79
80     if (opt_t) {
81         char *temp = strdup(name);
82         tgetent_sp(result->sp, temp, name);
83         free(temp);
84     } else {
85         setupterm((NCURSES_CONST char *) name, fileno(output), &error);
86     }
87     result->term = cur_term;
88
89     return result;
90 }
91
92 static void
93 show_flag(MYDATA * data, const char *name, int value)
94 {
95     if (value < 0) {
96         fprintf(data->fp, " %s = (unknown)\n", name);
97     } else if (value == 0) {
98         fprintf(data->fp, " %s = false\n", name);
99     } else {
100         fprintf(data->fp, " %s = true\n", name);
101     }
102 }
103
104 #define TC_PARMS data->sp, (NCURSES_CONST char *)tc
105 #define TI_PARMS data->sp, (NCURSES_CONST char *)ti
106
107 static void
108 show_cap_flag(MYDATA * data, const char *ti, const char *tc)
109 {
110     const char *name = (opt_t ? tc : ti);
111     show_flag(data, name, (opt_t
112                            ? tgetflag_sp(TC_PARMS)
113                            : tigetflag_sp(TI_PARMS)));
114 }
115
116 static void
117 show_number(MYDATA * data, const char *name, int value)
118 {
119     if (value <= -2) {
120         fprintf(data->fp, " %s = (unknown)\n", name);
121     } else if (value <= -1) {
122         fprintf(data->fp, " %s = (missing)\n", name);
123     } else {
124         fprintf(data->fp, " %s = %d\n", name, value);
125     }
126 }
127
128 static void
129 show_cap_number(MYDATA * data, const char *ti, const char *tc)
130 {
131     const char *name = (opt_t ? tc : ti);
132     show_number(data, name, (opt_t
133                              ? tgetnum_sp(TC_PARMS)
134                              : tigetnum_sp(TI_PARMS)));
135 }
136
137 static void
138 show_string(MYDATA * data, const char *name, const char *value)
139 {
140     fprintf(data->fp, " %s = ", name);
141     if (value == 0) {
142         fprintf(data->fp, "(missing)");
143     } else if (value == (char *) -1) {
144         fprintf(data->fp, "(canceled)");
145     } else {
146         int ch;
147         while ((ch = UChar(*value++)) != '\0') {
148             if (ch < 32) {
149                 fprintf(data->fp, "^%c", ch | '@');
150             } else if (ch == 127) {
151                 fprintf(data->fp, "^?");
152             } else if (ch > 127) {
153                 fprintf(data->fp, "\\%03o", ch);
154             } else {
155                 fprintf(data->fp, "%c", ch);
156             }
157         }
158     }
159     fprintf(data->fp, "\n");
160 }
161
162 static void
163 show_cap_string(MYDATA * data, const char *ti, const char *tc)
164 {
165     const char *name = (opt_t ? tc : ti);
166     char tcapjunk[1024];
167     char *tcap_ptr = tcapjunk;
168     show_string(data, name, (opt_t
169                              ? tgetstr_sp(TC_PARMS, &tcap_ptr)
170                              : tigetstr_sp(TI_PARMS)));
171 }
172
173 static void
174 show_char(MYDATA * data, const char *name, int value)
175 {
176     if (value < 0) {
177         show_string(data, name, "(missing)");
178     } else {
179         char temp[2];
180         temp[0] = (char) value;
181         temp[1] = '\0';
182         show_string(data, name, temp);
183     }
184 }
185
186 static void
187 do_stuff(MYDATA * data)
188 {
189     SCREEN *sp = data->sp;
190 #if NCURSES_EXT_FUNCS
191     char *s;
192     int my_code = 1234;
193     const char *my_text = "\033[?m";
194 #endif
195
196     set_curterm_sp(sp, data->term);
197
198     /* putp always goes to standard output */
199     putp_sp(sp, "Hello ");
200     putp_sp(sp, data->name);
201     putp_sp(sp, "!\n");
202
203     fprintf(data->fp, "Term: %s\n", termname_sp(sp));
204     fprintf(data->fp, "Long: %s\n", longname_sp(sp));
205     show_cap_flag(data, "am", "am");
206     show_cap_number(data, "lines", "li");
207     show_cap_string(data, "clear", "cl");
208     show_cap_string(data, "tbc", "ct");
209     show_flag(data, "has_ic", has_ic_sp(sp));
210     show_flag(data, "has_il", has_il_sp(sp));
211     show_number(data, "baudrate", baudrate_sp(sp));
212     show_char(data, "erase ch", erasechar_sp(sp));
213     show_char(data, "kill ch", killchar_sp(sp));
214     show_string(data, "unctrl", unctrl_sp(sp, 033));
215     fflush(data->fp);
216
217 #if NCURSES_EXT_FUNCS
218     define_key_sp(sp, my_text, my_code);
219     has_key_sp(sp, 0);
220     key_defined_sp(sp, my_text);
221     if ((s = keybound_sp(sp, my_code, 0)) != 0)
222         free(s);
223 #endif
224     keyname_sp(sp, '?');
225 #if NCURSES_EXT_FUNCS
226     keyok_sp(sp, my_code, FALSE);
227     keyok_sp(sp, my_code, TRUE);
228 #endif
229
230     savetty_sp(sp);
231
232     def_shell_mode_sp(sp);
233
234     /*
235      * These functions are low-level settings for ncurses.
236      */
237 #if NCURSES_EXT_FUNCS
238     set_tabsize_sp(sp, 5);      /* waddch */
239 #endif
240     typeahead_sp(sp, FALSE);    /* waddch */
241     use_env_sp(sp, FALSE);      /* newterm */
242     use_tioctl_sp(sp, FALSE);   /* newterm */
243     intrflush_sp(sp, 0, 0);     /* wgetch */
244     flushinp_sp(sp);            /* waddch */
245     halfdelay_sp(sp, 5);        /* wgetch */
246
247     /*
248      * These manipulate the terminal modes, mainly for wgetch.
249      */
250     cbreak_sp(sp);
251     raw_sp(sp);
252     def_prog_mode_sp(sp);
253
254     delay_output_sp(sp, 200);
255
256     napms_sp(sp, 10);
257
258     nocbreak_sp(sp);
259     noqiflush_sp(sp);
260     noraw_sp(sp);
261     qiflush_sp(sp);
262
263     resetty_sp(sp);
264
265     tputs_sp(sp, "{reset-mode}\n", 0, data->outc);
266
267     reset_prog_mode_sp(sp);
268
269     curs_set_sp(sp, 0);
270     tputs_sp(sp, "{prog-mode}\n", 0, data->outc);
271
272     reset_shell_mode_sp(sp);
273
274     tputs_sp(sp, "{shell-mode}\n", 0, data->outc);
275 }
276
277 static void
278 cleanup(MYDATA * data)
279 {
280     set_curterm(data->term);
281     del_curterm(data->term);
282 #if !NO_LEAKS
283     free(data->sp);             /* cannot use delscreen in tinfo */
284 #endif
285     free(data);
286 }
287
288 static void
289 usage(void)
290 {
291     static const char *tbl[] =
292     {
293         "Usage: sp_tinfo [output] [error]",
294         "",
295         "Options:",
296         " -n   suppress call to new_prescr()",
297         " -t   use termcap functions rather than terminfo",
298         NULL
299     };
300     size_t n;
301     for (n = 0; n < SIZEOF(tbl); ++n) {
302         fprintf(stderr, "%s\n", tbl[n]);
303     }
304     ExitProgram(EXIT_FAILURE);
305 }
306
307 int
308 main(int argc, char *argv[])
309 {
310     MYDATA *my_out;
311     MYDATA *my_err;
312     int n;
313
314     while ((n = getopt(argc, argv, "nt")) != -1) {
315         switch (n) {
316         case 'n':
317             opt_n = TRUE;
318             break;
319         case 't':
320             opt_t = TRUE;
321             break;
322         default:
323             usage();
324             /* NOTREACHED */
325         }
326     }
327     argv += (optind - 1);
328     argc -= (optind - 1);
329
330     if (argc > 3)
331         usage();
332
333     my_out = initialize((argc > 1) ? argv[1] : "vt100", stdout);
334     my_err = initialize((argc > 2) ? argv[2] : "ansi", stderr);
335
336     do_stuff(my_out);
337     do_stuff(my_err);
338
339     cleanup(my_out);
340     cleanup(my_err);
341
342     ExitProgram(EXIT_SUCCESS);
343 }
344 #else
345 int
346 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
347 {
348     fprintf(stderr,
349             "This program requires the low-level ncurses sp-funcs tputs_sp\n");
350     ExitProgram(EXIT_FAILURE);
351 }
352 #endif