diff options
author | Andrzej Rybczak <electricityispower@gmail.com> | 2012-09-05 23:19:34 +0200 |
---|---|---|
committer | Andrzej Rybczak <electricityispower@gmail.com> | 2012-09-05 23:19:34 +0200 |
commit | 1be7676187e6bad1c31e0dca5bea570e9f5f58ec (patch) | |
tree | b95d8a56bda0d966e7024de0b3e30e6fc3f3d225 /src/bindings.cpp | |
parent | 8ef252ec6ee841ae43cdfebbd66fc926558e1759 (diff) |
rename keys.{cpp,h} to bindings.{cpp,h}
Diffstat (limited to 'src/bindings.cpp')
-rw-r--r-- | src/bindings.cpp | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/src/bindings.cpp b/src/bindings.cpp new file mode 100644 index 00000000..dc84bd38 --- /dev/null +++ b/src/bindings.cpp @@ -0,0 +1,521 @@ +/*************************************************************************** + * Copyright (C) 2008-2012 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include <fstream> +#include <iostream> +#include "global.h" +#include "bindings.h" +#include "utility/string.h" + +BindingsConfiguration Bindings; + +Key Key::noOp = Key(ERR, NCurses); + +namespace {// + +Key stringToSpecialKey(const std::string &s) +{ + Key result = Key::noOp; + if (!s.compare("mouse")) + result = Key(KEY_MOUSE, Key::NCurses); + else if (!s.compare("up")) + result = Key(KEY_UP, Key::NCurses); + else if (!s.compare("down")) + result = Key(KEY_DOWN, Key::NCurses); + else if (!s.compare("page_up")) + result = Key(KEY_PPAGE, Key::NCurses); + else if (!s.compare("page_down")) + result = Key(KEY_NPAGE, Key::NCurses); + else if (!s.compare("home")) + result = Key(KEY_HOME, Key::NCurses); + else if (!s.compare("end")) + result = Key(KEY_END, Key::NCurses); + else if (!s.compare("space")) + result = Key(KEY_SPACE, Key::Standard); + else if (!s.compare("enter")) + result = Key(KEY_ENTER, Key::Standard); + else if (!s.compare("delete")) + result = Key(KEY_DC, Key::NCurses); + else if (!s.compare("left")) + result = Key(KEY_LEFT, Key::NCurses); + else if (!s.compare("right")) + result = Key(KEY_RIGHT, Key::NCurses); + else if (!s.compare("tab")) + result = Key(KEY_TAB, Key::Standard); + else if (!s.compare("shift_tab")) + result = Key(KEY_SHIFT_TAB, Key::NCurses); + else if (!s.compare(0, 5, "ctrl_") && s.length() > 5 && s[5] >= 'a' && s[5] <= 'z') + result = Key(KEY_CTRL_A + (s[5] - 'a'), Key::Standard); + else if (s.length() > 1 && s[0] == 'f') + { + int n = atoi(s.c_str() + 1); + if (n >= 1 && n <= 12) + result = Key(KEY_F1 + n - 1, Key::NCurses); + } + else if (!s.compare("backspace")) + result = Key(KEY_BACKSPACE, Key::NCurses); + else if (!s.compare("backspace_2")) + result = Key(KEY_BACKSPACE_2, Key::Standard); + return result; +} + +Key stringToKey(const std::string &s) +{ + Key result = stringToSpecialKey(s); + if (result == Key::noOp) + { + std::wstring ws = ToWString(s); + if (ws.length() == 1) + result = Key(ws[0], Key::Standard); + } + return result; +} + +template <typename F> +Action *parseActionLine(const std::string &line, F error) +{ + Action *result = 0; + size_t i = 0; + for (; i < line.size() && !isspace(line[i]); ++i) { } + if (i == line.size()) // only action name + result = Action::Get(line); + else // there is something else + { + std::string action_name = line.substr(0, i); + if (action_name == "push_character") + { + // push single character into input queue + std::string arg = getEnclosedString(line, '"', '"', 0); + Key k = stringToSpecialKey(arg); + if (k != Key::noOp) + result = new PushCharacters(&Global::wFooter, { k.getChar() }); + else + error() << "invalid character passed to push_character: '" << arg << "'\n"; + } + else if (action_name == "push_characters") + { + // push sequence of characters into input queue + std::string arg = getEnclosedString(line, '"', '"', 0); + if (!arg.empty()) + { + std::vector<int> queue(arg.begin(), arg.end()); + // if char is signed, cancel 1s from char -> int conversion + for (auto it = arg.begin(); it != arg.end(); ++it) + *it &= 0xff; + result = new PushCharacters(&Global::wFooter, std::move(queue)); + } + else + error() << "empty argument passed to push_characters\n"; + } + else if (action_name == "require_runnable") + { + // require that given action is runnable + std::string arg = getEnclosedString(line, '"', '"', 0); + Action *action = Action::Get(arg); + if (action) + result = new RequireRunnable(action); + else + error() << "unknown action passed to require_runnable: '" << arg << "'\n"; + } + } + return result; +} + +} + +Key Key::read(NC::Window &w) +{ + Key result = noOp; + std::string tmp; + int input; + while (true) + { + input = w.readKey(); + if (input == ERR) + break; + if (input > 255) + { + result = Key(input, NCurses); + break; + } + else + { + wchar_t wc; + tmp += input; + size_t conv_res = mbrtowc(&wc, tmp.c_str(), MB_CUR_MAX, 0); + if (conv_res == size_t(-1)) // incomplete multibyte character + continue; + else if (conv_res == size_t(-2)) // garbage character sequence + break; + else // character complete + { + result = Key(wc, Standard); + break; + } + } + } + return result; +} + +bool BindingsConfiguration::read(const std::string &file) +{ + bool result = true; + + std::ifstream f(file); + if (!f.is_open()) + return result; + + size_t line_no = 0; + bool key_def_in_progress = false; + Key key = Key::noOp; + Binding::ActionChain actions; + std::string line, strkey; + + auto error = [&]() -> std::ostream & { + std::cerr << file << ":" << line_no << ": "; + key_def_in_progress = false; + result = false; + return std::cerr; + }; + + auto bind_key_def = [&]() -> bool { + if (!actions.empty()) + { + bind(key, actions); + actions.clear(); + return true; + } + else + { + error() << "definition of key '" << strkey << "' cannot be empty.\n"; + return false; + } + }; + + while (!f.eof() && ++line_no) + { + getline(f, line); + if (line.empty() || line[0] == '#') + continue; + + if (!line.compare(0, 7, "def_key")) // beginning of key definition + { + if (key_def_in_progress) + { + if (!bind_key_def()) + break; + } + key_def_in_progress = true; + strkey = getEnclosedString(line, '"', '"', 0); + key = stringToKey(strkey); + if (key == Key::noOp) + { + error() << "invalid key: '" << strkey << "'\n"; + break; + } + } + else if (isspace(line[0])) // name of action to be bound + { + trim(line); + Action *action = parseActionLine(line, error); + if (action) + actions.push_back(action); + else + { + error() << "unknown action: '" << line << "'\n"; + break; + } + } + } + if (key_def_in_progress) + bind_key_def(); + f.close(); + return result; +} + +void BindingsConfiguration::generateDefault() +{ + Key k = Key::noOp; + if (notBound(k = stringToKey("mouse"))) + bind(k, aMouseEvent); + if (notBound(k = stringToKey("up"))) + bind(k, aScrollUp); + if (notBound(k = stringToKey("down"))) + bind(k, aScrollDown); + if (notBound(k = stringToKey("["))) + bind(k, aScrollUpAlbum); + if (notBound(k = stringToKey("]"))) + bind(k, aScrollDownAlbum); + if (notBound(k = stringToKey("{"))) + bind(k, aScrollUpArtist); + if (notBound(k = stringToKey("}"))) + bind(k, aScrollDownArtist); + if (notBound(k = stringToKey("page_up"))) + bind(k, aPageUp); + if (notBound(k = stringToKey("page_down"))) + bind(k, aPageDown); + if (notBound(k = stringToKey("home"))) + bind(k, aMoveHome); + if (notBound(k = stringToKey("end"))) + bind(k, aMoveEnd); + if (notBound(k = stringToKey("space"))) + bind(k, aPressSpace); + if (notBound(k = stringToKey("enter"))) + bind(k, aPressEnter); + if (notBound(k = stringToKey("delete"))) + bind(k, aDelete); + if (notBound(k = stringToKey("right"))) + { + bind(k, aNextColumn); + bind(k, aSlaveScreen); + bind(k, aVolumeUp); + } + if (notBound(k = stringToKey("left"))) + { + bind(k, aPreviousColumn); + bind(k, aMasterScreen); + bind(k, aVolumeDown); + } + if (notBound(k = stringToKey("tab"))) + bind(k, aNextScreen); + if (notBound(k = stringToKey("shift_tab"))) + bind(k, aPreviousScreen); + if (notBound(k = stringToKey("1"))) + bind(k, aShowHelp); + if (notBound(k = stringToKey("2"))) + bind(k, aShowPlaylist); + if (notBound(k = stringToKey("3"))) + bind(k, aShowBrowser); + if (notBound(k = stringToKey("4"))) + bind(k, aShowSearchEngine); + if (notBound(k = stringToKey("5"))) + bind(k, aShowMediaLibrary); + if (notBound(k = stringToKey("6"))) + bind(k, aShowPlaylistEditor); + if (notBound(k = stringToKey("7"))) + bind(k, aShowTagEditor); + if (notBound(k = stringToKey("8"))) + bind(k, aShowOutputs); + if (notBound(k = stringToKey("9"))) + bind(k, aShowVisualizer); + if (notBound(k = stringToKey("0"))) + bind(k, aShowClock); + if (notBound(k = stringToKey("@"))) + bind(k, aShowServerInfo); + if (notBound(k = stringToKey("s"))) + bind(k, aStop); + if (notBound(k = stringToKey("P"))) + bind(k, aPause); + if (notBound(k = stringToKey(">"))) + bind(k, aNextSong); + if (notBound(k = stringToKey("<"))) + bind(k, aPreviousSong); + if (notBound(k = stringToKey("ctrl_h"))) + { + bind(k, aJumpToParentDir); + bind(k, aReplaySong); + } + if (notBound(k = stringToKey("backspace"))) + { + bind(k, aJumpToParentDir); + bind(k, aReplaySong); + } + if (notBound(k = stringToKey("backspace_2"))) + { + bind(k, aJumpToParentDir); + bind(k, aReplaySong); + } + if (notBound(k = stringToKey("f"))) + bind(k, aSeekForward); + if (notBound(k = stringToKey("b"))) + bind(k, aSeekBackward); + if (notBound(k = stringToKey("r"))) + bind(k, aToggleRepeat); + if (notBound(k = stringToKey("z"))) + bind(k, aToggleRandom); + if (notBound(k = stringToKey("y"))) + { + bind(k, aSaveTagChanges); + bind(k, aStartSearching); + bind(k, aToggleSingle); + } + if (notBound(k = stringToKey("R"))) + bind(k, aToggleConsume); + if (notBound(k = stringToKey("Y"))) + bind(k, aToggleReplayGainMode); + if (notBound(k = stringToKey("t"))) + bind(k, aToggleSpaceMode); + if (notBound(k = stringToKey("T"))) + bind(k, aToggleAddMode); + if (notBound(k = stringToKey("|"))) + bind(k, aToggleMouse); + if (notBound(k = stringToKey("#"))) + bind(k, aToggleBitrateVisibility); + if (notBound(k = stringToKey("Z"))) + bind(k, aShuffle); + if (notBound(k = stringToKey("x"))) + bind(k, aToggleCrossfade); + if (notBound(k = stringToKey("X"))) + bind(k, aSetCrossfade); + if (notBound(k = stringToKey("u"))) + bind(k, aUpdateDatabase); + if (notBound(k = stringToKey("ctrl_v"))) + bind(k, aSortPlaylist); + if (notBound(k = stringToKey("ctrl_r"))) + bind(k, aReversePlaylist); + if (notBound(k = stringToKey("ctrl_f"))) + bind(k, aApplyFilter); + if (notBound(k = stringToKey("/"))) + { + bind(k, aFind); + bind(k, aFindItemForward); + } + if (notBound(k = stringToKey("/"))) + { + bind(k, aFind); + bind(k, aFindItemBackward); + } + if (notBound(k = stringToKey("."))) + bind(k, aNextFoundItem); + if (notBound(k = stringToKey(","))) + bind(k, aPreviousFoundItem); + if (notBound(k = stringToKey("w"))) + bind(k, aToggleFindMode); + if (notBound(k = stringToKey("e"))) + { + bind(k, aEditSong); + bind(k, aEditLibraryTag); + bind(k, aEditLibraryAlbum); + bind(k, aEditDirectoryName); + bind(k, aEditPlaylistName); + bind(k, aEditLyrics); + } + if (notBound(k = stringToKey("i"))) + bind(k, aShowSongInfo); + if (notBound(k = stringToKey("I"))) + bind(k, aShowArtistInfo); + if (notBound(k = stringToKey("g"))) + bind(k, aJumpToPositionInSong); + if (notBound(k = stringToKey("l"))) + bind(k, aShowLyrics); + if (notBound(k = stringToKey("v"))) + bind(k, aReverseSelection); + if (notBound(k = stringToKey("B"))) + bind(k, aSelectAlbum); + if (notBound(k = stringToKey("a"))) + bind(k, aAddSelectedItems); + if (notBound(k = stringToKey("c"))) + { + bind(k, aClearPlaylist); + bind(k, aClearMainPlaylist); + } + if (notBound(k = stringToKey("C"))) + { + bind(k, aCropPlaylist); + bind(k, aCropMainPlaylist); + } + if (notBound(k = stringToKey("m"))) + { + bind(k, aMoveSortOrderUp); + bind(k, aMoveSelectedItemsUp); + } + if (notBound(k = stringToKey("n"))) + { + bind(k, aMoveSortOrderDown); + bind(k, aMoveSelectedItemsDown); + } + if (notBound(k = stringToKey("M"))) + bind(k, aMoveSelectedItemsTo); + if (notBound(k = stringToKey("A"))) + bind(k, aAdd); + if (notBound(k = stringToKey("S"))) + bind(k, aSavePlaylist); + if (notBound(k = stringToKey("o"))) + bind(k, aJumpToPlayingSong); + if (notBound(k = stringToKey("G"))) + { + bind(k, aJumpToBrowser); + bind(k, aJumpToPlaylistEditor); + } + if (notBound(k = stringToKey("~"))) + bind(k, aJumpToMediaLibrary); + if (notBound(k = stringToKey("E"))) + bind(k, aJumpToTagEditor); + if (notBound(k = stringToKey("U"))) + bind(k, aToggleAutoCenter); + if (notBound(k = stringToKey("p"))) + bind(k, aToggleDisplayMode); + if (notBound(k = stringToKey("\\"))) + bind(k, aToggleInterface); + if (notBound(k = stringToKey("!"))) + bind(k, aToggleSeparatorsBetweenAlbums); + if (notBound(k = stringToKey("L"))) + bind(k, aToggleLyricsFetcher); + if (notBound(k = stringToKey("F"))) + bind(k, aToggleFetchingLyricsInBackground); + if (notBound(k = stringToKey("ctrl_l"))) + bind(k, aToggleScreenLock); + if (notBound(k = stringToKey("`"))) + { + bind(k, aToggleBrowserSortMode); + bind(k, aToggleLibraryTagType); + bind(k, aRefetchLyrics); + bind(k, aRefetchArtistInfo); + bind(k, aAddRandomItems); + } + if (notBound(k = stringToKey("ctrl_p"))) + bind(k, aSetSelectedItemsPriority); + if (notBound(k = stringToKey("q"))) + bind(k, aQuit); + + if (notBound(k = stringToKey("k"))) + bind(k, aScrollUp); + if (notBound(k = stringToKey("j"))) + bind(k, aScrollDown); + if (notBound(k = stringToKey("d"))) + bind(k, aDelete); + if (notBound(k = stringToKey("+"))) + bind(k, aVolumeUp); + if (notBound(k = stringToKey("-"))) + bind(k, aVolumeDown); + + if (notBound(k = stringToKey("f1"))) + bind(k, aShowHelp); + if (notBound(k = stringToKey("f2"))) + bind(k, aShowPlaylist); + if (notBound(k = stringToKey("f3"))) + bind(k, aShowBrowser); + if (notBound(k = stringToKey("f4"))) + bind(k, aShowSearchEngine); + if (notBound(k = stringToKey("f5"))) + bind(k, aShowMediaLibrary); + if (notBound(k = stringToKey("f6"))) + bind(k, aShowPlaylistEditor); + if (notBound(k = stringToKey("f7"))) + bind(k, aShowTagEditor); + if (notBound(k = stringToKey("f8"))) + bind(k, aShowOutputs); + if (notBound(k = stringToKey("f9"))) + bind(k, aShowVisualizer); + if (notBound(k = stringToKey("f10"))) + bind(k, aShowClock); + if (notBound(k = stringToKey("Q"))) + bind(k, aQuit); +} |