Interactive tools: add options to hide some fields
[platform/upstream/libxkbcommon.git] / tools / tools-common.c
1 /*
2  * Copyright © 2009 Dan Nicholson <dbn.lists@gmail.com>
3  * Copyright © 2012 Intel Corporation
4  * Copyright © 2012 Ran Benita <ran234@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Except as contained in this notice, the names of the authors or their
24  * institutions 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 from the authors.
27  *
28  * Author: Dan Nicholson <dbn.lists@gmail.com>
29  *         Daniel Stone <daniel@fooishbar.org>
30  *         Ran Benita <ran234@gmail.com>
31  */
32
33 #include "config.h"
34
35 #include <ctype.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <fcntl.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #ifdef _WIN32
44 #include <io.h>
45 #include <windows.h>
46 #else
47 #include <unistd.h>
48 #include <termios.h>
49 #endif
50
51 #include "tools-common.h"
52
53 static void
54 print_keycode(struct xkb_keymap *keymap, const char* prefix,
55               xkb_keycode_t keycode, const char *suffix) {
56     const char *keyname = xkb_keymap_key_get_name(keymap, keycode);
57     if (keyname) {
58         printf("%s%-4s%s", prefix, keyname, suffix);
59     } else {
60         printf("%s%-4d%s", prefix, keycode, suffix);
61     }
62 }
63
64 void
65 tools_print_keycode_state(struct xkb_state *state,
66                           struct xkb_compose_state *compose_state,
67                           xkb_keycode_t keycode,
68                           enum xkb_consumed_mode consumed_mode,
69                           print_state_fields_mask_t fields)
70 {
71     struct xkb_keymap *keymap;
72
73     xkb_keysym_t sym;
74     const xkb_keysym_t *syms;
75     int nsyms;
76     char s[16];
77     xkb_layout_index_t layout;
78     enum xkb_compose_status status;
79
80     keymap = xkb_state_get_keymap(state);
81
82     nsyms = xkb_state_key_get_syms(state, keycode, &syms);
83
84     if (nsyms <= 0)
85         return;
86
87     status = XKB_COMPOSE_NOTHING;
88     if (compose_state)
89         status = xkb_compose_state_get_status(compose_state);
90
91     if (status == XKB_COMPOSE_COMPOSING || status == XKB_COMPOSE_CANCELLED)
92         return;
93
94     if (status == XKB_COMPOSE_COMPOSED) {
95         sym = xkb_compose_state_get_one_sym(compose_state);
96         syms = &sym;
97         nsyms = 1;
98     }
99     else if (nsyms == 1) {
100         sym = xkb_state_key_get_one_sym(state, keycode);
101         syms = &sym;
102     }
103
104     print_keycode(keymap, "keycode [ ", keycode, " ] ");
105
106     printf("keysyms [ ");
107     for (int i = 0; i < nsyms; i++) {
108         xkb_keysym_get_name(syms[i], s, sizeof(s));
109         printf("%-*s ", (int) sizeof(s), s);
110     }
111     printf("] ");
112
113     if (fields & PRINT_UNICODE) {
114         if (status == XKB_COMPOSE_COMPOSED)
115             xkb_compose_state_get_utf8(compose_state, s, sizeof(s));
116         else
117             xkb_state_key_get_utf8(state, keycode, s, sizeof(s));
118         /* HACK: escape single control characters from C0 set using the
119         * Unicode codepoint convention. Ideally we would like to escape
120         * any non-printable character in the string.
121         */
122         if (!*s) {
123             printf("unicode [   ] ");
124         } else if (strlen(s) == 1 && (*s <= 0x1F || *s == 0x7F)) {
125             printf("unicode [ U+%04hX ] ", *s);
126         } else {
127             printf("unicode [ %s ] ", s);
128         }
129     }
130
131     layout = xkb_state_key_get_layout(state, keycode);
132     if (fields & PRINT_LAYOUT) {
133         printf("layout [ %s (%d) ] ",
134                xkb_keymap_layout_get_name(keymap, layout), layout);
135     }
136
137     printf("level [ %d ] ",
138            xkb_state_key_get_level(state, keycode, layout));
139
140     printf("mods [ ");
141     for (xkb_mod_index_t mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) {
142         if (xkb_state_mod_index_is_active(state, mod,
143                                           XKB_STATE_MODS_EFFECTIVE) <= 0)
144             continue;
145         if (xkb_state_mod_index_is_consumed2(state, keycode, mod,
146                                              consumed_mode))
147             printf("-%s ", xkb_keymap_mod_get_name(keymap, mod));
148         else
149             printf("%s ", xkb_keymap_mod_get_name(keymap, mod));
150     }
151     printf("] ");
152
153     printf("leds [ ");
154     for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) {
155         if (xkb_state_led_index_is_active(state, led) <= 0)
156             continue;
157         printf("%s ", xkb_keymap_led_get_name(keymap, led));
158     }
159     printf("] ");
160
161     printf("\n");
162 }
163
164 void
165 tools_print_state_changes(enum xkb_state_component changed)
166 {
167     if (changed == 0)
168         return;
169
170     printf("changed [ ");
171     if (changed & XKB_STATE_LAYOUT_EFFECTIVE)
172         printf("effective-layout ");
173     if (changed & XKB_STATE_LAYOUT_DEPRESSED)
174         printf("depressed-layout ");
175     if (changed & XKB_STATE_LAYOUT_LATCHED)
176         printf("latched-layout ");
177     if (changed & XKB_STATE_LAYOUT_LOCKED)
178         printf("locked-layout ");
179     if (changed & XKB_STATE_MODS_EFFECTIVE)
180         printf("effective-mods ");
181     if (changed & XKB_STATE_MODS_DEPRESSED)
182         printf("depressed-mods ");
183     if (changed & XKB_STATE_MODS_LATCHED)
184         printf("latched-mods ");
185     if (changed & XKB_STATE_MODS_LOCKED)
186         printf("locked-mods ");
187     if (changed & XKB_STATE_LEDS)
188         printf("leds ");
189     printf("]\n");
190 }
191
192 #ifdef _WIN32
193 void
194 tools_disable_stdin_echo(void)
195 {
196     HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
197     DWORD mode = 0;
198     GetConsoleMode(stdin_handle, &mode);
199     SetConsoleMode(stdin_handle, mode & ~ENABLE_ECHO_INPUT);
200 }
201
202 void
203 tools_enable_stdin_echo(void)
204 {
205     HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
206     DWORD mode = 0;
207     GetConsoleMode(stdin_handle, &mode);
208     SetConsoleMode(stdin_handle, mode | ENABLE_ECHO_INPUT);
209 }
210 #else
211 void
212 tools_disable_stdin_echo(void)
213 {
214     /* Same as `stty -echo`. */
215     struct termios termios;
216     if (tcgetattr(STDIN_FILENO, &termios) == 0) {
217         termios.c_lflag &= ~ECHO;
218         (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios);
219     }
220 }
221
222 void
223 tools_enable_stdin_echo(void)
224 {
225     /* Same as `stty echo`. */
226     struct termios termios;
227     if (tcgetattr(STDIN_FILENO, &termios) == 0) {
228         termios.c_lflag |= ECHO;
229         (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios);
230     }
231 }
232
233 #endif
234
235 int
236 tools_exec_command(const char *prefix, int real_argc, char **real_argv)
237 {
238     char *argv[64] = {NULL};
239     char executable[PATH_MAX];
240     const char *command;
241     int rc;
242
243     if (((size_t)real_argc >= ARRAY_SIZE(argv))) {
244         fprintf(stderr, "Too many arguments\n");
245         return EXIT_INVALID_USAGE;
246     }
247
248     command = real_argv[0];
249
250     rc = snprintf(executable, sizeof(executable),
251                   "%s/%s-%s", LIBXKBCOMMON_TOOL_PATH, prefix, command);
252     if (rc < 0 || (size_t) rc >= sizeof(executable)) {
253         fprintf(stderr, "Failed to assemble command\n");
254         return EXIT_FAILURE;
255     }
256
257     argv[0] = executable;
258     for (int i = 1; i < real_argc; i++)
259         argv[i] = real_argv[i];
260
261     execv(executable, argv);
262     if (errno == ENOENT) {
263         fprintf(stderr, "Command '%s' is not available\n", command);
264         return EXIT_INVALID_USAGE;
265     } else {
266         fprintf(stderr, "Failed to execute '%s' (%s)\n",
267                 command, strerror(errno));
268     }
269
270     return EXIT_FAILURE;
271 }