bc0e7c5d03ba6d2e8ba75340bc827aae7c012fc3
[ncurses.git] / test / list_keys.c
1 /****************************************************************************
2  * Copyright (c) 2016 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  * $Id: list_keys.c,v 1.4 2016/06/04 22:39:47 tom Exp $
30  *
31  * Author: Thomas E Dickey
32  *
33  * List function keys for one or more terminals.
34  */
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 f_opt = FALSE;
52 static bool t_opt = FALSE;
53 static bool x_opt = FALSE;
54
55 static const char *
56 full_name(const char *name)
57 {
58     const char *result = name;
59     int n;
60     for (n = 0; strnames[n] != 0; ++n) {
61         if (!strcmp(name, strnames[n])) {
62             result = strfnames[n];
63             break;
64         }
65     }
66     return result;
67 }
68
69 static int
70 show_key(const char *name, bool show)
71 {
72     int width = 0;
73     char buffer[10];
74     char *value = tigetstr(name);
75
76     if (show && t_opt)
77         fputc('"', stdout);
78
79     if (value != 0 && value != (char *) -1) {
80         while (*value != 0) {
81             int ch = UChar(*value++);
82             switch (ch) {
83             case '\177':
84                 strcpy(buffer, "^?");
85                 break;
86             case '\033':
87                 strcpy(buffer, "\\E");
88                 break;
89             case '\b':
90                 strcpy(buffer, "\\b");
91                 break;
92             case '\f':
93                 strcpy(buffer, "\\f");
94                 break;
95             case '\n':
96                 strcpy(buffer, "\\n");
97                 break;
98             case '\r':
99                 strcpy(buffer, "\\r");
100                 break;
101             case ' ':
102                 strcpy(buffer, "\\s");
103                 break;
104             case '\t':
105                 strcpy(buffer, "\\t");
106                 break;
107             case '^':
108                 strcpy(buffer, "\\^");
109                 break;
110             case ':':
111                 strcpy(buffer, "\\072");
112                 break;
113             case '\\':
114                 strcpy(buffer, "\\\\");
115                 break;
116             default:
117                 if (t_opt && ch == '"') {
118                     strcpy(buffer, "\"\"");
119                 } else if (isgraph(ch)) {
120                     sprintf(buffer, "%c", ch);
121                 } else if (ch < 32) {
122                     sprintf(buffer, "^%c", ch + '@');
123                 } else {
124                     sprintf(buffer, "\\%03o", ch);
125                 }
126                 break;
127             }
128             width += (int) strlen(buffer);
129             if (show)
130                 fputs(buffer, stdout);
131         }
132     }
133
134     if (show && t_opt)
135         fputc('"', stdout);
136
137     return width;
138 }
139
140 static bool
141 valid_key(const char *name, TERMINAL ** terms, int count)
142 {
143     bool result = FALSE;
144     if (*name == 'k') {
145         int k;
146         for (k = 0; k < count; ++k) {
147             set_curterm(terms[k]);
148             if (show_key(name, FALSE)) {
149                 result = TRUE;
150                 break;
151             }
152         }
153     }
154     return result;
155 }
156
157 static void
158 list_keys(TERMINAL ** terms, int count)
159 {
160     int j, k;
161     int widths0 = 0;
162     int widths1 = 0;
163     int check;
164     int total = 0;
165     const char *name = f_opt ? "strfname" : "strname";
166     const char **list;
167
168     for (total = 0; strnames[total]; ++total) {
169         ;
170     }
171 #if NCURSES_XNAMES
172     if (x_opt) {
173         TERMTYPE *term;
174         for (k = 0; k < count; ++k) {
175             set_curterm(terms[k]);
176             term = &(cur_term->type);
177             total += NUM_STRINGS(term) - STRCOUNT;
178         }
179     }
180 #endif
181     list = typeCalloc(const char *, total + 1);
182     for (j = 0; strnames[j]; ++j) {
183         list[j] = strnames[j];
184     }
185 #if NCURSES_XNAMES
186     if (x_opt) {
187         TERMTYPE *term;
188         int m, n;
189         for (k = 0; k < count; ++k) {
190             set_curterm(terms[k]);
191             term = &(cur_term->type);
192             for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) {
193                 bool found = FALSE;
194                 const char *estr = ExtStrname(term, (int) n, strnames);
195                 for (m = STRCOUNT; m < j; ++m) {
196                     if (!strcmp(estr, list[m])) {
197                         found = TRUE;
198                         break;
199                     }
200                 }
201                 if (!found) {
202                     list[j++] = estr;
203                 }
204             }
205         }
206     }
207 #endif
208
209     widths0 = (int) strlen(name);
210     for (k = 0; k < count; ++k) {
211         set_curterm(terms[k]);
212         check = (int) strlen(name);
213         if (widths1 < check)
214             widths1 = check;
215     }
216     for (j = 0; list[j] != 0; ++j) {
217         if (valid_key(list[j], terms, count)) {
218             const char *label = f_opt ? full_name(list[j]) : list[j];
219             check = (int) strlen(label);
220             if (widths0 < check)
221                 widths0 = check;
222             for (k = 0; k < count; ++k) {
223                 set_curterm(terms[k]);
224                 check = show_key(list[j], FALSE);
225                 if (widths1 < check)
226                     widths1 = check;
227             }
228         }
229     }
230
231     if (t_opt) {
232         printf("\"%s\"", name);
233     } else {
234         printf("%-*s", widths0, name);
235     }
236     for (k = 0; k < count; ++k) {
237         set_curterm(terms[k]);
238         if (t_opt) {
239             printf(",\"%s\"", termname());
240         } else if (k + 1 >= count) {
241             printf(" %s", termname());
242         } else {
243             printf(" %-*s", widths1, termname());
244         }
245     }
246     printf("\n");
247
248     for (j = 0; list[j] != 0; ++j) {
249         if (valid_key(list[j], terms, count)) {
250             const char *label = f_opt ? full_name(list[j]) : list[j];
251             if (t_opt) {
252                 printf("\"%s\"", label);
253             } else {
254                 printf("%-*s", widths0, label);
255             }
256             for (k = 0; k < count; ++k) {
257                 printf(t_opt ? "," : " ");
258                 set_curterm(terms[k]);
259                 check = show_key(list[j], TRUE);
260                 if (!t_opt) {
261                     if (k + 1 < count) {
262                         printf("%*s", widths1 + 1 - check, " ");
263                     }
264                 }
265             }
266             printf("\n");
267         }
268     }
269 }
270
271 static void
272 usage(void)
273 {
274     static const char *msg[] =
275     {
276         "Usage: list_keys [options] [terminal [terminal2 [...]]]",
277         "",
278         "Print capabilities for terminal special keys.",
279         "",
280         "Options:",
281         " -f       print full names",
282         " -t       print result as CSV table",
283 #ifdef NCURSES_VERSION
284         " -x       print extended capabilities",
285 #endif
286     };
287     unsigned n;
288     for (n = 0; n < SIZEOF(msg); ++n) {
289         fprintf(stderr, "%s\n", msg[n]);
290     }
291     ExitProgram(EXIT_FAILURE);
292 }
293
294 int
295 main(int argc, char *argv[])
296 {
297     int n;
298     TERMINAL **terms = typeCalloc(TERMINAL *, argc);
299
300     while ((n = getopt(argc, argv, "ftx")) != -1) {
301         switch (n) {
302         case 'f':
303             f_opt = TRUE;
304             break;
305         case 't':
306             t_opt = TRUE;
307             break;
308 #ifdef NCURSES_VERSION
309         case 'x':
310             x_opt = TRUE;
311             break;
312 #endif
313         default:
314             usage();
315             break;
316         }
317     }
318
319 #if HAVE_USE_EXTENDED_NAMES
320     use_extended_names(x_opt);
321 #endif
322
323     for (n = optind; n < argc; ++n) {
324         setupterm((NCURSES_CONST char *) argv[n], 1, (int *) 0);
325         terms[n - optind] = cur_term;
326     }
327     list_keys(terms, argc - optind);
328
329     ExitProgram(EXIT_SUCCESS);
330 }
331
332 #else
333 int
334 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
335 {
336     printf("This program requires the terminfo arrays\n");
337     ExitProgram(EXIT_FAILURE);
338 }
339 #endif
340 #else /* !HAVE_TIGETSTR */
341 int
342 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
343 {
344     printf("This program requires the terminfo functions such as tigetstr\n");
345     ExitProgram(EXIT_FAILURE);
346 }
347 #endif /* HAVE_TIGETSTR */