ncurses 6.1 - patch 20191123
[ncurses.git] / test / sp_tinfo.c
1 /****************************************************************************
2  * Copyright (c) 2017,2019 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.22 2019/04/06 20:42:57 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     SCREEN *sp = data->sp;
189 #if NCURSES_EXT_FUNCS
190     char *s;
191     int my_code = 1234;
192     const char *my_text = "\033[?m";
193 #endif
194
195     set_curterm_sp(sp, data->term);
196
197     /* putp always goes to standard output */
198     putp_sp(sp, "Hello ");
199     putp_sp(sp, data->name);
200     putp_sp(sp, "!\n");
201
202     fprintf(data->fp, "Term: %s\n", termname_sp(sp));
203     fprintf(data->fp, "Long: %s\n", longname_sp(sp));
204     show_cap_flag(data, "am", "am");
205     show_cap_number(data, "lines", "li");
206     show_cap_string(data, "clear", "cl");
207     show_cap_string(data, "tbc", "ct");
208     show_flag(data, "has_ic", has_ic_sp(sp));
209     show_flag(data, "has_il", has_il_sp(sp));
210     show_number(data, "baudrate", baudrate_sp(sp));
211     show_char(data, "erase ch", erasechar_sp(sp));
212     show_char(data, "kill ch", killchar_sp(sp));
213     show_string(data, "unctrl", unctrl_sp(sp, 033));
214     fflush(data->fp);
215
216 #if NCURSES_EXT_FUNCS
217     define_key_sp(sp, my_text, my_code);
218     has_key_sp(sp, 0);
219     key_defined_sp(sp, my_text);
220     if ((s = keybound_sp(sp, my_code, 0)) != 0)
221         free(s);
222 #endif
223     keyname_sp(sp, '?');
224 #if NCURSES_EXT_FUNCS
225     keyok_sp(sp, my_code, FALSE);
226     keyok_sp(sp, my_code, TRUE);
227 #endif
228
229     savetty_sp(sp);
230
231     def_shell_mode_sp(sp);
232
233     /*
234      * These functions are low-level settings for ncurses.
235      */
236 #if NCURSES_EXT_FUNCS
237     set_tabsize_sp(sp, 5);      /* waddch */
238 #endif
239     typeahead_sp(sp, FALSE);    /* waddch */
240     use_env_sp(sp, FALSE);      /* newterm */
241     use_tioctl_sp(sp, FALSE);   /* newterm */
242     intrflush_sp(sp, 0, 0);     /* wgetch */
243     flushinp_sp(sp);            /* waddch */
244     halfdelay_sp(sp, 5);        /* wgetch */
245
246     /*
247      * These manipulate the terminal modes, mainly for wgetch.
248      */
249     cbreak_sp(sp);
250     raw_sp(sp);
251     def_prog_mode_sp(sp);
252
253     delay_output_sp(sp, 200);
254
255     napms_sp(sp, 10);
256
257     nocbreak_sp(sp);
258     noqiflush_sp(sp);
259     noraw_sp(sp);
260     qiflush_sp(sp);
261
262     resetty_sp(sp);
263
264     tputs_sp(sp, "{reset-mode}\n", 0, data->outc);
265
266     reset_prog_mode_sp(sp);
267
268     curs_set_sp(sp, 0);
269     tputs_sp(sp, "{prog-mode}\n", 0, data->outc);
270
271     reset_shell_mode_sp(sp);
272
273     tputs_sp(sp, "{shell-mode}\n", 0, data->outc);
274 }
275
276 static void
277 cleanup(MYDATA * data)
278 {
279     set_curterm(data->term);
280     del_curterm(data->term);
281 #if !NO_LEAKS
282     free(data->sp);             /* cannot use delscreen in tinfo */
283 #endif
284     free(data);
285 }
286
287 static void
288 usage(void)
289 {
290     static const char *tbl[] =
291     {
292         "Usage: sp_tinfo [output] [error]",
293         "",
294         "Options:",
295         " -n   suppress call to new_prescr()",
296         " -t   use termcap functions rather than terminfo",
297         NULL
298     };
299     size_t n;
300     for (n = 0; n < SIZEOF(tbl); ++n) {
301         fprintf(stderr, "%s\n", tbl[n]);
302     }
303     ExitProgram(EXIT_FAILURE);
304 }
305
306 int
307 main(int argc, char *argv[])
308 {
309     MYDATA *my_out;
310     MYDATA *my_err;
311     int n;
312
313     while ((n = getopt(argc, argv, "nt")) != -1) {
314         switch (n) {
315         case 'n':
316             opt_n = TRUE;
317             break;
318         case 't':
319             opt_t = TRUE;
320             break;
321         default:
322             usage();
323             /* NOTREACHED */
324         }
325     }
326     argv += (optind - 1);
327     argc -= (optind - 1);
328
329     if (argc > 3)
330         usage();
331
332     my_out = initialize((argc > 1) ? argv[1] : "vt100", stdout);
333     my_err = initialize((argc > 2) ? argv[2] : "ansi", stderr);
334
335     do_stuff(my_out);
336     do_stuff(my_err);
337
338     cleanup(my_out);
339     cleanup(my_err);
340
341     ExitProgram(EXIT_SUCCESS);
342 }
343 #else
344 int
345 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
346 {
347     fprintf(stderr,
348             "This program requires the low-level ncurses sp-funcs tputs_sp\n");
349     ExitProgram(EXIT_FAILURE);
350 }
351 #endif