Interactive tools: Escape control character for Unicode output
[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 void
54 tools_print_keycode_state(struct xkb_state *state,
55                           struct xkb_compose_state *compose_state,
56                           xkb_keycode_t keycode,
57                           enum xkb_consumed_mode consumed_mode)
58 {
59     struct xkb_keymap *keymap;
60
61     xkb_keysym_t sym;
62     const xkb_keysym_t *syms;
63     int nsyms;
64     char s[16];
65     xkb_layout_index_t layout;
66     enum xkb_compose_status status;
67
68     keymap = xkb_state_get_keymap(state);
69
70     nsyms = xkb_state_key_get_syms(state, keycode, &syms);
71
72     if (nsyms <= 0)
73         return;
74
75     status = XKB_COMPOSE_NOTHING;
76     if (compose_state)
77         status = xkb_compose_state_get_status(compose_state);
78
79     if (status == XKB_COMPOSE_COMPOSING || status == XKB_COMPOSE_CANCELLED)
80         return;
81
82     if (status == XKB_COMPOSE_COMPOSED) {
83         sym = xkb_compose_state_get_one_sym(compose_state);
84         syms = &sym;
85         nsyms = 1;
86     }
87     else if (nsyms == 1) {
88         sym = xkb_state_key_get_one_sym(state, keycode);
89         syms = &sym;
90     }
91
92     printf("keysyms [ ");
93     for (int i = 0; i < nsyms; i++) {
94         xkb_keysym_get_name(syms[i], s, sizeof(s));
95         printf("%-*s ", (int) sizeof(s), s);
96     }
97     printf("] ");
98
99     if (status == XKB_COMPOSE_COMPOSED)
100         xkb_compose_state_get_utf8(compose_state, s, sizeof(s));
101     else
102         xkb_state_key_get_utf8(state, keycode, s, sizeof(s));
103     /* HACK: escape single control characters from C0 set using the
104     * Unicode codepoint convention. Ideally we would like to escape
105     * any non-printable character in the string.
106     */
107     if (!*s) {
108         printf("unicode [   ] ");
109     } else if (strlen(s) == 1 && (*s <= 0x1F || *s == 0x7F)) {
110         printf("unicode [ U+%04hX ] ", *s);
111     } else {
112         printf("unicode [ %s ] ", s);
113     }
114
115     layout = xkb_state_key_get_layout(state, keycode);
116     printf("layout [ %s (%d) ] ",
117            xkb_keymap_layout_get_name(keymap, layout), layout);
118
119     printf("level [ %d ] ",
120            xkb_state_key_get_level(state, keycode, layout));
121
122     printf("mods [ ");
123     for (xkb_mod_index_t mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) {
124         if (xkb_state_mod_index_is_active(state, mod,
125                                           XKB_STATE_MODS_EFFECTIVE) <= 0)
126             continue;
127         if (xkb_state_mod_index_is_consumed2(state, keycode, mod,
128                                              consumed_mode))
129             printf("-%s ", xkb_keymap_mod_get_name(keymap, mod));
130         else
131             printf("%s ", xkb_keymap_mod_get_name(keymap, mod));
132     }
133     printf("] ");
134
135     printf("leds [ ");
136     for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) {
137         if (xkb_state_led_index_is_active(state, led) <= 0)
138             continue;
139         printf("%s ", xkb_keymap_led_get_name(keymap, led));
140     }
141     printf("] ");
142
143     printf("\n");
144 }
145
146 void
147 tools_print_state_changes(enum xkb_state_component changed)
148 {
149     if (changed == 0)
150         return;
151
152     printf("changed [ ");
153     if (changed & XKB_STATE_LAYOUT_EFFECTIVE)
154         printf("effective-layout ");
155     if (changed & XKB_STATE_LAYOUT_DEPRESSED)
156         printf("depressed-layout ");
157     if (changed & XKB_STATE_LAYOUT_LATCHED)
158         printf("latched-layout ");
159     if (changed & XKB_STATE_LAYOUT_LOCKED)
160         printf("locked-layout ");
161     if (changed & XKB_STATE_MODS_EFFECTIVE)
162         printf("effective-mods ");
163     if (changed & XKB_STATE_MODS_DEPRESSED)
164         printf("depressed-mods ");
165     if (changed & XKB_STATE_MODS_LATCHED)
166         printf("latched-mods ");
167     if (changed & XKB_STATE_MODS_LOCKED)
168         printf("locked-mods ");
169     if (changed & XKB_STATE_LEDS)
170         printf("leds ");
171     printf("]\n");
172 }
173
174 #ifdef _WIN32
175 void
176 tools_disable_stdin_echo(void)
177 {
178     HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
179     DWORD mode = 0;
180     GetConsoleMode(stdin_handle, &mode);
181     SetConsoleMode(stdin_handle, mode & ~ENABLE_ECHO_INPUT);
182 }
183
184 void
185 tools_enable_stdin_echo(void)
186 {
187     HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
188     DWORD mode = 0;
189     GetConsoleMode(stdin_handle, &mode);
190     SetConsoleMode(stdin_handle, mode | ENABLE_ECHO_INPUT);
191 }
192 #else
193 void
194 tools_disable_stdin_echo(void)
195 {
196     /* Same as `stty -echo`. */
197     struct termios termios;
198     if (tcgetattr(STDIN_FILENO, &termios) == 0) {
199         termios.c_lflag &= ~ECHO;
200         (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios);
201     }
202 }
203
204 void
205 tools_enable_stdin_echo(void)
206 {
207     /* Same as `stty echo`. */
208     struct termios termios;
209     if (tcgetattr(STDIN_FILENO, &termios) == 0) {
210         termios.c_lflag |= ECHO;
211         (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios);
212     }
213 }
214
215 #endif
216
217 int
218 tools_exec_command(const char *prefix, int real_argc, char **real_argv)
219 {
220     char *argv[64] = {NULL};
221     char executable[PATH_MAX];
222     const char *command;
223     int rc;
224
225     if (((size_t)real_argc >= ARRAY_SIZE(argv))) {
226         fprintf(stderr, "Too many arguments\n");
227         return EXIT_INVALID_USAGE;
228     }
229
230     command = real_argv[0];
231
232     rc = snprintf(executable, sizeof(executable),
233                   "%s/%s-%s", LIBXKBCOMMON_TOOL_PATH, prefix, command);
234     if (rc < 0 || (size_t) rc >= sizeof(executable)) {
235         fprintf(stderr, "Failed to assemble command\n");
236         return EXIT_FAILURE;
237     }
238
239     argv[0] = executable;
240     for (int i = 1; i < real_argc; i++)
241         argv[i] = real_argv[i];
242
243     execv(executable, argv);
244     if (errno == ENOENT) {
245         fprintf(stderr, "Command '%s' is not available\n", command);
246         return EXIT_INVALID_USAGE;
247     } else {
248         fprintf(stderr, "Failed to execute '%s' (%s)\n",
249                 command, strerror(errno));
250     }
251
252     return EXIT_FAILURE;
253 }