ncurses 5.9 - patch 20130928
[ncurses.git] / test / demo_terminfo.c
1 /****************************************************************************
2  * Copyright (c) 2009-2012,2013 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_terminfo.c,v 1.19 2013/09/28 21:50:01 tom Exp $
33  *
34  * A simple demo of the terminfo interface.
35  */
36 #define USE_TINFO
37 #include <test.priv.h>
38
39 #if NCURSES_XNAMES
40 #if HAVE_TERM_ENTRY_H
41 #include <term_entry.h>
42 #else
43 #undef NCURSES_XNAMES
44 #define NCURSES_XNAMES 0
45 #endif
46 #endif
47
48 #if HAVE_TIGETSTR
49 #if defined(HAVE_CURSES_DATA_BOOLNAMES) || defined(DECL_CURSES_DATA_BOOLNAMES)
50
51 static bool b_opt = FALSE;
52 static bool f_opt = FALSE;
53 static bool n_opt = FALSE;
54 static bool q_opt = FALSE;
55 static bool s_opt = FALSE;
56 static bool x_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 FCOLS 8
66 #define FNAME(type) "%s %-*s = ", #type, FCOLS
67
68 static char *
69 make_dbitem(char *p, char *q)
70 {
71     char *result = malloc(strlen(e_opt) + 2 + (size_t) (p - q));
72     sprintf(result, "%s=%.*s", e_opt, (int) (p - q), q);
73     return result;
74 }
75
76 static void
77 make_dblist(void)
78 {
79     if (d_opt && e_opt) {
80         int pass;
81
82         for (pass = 0; pass < 2; ++pass) {
83             char *p, *q;
84             size_t count = 0;
85
86             for (p = q = d_opt; *p != '\0'; ++p) {
87                 if (*p == ':') {
88                     if (p != q + 1) {
89                         if (pass) {
90                             db_list[count] = make_dbitem(p, q);
91                         }
92                         count++;
93                     }
94                     q = p + 1;
95                 }
96             }
97             if (p != q + 1) {
98                 if (pass) {
99                     db_list[count] = make_dbitem(p, q);
100                 }
101                 count++;
102             }
103             if (!pass) {
104                 db_list = typeCalloc(char *, count + 1);
105             }
106         }
107     }
108 }
109
110 static char *
111 next_dbitem(void)
112 {
113     char *result = 0;
114
115     if (db_list) {
116         if ((result = db_list[db_item]) == 0) {
117             db_item = 0;
118             result = db_list[0];
119         } else {
120             db_item++;
121         }
122     }
123     printf("** %s\n", result);
124     return result;
125 }
126
127 static void
128 free_dblist(void)
129 {
130     if (db_list) {
131         int n;
132         for (n = 0; db_list[n]; ++n)
133             free(db_list[n]);
134         free(db_list);
135         db_list = 0;
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     const char *str;
149     int num;
150
151     if ((str = tigetstr(cap)) != 0 && (str != (char *) -1)) {
152         total_values++;
153         if (!q_opt) {
154             /*
155              * Note that the strings returned are mostly terminfo format, since
156              * ncurses does not convert except for a handful of special cases.
157              */
158             printf(FNAME(str), cap);
159             while (*str != 0) {
160                 int ch = UChar(*str++);
161                 switch (ch) {
162                 case '\177':
163                     fputs("^?", stdout);
164                     break;
165                 case '\033':
166                     fputs("\\E", stdout);
167                     break;
168                 case '\b':
169                     fputs("\\b", stdout);
170                     break;
171                 case '\f':
172                     fputs("\\f", stdout);
173                     break;
174                 case '\n':
175                     fputs("\\n", stdout);
176                     break;
177                 case '\r':
178                     fputs("\\r", stdout);
179                     break;
180                 case ' ':
181                     fputs("\\s", stdout);
182                     break;
183                 case '\t':
184                     fputs("\\t", stdout);
185                     break;
186                 case '^':
187                     fputs("\\^", stdout);
188                     break;
189                 case ':':
190                     fputs("\\072", stdout);
191                     break;
192                 case '\\':
193                     fputs("\\\\", stdout);
194                     break;
195                 default:
196                     if (isgraph(ch))
197                         fputc(ch, stdout);
198                     else if (ch < 32)
199                         printf("^%c", ch + '@');
200                     else
201                         printf("\\%03o", ch);
202                     break;
203                 }
204             }
205             printf("\n");
206         }
207     } else if ((num = tigetnum(cap)) >= 0) {
208         total_values++;
209         if (!q_opt) {
210             printf(FNAME(num), cap);
211             printf(" %d\n", num);
212         }
213     } else if ((num = tigetflag(cap)) >= 0) {
214         total_values++;
215         if (!q_opt) {
216             printf(FNAME(flg), cap);
217             printf("%s\n", num ? "true" : "false");
218         }
219     }
220
221     if (!q_opt)
222         fflush(stdout);
223 }
224
225 static void
226 demo_terminfo(char *name)
227 {
228     unsigned n;
229     NCURSES_CONST char *cap;
230
231     if (db_list) {
232         putenv(next_dbitem());
233     }
234     printf("Terminal type \"%s\"\n", name);
235     setupterm(name, 1, (int *) 0);
236
237     if (b_opt) {
238         for (n = 0;; ++n) {
239             cap = f_opt ? boolfnames[n] : boolnames[n];
240             if (cap == 0)
241                 break;
242             dumpit(cap);
243         }
244     }
245
246     if (n_opt) {
247         for (n = 0;; ++n) {
248             cap = f_opt ? numfnames[n] : numnames[n];
249             if (cap == 0)
250                 break;
251             dumpit(cap);
252         }
253     }
254
255     if (s_opt) {
256         for (n = 0;; ++n) {
257             cap = f_opt ? strfnames[n] : strnames[n];
258             if (cap == 0)
259                 break;
260             dumpit(cap);
261         }
262     }
263 #ifdef NCURSES_VERSION
264     if (x_opt) {
265         int mod;
266         if (f_opt) {
267 #if NCURSES_XNAMES
268             TERMTYPE *term = &(cur_term->type);
269             if (term != 0
270                 && ((NUM_BOOLEANS(term) != BOOLCOUNT)
271                     || (NUM_NUMBERS(term) != NUMCOUNT)
272                     || (NUM_STRINGS(term) != STRCOUNT))) {
273                 for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) {
274                     dumpit(ExtBoolname(term, (int) n, boolnames));
275                 }
276                 for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) {
277                     dumpit(ExtNumname(term, (int) n, numnames));
278                 }
279                 for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) {
280                     dumpit(ExtStrname(term, (int) n, strnames));
281                 }
282             }
283 #endif
284         } else {
285             char temp[80];
286             static const char *xterm_keys[] =
287             {
288                 "kDC", "kDN", "kEND", "kHOM", "kIC",
289                 "kLFT", "kNXT", "kPRV", "kRIT", "kUP",
290             };
291             for (n = 0; n < SIZEOF(xterm_keys); ++n) {
292                 for (mod = 0; mod < 8; ++mod) {
293                     if (mod == 0)
294                         sprintf(temp, "%.*s", 8, xterm_keys[n]);
295                     else
296                         sprintf(temp, "%.*s%d", 8, xterm_keys[n], mod);
297                     dumpit(temp);
298                 }
299             }
300         }
301     }
302 #endif
303
304 }
305
306 static void
307 usage(void)
308 {
309     static const char *msg[] =
310     {
311         "Usage: demo_terminfo [options] [terminal]",
312         "",
313         "If no options are given, print all (boolean, numeric, string)",
314         "capabilities for the given terminal, using short names.",
315         "",
316         "Options:",
317         " -b       print boolean-capabilities",
318         " -d LIST  colon-separated list of databases to use",
319         " -e NAME  environment variable to set with -d option",
320         " -f       print full names",
321         " -n       print numeric-capabilities",
322         " -q       quiet (prints only counts)",
323         " -r COUNT repeat for given count",
324         " -s       print string-capabilities",
325 #ifdef NCURSES_VERSION
326         " -x       print extended capabilities",
327         " -y       disable extended capabilities",
328 #endif
329     };
330     unsigned n;
331     for (n = 0; n < SIZEOF(msg); ++n) {
332         fprintf(stderr, "%s\n", msg[n]);
333     }
334     ExitProgram(EXIT_FAILURE);
335 }
336
337 int
338 main(int argc, char *argv[])
339 {
340     int n;
341     int repeat;
342     char *name;
343     int r_opt = 1;
344 #ifdef NCURSES_VERSION
345     bool xy_opt = TRUE;         /* by default, use_extended_names is true */
346 #endif
347
348     while ((n = getopt(argc, argv, "bd:e:fnqr:sxy")) != -1) {
349         switch (n) {
350         case 'b':
351             b_opt = TRUE;
352             break;
353         case 'd':
354             d_opt = optarg;
355             break;
356         case 'e':
357             e_opt = optarg;
358             break;
359         case 'f':
360             f_opt = TRUE;
361             break;
362         case 'n':
363             n_opt = TRUE;
364             break;
365         case 'q':
366             q_opt = TRUE;
367             break;
368         case 'r':
369             if ((r_opt = atoi(optarg)) <= 0)
370                 usage();
371             break;
372         case 's':
373             s_opt = TRUE;
374             break;
375 #ifdef NCURSES_VERSION
376         case 'x':
377             x_opt = TRUE;
378             xy_opt = TRUE;
379             break;
380         case 'y':
381             xy_opt = FALSE;
382             break;
383 #endif
384         default:
385             usage();
386             break;
387         }
388     }
389
390 #if NCURSES_XNAMES
391     use_extended_names(xy_opt);
392 #endif
393
394     if (!(b_opt || n_opt || s_opt || x_opt)) {
395         b_opt = TRUE;
396         n_opt = TRUE;
397         s_opt = TRUE;
398     }
399
400     make_dblist();
401
402     for (repeat = 0; repeat < r_opt; ++repeat) {
403         if (optind < argc) {
404             for (n = optind; n < argc; ++n) {
405                 demo_terminfo(argv[n]);
406             }
407         } else if ((name = getenv("TERM")) != 0) {
408             demo_terminfo(name);
409         } else {
410             static char dumb[] = "dumb";
411             demo_terminfo(dumb);
412         }
413     }
414
415     printf("%ld values\n", total_values);
416
417     free_dblist();
418
419     ExitProgram(EXIT_SUCCESS);
420 }
421
422 #else
423 int
424 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
425 {
426     printf("This program requires the terminfo arrays\n");
427     ExitProgram(EXIT_FAILURE);
428 }
429 #endif
430 #else /* !HAVE_TIGETSTR */
431 int
432 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
433 {
434     printf("This program requires the terminfo functions such as tigetstr\n");
435     ExitProgram(EXIT_FAILURE);
436 }
437 #endif /* HAVE_TIGETSTR */