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