hotkeys.cpp

Go to the documentation of this file.
00001 /* $Id: hotkeys.cpp 53730 2012-03-31 18:46:48Z espreon $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "global.hpp"
00017 
00018 #define GETTEXT_DOMAIN "wesnoth-lib"
00019 
00020 #include "construct_dialog.hpp"
00021 #include "display.hpp"
00022 #include "foreach.hpp"
00023 #include "hotkeys.hpp"
00024 #include "game_end_exceptions.hpp"
00025 #include "game_preferences.hpp"
00026 #include "gettext.hpp"
00027 #include "gui/dialogs/message.hpp"
00028 #include "gui/dialogs/transient_message.hpp"
00029 #include "gui/widgets/window.hpp"
00030 #include "filesystem.hpp"
00031 #include "log.hpp"
00032 #include "preferences_display.hpp"
00033 #include "wesconfig.h"
00034 #include "wml_separators.hpp"
00035 
00036 static lg::log_domain log_config("config");
00037 #define ERR_G LOG_STREAM(err, lg::general)
00038 #define LOG_G LOG_STREAM(info, lg::general)
00039 #define DBG_G LOG_STREAM(debug, lg::general)
00040 #define ERR_CF LOG_STREAM(err, log_config)
00041 
00042 namespace {
00043 
00044 const struct {
00045     hotkey::HOTKEY_COMMAND id;
00046     const char* command;
00047     const char* description;
00048     bool hidden;
00049     hotkey::scope scope;
00050 } hotkey_list_[] = {
00051 
00052     { hotkey::HOTKEY_CANCEL, "cancel", N_("Cancel"), false, hotkey::SCOPE_GENERAL },
00053     { hotkey::HOTKEY_LEFT_MOUSE_CLICK, "leftmouseclick", N_("Left Mouse Click"), false, hotkey::SCOPE_GENERAL },
00054     { hotkey::HOTKEY_RIGHT_MOUSE_CLICK, "rightmouseclick", N_("Right Mouse Click"), false, hotkey::SCOPE_GENERAL },
00055     { hotkey::HOTKEY_ANIMATE_MAP, "animatemap", N_("Animate Map"), false, hotkey::SCOPE_GENERAL },
00056     { hotkey::HOTKEY_CYCLE_UNITS, "cycle", N_("Next Unit"), false, hotkey::SCOPE_GAME },
00057     { hotkey::HOTKEY_CYCLE_BACK_UNITS, "cycleback", N_("Previous Unit"), false, hotkey::SCOPE_GAME },
00058     { hotkey::HOTKEY_UNIT_HOLD_POSITION, "holdposition", N_("Hold Position"), false, hotkey::SCOPE_GAME },
00059     { hotkey::HOTKEY_END_UNIT_TURN, "endunitturn", N_("End Unit Turn"), false, hotkey::SCOPE_GAME },
00060     { hotkey::HOTKEY_LEADER, "leader", N_("Leader"), false, hotkey::SCOPE_GAME },
00061     { hotkey::HOTKEY_UNDO, "undo", N_("Undo"), false, hotkey::SCOPE_GENERAL },
00062     { hotkey::HOTKEY_REDO, "redo", N_("Redo"), false, hotkey::SCOPE_GENERAL },
00063     { hotkey::HOTKEY_ZOOM_IN, "zoomin", N_("Zoom In"), false, hotkey::SCOPE_GENERAL },
00064     { hotkey::HOTKEY_ZOOM_OUT, "zoomout", N_("Zoom Out"), false, hotkey::SCOPE_GENERAL },
00065     { hotkey::HOTKEY_ZOOM_DEFAULT, "zoomdefault", N_("Default Zoom"), false, hotkey::SCOPE_GENERAL },
00066     { hotkey::HOTKEY_FULLSCREEN, "fullscreen", N_("Toggle Full Screen"), false, hotkey::SCOPE_GENERAL },
00067     { hotkey::HOTKEY_SCREENSHOT, "screenshot", N_("Screenshot"), false, hotkey::SCOPE_GENERAL },
00068     { hotkey::HOTKEY_MAP_SCREENSHOT, "mapscreenshot", N_("Map Screenshot"), false, hotkey::SCOPE_GENERAL },
00069     { hotkey::HOTKEY_ACCELERATED, "accelerated", N_("Accelerated"), false, hotkey::SCOPE_GAME },
00070     { hotkey::HOTKEY_UNIT_DESCRIPTION, "describeunit", N_("Unit Description"), false, hotkey::SCOPE_GAME },
00071     { hotkey::HOTKEY_RENAME_UNIT, "renameunit", N_("Rename Unit"), false, hotkey::SCOPE_GAME },
00072     { hotkey::HOTKEY_SAVE_GAME, "save", N_("Save Game"), false, hotkey::SCOPE_GAME },
00073     { hotkey::HOTKEY_SAVE_REPLAY, "savereplay", N_("Save Replay"), false, hotkey::SCOPE_GAME },
00074     { hotkey::HOTKEY_SAVE_MAP, "savemap", N_("Save Map"), false, hotkey::SCOPE_GAME },
00075     { hotkey::HOTKEY_LOAD_GAME, "load", N_("Load Game"), false, hotkey::SCOPE_GAME },
00076     { hotkey::HOTKEY_RECRUIT, "recruit", N_("Recruit"), false, hotkey::SCOPE_GAME },
00077     { hotkey::HOTKEY_REPEAT_RECRUIT, "repeatrecruit", N_("Repeat Recruit"), false, hotkey::SCOPE_GAME },
00078     { hotkey::HOTKEY_RECALL, "recall", N_("Recall"), false, hotkey::SCOPE_GAME },
00079     { hotkey::HOTKEY_ENDTURN, "endturn", N_("End Turn"), false, hotkey::SCOPE_GAME },
00080     { hotkey::HOTKEY_TOGGLE_ELLIPSES, "toggleellipses", N_("Toggle Ellipses"), false, hotkey::SCOPE_GENERAL },
00081     { hotkey::HOTKEY_TOGGLE_GRID, "togglegrid", N_("Toggle Grid"), false, hotkey::SCOPE_GENERAL },
00082     { hotkey::HOTKEY_MOUSE_SCROLL, "mousescroll", N_("Mouse Scrolling"), false, hotkey::SCOPE_GENERAL },
00083     { hotkey::HOTKEY_STATUS_TABLE, "statustable", N_("Status Table"), false, hotkey::SCOPE_GAME },
00084     { hotkey::HOTKEY_MUTE, "mute", N_("Mute"), false, hotkey::SCOPE_GENERAL },
00085     { hotkey::HOTKEY_SPEAK, "speak", N_("Speak"), false, hotkey::SCOPE_GAME },
00086     { hotkey::HOTKEY_CREATE_UNIT, "createunit", N_("Create Unit (Debug!)"), false, hotkey::SCOPE_GAME },
00087     { hotkey::HOTKEY_CHANGE_SIDE, "changeside", N_("Change Side (Debug!)"), false, hotkey::SCOPE_GAME },
00088     { hotkey::HOTKEY_PREFERENCES, "preferences", N_("Preferences"), false, hotkey::SCOPE_GENERAL },
00089     { hotkey::HOTKEY_OBJECTIVES, "objectives", N_("Scenario Objectives"), false, hotkey::SCOPE_GAME },
00090     { hotkey::HOTKEY_UNIT_LIST, "unitlist", N_("Unit List"), false, hotkey::SCOPE_GAME },
00091     { hotkey::HOTKEY_STATISTICS, "statistics", N_("Statistics"), false, hotkey::SCOPE_GAME },
00092     { hotkey::HOTKEY_STOP_NETWORK, "stopnetwork", N_("Pause Network Game"), false, hotkey::SCOPE_GAME },
00093     { hotkey::HOTKEY_START_NETWORK, "startnetwork", N_("Continue Network Game"), false, hotkey::SCOPE_GAME },
00094     { hotkey::HOTKEY_QUIT_GAME, "quit", N_("Quit Game"), false, hotkey::SCOPE_GENERAL },
00095     { hotkey::HOTKEY_LABEL_TEAM_TERRAIN, "labelteamterrain", N_("Set Team Label"), false, hotkey::SCOPE_GAME },
00096     { hotkey::HOTKEY_LABEL_TERRAIN, "labelterrain", N_("Set Label"), false, hotkey::SCOPE_GAME },
00097     { hotkey::HOTKEY_CLEAR_LABELS, "clearlabels", N_("Clear Labels"), false, hotkey::SCOPE_GAME },
00098     { hotkey::HOTKEY_SHOW_ENEMY_MOVES, "showenemymoves", N_("Show Enemy Moves"), false, hotkey::SCOPE_GAME },
00099     { hotkey::HOTKEY_BEST_ENEMY_MOVES, "bestenemymoves", N_("Best Possible Enemy Moves"), false, hotkey::SCOPE_GAME },
00100     { hotkey::HOTKEY_PLAY_REPLAY, "playreplay", N_("Play Replay"), false, hotkey::SCOPE_GAME },
00101     { hotkey::HOTKEY_RESET_REPLAY, "resetreplay", N_("Reset Replay"), false, hotkey::SCOPE_GAME },
00102     { hotkey::HOTKEY_STOP_REPLAY, "stopreplay", N_("Stop Replay"), false, hotkey::SCOPE_GAME },
00103     { hotkey::HOTKEY_REPLAY_NEXT_TURN, "replaynextturn", N_("Next Turn"), false, hotkey::SCOPE_GAME },
00104     { hotkey::HOTKEY_REPLAY_NEXT_SIDE, "replaynextside", N_("Next Side"), false, hotkey::SCOPE_GAME },
00105     { hotkey::HOTKEY_REPLAY_SHOW_EVERYTHING, "replayshoweverything",
00106       N_("Full Map"), false, hotkey::SCOPE_GAME },
00107     { hotkey::HOTKEY_REPLAY_SHOW_EACH, "replayshoweach",
00108       N_("Each Team"), false, hotkey::SCOPE_GAME },
00109     { hotkey::HOTKEY_REPLAY_SHOW_TEAM1, "replayshowteam1",
00110       N_("Team 1"), false, hotkey::SCOPE_GAME },
00111     { hotkey::HOTKEY_REPLAY_SKIP_ANIMATION, "replayskipanimation", N_("Skip Animation"), false, hotkey::SCOPE_GAME },
00112     // Whiteboard commands
00113     // TRANSLATORS: whiteboard menu entry: toggle planning mode
00114     { hotkey::HOTKEY_WB_TOGGLE, "wbtoggle", N_("whiteboard^Planning Mode"), false, hotkey::SCOPE_GAME },
00115     // TRANSLATORS: whiteboard menu entry: execute planned action
00116     { hotkey::HOTKEY_WB_EXECUTE_ACTION, "wbexecuteaction", N_("whiteboard^Execute Action"), false, hotkey::SCOPE_GAME },
00117     // TRANSLATORS: whiteboard menu entry: execute all planned actions
00118     { hotkey::HOTKEY_WB_EXECUTE_ALL_ACTIONS, "wbexecuteallactions", N_("whiteboard^Execute All Actions"), false, hotkey::SCOPE_GAME },
00119     // TRANSLATORS: whiteboard menu entry: delete planned action
00120     { hotkey::HOTKEY_WB_DELETE_ACTION, "wbdeleteaction", N_("whiteboard^Delete Action"), false, hotkey::SCOPE_GAME },
00121     // TRANSLATORS: whiteboard menu entry: move planned action up queue
00122     { hotkey::HOTKEY_WB_BUMP_UP_ACTION, "wbbumpupaction", N_("whiteboard^Move Action Up"), false, hotkey::SCOPE_GAME },
00123     // TRANSLATORS: whiteboard menu entry: move planned action down queue
00124     { hotkey::HOTKEY_WB_BUMP_DOWN_ACTION, "wbbumpdownaction", N_("whiteboard^Move Action Down"), false, hotkey::SCOPE_GAME },
00125     // TRANSLATORS: whiteboard menu entry: plan as though the chosen unit were dead
00126     { hotkey::HOTKEY_WB_SUPPOSE_DEAD, "wbsupposedead", N_("whiteboard^Suppose Dead"), false, hotkey::SCOPE_GAME },
00127 
00128     { hotkey::HOTKEY_EDITOR_QUIT_TO_DESKTOP, "editor-quit-to-desktop", N_("Quit to Desktop"), false, hotkey::SCOPE_EDITOR },
00129     { hotkey::HOTKEY_EDITOR_CLOSE_MAP, "editor-close-map", N_("Close Map"), false, hotkey::SCOPE_EDITOR },
00130     { hotkey::HOTKEY_EDITOR_SWITCH_MAP, "editor-switch-map", N_("Switch Map"), false, hotkey::SCOPE_EDITOR },
00131     { hotkey::HOTKEY_EDITOR_SETTINGS, "editor-settings", N_("Editor Settings"), false, hotkey::SCOPE_EDITOR },
00132     { hotkey::HOTKEY_EDITOR_PARTIAL_UNDO, "editor-partial-undo", N_("Partial Undo"), false, hotkey::SCOPE_EDITOR },
00133     { hotkey::HOTKEY_EDITOR_MAP_NEW, "editor-map-new", N_("New Map"), false, hotkey::SCOPE_EDITOR },
00134     { hotkey::HOTKEY_EDITOR_MAP_LOAD, "editor-map-load", N_("Load Map"), false, hotkey::SCOPE_EDITOR },
00135     { hotkey::HOTKEY_EDITOR_MAP_SAVE, "editor-map-save", N_("Save Map"), false, hotkey::SCOPE_EDITOR },
00136     { hotkey::HOTKEY_EDITOR_MAP_SAVE_AS, "editor-map-save-as", N_("Save Map As"), false, hotkey::SCOPE_EDITOR },
00137     { hotkey::HOTKEY_EDITOR_MAP_SAVE_ALL, "editor-map-save-all", N_("Save All Maps"), false, hotkey::SCOPE_EDITOR },
00138     { hotkey::HOTKEY_EDITOR_MAP_REVERT, "editor-map-revert", N_("Revert All Changes"), false, hotkey::SCOPE_EDITOR },
00139     { hotkey::HOTKEY_EDITOR_MAP_INFO, "editor-map-info", N_("Map Information"), false, hotkey::SCOPE_EDITOR },
00140     { hotkey::HOTKEY_EDITOR_PALETTE_ITEM_SWAP, "editor-terrain-palette-swap",
00141         N_("Swap Foreground/Background Terrains"), false, hotkey::SCOPE_EDITOR },
00142     { hotkey::HOTKEY_EDITOR_PALETTE_GROUPS, "editor-palette-groups", N_("Change Palette Group"), false, hotkey::SCOPE_EDITOR },
00143     { hotkey::HOTKEY_EDITOR_PALETTE_UPSCROLL, "editor-palette-upscroll", N_("Scroll Palette Left"), false, hotkey::SCOPE_EDITOR },
00144     { hotkey::HOTKEY_EDITOR_PALETTE_DOWNSCROLL, "editor-palette-downscroll", N_("Scroll Palette Right"), false, hotkey::SCOPE_EDITOR },
00145     { hotkey::HOTKEY_EDITOR_TOOL_NEXT, "editor-tool-next", N_("Next Tool"), false, hotkey::SCOPE_EDITOR },
00146     { hotkey::HOTKEY_EDITOR_TOOL_PAINT, "editor-tool-paint", N_("Paint Tool"), false, hotkey::SCOPE_EDITOR },
00147     { hotkey::HOTKEY_EDITOR_TOOL_FILL, "editor-tool-fill", N_("Fill Tool"), false, hotkey::SCOPE_EDITOR },
00148     { hotkey::HOTKEY_EDITOR_TOOL_SELECT, "editor-tool-select", N_("Selection Tool"), false, hotkey::SCOPE_EDITOR },
00149     { hotkey::HOTKEY_EDITOR_TOOL_STARTING_POSITION, "editor-tool-starting-position",
00150         N_("Set Starting Positions Tool"), false, hotkey::SCOPE_EDITOR },
00151     { hotkey::HOTKEY_EDITOR_TOOL_LABEL, "editor-tool-label",
00152         N_("Place a map label Tool"), false, hotkey::SCOPE_EDITOR },
00153     { hotkey::HOTKEY_EDITOR_TOOL_UNIT, "editor-tool-unit",
00154         N_("Place Unit Tool"), false, hotkey::SCOPE_EDITOR },
00155     { hotkey::HOTKEY_EDITOR_BRUSH_NEXT, "editor-brush-next", N_("Next Brush"), false, hotkey::SCOPE_EDITOR },
00156     { hotkey::HOTKEY_EDITOR_BRUSH_DEFAULT, "editor-brush-default", N_("Default Brush"), false, hotkey::SCOPE_EDITOR },
00157     { hotkey::HOTKEY_EDITOR_CUT, "editor-cut", N_("Cut"), false, hotkey::SCOPE_EDITOR },
00158     { hotkey::HOTKEY_EDITOR_COPY, "editor-copy", N_("Copy"), false, hotkey::SCOPE_EDITOR },
00159     { hotkey::HOTKEY_EDITOR_PASTE, "editor-paste", N_("Paste"), false, hotkey::SCOPE_EDITOR },
00160     { hotkey::HOTKEY_EDITOR_EXPORT_SELECTION_COORDS, "editor-export-selection-coords", N_("Export Selected Coordinates to System Clipboard"), false, hotkey::SCOPE_EDITOR },
00161     { hotkey::HOTKEY_EDITOR_SELECT_ALL, "editor-select-all",
00162          N_("Select All"), false, hotkey::SCOPE_EDITOR },
00163     { hotkey::HOTKEY_EDITOR_SELECT_INVERSE, "editor-select-inverse",
00164          N_("Select Inverse"), false, hotkey::SCOPE_EDITOR },
00165     { hotkey::HOTKEY_EDITOR_SELECT_NONE, "editor-select-none",
00166          N_("Select None"), false, hotkey::SCOPE_EDITOR },
00167     { hotkey::HOTKEY_EDITOR_CLIPBOARD_ROTATE_CW, "editor-clipboard-rotate-cw",
00168          N_("Rotate Clipboard Clockwise"), false, hotkey::SCOPE_EDITOR },
00169     { hotkey::HOTKEY_EDITOR_CLIPBOARD_ROTATE_CCW, "editor-clipboard-rotate-ccw",
00170          N_("Rotate Clipboard Counter-Clockwise"), false, hotkey::SCOPE_EDITOR },
00171     { hotkey::HOTKEY_EDITOR_CLIPBOARD_FLIP_HORIZONTAL, "editor-clipboard-flip-horizontal",
00172         N_("Flip Clipboard Horizontally"), false, hotkey::SCOPE_EDITOR },
00173     { hotkey::HOTKEY_EDITOR_CLIPBOARD_FLIP_VERTICAL, "editor-clipboard-flip-vertical",
00174         N_("Flip Clipboard Vertically"), false, hotkey::SCOPE_EDITOR },
00175     { hotkey::HOTKEY_EDITOR_SELECTION_ROTATE, "editor-selection-rotate",
00176         N_("Rotate Selection"), false, hotkey::SCOPE_EDITOR },
00177     { hotkey::HOTKEY_EDITOR_SELECTION_FLIP, "editor-selection-flip",
00178         N_("Flip Selection"), false, hotkey::SCOPE_EDITOR },
00179     { hotkey::HOTKEY_EDITOR_SELECTION_FILL, "editor-selection-fill",
00180         N_("Fill Selection"), false, hotkey::SCOPE_EDITOR },
00181     { hotkey::HOTKEY_EDITOR_SELECTION_GENERATE, "editor-selection-generate",
00182         N_("Generate Tiles In Selection"), false, hotkey::SCOPE_EDITOR },
00183     { hotkey::HOTKEY_EDITOR_SELECTION_RANDOMIZE, "editor-selection-randomize",
00184         N_("Randomize Tiles In Selection"), false, hotkey::SCOPE_EDITOR },
00185     { hotkey::HOTKEY_EDITOR_MAP_RESIZE, "editor-map-resize",
00186         N_("Resize Map"), false, hotkey::SCOPE_EDITOR },
00187     { hotkey::HOTKEY_EDITOR_MAP_ROTATE, "editor-map-rotate",
00188         N_("Rotate Map"), false, hotkey::SCOPE_EDITOR },
00189     { hotkey::HOTKEY_EDITOR_MAP_GENERATE, "editor-map-generate",
00190          N_("Generate Map"), false, hotkey::SCOPE_EDITOR },
00191     { hotkey::HOTKEY_EDITOR_MAP_APPLY_MASK, "editor-map-apply-mask",
00192          N_("Apply a Mask"), false, hotkey::SCOPE_EDITOR },
00193     { hotkey::HOTKEY_EDITOR_MAP_CREATE_MASK_TO, "editor-map-create-mask-to",
00194          N_("Create Mask"), false, hotkey::SCOPE_EDITOR },
00195     { hotkey::HOTKEY_EDITOR_REFRESH, "editor-refresh",
00196         N_("Refresh Display"), false, hotkey::SCOPE_EDITOR },
00197     { hotkey::HOTKEY_EDITOR_UPDATE_TRANSITIONS, "editor-update-transitions",
00198         N_("Update Terrain Transitions"), false, hotkey::SCOPE_EDITOR },
00199     { hotkey::HOTKEY_EDITOR_AUTO_UPDATE_TRANSITIONS, "editor-auto-update-transitions",
00200         N_("Auto-update Terrain Transitions"), false, hotkey::SCOPE_EDITOR },
00201     { hotkey::HOTKEY_EDITOR_REFRESH_IMAGE_CACHE, "editor-refresh-image-cache",
00202         N_("Refresh Image Cache"), false, hotkey::SCOPE_EDITOR },
00203     { hotkey::HOTKEY_EDITOR_DRAW_COORDINATES, "editor-draw-coordinates",
00204         N_("Draw Hex Coordinates"), false, hotkey::SCOPE_EDITOR },
00205     { hotkey::HOTKEY_EDITOR_DRAW_TERRAIN_CODES, "editor-draw-terrain-codes",
00206         N_("Draw Terrain Codes"), false, hotkey::SCOPE_EDITOR },
00207 
00208 
00209 
00210     { hotkey::HOTKEY_DELAY_SHROUD, "delayshroud", N_("Delay Shroud Updates"), false, hotkey::SCOPE_GAME },
00211     { hotkey::HOTKEY_UPDATE_SHROUD, "updateshroud", N_("Update Shroud Now"), false, hotkey::SCOPE_GAME },
00212     { hotkey::HOTKEY_CONTINUE_MOVE, "continue", N_("Continue Move"), false, hotkey::SCOPE_GAME },
00213     { hotkey::HOTKEY_SEARCH, "search", N_("Find Label or Unit"), false, hotkey::SCOPE_GAME },
00214     { hotkey::HOTKEY_SPEAK_ALLY, "speaktoally", N_("Speak to Ally"), false, hotkey::SCOPE_GAME },
00215     { hotkey::HOTKEY_SPEAK_ALL, "speaktoall", N_("Speak to All"), false, hotkey::SCOPE_GAME },
00216     { hotkey::HOTKEY_HELP, "help", N_("Help"), false, hotkey::SCOPE_GENERAL },
00217     { hotkey::HOTKEY_CHAT_LOG, "chatlog", N_("View Chat Log"), false, hotkey::SCOPE_GAME },
00218     { hotkey::HOTKEY_LANGUAGE, "changelanguage", N_("Change Language"), false, hotkey::SCOPE_GENERAL },
00219 
00220     { hotkey::HOTKEY_USER_CMD, "command", N_("Enter User Command"), false, hotkey::SCOPE_GENERAL },
00221     { hotkey::HOTKEY_CUSTOM_CMD, "customcommand", N_("Custom Command"), false, hotkey::SCOPE_GAME },
00222     { hotkey::HOTKEY_AI_FORMULA, "aiformula", N_("Run Formula"), false, hotkey::SCOPE_GAME },
00223     { hotkey::HOTKEY_CLEAR_MSG, "clearmessages", N_("Clear Messages"), false, hotkey::SCOPE_GAME },
00224     {
00225           hotkey::TITLE_SCREEN__RELOAD_WML
00226         , "title_screen__reload_wml"
00227         , N_("Refresh WML")
00228         , true
00229         , hotkey::SCOPE_GENERAL
00230     },
00231     {
00232           hotkey::TITLE_SCREEN__NEXT_TIP
00233         , "title_screen__next_tip"
00234         , N_("Next Tip of the Day")
00235         , false
00236         , hotkey::SCOPE_GENERAL
00237     },
00238     {
00239           hotkey::TITLE_SCREEN__PREVIOUS_TIP
00240         , "title_screen__previous_tip"
00241         , N_("Previous Tip of the Day")
00242         , false
00243         , hotkey::SCOPE_GENERAL
00244     },
00245     {
00246           hotkey::TITLE_SCREEN__TUTORIAL
00247         , "title_screen__tutorial"
00248         , N_("Start Tutorial")
00249         , false
00250         , hotkey::SCOPE_GENERAL
00251     },
00252     {
00253           hotkey::TITLE_SCREEN__CAMPAIGN
00254         , "title_screen__campaign"
00255         , N_("Start Campaign")
00256         , false
00257         , hotkey::SCOPE_GENERAL
00258     },
00259     {
00260           hotkey::TITLE_SCREEN__MULTIPLAYER
00261         , "title_screen__multiplayer"
00262         , N_("Start Multiplayer Game")
00263         , false
00264         , hotkey::SCOPE_GENERAL
00265     },
00266     {
00267           hotkey::TITLE_SCREEN__ADDONS
00268         , "title_screen__addons"
00269         , N_("Manage Add-ons")
00270         , false
00271         , hotkey::SCOPE_GENERAL
00272     },
00273     {
00274           hotkey::TITLE_SCREEN__EDITOR
00275         , "title_screen__editor"
00276         , N_("Start Editor")
00277         , false
00278         , hotkey::SCOPE_GENERAL
00279     },
00280     {
00281           hotkey::TITLE_SCREEN__CREDITS
00282         , "title_screen__credits"
00283         , N_("Show Credits")
00284         , false
00285         , hotkey::SCOPE_GENERAL
00286     },
00287 
00288     {
00289           hotkey::GLOBAL__HELPTIP
00290         , "global__helptip"
00291         , N_("Show Helptip")
00292         , false
00293         , hotkey::SCOPE_GENERAL
00294     },
00295 
00296     { hotkey::HOTKEY_NULL, NULL, NULL, true, hotkey::SCOPE_GENERAL }
00297 };
00298 
00299 std::vector<hotkey::hotkey_item> hotkeys_;
00300 hotkey::hotkey_item null_hotkey_;
00301 
00302 config default_hotkeys_cfg_;
00303 
00304 std::string hotkey_tag_name = "hotkey";
00305 
00306 std::vector<bool> scope_active_(hotkey::SCOPE_COUNT, false);
00307 }
00308 
00309 namespace hotkey {
00310 
00311 
00312 void deactivate_all_scopes()
00313 {
00314     for (int i = 0; i < hotkey::SCOPE_COUNT; ++i) {
00315         scope_active_[i] = false;
00316     }
00317 }
00318 
00319 void set_scope_active(scope s, bool set)
00320 {
00321     scope_active_[s] = set;
00322 }
00323 
00324 bool is_scope_active(scope s)
00325 {
00326     return scope_active_[s];
00327 }
00328 
00329 static void key_event_execute(display& disp, const SDL_KeyboardEvent& event, command_executor* executor);
00330 static void button_event_execute(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor);
00331 static void hat_event_execute(display& disp, const SDL_JoyHatEvent& event, command_executor* executor);
00332 
00333 const std::string CLEARED_TEXT = "__none__";
00334 
00335 hotkey_item::hotkey_item(HOTKEY_COMMAND id,
00336         const std::string& command, const t_string &description, bool hidden,
00337         scope s) :
00338     id_(id),
00339     command_(command),
00340     description_(description),
00341     scope_(s),
00342     type_(UNBOUND),
00343     character_(0),
00344     ctrl_(false),
00345     alt_(false),
00346     cmd_(false),
00347     shift_(false),
00348     keycode_(0),
00349     button_(0),
00350     joystick_(0),
00351     hat_(0),
00352     value_(0),
00353     hidden_(hidden)
00354 {
00355 }
00356 
00357 // There are two kinds of "key" values.  One refers to actual keys, like
00358 // F1 or SPACE.  The other refers to characters produced, eg 'M' or ':'.
00359 // For the latter, specifying shift+; doesn't make sense, because ; is
00360 // already shifted on French keyboards, for example.  You really want to
00361 // say ':', however that is typed.  However, when you say shift+SPACE,
00362 // you're really referring to the space bar, as shift+SPACE usually just
00363 // produces a SPACE character.
00364 void hotkey_item::load_from_config(const config& cfg)
00365 {
00366     const std::string& button = cfg["button"];
00367     if (!button.empty()) {
00368         joystick_ = cfg["joystick"].to_int();
00369         button_ = cfg["button"].to_int();
00370         type_ = hotkey_item::BUTTON;
00371     }
00372     const std::string& hat = cfg["hat"];
00373     if (!hat.empty()) {
00374         joystick_ = cfg["joystick"].to_int();
00375         hat_ = cfg["hat"].to_int();
00376         value_ = cfg["value"].to_int();
00377         type_ = hotkey_item::HAT;
00378     }
00379 
00380     const std::string& key = cfg["key"];
00381 
00382     alt_ = cfg["alt"].to_bool();
00383     cmd_ = cfg["cmd"].to_bool();
00384     ctrl_ = cfg["ctrl"].to_bool();
00385     shift_ = cfg["shift"].to_bool();
00386 
00387     if (key.empty()) return;
00388 
00389     if (key == CLEARED_TEXT)
00390     {
00391         type_ = hotkey_item::CLEARED;
00392         return;
00393     }
00394 
00395     wide_string wkey = utils::string_to_wstring(key);
00396 
00397     // They may really want a specific key on the keyboard: we assume
00398     // that any single character keyname is a character.
00399     if (wkey.size() > 1) {
00400         type_ = BY_KEYCODE;
00401 
00402         keycode_ = sdl_keysym_from_name(key);
00403         if (keycode_ == SDLK_UNKNOWN) {
00404             if (tolower(key[0]) != 'f') {
00405                 ERR_CF << "hotkey key '" << key << "' invalid\n";
00406             } else {
00407                 int num = lexical_cast_default<int>(key.c_str() + 1);
00408                 keycode_ = num + SDLK_F1 - 1;
00409             }
00410         }
00411     } else if (key == " " || shift_
00412 #ifdef __APPLE__
00413         || alt_
00414 #endif
00415         ) {
00416         // Space must be treated as a key because shift-space
00417         // isn't a different character from space, and control key
00418         // makes it go weird.  shift=yes should never be specified
00419         // on single characters (eg. key=m, shift=yes would be
00420         // key=M), but we don't want to break old preferences
00421         // files.
00422         type_ = BY_KEYCODE;
00423         keycode_ = wkey[0];
00424     } else {
00425         type_ = BY_CHARACTER;
00426         character_ = wkey[0];
00427     }
00428 }
00429 
00430 std::string hotkey_item::get_name() const
00431 {
00432     std::stringstream str;
00433     if (type_ == BY_CHARACTER) {
00434         if (alt_)
00435             str << "alt+";
00436         if (cmd_)
00437             str << "cmd+";
00438         if (ctrl_)
00439             str << "ctrl+";
00440         str << static_cast<char>(character_);
00441     } else if (type_ == BY_KEYCODE) {
00442         if (alt_)
00443             str << "alt+";
00444         if (ctrl_)
00445             str << "ctrl+";
00446         if (shift_)
00447             str << "shift+";
00448         if (cmd_)
00449             str << "cmd+";
00450         str << SDL_GetKeyName(SDLKey(keycode_));
00451     } else if (type_ == BUTTON) {
00452         str << "Joy" << joystick_ << "Btn" << button_;
00453     } else if (type_ == HAT) {
00454         std::string direction;
00455         switch (value_) {
00456             case SDL_HAT_CENTERED:
00457                 direction = "Centered";
00458                 break;
00459             case SDL_HAT_UP:
00460                 direction = "Up";
00461                 break;
00462             case SDL_HAT_RIGHT:
00463                 direction = "Right";
00464                 break;
00465             case SDL_HAT_DOWN:
00466                 direction = "Down";
00467                 break;
00468             case SDL_HAT_LEFT:
00469                 direction = "Left";
00470                 break;
00471             case SDL_HAT_RIGHTUP:
00472                 direction = "RightUp";
00473                 break;
00474             case SDL_HAT_RIGHTDOWN:
00475                 direction = "RightDown";
00476                 break;
00477             case SDL_HAT_LEFTUP:
00478                 direction = "LeftUp";
00479                 break;
00480             case SDL_HAT_LEFTDOWN:
00481                 direction = "LeftDown";
00482                 break;
00483             default:
00484                 direction = "Unknown";
00485         }
00486         str << "Joy" << joystick_ << "Hat" << hat_ << direction;
00487     }
00488     return str.str();
00489 }
00490 
00491 void hotkey_item::set_description(const t_string &description)
00492 {
00493     description_ = description;
00494 }
00495 void hotkey_item::clear_hotkey()
00496 {
00497     type_ = CLEARED;
00498 }
00499 
00500 void hotkey_item::set_button(int button, int joystick)
00501 {
00502     joystick_ = joystick;
00503     button_ = button;
00504     type_ = BUTTON;
00505 }
00506 
00507 void hotkey_item::set_hat(int joystick, int hat, int value)
00508 {
00509     joystick_ = joystick;
00510     hat_ = hat;
00511     value_ = value;
00512     type_ = HAT;
00513 }
00514 
00515 void hotkey_item::set_key(int character, int keycode, bool shift, bool ctrl, bool alt, bool cmd)
00516 {
00517     LOG_G << "setting hotkey: char=" << lexical_cast<std::string>(character)
00518            << " keycode="  << lexical_cast<std::string>(keycode) << " "
00519            << (shift ? "shift," : "")
00520            << (ctrl ? "ctrl," : "")
00521            << (alt ? "alt," : "")
00522            << (cmd ? "cmd," : "")
00523            << "\n";
00524 
00525     // Sometimes control modifies by -64, ie ^A == 1.
00526     if (character < 64 && ctrl) {
00527         if (shift)
00528             character += 64;
00529         else
00530             character += 96;
00531         LOG_G << "Mapped to character " << lexical_cast<std::string>(character) << "\n";
00532     }
00533 
00534     // For some reason on Mac OS, if cmd and shift are down, the character doesn't get upper-cased
00535     if (cmd && character > 96 && character < 123 && shift)
00536         character -= 32;
00537 
00538     // We handle simple cases by character, others by the actual key.
00539     if (isprint(character) && !isspace(character)) {
00540         type_ = BY_CHARACTER;
00541         character_ = character;
00542         ctrl_ = ctrl;
00543         alt_ = alt;
00544         cmd_ = cmd;
00545         LOG_G << "type = BY_CHARACTER\n";
00546     } else {
00547         type_ = BY_KEYCODE;
00548         keycode_ = keycode;
00549         shift_ = shift;
00550         ctrl_ = ctrl;
00551         alt_ = alt;
00552         cmd_ = cmd;
00553         LOG_G << "type = BY_KEYCODE\n";
00554     }
00555 }
00556 
00557 manager::manager()
00558 {
00559     init();
00560 }
00561 
00562 void manager::init()
00563 {
00564     for (int i = 0; hotkey_list_[i].command; ++i) {
00565         hotkeys_.push_back(hotkey_item(hotkey_list_[i].id, hotkey_list_[i].command,
00566                 "", hotkey_list_[i].hidden, hotkey_list_[i].scope));
00567     }
00568 }
00569 
00570 void manager::wipe()
00571 {
00572     hotkeys_.clear();
00573 }
00574 
00575 manager::~manager()
00576 {
00577     wipe();
00578 }
00579 
00580 scope_changer::scope_changer(const config& cfg, const std::string& hotkey_tag)
00581 : cfg_(cfg)
00582 , prev_tag_name_(hotkey_tag_name)
00583 , prev_scope_active_(scope_active_)
00584 {
00585     manager::wipe();
00586     manager::init();
00587     hotkey::load_descriptions();
00588     load_hotkeys(cfg_);
00589     set_hotkey_tag_name(hotkey_tag);
00590 }
00591 
00592 scope_changer::~scope_changer()
00593 {
00594     scope_active_.swap(prev_scope_active_);
00595     manager::wipe();
00596     manager::init();
00597     hotkey::load_descriptions();
00598     set_hotkey_tag_name(prev_tag_name_);
00599     load_hotkeys(cfg_);
00600 }
00601 
00602 void load_descriptions()
00603 {
00604     for (size_t i = 0; hotkey_list_[i].command; ++i) {
00605         if (i >= hotkeys_.size()) {
00606             ERR_G << "Hotkey list too short: " << hotkeys_.size() << "\n";
00607         }
00608         hotkeys_[i].set_description(t_string(hotkey_list_[i].description, PACKAGE "-lib"));
00609     }
00610 }
00611 
00612 void set_hotkey_tag_name(const std::string& name)
00613 {
00614     hotkey_tag_name = name;
00615 }
00616 
00617 void load_hotkeys(const config& cfg, bool set_as_default)
00618 {
00619     foreach (const config &hk, cfg.child_range(hotkey_tag_name))
00620     {
00621         hotkey_item& h = get_hotkey(hk["command"]);
00622         if(h.get_id() != HOTKEY_NULL) {
00623             h.load_from_config(hk);
00624         }
00625     }
00626 
00627     if(set_as_default) {
00628         default_hotkeys_cfg_ = cfg;
00629     }
00630 }
00631 
00632 void reset_default_hotkeys()
00633 {
00634     foreach(hotkey_item& hi, hotkeys_) {
00635         hi.clear_hotkey();
00636     }
00637 
00638     if(!default_hotkeys_cfg_.empty()) {
00639         load_hotkeys(default_hotkeys_cfg_);
00640     } else {
00641         ERR_G << "no default hotkeys set yet; all hotkeys are now unassigned!\n";
00642     }
00643 }
00644 
00645 void save_hotkeys(config& cfg)
00646 {
00647     cfg.clear_children(hotkey_tag_name);
00648 
00649     for(std::vector<hotkey_item>::iterator i = hotkeys_.begin(); i != hotkeys_.end(); ++i) {
00650         if (i->hidden() || i->get_type() == hotkey_item::UNBOUND || !i->is_in_active_scope())
00651             continue;
00652 
00653         config& item = cfg.add_child(hotkey_tag_name);
00654         item["command"] = i->get_command();
00655         if (i->get_type() == hotkey_item::CLEARED)
00656         {
00657             item["key"] = CLEARED_TEXT;
00658             continue;
00659         }
00660 
00661         if (i->get_type() == hotkey_item::BUTTON)
00662         {
00663             item["joystick"] = i->get_joystick();
00664             item["button"] = i->get_button();
00665         }
00666 
00667         if (i->get_type() == hotkey_item::HAT)
00668         {
00669             item["joystick"] = i->get_joystick();
00670             item["hat"] = i->get_hat();
00671             item["value"] = i->get_value();
00672         }
00673 
00674         if (i->get_type() == hotkey_item::BY_KEYCODE) {
00675             item["key"] = SDL_GetKeyName(SDLKey(i->get_keycode()));
00676             item["shift"] = i->get_shift();
00677         } else if (i->get_type() == hotkey_item::BY_CHARACTER) {
00678             item["key"] = utils::wchar_to_string(i->get_character());
00679         }
00680         item["alt"] = i->get_alt();
00681         item["ctrl"] = i->get_ctrl();
00682         item["cmd"] = i->get_cmd();
00683     }
00684 }
00685 
00686 hotkey_item& get_hotkey(HOTKEY_COMMAND id)
00687 {
00688     std::vector<hotkey_item>::iterator itor;
00689 
00690     for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
00691         if (itor->get_id() == id)
00692             break;
00693     }
00694 
00695     if (itor == hotkeys_.end())
00696         return null_hotkey_;
00697 
00698     return *itor;
00699 }
00700 
00701 hotkey_item& get_hotkey(const std::string& command)
00702 {
00703     std::vector<hotkey_item>::iterator itor;
00704 
00705     for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
00706         if (itor->get_command() == command)
00707             break;
00708     }
00709 
00710     if (itor == hotkeys_.end())
00711         return null_hotkey_;
00712 
00713     return *itor;
00714 }
00715 
00716 HOTKEY_COMMAND get_hotkey_command(const std::string& command)
00717 {
00718     for (size_t i = 0; hotkey_list_[i].command; ++i) {
00719         if (hotkey_list_[i].command == command)
00720             return hotkey_list_[i].id;
00721     }
00722 
00723     return HOTKEY_NULL;
00724 }
00725 
00726 hotkey_item& get_hotkey(int joy_num, int button_num)
00727 {
00728     std::vector<hotkey_item>::iterator itor;
00729 
00730     for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
00731         if (joy_num == itor->get_joystick() &&  button_num == itor->get_button() && (itor->get_type() == hotkey_item::BUTTON) )
00732             break;
00733     }
00734     if (itor == hotkeys_.end())
00735         return null_hotkey_;
00736 
00737     return *itor;
00738 }
00739 
00740 hotkey_item& get_hotkey(int joy_num, int hat_num, int hat_value)
00741 {
00742     std::vector<hotkey_item>::iterator itor;
00743 
00744     for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
00745         if (joy_num == itor->get_joystick() &&  hat_num == itor->get_hat()
00746                 && hat_value == itor->get_value() && (itor->get_type() == hotkey_item::HAT) )
00747             break;
00748     }
00749     if (itor == hotkeys_.end())
00750         return null_hotkey_;
00751 
00752     return *itor;
00753 }
00754 
00755 hotkey_item& get_hotkey(int character, int keycode, bool shift, bool ctrl,
00756     bool alt, bool cmd)
00757 {
00758     std::vector<hotkey_item>::iterator itor;
00759 
00760     DBG_G << "getting hotkey: char=" << lexical_cast<std::string>(character)
00761            << " keycode="  << lexical_cast<std::string>(keycode) << " "
00762            << (shift ? "shift," : "")
00763            << (ctrl ? "ctrl," : "")
00764            << (alt ? "alt," : "")
00765            << (cmd ? "cmd," : "")
00766            << "\n";
00767 
00768     // Sometimes control modifies by -64, ie ^A == 1.
00769     if (0 < character && character < 64 && ctrl) {
00770         if (shift)
00771             character += 64;
00772         else
00773             character += 96;
00774         DBG_G << "Mapped to character " << lexical_cast<std::string>(character) << "\n";
00775     }
00776 
00777     // For some reason on Mac OS, if cmd and shift are down, the character doesn't get upper-cased
00778     if (cmd && character > 96 && character < 123 && shift)
00779         character -= 32;
00780 
00781     for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
00782         if (itor->get_type() == hotkey_item::BY_CHARACTER) {
00783             if (character == itor->get_character()) {
00784                 if (ctrl == itor->get_ctrl()
00785                         && alt == itor->get_alt()
00786                         && cmd == itor->get_cmd()) {
00787                     if (itor->is_in_active_scope()) {
00788                         DBG_G << "Could match by character..." << "yes\n";
00789                         break;
00790                     } else {
00791                         DBG_G << "Could match by character..." << "yes, but scope is inactive\n";
00792                     }
00793                 }
00794                 DBG_G << "Could match by character..." << "but modifiers different\n";
00795             }
00796         } else if (itor->get_type() == hotkey_item::BY_KEYCODE) {
00797             if (keycode == itor->get_keycode()) {
00798                 if (shift == itor->get_shift()
00799                         && ctrl == itor->get_ctrl()
00800                         && alt == itor->get_alt()
00801                         && cmd == itor->get_cmd()) {
00802                     if (itor->is_in_active_scope()) {
00803                         DBG_G << "Could match by keycode..." << "yes\n";
00804                         break;
00805                     } else {
00806                         DBG_G << "Could match by keycode..." << "yes, but scope is inactive\n";
00807                     }
00808                 }
00809                 DBG_G << "Could match by keycode..." << "but modifiers different\n";
00810             }
00811         }
00812     }
00813 
00814     if (itor == hotkeys_.end())
00815         return null_hotkey_;
00816 
00817     return *itor;
00818 }
00819 
00820 hotkey_item& get_hotkey(const SDL_JoyButtonEvent& event)
00821 {
00822     return get_hotkey(event.which, event.button);
00823 }
00824 
00825 hotkey_item& get_hotkey(const SDL_JoyHatEvent& event)
00826 {
00827     return get_hotkey(event.which, event.hat, event.value);
00828 }
00829 
00830 hotkey_item& get_hotkey(const SDL_KeyboardEvent& event)
00831 {
00832     return get_hotkey(event.keysym.unicode, event.keysym.sym,
00833             (event.keysym.mod & KMOD_SHIFT) != 0,
00834             (event.keysym.mod & KMOD_CTRL) != 0,
00835             (event.keysym.mod & KMOD_ALT) != 0,
00836             (event.keysym.mod & KMOD_LMETA) != 0
00837 #ifdef __APPLE__
00838             || (event.keysym.mod & KMOD_RMETA) != 0
00839 #endif
00840             );
00841 }
00842 
00843 static void _get_visible_hotkey_itor(int index, std::vector<hotkey_item>::iterator& itor)
00844 {
00845     int counter = 0;
00846     for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
00847         if (itor->hidden() || !itor->is_in_active_scope())
00848             continue;
00849 
00850         if (index == counter)
00851             break;
00852 
00853         counter++;
00854     }
00855 }
00856 
00857 hotkey_item& get_visible_hotkey(int index)
00858 {
00859 
00860     std::vector<hotkey_item>::iterator itor;
00861     _get_visible_hotkey_itor(index, itor);
00862     if (itor == hotkeys_.end())
00863         return null_hotkey_;
00864 
00865     return *itor;
00866 }
00867 
00868 std::vector<hotkey_item>& get_hotkeys()
00869 {
00870     return hotkeys_;
00871 }
00872 
00873 basic_handler::basic_handler(display* disp, command_executor* exec) : disp_(disp), exec_(exec) {}
00874 
00875 void basic_handler::handle_event(const SDL_Event& event)
00876 {
00877     if(event.type == SDL_KEYDOWN && disp_ != NULL) {
00878 
00879         //if we're in a dialog we only want to handle things that are explicitly handled
00880         //by the executor. If we're not in a dialog we can call the regular key event handler
00881         if(!gui::in_dialog()) {
00882             key_event(*disp_,event.key,exec_);
00883         } else if(exec_ != NULL) {
00884             key_event_execute(*disp_,event.key,exec_);
00885         }
00886     }
00887     if(event.type == SDL_JOYBUTTONDOWN && disp_ != NULL) {
00888         button_event_execute(*disp_, event.jbutton, exec_);
00889     }
00890 }
00891 
00892 void button_event(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor)
00893 {
00894     button_event_execute(disp,event,executor);
00895 }
00896 
00897 void hat_event(display& disp, const SDL_JoyHatEvent& event, command_executor* executor)
00898 {
00899     hat_event_execute(disp,event,executor);
00900 }
00901 
00902 void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor* executor)
00903 {
00904     if(event.keysym.sym == SDLK_ESCAPE && disp.in_game()) {
00905         LOG_G << "escape pressed..showing quit\n";
00906         const int res = gui2::show_message(disp.video(), _("Quit"), _("Do you really want to quit?"), gui2::tmessage::yes_no_buttons);
00907         if(res != gui2::twindow::CANCEL) {
00908             throw end_level_exception(QUIT);
00909         } else {
00910             return;
00911         }
00912     }
00913 
00914     key_event_execute(disp,event,executor);
00915 }
00916 
00917 void button_event_execute(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor)
00918 {
00919     const hotkey_item* hk = &get_hotkey(event);
00920 
00921 #if 0
00922     // This is not generally possible without knowing keyboard layout.
00923     if(hk->null()) {
00924         //no matching hotkey was found, but try an in-exact match.
00925         hk = &get_hotkey(event, true);
00926     }
00927 #endif
00928 
00929     if(hk->null())
00930         return;
00931 
00932     execute_command(disp,hk->get_id(),executor);
00933 }
00934 
00935 void hat_event_execute(display& disp, const SDL_JoyHatEvent& event, command_executor* executor)
00936 {
00937     const hotkey_item* hk = &get_hotkey(event);
00938 
00939 #if 0
00940     // This is not generally possible without knowing keyboard layout.
00941     if(hk->null()) {
00942         //no matching hotkey was found, but try an in-exact match.
00943         hk = &get_hotkey(event, true);
00944     }
00945 #endif
00946 
00947     if(hk->null())
00948         return;
00949 
00950     execute_command(disp,hk->get_id(),executor);
00951 }
00952 
00953 
00954 void key_event_execute(display& disp, const SDL_KeyboardEvent& event, command_executor* executor)
00955 {
00956     const hotkey_item* hk = &get_hotkey(event);
00957 
00958 #if 0
00959     // This is not generally possible without knowing keyboard layout.
00960     if(hk->null()) {
00961         //no matching hotkey was found, but try an in-exact match.
00962         hk = &get_hotkey(event, true);
00963     }
00964 #endif
00965 
00966     if(hk->null())
00967         return;
00968 
00969     execute_command(disp,hk->get_id(),executor);
00970 }
00971 
00972 bool command_executor::execute_command(HOTKEY_COMMAND command, int /*index*/)
00973 {
00974     switch(command) {
00975         case HOTKEY_CYCLE_UNITS:
00976             cycle_units();
00977             break;
00978         case HOTKEY_CYCLE_BACK_UNITS:
00979             cycle_back_units();
00980             break;
00981         case HOTKEY_ENDTURN:
00982             end_turn();
00983             break;
00984         case HOTKEY_UNIT_HOLD_POSITION:
00985             unit_hold_position();
00986             break;
00987         case HOTKEY_END_UNIT_TURN:
00988             end_unit_turn();
00989             break;
00990         case HOTKEY_LEADER:
00991             goto_leader();
00992             break;
00993         case HOTKEY_UNDO:
00994             undo();
00995             break;
00996         case HOTKEY_REDO:
00997             redo();
00998             break;
00999         case HOTKEY_UNIT_DESCRIPTION:
01000             unit_description();
01001             break;
01002         case HOTKEY_RENAME_UNIT:
01003             rename_unit();
01004             break;
01005         case HOTKEY_SAVE_GAME:
01006             save_game();
01007             break;
01008         case HOTKEY_SAVE_REPLAY:
01009             save_replay();
01010             break;
01011         case HOTKEY_SAVE_MAP:
01012             save_map();
01013             break;
01014         case HOTKEY_LOAD_GAME:
01015             load_game();
01016             break;
01017         case HOTKEY_TOGGLE_ELLIPSES:
01018             toggle_ellipses();
01019             break;
01020         case HOTKEY_TOGGLE_GRID:
01021             toggle_grid();
01022             break;
01023         case HOTKEY_STATUS_TABLE:
01024             status_table();
01025             break;
01026         case HOTKEY_RECALL:
01027             recall();
01028             break;
01029         case HOTKEY_RECRUIT:
01030             recruit();
01031             break;
01032         case hotkey::HOTKEY_REPEAT_RECRUIT:
01033             repeat_recruit();
01034             break;
01035         case HOTKEY_SPEAK:
01036             speak();
01037             break;
01038         case HOTKEY_SPEAK_ALLY:
01039             whisper();
01040             break;
01041         case HOTKEY_SPEAK_ALL:
01042             shout();
01043             break;
01044         case HOTKEY_CREATE_UNIT:
01045             create_unit();
01046             break;
01047         case HOTKEY_CHANGE_SIDE:
01048             change_side();
01049             break;
01050         case HOTKEY_PREFERENCES:
01051             preferences();
01052             break;
01053         case HOTKEY_OBJECTIVES:
01054             objectives();
01055             break;
01056         case HOTKEY_UNIT_LIST:
01057             unit_list();
01058             break;
01059         case HOTKEY_STATISTICS:
01060             show_statistics();
01061             break;
01062         case HOTKEY_STOP_NETWORK:
01063             stop_network();
01064             break;
01065         case HOTKEY_START_NETWORK:
01066             start_network();
01067             break;
01068         case HOTKEY_LABEL_TEAM_TERRAIN:
01069             label_terrain(true);
01070             break;
01071         case HOTKEY_LABEL_TERRAIN:
01072             label_terrain(false);
01073             break;
01074         case HOTKEY_CLEAR_LABELS:
01075             clear_labels();
01076             break;
01077         case HOTKEY_SHOW_ENEMY_MOVES:
01078             show_enemy_moves(false);
01079             break;
01080         case HOTKEY_BEST_ENEMY_MOVES:
01081             show_enemy_moves(true);
01082             break;
01083         case HOTKEY_DELAY_SHROUD:
01084             toggle_shroud_updates();
01085             break;
01086         case HOTKEY_UPDATE_SHROUD:
01087             update_shroud_now();
01088             break;
01089         case HOTKEY_CONTINUE_MOVE:
01090             continue_move();
01091             break;
01092         case HOTKEY_SEARCH:
01093             search();
01094             break;
01095         case HOTKEY_HELP:
01096             show_help();
01097             break;
01098         case HOTKEY_CHAT_LOG:
01099             show_chat_log();
01100             break;
01101         case HOTKEY_USER_CMD:
01102             user_command();
01103             break;
01104         case HOTKEY_CUSTOM_CMD:
01105             custom_command();
01106             break;
01107         case HOTKEY_AI_FORMULA:
01108             ai_formula();
01109             break;
01110         case HOTKEY_CLEAR_MSG:
01111             clear_messages();
01112             break;
01113          case HOTKEY_LANGUAGE:
01114             change_language();
01115             break;
01116          case HOTKEY_PLAY_REPLAY:
01117             play_replay();
01118              break;
01119          case HOTKEY_RESET_REPLAY:
01120             reset_replay();
01121              break;
01122          case HOTKEY_STOP_REPLAY:
01123              stop_replay();
01124              break;
01125          case HOTKEY_REPLAY_NEXT_TURN:
01126             replay_next_turn();
01127              break;
01128          case HOTKEY_REPLAY_NEXT_SIDE:
01129             replay_next_side();
01130              break;
01131          case HOTKEY_REPLAY_SHOW_EVERYTHING:
01132             replay_show_everything();
01133              break;
01134          case HOTKEY_REPLAY_SHOW_EACH:
01135             replay_show_each();
01136              break;
01137          case HOTKEY_REPLAY_SHOW_TEAM1:
01138             replay_show_team1();
01139              break;
01140          case HOTKEY_REPLAY_SKIP_ANIMATION:
01141             replay_skip_animation();
01142              break;
01143          case HOTKEY_WB_TOGGLE:
01144              whiteboard_toggle();
01145              break;
01146          case HOTKEY_WB_EXECUTE_ACTION:
01147              whiteboard_execute_action();
01148              break;
01149          case HOTKEY_WB_EXECUTE_ALL_ACTIONS:
01150              whiteboard_execute_all_actions();
01151              break;
01152          case HOTKEY_WB_DELETE_ACTION:
01153              whiteboard_delete_action();
01154              break;
01155          case HOTKEY_WB_BUMP_UP_ACTION:
01156              whiteboard_bump_up_action();
01157              break;
01158          case HOTKEY_WB_BUMP_DOWN_ACTION:
01159              whiteboard_bump_down_action();
01160              break;
01161          case HOTKEY_WB_SUPPOSE_DEAD:
01162              whiteboard_suppose_dead();
01163              break;
01164          case HOTKEY_LEFT_MOUSE_CLICK:
01165              left_mouse_click();
01166              break;
01167          case HOTKEY_RIGHT_MOUSE_CLICK:
01168              right_mouse_click();
01169              break;
01170          default:
01171              return false;
01172     }
01173     return true;
01174 }
01175 
01176 void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* executor, int index)
01177 {
01178     const int zoom_amount = 4;
01179     bool map_screenshot = false;
01180 
01181     if(executor != NULL) {
01182         if(!executor->can_execute_command(command, index) || executor->execute_command(command, index))
01183         return;
01184     }
01185     switch(command) {
01186         case HOTKEY_ZOOM_IN:
01187             disp.set_zoom(zoom_amount);
01188             break;
01189         case HOTKEY_ZOOM_OUT:
01190             disp.set_zoom(-zoom_amount);
01191             break;
01192         case HOTKEY_ZOOM_DEFAULT:
01193             disp.set_default_zoom();
01194             break;
01195         case HOTKEY_FULLSCREEN:
01196             preferences::set_fullscreen(!preferences::fullscreen());
01197             break;
01198         case HOTKEY_MAP_SCREENSHOT:
01199             if (!disp.in_game() && !disp.in_editor())
01200                 break;
01201             map_screenshot = true;
01202         case HOTKEY_SCREENSHOT: {
01203             std::string name = map_screenshot ? _("Map-Screenshot") : _("Screenshot");
01204             std::string filename = get_screenshot_dir() + "/" + name + "_";
01205             filename = get_next_filename(filename, ".bmp");
01206             int size = disp.screenshot(filename, map_screenshot);
01207             if (size > 0) {
01208                 std::stringstream res;
01209                 res << filename << " ( " << utils::si_string(size, true, _("unit_byte^B")) << " )";
01210                 gui2::show_message(disp.video(), _("Screenshot done"), res.str());
01211             } else
01212                 gui2::show_message(disp.video(), _("Screenshot done"), "");
01213             break;
01214         }
01215         case HOTKEY_ANIMATE_MAP:
01216             preferences::set_animate_map(!preferences::animate_map());
01217             break;
01218         case HOTKEY_MOUSE_SCROLL:
01219             preferences::enable_mouse_scroll(!preferences::mouse_scroll_enabled());
01220             break;
01221         case HOTKEY_ACCELERATED:
01222             preferences::set_turbo(!preferences::turbo());
01223             break;
01224         case HOTKEY_MUTE:
01225             {
01226                 // look if both is not playing
01227                 static struct before_muted_s
01228                 {
01229                     bool playing_sound,playing_music;
01230                     before_muted_s() : playing_sound(false),playing_music(false){}
01231                 } before_muted;
01232                 if (preferences::music_on() || preferences::sound_on())
01233                 {
01234                     //then remember settings and mute both
01235                     before_muted.playing_sound = preferences::sound_on();
01236                     before_muted.playing_music = preferences::music_on();
01237                     preferences::set_sound(false);
01238                     preferences::set_music(false);
01239                 }
01240                 else
01241                 {
01242                     //then set settings before mute
01243                     preferences::set_sound(before_muted.playing_sound);
01244                     preferences::set_music(before_muted.playing_music);
01245                 }
01246             }
01247             break;
01248         case HOTKEY_QUIT_GAME: {
01249             if(disp.in_game()) {
01250                 DBG_G << "is in game -- showing quit message\n";
01251                 const int res = gui2::show_message(disp.video(), _("Quit"), _("Do you really want to quit?"), gui2::tmessage::yes_no_buttons);
01252                 if(res != gui2::twindow::CANCEL) {
01253                     throw end_level_exception(QUIT);
01254                 }
01255             }
01256 
01257             break;
01258         }
01259         default:
01260             DBG_G << "command_executor: unknown command number " << command << ", ignoring.\n";
01261             break;
01262     }
01263 }
01264 
01265 void command_executor::show_menu(const std::vector<std::string>& items_arg, int xloc, int yloc, bool context_menu, display& gui)
01266 {
01267     std::vector<std::string> items = items_arg;
01268     if (items.empty())
01269         return;
01270     if (can_execute_command(hotkey::get_hotkey(items.front()).get_id(), 0)){
01271         //if just one item is passed in, that means we should execute that item
01272         if(!context_menu && items.size() == 1 && items_arg.size() == 1) {
01273             hotkey::execute_command(gui,hotkey::get_hotkey(items.front()).get_id(),this);
01274             return;
01275         }
01276 
01277         std::vector<std::string> menu = get_menu_images(gui, items);
01278 
01279         int res = 0;
01280         {
01281             gui::dialog mmenu = gui::dialog(gui,"","",
01282             gui::MESSAGE, gui::dialog::hotkeys_style);
01283             mmenu.set_menu(menu);
01284             res = mmenu.show(xloc, yloc);
01285         } // this will kill the dialog
01286         if (res < 0 || size_t(res) >= items.size())
01287             return;
01288 
01289         const hotkey::HOTKEY_COMMAND cmd = hotkey::get_hotkey(items[res]).get_id();
01290         hotkey::execute_command(gui,cmd,this,res);
01291     }
01292 }
01293 
01294 std::string command_executor::get_menu_image(hotkey::HOTKEY_COMMAND command, int index) const {
01295     switch(get_action_state(command, index)) {
01296         case ACTION_ON: return game_config::images::checked_menu;
01297         case ACTION_OFF: return game_config::images::unchecked_menu;
01298         default: return get_action_image(command, index);
01299     }
01300 }
01301 
01302 std::vector<std::string> command_executor::get_menu_images(display &disp, const std::vector<std::string>& items){
01303     std::vector<std::string> result;
01304     bool has_image = false;
01305 
01306     for(size_t i = 0; i < items.size(); ++i) {
01307         std::string const& item = items[i];
01308         const hotkey::hotkey_item hk = hotkey::get_hotkey(item);
01309 
01310         std::stringstream str;
01311         //see if this menu item has an associated image
01312         std::string img(get_menu_image(hk.get_id(), i));
01313         if(img.empty() == false) {
01314             has_image = true;
01315             str << IMAGE_PREFIX << img << COLUMN_SEPARATOR;
01316         }
01317 
01318         if (hk.get_id() == hotkey::HOTKEY_NULL) {
01319             str << item.substr(0, item.find_last_not_of(' ') + 1) << COLUMN_SEPARATOR;
01320         } else {
01321             std::string desc = hk.get_description();
01322             if (hk.get_id() == HOTKEY_ENDTURN) {
01323                 const theme::menu *b = disp.get_theme().get_menu_item("button-endturn");
01324                 if(b) {
01325                     desc = b->title();
01326                 }
01327             }
01328             str << desc << COLUMN_SEPARATOR << hk.get_name();
01329         }
01330 
01331         result.push_back(str.str());
01332     }
01333     //If any of the menu items have an image, create an image column
01334     if(has_image)
01335         for(std::vector<std::string>::iterator i = result.begin(); i != result.end(); ++i)
01336             if(*(i->begin()) != IMAGE_PREFIX)
01337                 i->insert(i->begin(), COLUMN_SEPARATOR);
01338     return result;
01339 }
01340 
01341 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:01 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs