ncurses 5.9 - patch 20120303
[ncurses.git] / test / demo_termcap.c
1 /****************************************************************************
2  * Copyright (c) 2005-2011,2012 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  * Author: Thomas E. Dickey
31  *
32  * $Id: demo_termcap.c,v 1.17 2012/03/01 01:09:30 tom Exp $
33  *
34  * A simple demo of the termcap interface.
35  */
36 #define USE_TINFO
37 #include <test.priv.h>
38
39 #if HAVE_TGETENT
40
41 #if defined(HAVE_CURSES_DATA_BOOLNAMES) || defined(DECL_CURSES_DATA_BOOLNAMES)
42 #define USE_CODE_LISTS 1
43 #else
44 #define USE_CODE_LISTS 0
45 #endif
46
47 #define FCOLS 8
48 #define FNAME(type) "%s %-*s = ", #type, FCOLS
49
50 #if USE_CODE_LISTS
51 static bool b_opt = FALSE;
52 static bool n_opt = FALSE;
53 static bool s_opt = FALSE;
54 #endif
55
56 #define isCapName(c) (isgraph(c) && strchr("^#=:\\", c) == 0)
57
58 #if NO_LEAKS && USE_CODE_LISTS
59
60 #define MYSCR struct _myscr
61 MYSCR {
62     MYSCR *next;
63     TERMINAL *term;
64 };
65
66 static MYSCR *my_screens;
67
68 static void
69 save_screen(void)
70 {
71     MYSCR *obj = malloc(sizeof(MYSCR));
72     obj->next = my_screens;
73     obj->term = cur_term;
74     my_screens = obj;
75 }
76 #else
77 #define save_screen()           /* nothing */
78 #endif
79
80 static void
81 dumpit(NCURSES_CONST char *cap)
82 {
83     /*
84      * One of the limitations of the termcap interface is that the library
85      * cannot determine the size of the buffer passed via tgetstr(), nor the
86      * amount of space remaining.  This demo simply reuses the whole buffer
87      * for each call; a normal termcap application would try to use the buffer
88      * to hold all of the strings extracted from the terminal entry.
89      */
90     char area[1024], *ap = area;
91     char *str;
92     int num;
93
94     if ((str = tgetstr(cap, &ap)) != 0) {
95         /*
96          * Note that the strings returned are mostly terminfo format, since
97          * ncurses does not convert except for a handful of special cases.
98          */
99         printf(FNAME(str), cap);
100         while (*str != 0) {
101             int ch = UChar(*str++);
102             switch (ch) {
103             case '\177':
104                 fputs("^?", stdout);
105                 break;
106             case '\033':
107                 fputs("\\E", stdout);
108                 break;
109             case '\b':
110                 fputs("\\b", stdout);
111                 break;
112             case '\f':
113                 fputs("\\f", stdout);
114                 break;
115             case '\n':
116                 fputs("\\n", stdout);
117                 break;
118             case '\r':
119                 fputs("\\r", stdout);
120                 break;
121             case ' ':
122                 fputs("\\s", stdout);
123                 break;
124             case '\t':
125                 fputs("\\t", stdout);
126                 break;
127             case '^':
128                 fputs("\\^", stdout);
129                 break;
130             case ':':
131                 fputs("\\072", stdout);
132                 break;
133             case '\\':
134                 fputs("\\\\", stdout);
135                 break;
136             default:
137                 if (isgraph(ch))
138                     fputc(ch, stdout);
139                 else if (ch < 32)
140                     printf("^%c", ch + '@');
141                 else
142                     printf("\\%03o", ch);
143                 break;
144             }
145         }
146         printf("\n");
147     } else if ((num = tgetnum(cap)) >= 0) {
148         printf(FNAME(num), cap);
149         printf(" %d\n", num);
150     } else if (tgetflag(cap) > 0) {
151         printf(FNAME(flg), cap);
152         printf("%s\n", "true");
153     }
154     fflush(stdout);
155 }
156
157 static void
158 brute_force(const char *name)
159 {
160     char buffer[1024];
161
162     printf("Terminal type %s\n", name);
163     if (tgetent(buffer, name) >= 0) {
164         char cap[3];
165         int c1, c2;
166
167         cap[2] = 0;
168         for (c1 = 0; c1 < 256; ++c1) {
169             cap[0] = (char) c1;
170             if (isCapName(c1)) {
171                 for (c2 = 0; c2 < 256; ++c2) {
172                     cap[1] = (char) c2;
173                     if (isCapName(c2)) {
174                         dumpit(cap);
175                     }
176                 }
177             }
178         }
179     }
180 }
181
182 #if USE_CODE_LISTS
183 static void
184 demo_termcap(NCURSES_CONST char *name)
185 {
186     unsigned n;
187     NCURSES_CONST char *cap;
188
189     printf("Terminal type \"%s\"\n", name);
190 #if HAVE_SETUPTERM
191     setupterm(name, 1, (int *) 0);
192 #else
193     setterm(name);
194 #endif
195     save_screen();
196
197     if (b_opt) {
198         for (n = 0;; ++n) {
199             cap = boolcodes[n];
200             if (cap == 0)
201                 break;
202             dumpit(cap);
203         }
204     }
205
206     if (n_opt) {
207         for (n = 0;; ++n) {
208             cap = numcodes[n];
209             if (cap == 0)
210                 break;
211             dumpit(cap);
212         }
213     }
214
215     if (s_opt) {
216         for (n = 0;; ++n) {
217             cap = strcodes[n];
218             if (cap == 0)
219                 break;
220             dumpit(cap);
221         }
222     }
223 }
224
225 static void
226 usage(void)
227 {
228     static const char *msg[] =
229     {
230         "Usage: demo_termcap [options] [terminal]",
231         "",
232         "If no options are given, print all (boolean, numeric, string)",
233         "capabilities for the given terminal, using short names.",
234         "",
235         "Options:",
236         " -a       try all names, print capabilities found",
237         " -b       print boolean-capabilities",
238         " -n       print numeric-capabilities",
239         " -r COUNT repeat for given count",
240         " -s       print string-capabilities",
241     };
242     unsigned n;
243     for (n = 0; n < SIZEOF(msg); ++n) {
244         fprintf(stderr, "%s\n", msg[n]);
245     }
246     ExitProgram(EXIT_FAILURE);
247 }
248 #endif
249
250 int
251 main(int argc, char *argv[])
252 {
253     int n;
254     char *name;
255     bool a_opt = FALSE;
256
257 #if USE_CODE_LISTS
258     int repeat;
259     int r_opt = 1;
260
261     while ((n = getopt(argc, argv, "abnr:s")) != -1) {
262         switch (n) {
263         case 'a':
264             a_opt = TRUE;
265             break;
266         case 'b':
267             b_opt = TRUE;
268             break;
269         case 'n':
270             n_opt = TRUE;
271             break;
272         case 'r':
273             if ((r_opt = atoi(optarg)) <= 0)
274                 usage();
275             break;
276         case 's':
277             s_opt = TRUE;
278             break;
279         default:
280             usage();
281             break;
282         }
283     }
284
285     if (!(b_opt || n_opt || s_opt)) {
286         b_opt = TRUE;
287         n_opt = TRUE;
288         s_opt = TRUE;
289     }
290 #else
291     a_opt = TRUE;
292 #endif
293
294     if (a_opt) {
295         if (optind < argc) {
296             for (n = optind; n < argc; ++n) {
297                 brute_force(argv[n]);
298             }
299         } else if ((name = getenv("TERM")) != 0) {
300             brute_force(name);
301         } else {
302             static char dumb[] = "dumb";
303             brute_force(dumb);
304         }
305     }
306 #if USE_CODE_LISTS
307     else {
308         for (repeat = 0; repeat < r_opt; ++repeat) {
309             if (optind < argc) {
310                 for (n = optind; n < argc; ++n) {
311                     demo_termcap(argv[n]);
312                 }
313             } else if ((name = getenv("TERM")) != 0) {
314                 demo_termcap(name);
315             } else {
316                 static char dumb[] = "dumb";
317                 demo_termcap(dumb);
318             }
319         }
320 #if NO_LEAKS
321         /*
322          * ncurses' tgetent() interface caches some entries and its no-leaks
323          * code discards those.  The calls to setupterm() on the other hand
324          * are not cached, and each call allocates a chunk of memory, even
325          * if the same terminal type is requested repeatedly.
326          */
327         while (my_screens != 0) {
328             MYSCR *next = my_screens->next;
329             del_curterm(my_screens->term);
330             free(my_screens);
331             my_screens = next;
332         }
333 #endif
334     }
335 #endif /* USE_CODE_LISTS */
336
337     ExitProgram(EXIT_SUCCESS);
338 }
339
340 #else
341 int
342 main(int argc GCC_UNUSED,
343      char *argv[]GCC_UNUSED)
344 {
345     printf("This program requires termcap\n");
346     exit(EXIT_FAILURE);
347 }
348 #endif