cc0fae900107648074d7b06b6ac3cc61d27d7883
[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.17 2013/06/08 16:52:47 tom Exp $
33  *
34  * A simple demo of the terminfo interface.
35  */
36 #define USE_TINFO
37 #include <test.priv.h>
38
39 #ifdef NCURSES_VERSION
40 #if !(defined(HAVE_TERM_ENTRY_H) && HAVE_TERM_ENTRY_H)
41 #undef NCURSES_XNAMES
42 #define NCURSES_XNAMES 0
43 #endif
44 #if NCURSES_XNAMES
45 #include <term_entry.h>
46 #endif
47 #endif
48
49 #if HAVE_TIGETSTR
50 #if defined(HAVE_CURSES_DATA_BOOLNAMES) || defined(DECL_CURSES_DATA_BOOLNAMES)
51
52 static bool b_opt = FALSE;
53 static bool f_opt = FALSE;
54 static bool n_opt = FALSE;
55 static bool q_opt = FALSE;
56 static bool s_opt = FALSE;
57 static bool x_opt = FALSE;
58
59 static char *d_opt;
60 static char *e_opt;
61 static char **db_list;
62 static int db_item;
63
64 static long total_values;
65
66 #define FCOLS 8
67 #define FNAME(type) "%s %-*s = ", #type, FCOLS
68
69 static char *
70 make_dbitem(char *p, char *q)
71 {
72     char *result = malloc(strlen(e_opt) + 2 + (size_t) (p - q));
73     sprintf(result, "%s=%.*s", e_opt, (int) (p - q), q);
74     return result;
75 }
76
77 static void
78 make_dblist(void)
79 {
80     if (d_opt && e_opt) {
81         int pass;
82
83         for (pass = 0; pass < 2; ++pass) {
84             char *p, *q;
85             size_t count = 0;
86
87             for (p = q = d_opt; *p != '\0'; ++p) {
88                 if (*p == ':') {
89                     if (p != q + 1) {
90                         if (pass) {
91                             db_list[count] = make_dbitem(p, q);
92                         }
93                         count++;
94                     }
95                     q = p + 1;
96                 }
97             }
98             if (p != q + 1) {
99                 if (pass) {
100                     db_list[count] = make_dbitem(p, q);
101                 }
102                 count++;
103             }
104             if (!pass) {
105                 db_list = typeCalloc(char *, count + 1);
106             }
107         }
108     }
109 }
110
111 static char *
112 next_dbitem(void)
113 {
114     char *result = 0;
115
116     if (db_list) {
117         if ((result = db_list[db_item]) == 0) {
118             db_item = 0;
119             result = db_list[0];
120         } else {
121             db_item++;
122         }
123     }
124     printf("** %s\n", result);
125     return result;
126 }
127
128 static void
129 free_dblist(void)
130 {
131     if (db_list) {
132         int n;
133         for (n = 0; db_list[n]; ++n)
134             free(db_list[n]);
135         free(db_list);
136         db_list = 0;
137     }
138 }
139 static void
140 dumpit(NCURSES_CONST char *cap)
141 {
142     /*
143      * One of the limitations of the termcap interface is that the library
144      * cannot determine the size of the buffer passed via tgetstr(), nor the
145      * amount of space remaining.  This demo simply reuses the whole buffer
146      * for each call; a normal termcap application would try to use the buffer
147      * to hold all of the strings extracted from the terminal entry.
148      */
149     const char *str;
150     int num;
151
152     if ((str = tigetstr(cap)) != 0 && (str != (char *) -1)) {
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 = tigetnum(cap)) >= 0) {
209         total_values++;
210         if (!q_opt) {
211             printf(FNAME(num), cap);
212             printf(" %d\n", num);
213         }
214     } else if ((num = tigetflag(cap)) >= 0) {
215         total_values++;
216         if (!q_opt) {
217             printf(FNAME(flg), cap);
218             printf("%s\n", num ? "true" : "false");
219         }
220     }
221
222     if (!q_opt)
223         fflush(stdout);
224 }
225
226 static void
227 demo_terminfo(char *name)
228 {
229     unsigned n;
230     NCURSES_CONST char *cap;
231
232     if (db_list) {
233         putenv(next_dbitem());
234     }
235     printf("Terminal type \"%s\"\n", name);
236     setupterm(name, 1, (int *) 0);
237
238     if (b_opt) {
239         for (n = 0;; ++n) {
240             cap = f_opt ? boolfnames[n] : boolnames[n];
241             if (cap == 0)
242                 break;
243             dumpit(cap);
244         }
245     }
246
247     if (n_opt) {
248         for (n = 0;; ++n) {
249             cap = f_opt ? numfnames[n] : numnames[n];
250             if (cap == 0)
251                 break;
252             dumpit(cap);
253         }
254     }
255
256     if (s_opt) {
257         for (n = 0;; ++n) {
258             cap = f_opt ? strfnames[n] : strnames[n];
259             if (cap == 0)
260                 break;
261             dumpit(cap);
262         }
263     }
264 #ifdef NCURSES_VERSION
265     if (x_opt) {
266         int mod;
267         if (f_opt) {
268 #if NCURSES_XNAMES
269             TERMTYPE *term = &(cur_term->type);
270             if (term != 0
271                 && ((NUM_BOOLEANS(term) != BOOLCOUNT)
272                     || (NUM_NUMBERS(term) != NUMCOUNT)
273                     || (NUM_STRINGS(term) != STRCOUNT))) {
274                 for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) {
275                     dumpit(ExtBoolname(term, (int) n, boolnames));
276                 }
277                 for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) {
278                     dumpit(ExtNumname(term, (int) n, numnames));
279                 }
280                 for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) {
281                     dumpit(ExtStrname(term, (int) n, strnames));
282                 }
283             }
284 #endif
285         } else {
286             char temp[80];
287             static const char *xterm_keys[] =
288             {
289                 "kDC", "kDN", "kEND", "kHOM", "kIC",
290                 "kLFT", "kNXT", "kPRV", "kRIT", "kUP",
291             };
292             for (n = 0; n < SIZEOF(xterm_keys); ++n) {
293                 for (mod = 0; mod < 8; ++mod) {
294                     if (mod == 0)
295                         sprintf(temp, "%.*s", 8, xterm_keys[n]);
296                     else
297                         sprintf(temp, "%.*s%d", 8, xterm_keys[n], mod);
298                     dumpit(temp);
299                 }
300             }
301         }
302     }
303 #endif
304
305 }
306
307 static void
308 usage(void)
309 {
310     static const char *msg[] =
311     {
312         "Usage: demo_terminfo [options] [terminal]",
313         "",
314         "If no options are given, print all (boolean, numeric, string)",
315         "capabilities for the given terminal, using short names.",
316         "",
317         "Options:",
318         " -b       print boolean-capabilities",
319         " -d LIST  colon-separated list of databases to use",
320         " -e NAME  environment variable to set with -d option",
321         " -f       print full names",
322         " -n       print numeric-capabilities",
323         " -q       quiet (prints only counts)",
324         " -r COUNT repeat for given count",
325         " -s       print string-capabilities",
326 #ifdef NCURSES_VERSION
327         " -x       print extended capabilities",
328         " -y       disable extended capabilities",
329 #endif
330     };
331     unsigned n;
332     for (n = 0; n < SIZEOF(msg); ++n) {
333         fprintf(stderr, "%s\n", msg[n]);
334     }
335     ExitProgram(EXIT_FAILURE);
336 }
337
338 int
339 main(int argc, char *argv[])
340 {
341     int n;
342     int repeat;
343     char *name;
344     int r_opt = 1;
345 #ifdef NCURSES_VERSION
346     bool xy_opt = TRUE;         /* by default, use_extended_names is true */
347 #endif
348
349     while ((n = getopt(argc, argv, "bd:e:fnqr:sxy")) != -1) {
350         switch (n) {
351         case 'b':
352             b_opt = TRUE;
353             break;
354         case 'd':
355             d_opt = optarg;
356             break;
357         case 'e':
358             e_opt = optarg;
359             break;
360         case 'f':
361             f_opt = TRUE;
362             break;
363         case 'n':
364             n_opt = TRUE;
365             break;
366         case 'q':
367             q_opt = TRUE;
368             break;
369         case 'r':
370             if ((r_opt = atoi(optarg)) <= 0)
371                 usage();
372             break;
373         case 's':
374             s_opt = TRUE;
375             break;
376 #ifdef NCURSES_VERSION
377         case 'x':
378             x_opt = TRUE;
379             xy_opt = TRUE;
380             break;
381         case 'y':
382             xy_opt = FALSE;
383             break;
384 #endif
385         default:
386             usage();
387             break;
388         }
389     }
390
391 #if NCURSES_XNAMES
392     use_extended_names(xy_opt);
393 #endif
394
395     if (!(b_opt || n_opt || s_opt || x_opt)) {
396         b_opt = TRUE;
397         n_opt = TRUE;
398         s_opt = TRUE;
399     }
400
401     make_dblist();
402
403     for (repeat = 0; repeat < r_opt; ++repeat) {
404         if (optind < argc) {
405             for (n = optind; n < argc; ++n) {
406                 demo_terminfo(argv[n]);
407             }
408         } else if ((name = getenv("TERM")) != 0) {
409             demo_terminfo(name);
410         } else {
411             static char dumb[] = "dumb";
412             demo_terminfo(dumb);
413         }
414     }
415
416     printf("%ld values\n", total_values);
417
418     free_dblist();
419
420     ExitProgram(EXIT_SUCCESS);
421 }
422
423 #else
424 int
425 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
426 {
427     printf("This program requires the terminfo arrays\n");
428     ExitProgram(EXIT_FAILURE);
429 }
430 #endif
431 #else /* !HAVE_TIGETSTR */
432 int
433 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
434 {
435     printf("This program requires the terminfo functions such as tigetstr\n");
436     ExitProgram(EXIT_FAILURE);
437 }
438 #endif /* HAVE_TIGETSTR */