blob: 72b20cfb0c1da7d018101329acab146b6d98457d [file] [log] [blame]
micky3879b9f5e72025-07-08 18:04:53 -04001/****************************************************************************
2 * Copyright 2019-2022,2023 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.29 2023/06/24 14:14:56 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 */
44typedef struct {
45 const char *name;
46 FILE *fp;
47 SCREEN *sp;
48 TERMINAL *term;
49 int (*outc) (SCREEN *, int);
50} MYDATA;
51
52static bool opt_n = FALSE; /* true to suppress new_prescr */
53static bool opt_t = FALSE; /* true to use termcap */
54
55static int
56my_outc(SCREEN *sp, int ch)
57{
58 (void) sp;
59 return fputc(ch, stdout);
60}
61
62static int
63my_errc(SCREEN *sp, int ch)
64{
65 (void) sp;
66 return fputc(ch, stderr);
67}
68
69static MYDATA *
70initialize(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
92static void
93show_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
107static void
108show_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
116static void
117show_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
128static void
129show_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
137static void
138show_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
162static void
163show_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
173static void
174show_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
186static void
187do_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
277static void
278cleanup(MYDATA * data)
279{
280 set_curterm(data->term);
281 del_curterm(data->term);
282 free(data);
283}
284
285static void
286usage(int ok)
287{
288 static const char *tbl[] =
289 {
290 "Usage: sp_tinfo [output] [error]"
291 ,""
292 ,USAGE_COMMON
293 ,"Options:"
294 ," -n suppress call to new_prescr()"
295 ," -t use termcap functions rather than terminfo"
296 };
297 size_t n;
298 for (n = 0; n < SIZEOF(tbl); ++n) {
299 fprintf(stderr, "%s\n", tbl[n]);
300 }
301 ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
302}
303/* *INDENT-OFF* */
304VERSION_COMMON()
305/* *INDENT-ON* */
306
307int
308main(int argc, char *argv[])
309{
310 MYDATA *my_out;
311 MYDATA *my_err;
312 int ch;
313
314 while ((ch = getopt(argc, argv, OPTS_COMMON "nt")) != -1) {
315 switch (ch) {
316 case 'n':
317 opt_n = TRUE;
318 break;
319 case 't':
320 opt_t = TRUE;
321 break;
322 case OPTS_VERSION:
323 show_version(argv);
324 ExitProgram(EXIT_SUCCESS);
325 default:
326 usage(ch == OPTS_USAGE);
327 /* NOTREACHED */
328 }
329 }
330 argv += (optind - 1);
331 argc -= (optind - 1);
332
333 if (argc > 3)
334 usage(FALSE);
335
336 my_out = initialize((argc > 1) ? argv[1] : "vt100", stdout);
337 my_err = initialize((argc > 2) ? argv[2] : "ansi", stderr);
338
339 do_stuff(my_out);
340 do_stuff(my_err);
341
342 if (my_out != my_err) {
343 cleanup(my_out);
344 cleanup(my_err);
345 } else {
346 cleanup(my_out);
347 }
348
349 ExitProgram(EXIT_SUCCESS);
350}
351#else
352int
353main(void)
354{
355 fprintf(stderr,
356 "This program requires the low-level ncurses sp-funcs tputs_sp\n");
357 ExitProgram(EXIT_FAILURE);
358}
359#endif