xref: /haiku/src/bin/keymap/main.cpp (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
1 /*
2  * Copyright 2004-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jérôme Duval
7  *		Axel Dörfler, axeld@pinc-software.de.
8  */
9 
10 
11 #include <getopt.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include <Application.h>
17 #include <FileIO.h>
18 
19 #include "Keymap.h"
20 
21 
22 #ifdef HAIKU_HOST_PLATFORM_SUNOS
23 static const char *sProgramName = "keymap";
24 #else
25 extern char *__progname;
26 static const char *sProgramName = __progname;
27 #endif
28 
29 
30 static void
31 usage()
32 {
33 	printf("usage: %s {-o <output-file>} [-[l|r] | -[b|h|c|d <input-file>]]\n"
34 		"  -o, --output       Change output file to output-file (default: "
35 			"keymap.out|h).\n"
36 		"  -d, --dump         Decompile key map to standard output (can be "
37 			"redirected\n"
38 		"                     via -o).\n"
39 		"  -l, --load         Load key map. If no input-file is specified, it "
40 			"will be\n"
41 		"                     read from standard input.\n"
42 		"  -s, --load-source  Load source key map from standard input when no\n"
43 		"                     input-file is specified.\n"
44 		"  -r, --restore      Restore system default key map.\n"
45 		"  -c, --compile      Compile source keymap to binary.\n"
46 		"  -h, --header       Translate source keymap to C++ header.\n",
47 		sProgramName);
48 }
49 
50 
51 static const char*
52 keymap_error(status_t status)
53 {
54 	if (status == KEYMAP_ERROR_UNKNOWN_VERSION)
55 		return "Unknown keymap version";
56 
57 	return strerror(status);
58 }
59 
60 
61 static void
62 load_keymap(Keymap& keymap, const char* name, bool source)
63 {
64 	status_t status;
65 	if (source) {
66 		if (name != NULL)
67 			status = keymap.LoadSource(name);
68 		else
69 			status = keymap.LoadSource(stdin);
70 	} else {
71 		if (name != NULL)
72 			status = keymap.SetTo(name);
73 		else {
74 			BFileIO fileIO(stdin);
75 			status = keymap.SetTo(fileIO);
76 		}
77 	}
78 
79 	if (status != B_OK) {
80 		fprintf(stderr, "%s: error when loading the keymap: %s\n", sProgramName,
81 			keymap_error(status));
82 		exit(1);
83 	}
84 }
85 
86 
87 int
88 main(int argc, char** argv)
89 {
90 	const char* output = NULL;
91 	const char* input = NULL;
92 	enum {
93 		kUnspecified,
94 		kLoadBinary,
95 		kLoadText,
96 		kSaveText,
97 		kRestore,
98 		kCompile,
99 		kSaveHeader,
100 	} mode = kUnspecified;
101 
102 	static struct option const kLongOptions[] = {
103 		{"output", required_argument, 0, 'o'},
104 		{"dump", optional_argument, 0, 'd'},
105 		{"load", optional_argument, 0, 'l'},
106 		{"load-source", optional_argument, 0, 's'},
107 		{"restore", no_argument, 0, 'r'},
108 		{"compile", optional_argument, 0, 'c'},
109 		{"header", optional_argument, 0, 'h'},
110 		{"help", no_argument, 0, 'H'},
111 		{NULL}
112 	};
113 
114 	int c;
115 	while ((c = getopt_long(argc, argv, "o:dblsrchH", kLongOptions,
116 			NULL)) != -1) {
117 		switch (c) {
118 			case 0:
119 				break;
120 			case 'o':
121 				output = optarg;
122 				break;
123 			case 'd':
124 				mode = kSaveText;
125 				input = optarg;
126 				break;
127 			case 'l':
128 			case 'b':
129 				mode = kLoadBinary;
130 				input = optarg;
131 				break;
132 			case 's':
133 				mode = kLoadText;
134 				input = optarg;
135 				break;
136 			case 'r':
137 				mode = kRestore;
138 				break;
139 			case 'c':
140 				mode = kCompile;
141 				input = optarg;
142 				break;
143 			case 'h':
144 				mode = kSaveHeader;
145 				input = optarg;
146 				break;
147 
148 			case 'H':
149 			default:
150 				usage();
151 				break;
152 		}
153 	}
154 
155 	if (argc > optind && input == NULL)
156 		input = argv[optind];
157 
158 	BApplication app("application/x-vnd.Haiku-keymap-cli");
159 	Keymap keymap;
160 
161 	switch (mode) {
162 		case kUnspecified:
163 			usage();
164 			break;
165 
166 		case kLoadBinary:
167 		case kLoadText:
168 		{
169 			load_keymap(keymap, input, mode == kLoadText);
170 
171 			status_t status = keymap.SaveAsCurrent();
172 			if (status != B_OK) {
173 				fprintf(stderr, "%s: error when saving as current: %s",
174 					sProgramName, strerror(status));
175 				return 1;
176 			}
177 
178 			printf("Key map loaded.\n");
179 			break;
180 		}
181 
182 		case kSaveText:
183 		{
184 			if (input == NULL) {
185 				status_t status = keymap.SetToCurrent();
186 				if (status != B_OK) {
187 					fprintf(stderr, "%s: error while getting keymap: %s!\n",
188 						sProgramName, keymap_error(status));
189 					return 1;
190 				}
191 			} else
192 				load_keymap(keymap, input, false);
193 
194 			if (output != NULL)
195 				keymap.SaveAsSource(output);
196 			else
197 				keymap.SaveAsSource(stdout);
198 			break;
199 		}
200 
201 		case kRestore:
202 			keymap.RestoreSystemDefault();
203 			break;
204 
205 		case kCompile:
206 		{
207 			load_keymap(keymap, input, true);
208 
209 			if (output == NULL)
210 				output = "keymap.out";
211 
212 			status_t status = keymap.Save(output);
213 			if (status != B_OK) {
214 				fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName,
215 					output, strerror(status));
216 				return 1;
217 			}
218 			break;
219 		}
220 
221 		case kSaveHeader:
222 		{
223 			load_keymap(keymap, input, true);
224 
225 			if (output == NULL)
226 				output = "keymap.h";
227 
228 			status_t status = keymap.SaveAsCppHeader(output, input);
229 			if (status != B_OK) {
230 				fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName,
231 					output, strerror(status));
232 				return 1;
233 			}
234 			break;
235 		}
236 	}
237 
238 	return 0;
239 }
240