00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "openttd.h"
00014 #include "hotkeys.h"
00015 #include "ini_type.h"
00016 #include "string_func.h"
00017 #include "window_gui.h"
00018
00019 char *_hotkeys_file;
00020
00022 struct KeycodeNames {
00023 const char *name;
00024 WindowKeyCodes keycode;
00025 };
00026
00028 static const KeycodeNames _keycode_to_name[] = {
00029 {"SHIFT", WKC_SHIFT},
00030 {"CTRL", WKC_CTRL},
00031 {"ALT", WKC_ALT},
00032 {"META", WKC_META},
00033 {"GLOBAL", WKC_GLOBAL_HOTKEY},
00034 {"ESC", WKC_ESC},
00035 {"DEL", WKC_DELETE},
00036 {"RETURN", WKC_RETURN},
00037 {"BACKQUOTE", WKC_BACKQUOTE},
00038 {"F1", WKC_F1},
00039 {"F2", WKC_F2},
00040 {"F3", WKC_F3},
00041 {"F4", WKC_F4},
00042 {"F5", WKC_F5},
00043 {"F6", WKC_F6},
00044 {"F7", WKC_F7},
00045 {"F8", WKC_F8},
00046 {"F9", WKC_F9},
00047 {"F10", WKC_F10},
00048 {"F11", WKC_F11},
00049 {"F12", WKC_F12},
00050 {"PAUSE", WKC_PAUSE},
00051 {"COMMA", WKC_COMMA},
00052 {"NUM_PLUS", WKC_NUM_PLUS},
00053 {"NUM_MINUS", WKC_NUM_MINUS},
00054 {"=", WKC_EQUALS},
00055 {"-", WKC_MINUS},
00056 };
00057
00064 static uint16 ParseCode(const char *start, const char *end)
00065 {
00066 assert(start <= end);
00067 while (start < end && *start == ' ') start++;
00068 while (end > start && *end == ' ') end--;
00069 for (uint i = 0; i < lengthof(_keycode_to_name); i++) {
00070 if (strlen(_keycode_to_name[i].name) == (size_t)(end - start) && strncasecmp(start, _keycode_to_name[i].name, end - start) == 0) {
00071 return _keycode_to_name[i].keycode;
00072 }
00073 }
00074 if (end - start == 1) {
00075 if (*start >= 'a' && *start <= 'z') return *start - ('a'-'A');
00076
00077 if (*(const uint8 *)start < 128) return *start;
00078 }
00079 return 0;
00080 }
00081
00088 static uint16 ParseKeycode(const char *start, const char *end)
00089 {
00090 assert(start <= end);
00091 uint16 keycode = 0;
00092 for (;;) {
00093 const char *cur = start;
00094 while (*cur != '+' && cur != end) cur++;
00095 uint16 code = ParseCode(start, cur);
00096 if (code == 0) return 0;
00097 if (code & WKC_SPECIAL_KEYS) {
00098
00099 if (code & ~WKC_SPECIAL_KEYS) return 0;
00100 keycode |= code;
00101 } else {
00102
00103 if (keycode & ~WKC_SPECIAL_KEYS) return 0;
00104 keycode |= code;
00105 }
00106 if (cur == end) break;
00107 assert(cur < end);
00108 start = cur + 1;
00109 }
00110 return keycode;
00111 }
00112
00118 template<class T>
00119 static void ParseHotkeys(Hotkey<T> *hotkey, const char *value)
00120 {
00121 const char *start = value;
00122 while (*start != '\0') {
00123 const char *end = start;
00124 while (*end != '\0' && *end != ',') end++;
00125 uint16 keycode = ParseKeycode(start, end);
00126 if (keycode != 0) hotkey->AddKeycode(keycode);
00127 start = (*end == ',') ? end + 1: end;
00128 }
00129 }
00130
00140 static const char *KeycodeToString(uint16 keycode)
00141 {
00142 static char buf[32];
00143 buf[0] = '\0';
00144 bool first = true;
00145 if (keycode & WKC_GLOBAL_HOTKEY) {
00146 strecat(buf, "GLOBAL", lastof(buf));
00147 first = false;
00148 }
00149 if (keycode & WKC_SHIFT) {
00150 if (!first) strecat(buf, "+", lastof(buf));
00151 strecat(buf, "SHIFT", lastof(buf));
00152 first = false;
00153 }
00154 if (keycode & WKC_CTRL) {
00155 if (!first) strecat(buf, "+", lastof(buf));
00156 strecat(buf, "CTRL", lastof(buf));
00157 first = false;
00158 }
00159 if (keycode & WKC_ALT) {
00160 if (!first) strecat(buf, "+", lastof(buf));
00161 strecat(buf, "ALT", lastof(buf));
00162 first = false;
00163 }
00164 if (keycode & WKC_META) {
00165 if (!first) strecat(buf, "+", lastof(buf));
00166 strecat(buf, "META", lastof(buf));
00167 first = false;
00168 }
00169 if (!first) strecat(buf, "+", lastof(buf));
00170 keycode = keycode & ~WKC_SPECIAL_KEYS;
00171
00172 for (uint i = 0; i < lengthof(_keycode_to_name); i++) {
00173 if (_keycode_to_name[i].keycode == keycode) {
00174 strecat(buf, _keycode_to_name[i].name, lastof(buf));
00175 return buf;
00176 }
00177 }
00178 assert(keycode < 128);
00179 char key[2];
00180 key[0] = keycode;
00181 key[1] = '\0';
00182 strecat(buf, key, lastof(buf));
00183 return buf;
00184 }
00185
00194 template<class T>
00195 const char *SaveKeycodes(const Hotkey<T> *hotkey)
00196 {
00197 static char buf[128];
00198 buf[0] = '\0';
00199 for (uint i = 0; i < hotkey->keycodes.Length(); i++) {
00200 const char *str = KeycodeToString(hotkey->keycodes[i]);
00201 if (i > 0) strecat(buf, ",", lastof(buf));
00202 strecat(buf, str, lastof(buf));
00203 }
00204 return buf;
00205 }
00206
00207 template<class T>
00208 void LoadHotkeyGroup(IniGroup *group, T *hotkey_list)
00209 {
00210 for (uint i = 0; hotkey_list[i].num != -1; i++) {
00211 T *hotkey = &hotkey_list[i];
00212 IniItem *item = group->GetItem(hotkey->name, false);
00213 if (item != NULL) {
00214 hotkey->keycodes.Clear();
00215 if (item->value != NULL) ParseHotkeys(hotkey, item->value);
00216 }
00217 }
00218 }
00219
00220 template<class T>
00221 void SaveHotkeyGroup(IniGroup *group, T *hotkey_list)
00222 {
00223 for (uint i = 0; hotkey_list[i].num != -1; i++) {
00224 T *hotkey = &hotkey_list[i];
00225 IniItem *item = group->GetItem(hotkey->name, true);
00226 item->SetValue(SaveKeycodes(hotkey));
00227 }
00228 }
00229
00230 template<class T>
00231 void SaveLoadHotkeyGroup(IniGroup *group, T *hotkey_list, bool save)
00232 {
00233 if (save) {
00234 SaveHotkeyGroup(group, hotkey_list);
00235 } else {
00236 LoadHotkeyGroup(group, hotkey_list);
00237 }
00238 }
00239
00240 struct MainWindow;
00241 struct MainToolbarWindow;
00242 struct ScenarioEditorToolbarWindow;
00243 struct TerraformToolbarWindow;
00244 struct ScenarioEditorLandscapeGenerationWindow;
00245 struct OrdersWindow;
00246 struct BuildAirToolbarWindow;
00247 struct BuildDocksToolbarWindow;
00248 struct BuildRailToolbarWindow;
00249 struct BuildRoadToolbarWindow;
00250 struct SignListWindow;
00251 struct AIDebugWindow;
00252
00253 static void SaveLoadHotkeys(bool save)
00254 {
00255 IniFile *ini = new IniFile();
00256 ini->LoadFromDisk(_hotkeys_file, BASE_DIR);
00257
00258 IniGroup *group;
00259
00260 #define SL_HOTKEYS(name, window_name) \
00261 extern Hotkey<window_name> *_##name##_hotkeys;\
00262 group = ini->GetGroup(#name);\
00263 SaveLoadHotkeyGroup(group, _##name##_hotkeys, save);
00264
00265 SL_HOTKEYS(global, MainWindow);
00266 SL_HOTKEYS(maintoolbar, MainToolbarWindow);
00267 SL_HOTKEYS(scenedit_maintoolbar, ScenarioEditorToolbarWindow);
00268 SL_HOTKEYS(terraform, TerraformToolbarWindow);
00269 SL_HOTKEYS(terraform_editor, ScenarioEditorLandscapeGenerationWindow);
00270 SL_HOTKEYS(order, OrdersWindow);
00271 SL_HOTKEYS(airtoolbar, BuildAirToolbarWindow);
00272 SL_HOTKEYS(dockstoolbar, BuildDocksToolbarWindow);
00273 SL_HOTKEYS(railtoolbar, BuildRailToolbarWindow);
00274 SL_HOTKEYS(roadtoolbar, BuildRoadToolbarWindow);
00275 SL_HOTKEYS(signlist, SignListWindow);
00276 SL_HOTKEYS(aidebug, AIDebugWindow);
00277
00278
00279 #undef SL_HOTKEYS
00280 if (save) ini->SaveToDisk(_hotkeys_file);
00281 delete ini;
00282 }
00283
00284
00286 void LoadHotkeysFromConfig()
00287 {
00288 SaveLoadHotkeys(false);
00289 }
00290
00292 void SaveHotkeysToConfig()
00293 {
00294 SaveLoadHotkeys(true);
00295 }
00296
00297 typedef EventState GlobalHotkeyHandler(WChar, uint16);
00298
00299 GlobalHotkeyHandler RailToolbarGlobalHotkeys;
00300 GlobalHotkeyHandler DockToolbarGlobalHotkeys;
00301 GlobalHotkeyHandler AirportToolbarGlobalHotkeys;
00302 GlobalHotkeyHandler TerraformToolbarGlobalHotkeys;
00303 GlobalHotkeyHandler TerraformToolbarEditorGlobalHotkeys;
00304 GlobalHotkeyHandler RoadToolbarGlobalHotkeys;
00305 GlobalHotkeyHandler RoadToolbarEditorGlobalHotkeys;
00306 GlobalHotkeyHandler SignListGlobalHotkeys;
00307 GlobalHotkeyHandler AIDebugGlobalHotkeys;
00308
00309
00310 GlobalHotkeyHandler *_global_hotkey_handlers[] = {
00311 RailToolbarGlobalHotkeys,
00312 DockToolbarGlobalHotkeys,
00313 AirportToolbarGlobalHotkeys,
00314 TerraformToolbarGlobalHotkeys,
00315 RoadToolbarGlobalHotkeys,
00316 SignListGlobalHotkeys,
00317 AIDebugGlobalHotkeys,
00318 };
00319
00320 GlobalHotkeyHandler *_global_hotkey_handlers_editor[] = {
00321 TerraformToolbarEditorGlobalHotkeys,
00322 RoadToolbarEditorGlobalHotkeys,
00323 };
00324
00325
00326 void HandleGlobalHotkeys(WChar key, uint16 keycode)
00327 {
00328 if (_game_mode == GM_NORMAL) {
00329 for (uint i = 0; i < lengthof(_global_hotkey_handlers); i++) {
00330 if (_global_hotkey_handlers[i](key, keycode) == ES_HANDLED) return;
00331 }
00332 } else if (_game_mode == GM_EDITOR) {
00333 for (uint i = 0; i < lengthof(_global_hotkey_handlers_editor); i++) {
00334 if (_global_hotkey_handlers_editor[i](key, keycode) == ES_HANDLED) return;
00335 }
00336 }
00337 }
00338