ncurses 5.9 - patch 20140719
[ncurses.git] / test / demo_termcap.c
1 /****************************************************************************
2  * Copyright (c) 2005-2013,2014 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.26 2014/07/19 22:49:52 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 static bool q_opt = FALSE;
57
58 static char *d_opt;
59 static char *e_opt;
60 static char **db_list;
61 static int db_item;
62
63 static long total_values;
64
65 #define isCapName(c) (isgraph(c) && strchr("^#=:\\", c) == 0)
66
67 static char *
68 make_dbitem(char *p, char *q)
69 {
70     char *result = malloc(strlen(e_opt) + 2 + (size_t) (p - q));
71     sprintf(result, "%s=%.*s", e_opt, (int) (p - q), q);
72     return result;
73 }
74
75 static void
76 make_dblist(void)
77 {
78     if (d_opt && e_opt) {
79         int pass;
80
81         for (pass = 0; pass < 2; ++pass) {
82             char *p, *q;
83             size_t count = 0;
84
85             for (p = q = d_opt; *p != '\0'; ++p) {
86                 if (*p == ':') {
87                     if (p != q + 1) {
88                         if (pass) {
89                             db_list[count] = make_dbitem(p, q);
90                         }
91                         count++;
92                     }
93                     q = p + 1;
94                 }
95             }
96             if (p != q + 1) {
97                 if (pass) {
98                     db_list[count] = make_dbitem(p, q);
99                 }
100                 count++;
101             }
102             if (!pass) {
103                 db_list = typeCalloc(char *, count + 1);
104             }
105         }
106     }
107 }
108
109 static char *
110 next_dbitem(void)
111 {
112     char *result = 0;
113
114     if (db_list) {
115         if ((result = db_list[db_item]) == 0) {
116             db_item = 0;
117             result = db_list[0];
118         } else {
119             db_item++;
120         }
121     }
122     printf("** %s\n", result);
123     return result;
124 }
125
126 static void
127 free_dblist(void)
128 {
129     if (db_list) {
130         int n;
131         for (n = 0; db_list[n]; ++n)
132             free(db_list[n]);
133         free(db_list);
134         db_list = 0;
135     }
136 }
137
138 static void
139 dumpit(NCURSES_CONST char *cap)
140 {
141     /*
142      * One of the limitations of the termcap interface is that the library
143      * cannot determine the size of the buffer passed via tgetstr(), nor the
144      * amount of space remaining.  This demo simply reuses the whole buffer
145      * for each call; a normal termcap application would try to use the buffer
146      * to hold all of the strings extracted from the terminal entry.
147      */
148     char area[1024], *ap = area;
149     char *str;
150     int num;
151
152     if ((str = tgetstr(cap, &ap)) != 0) {
153         total_values++;
154         if (!q_opt) {
155             /*
156              * Note that the strings returned are mostly terminfo format, since
157              * ncurses does not convert except for a handful of special cases.
158              */
159             printf(FNAME(str), cap);
160             while (*str != 0) {
161                 int ch = UChar(*str++);
162                 switch (ch) {
163                 case '\177':
164                     fputs("^?", stdout);
165                     break;
166                 case '\033':
167                     fputs("\\E", stdout);
168                     break;
169                 case '\b':
170                     fputs("\\b", stdout);
171                     break;
172                 case '\f':
173                     fputs("\\f", stdout);
174                     break;
175                 case '\n':
176                     fputs("\\n", stdout);
177                     break;
178                 case '\r':
179                     fputs("\\r", stdout);
180                     break;
181                 case ' ':
182                     fputs("\\s", stdout);
183                     break;
184                 case '\t':
185                     fputs("\\t", stdout);
186                     break;
187                 case '^':
188                     fputs("\\^", stdout);
189                     break;
190                 case ':':
191                     fputs("\\072", stdout);
192                     break;
193                 case '\\':
194                     fputs("\\\\", stdout);
195                     break;
196                 default:
197                     if (isgraph(ch))
198                         fputc(ch, stdout);
199                     else if (ch < 32)
200                         printf("^%c", ch + '@');
201                     else
202                         printf("\\%03o", ch);
203                     break;
204                 }
205             }
206             printf("\n");
207         }
208     } else if ((num = tgetnum(cap)) >= 0) {
209         total_values++;
210         if (!q_opt) {
211             printf(FNAME(num), cap);
212             printf(" %d\n", num);
213         }
214     } else if (tgetflag(cap) > 0) {
215         ++total_values;
216         if (!q_opt) {
217             printf(FNAME(flg), cap);
218             printf("%s\n", "true");
219         }
220     }
221
222     if (!q_opt)
223         fflush(stdout);
224 }
225
226 static void
227 brute_force(const char *name)
228 {
229     char buffer[1024];
230
231     if (db_list) {
232         putenv(next_dbitem());
233     }
234     printf("Terminal type %s\n", name);
235     if (tgetent(buffer, name) >= 0) {
236         char cap[3];
237         int c1, c2;
238
239         cap[2] = 0;
240         for (c1 = 0; c1 < 256; ++c1) {
241             cap[0] = (char) c1;
242             if (isCapName(c1)) {
243                 for (c2 = 0; c2 < 256; ++c2) {
244                     cap[1] = (char) c2;
245                     if (isCapName(c2)) {
246                         dumpit(cap);
247                     }
248                 }
249             }
250         }
251     }
252 }
253
254 #if USE_CODE_LISTS
255 static void
256 demo_termcap(NCURSES_CONST char *name)
257 {
258     unsigned n;
259     NCURSES_CONST char *cap;
260     char buffer[1024];
261
262     if (db_list) {
263         putenv(next_dbitem());
264     }
265     printf("Terminal type \"%s\"\n", name);
266     if (tgetent(buffer, name) >= 0) {
267
268         if (b_opt) {
269             for (n = 0;; ++n) {
270                 cap = boolcodes[n];
271                 if (cap == 0)
272                     break;
273                 dumpit(cap);
274             }
275         }
276
277         if (n_opt) {
278             for (n = 0;; ++n) {
279                 cap = numcodes[n];
280                 if (cap == 0)
281                     break;
282                 dumpit(cap);
283             }
284         }
285
286         if (s_opt) {
287             for (n = 0;; ++n) {
288                 cap = strcodes[n];
289                 if (cap == 0)
290                     break;
291                 dumpit(cap);
292             }
293         }
294     }
295 }
296
297 static void
298 usage(void)
299 {
300     static const char *msg[] =
301     {
302         "Usage: demo_termcap [options] [terminal]",
303         "",
304         "If no options are given, print all (boolean, numeric, string)",
305         "capabilities for the given terminal, using short names.",
306         "",
307         "Options:",
308         " -a       try all names, print capabilities found",
309         " -b       print boolean-capabilities",
310         " -d LIST  colon-separated list of databases to use",
311         " -e NAME  environment variable to set with -d option",
312         " -n       print numeric-capabilities",
313         " -q       quiet (prints only counts)",
314         " -r COUNT repeat for given count",
315         " -s       print string-capabilities",
316 #ifdef NCURSES_VERSION
317         " -y       disable extended capabilities",
318 #endif
319     };
320     unsigned n;
321     for (n = 0; n < SIZEOF(msg); ++n) {
322         fprintf(stderr, "%s\n", msg[n]);
323     }
324     ExitProgram(EXIT_FAILURE);
325 }
326 #endif
327
328 int
329 main(int argc, char *argv[])
330 {
331     int n;
332     char *name;
333     bool a_opt = FALSE;
334
335 #if USE_CODE_LISTS
336     int repeat;
337     int r_opt = 1;
338
339     while ((n = getopt(argc, argv, "abd:e:nqr:sy")) != -1) {
340         switch (n) {
341         case 'a':
342             a_opt = TRUE;
343             break;
344         case 'b':
345             b_opt = TRUE;
346             break;
347         case 'd':
348             d_opt = optarg;
349             break;
350         case 'e':
351             e_opt = optarg;
352             break;
353         case 'n':
354             n_opt = TRUE;
355             break;
356         case 'q':
357             q_opt = TRUE;
358             break;
359         case 'r':
360             if ((r_opt = atoi(optarg)) <= 0)
361                 usage();
362             break;
363         case 's':
364             s_opt = TRUE;
365             break;
366 #if NCURSES_XNAMES
367         case 'y':
368             use_extended_names(FALSE);
369             break;
370 #endif
371         default:
372             usage();
373             break;
374         }
375     }
376
377     if (!(b_opt || n_opt || s_opt)) {
378         b_opt = TRUE;
379         n_opt = TRUE;
380         s_opt = TRUE;
381     }
382 #else
383     a_opt = TRUE;
384 #endif
385
386     make_dblist();
387
388     if (a_opt) {
389         if (optind < argc) {
390             for (n = optind; n < argc; ++n) {
391                 brute_force(argv[n]);
392             }
393         } else if ((name = getenv("TERM")) != 0) {
394             brute_force(name);
395         } else {
396             static char dumb[] = "dumb";
397             brute_force(dumb);
398         }
399     }
400 #if USE_CODE_LISTS
401     else {
402         for (repeat = 0; repeat < r_opt; ++repeat) {
403             if (optind < argc) {
404                 for (n = optind; n < argc; ++n) {
405                     demo_termcap(argv[n]);
406                 }
407             } else if ((name = getenv("TERM")) != 0) {
408                 demo_termcap(name);
409             } else {
410                 static char dumb[] = "dumb";
411                 demo_termcap(dumb);
412             }
413         }
414     }
415 #endif /* USE_CODE_LISTS */
416
417     printf("%ld values\n", total_values);
418
419     free_dblist();
420
421     ExitProgram(EXIT_SUCCESS);
422 }
423
424 #else
425 int
426 main(int argc GCC_UNUSED,
427      char *argv[]GCC_UNUSED)
428 {
429     printf("This program requires termcap\n");
430     ExitProgram(EXIT_FAILURE);
431 }
432 #endif