bindinds: add support for alt/ctrl/shift modifiers and escape key
This commit is contained in:
1
NEWS
1
NEWS
@@ -21,6 +21,7 @@ ncmpcpp-0.7 (????-??-??)
|
|||||||
* Shuffle function now shuffles only selected range if selection in playlist is active.
|
* Shuffle function now shuffles only selected range if selection in playlist is active.
|
||||||
* NCurses terminal sequence escaping is no longer used as it's not accurate enough.
|
* NCurses terminal sequence escaping is no longer used as it's not accurate enough.
|
||||||
* Selecting items no longer depends on space mode and is bound by default to Insert key.
|
* Selecting items no longer depends on space mode and is bound by default to Insert key.
|
||||||
|
* Support for Alt, Ctrl and Shift modifiers as well as Escape key was added.
|
||||||
|
|
||||||
ncmpcpp-0.6.4 (2015-05-02)
|
ncmpcpp-0.6.4 (2015-05-02)
|
||||||
|
|
||||||
|
|||||||
@@ -51,9 +51,11 @@
|
|||||||
## picked by ncmpcpp upon next call to readKey function.
|
## picked by ncmpcpp upon next call to readKey function.
|
||||||
## Accepted values: mouse, up, down, page_up, page_down,
|
## Accepted values: mouse, up, down, page_up, page_down,
|
||||||
## home, end, space, enter, insert, delete, left, right,
|
## home, end, space, enter, insert, delete, left, right,
|
||||||
## tab, shift_tab, ctrl_a, ctrl_b, ..., ctrl_z, ctrl_[,
|
## tab, ctrl_a, ctrl_b, ..., ctrl_z, ctrl_[, ctrl_\\,
|
||||||
## ctrl_\\, ctrl_], ctrl_^, ctrl__, f1, f2, ..., f12,
|
## ctrl_], ctrl_^, ctrl__, f1, f2, ..., f12, backspace.
|
||||||
## backspace.
|
## In addition, most of these names can be prefixed with
|
||||||
|
## alt_/ctrl_/shift_ to be recognized with the appropriate
|
||||||
|
## modifier key(s).
|
||||||
##
|
##
|
||||||
## - push_characters "string" - pushes given string into
|
## - push_characters "string" - pushes given string into
|
||||||
## input queue.
|
## input queue.
|
||||||
|
|||||||
@@ -2626,7 +2626,7 @@ void seek()
|
|||||||
? (Timer-t).total_seconds()/2+Config.seek_time
|
? (Timer-t).total_seconds()/2+Config.seek_time
|
||||||
: Config.seek_time;
|
: Config.seek_time;
|
||||||
|
|
||||||
Key input = Key::read(*wFooter);
|
NC::Key::Type input = readKey(*wFooter);
|
||||||
auto k = Bindings.get(input);
|
auto k = Bindings.get(input);
|
||||||
if (k.first == k.second || !k.first->isSingle()) // no single action?
|
if (k.first == k.second || !k.first->isSingle()) // no single action?
|
||||||
break;
|
break;
|
||||||
|
|||||||
221
src/bindings.cpp
221
src/bindings.cpp
@@ -28,77 +28,83 @@
|
|||||||
|
|
||||||
BindingsConfiguration Bindings;
|
BindingsConfiguration Bindings;
|
||||||
|
|
||||||
Key Key::noOp = Key(ERR, NCurses);
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Key stringToSpecialKey(const std::string &s)
|
NC::Key::Type stringToKey(const std::string &s);
|
||||||
|
|
||||||
|
NC::Key::Type stringToSpecialKey(const std::string &s)
|
||||||
{
|
{
|
||||||
Key result = Key::noOp;
|
NC::Key::Type result = NC::Key::None;
|
||||||
if (!s.compare("mouse"))
|
if (!s.compare(0, 5, "ctrl_") && s.length() == 6)
|
||||||
result = Key(NC::Key::Mouse, Key::NCurses);
|
|
||||||
else if (!s.compare("up"))
|
|
||||||
result = Key(NC::Key::Up, Key::NCurses);
|
|
||||||
else if (!s.compare("down"))
|
|
||||||
result = Key(NC::Key::Down, Key::NCurses);
|
|
||||||
else if (!s.compare("page_up"))
|
|
||||||
result = Key(NC::Key::PageUp, Key::NCurses);
|
|
||||||
else if (!s.compare("page_down"))
|
|
||||||
result = Key(NC::Key::PageDown, Key::NCurses);
|
|
||||||
else if (!s.compare("home"))
|
|
||||||
result = Key(NC::Key::Home, Key::NCurses);
|
|
||||||
else if (!s.compare("end"))
|
|
||||||
result = Key(NC::Key::End, Key::NCurses);
|
|
||||||
else if (!s.compare("space"))
|
|
||||||
result = Key(NC::Key::Space, Key::Standard);
|
|
||||||
else if (!s.compare("enter"))
|
|
||||||
result = Key(NC::Key::Enter, Key::Standard);
|
|
||||||
else if (!s.compare("insert"))
|
|
||||||
result = Key(NC::Key::Insert, Key::NCurses);
|
|
||||||
else if (!s.compare("delete"))
|
|
||||||
result = Key(NC::Key::Delete, Key::NCurses);
|
|
||||||
else if (!s.compare("left"))
|
|
||||||
result = Key(NC::Key::Left, Key::NCurses);
|
|
||||||
else if (!s.compare("right"))
|
|
||||||
result = Key(NC::Key::Right, Key::NCurses);
|
|
||||||
else if (!s.compare("tab"))
|
|
||||||
result = Key(NC::Key::Tab, Key::Standard);
|
|
||||||
else if (!s.compare("shift_tab"))
|
|
||||||
result = Key(NC::Key::Shift | NC::Key::Tab, Key::NCurses);
|
|
||||||
else if (!s.compare(0, 5, "ctrl_") && s.length() > 5)
|
|
||||||
{
|
{
|
||||||
if (s[5] >= 'a' && s[5] <= 'z')
|
if (s[5] >= 'a' && s[5] <= 'z')
|
||||||
result = Key(NC::Key::Ctrl_A + (s[5] - 'a'), Key::Standard);
|
result = NC::Key::Ctrl_A + (s[5] - 'a');
|
||||||
else if (s[5] == '[')
|
else if (s[5] == '[')
|
||||||
result = Key(NC::Key::Ctrl_LeftBracket, Key::Standard);
|
result = NC::Key::Ctrl_LeftBracket;
|
||||||
else if (s[5] == '\\')
|
else if (s[5] == '\\')
|
||||||
result = Key(NC::Key::Ctrl_Backslash, Key::Standard);
|
result = NC::Key::Ctrl_Backslash;
|
||||||
else if (s[5] == ']')
|
else if (s[5] == ']')
|
||||||
result = Key(NC::Key::Ctrl_RightBracket, Key::Standard);
|
result = NC::Key::Ctrl_RightBracket;
|
||||||
else if (s[5] == '^')
|
else if (s[5] == '^')
|
||||||
result = Key(NC::Key::Ctrl_Caret, Key::Standard);
|
result = NC::Key::Ctrl_Caret;
|
||||||
else if (s[5] == '_')
|
else if (s[5] == '_')
|
||||||
result = Key(NC::Key::Ctrl_Underscore, Key::Standard);
|
result = NC::Key::Ctrl_Underscore;
|
||||||
}
|
}
|
||||||
else if (s.length() > 1 && s[0] == 'f')
|
else if (!s.compare(0, 4, "alt_"))
|
||||||
|
result = NC::Key::Alt | stringToKey(s.substr(4));
|
||||||
|
else if (!s.compare(0, 5, "ctrl_"))
|
||||||
|
result = NC::Key::Ctrl | stringToKey(s.substr(5));
|
||||||
|
else if (!s.compare(0, 6, "shift_"))
|
||||||
|
result = NC::Key::Shift | stringToKey(s.substr(6));
|
||||||
|
else if (!s.compare("escape"))
|
||||||
|
result = NC::Key::Escape;
|
||||||
|
else if (!s.compare("mouse"))
|
||||||
|
result = NC::Key::Mouse;
|
||||||
|
else if (!s.compare("up"))
|
||||||
|
result = NC::Key::Up;
|
||||||
|
else if (!s.compare("down"))
|
||||||
|
result = NC::Key::Down;
|
||||||
|
else if (!s.compare("page_up"))
|
||||||
|
result = NC::Key::PageUp;
|
||||||
|
else if (!s.compare("page_down"))
|
||||||
|
result = NC::Key::PageDown;
|
||||||
|
else if (!s.compare("home"))
|
||||||
|
result = NC::Key::Home;
|
||||||
|
else if (!s.compare("end"))
|
||||||
|
result = NC::Key::End;
|
||||||
|
else if (!s.compare("space"))
|
||||||
|
result = NC::Key::Space;
|
||||||
|
else if (!s.compare("enter"))
|
||||||
|
result = NC::Key::Enter;
|
||||||
|
else if (!s.compare("insert"))
|
||||||
|
result = NC::Key::Insert;
|
||||||
|
else if (!s.compare("delete"))
|
||||||
|
result = NC::Key::Delete;
|
||||||
|
else if (!s.compare("left"))
|
||||||
|
result = NC::Key::Left;
|
||||||
|
else if (!s.compare("right"))
|
||||||
|
result = NC::Key::Right;
|
||||||
|
else if (!s.compare("tab"))
|
||||||
|
result = NC::Key::Tab;
|
||||||
|
else if ((s.length() == 2 || s.length() == 3) && s[0] == 'f')
|
||||||
{
|
{
|
||||||
int n = atoi(s.c_str() + 1);
|
int n = atoi(s.c_str() + 1);
|
||||||
if (n >= 1 && n <= 12)
|
if (n >= 1 && n <= 12)
|
||||||
result = Key(NC::Key::F1 + n - 1, Key::NCurses);
|
result = NC::Key::F1 + n - 1;
|
||||||
}
|
}
|
||||||
else if (!s.compare("backspace"))
|
else if (!s.compare("backspace"))
|
||||||
result = Key(NC::Key::Backspace, Key::Standard);
|
result = NC::Key::Backspace;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key stringToKey(const std::string &s)
|
NC::Key::Type stringToKey(const std::string &s)
|
||||||
{
|
{
|
||||||
Key result = stringToSpecialKey(s);
|
NC::Key::Type result = stringToSpecialKey(s);
|
||||||
if (result == Key::noOp)
|
if (result == NC::Key::None)
|
||||||
{
|
{
|
||||||
std::wstring ws = ToWString(s);
|
std::wstring ws = ToWString(s);
|
||||||
if (ws.length() == 1)
|
if (ws.length() == 1)
|
||||||
result = Key(ws[0], Key::Standard);
|
result = ws[0];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -118,9 +124,9 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
{
|
{
|
||||||
// push single character into input queue
|
// push single character into input queue
|
||||||
std::string arg = getEnclosedString(line, '"', '"', 0);
|
std::string arg = getEnclosedString(line, '"', '"', 0);
|
||||||
Key k = stringToSpecialKey(arg);
|
NC::Key::Type k = stringToSpecialKey(arg);
|
||||||
auto queue = std::vector<int>{ k.getChar() };
|
auto queue = std::vector<NC::Key::Type>{ k };
|
||||||
if (k != Key::noOp)
|
if (k != NC::Key::None)
|
||||||
result = new Actions::PushCharacters(&Global::wFooter, std::move(queue));
|
result = new Actions::PushCharacters(&Global::wFooter, std::move(queue));
|
||||||
else
|
else
|
||||||
error() << "invalid character passed to push_character: '" << arg << "'\n";
|
error() << "invalid character passed to push_character: '" << arg << "'\n";
|
||||||
@@ -131,7 +137,7 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
std::string arg = getEnclosedString(line, '"', '"', 0);
|
std::string arg = getEnclosedString(line, '"', '"', 0);
|
||||||
if (!arg.empty())
|
if (!arg.empty())
|
||||||
{
|
{
|
||||||
std::vector<int> queue(arg.begin(), arg.end());
|
std::vector<NC::Key::Type> queue(arg.begin(), arg.end());
|
||||||
// if char is signed, erase 1s from char -> int conversion
|
// if char is signed, erase 1s from char -> int conversion
|
||||||
for (auto it = arg.begin(); it != arg.end(); ++it)
|
for (auto it = arg.begin(); it != arg.end(); ++it)
|
||||||
*it &= 0xff;
|
*it &= 0xff;
|
||||||
@@ -174,19 +180,26 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Key Key::read(NC::Window &w)
|
NC::Key::Type readKey(NC::Window &w)
|
||||||
{
|
{
|
||||||
Key result = noOp;
|
NC::Key::Type result = NC::Key::None;
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
int input;
|
NC::Key::Type input;
|
||||||
|
bool alt_pressed = false;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
input = w.readKey();
|
input = w.readKey();
|
||||||
if (input == ERR)
|
if (input == NC::Key::None)
|
||||||
break;
|
break;
|
||||||
if (input > 255)
|
if (input & NC::Key::Alt)
|
||||||
{
|
{
|
||||||
result = Key(input, NCurses);
|
// Complete the key and reapply the mask at the end.
|
||||||
|
alt_pressed = true;
|
||||||
|
input &= ~NC::Key::Alt;
|
||||||
|
}
|
||||||
|
if (input > 255) // NC special character
|
||||||
|
{
|
||||||
|
result = input;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -200,11 +213,93 @@ Key Key::read(NC::Window &w)
|
|||||||
break;
|
break;
|
||||||
else // character complete
|
else // character complete
|
||||||
{
|
{
|
||||||
result = Key(wc, Standard);
|
result = wc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (alt_pressed)
|
||||||
|
result |= NC::Key::Alt;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring keyToWString(const NC::Key::Type key)
|
||||||
|
{
|
||||||
|
std::wstring result;
|
||||||
|
|
||||||
|
if (key == NC::Key::Tab)
|
||||||
|
result += L"Tab";
|
||||||
|
else if (key == NC::Key::Enter)
|
||||||
|
result += L"Enter";
|
||||||
|
else if (key == NC::Key::Escape)
|
||||||
|
result += L"Escape";
|
||||||
|
else if (key >= NC::Key::Ctrl_A && key <= NC::Key::Ctrl_Z)
|
||||||
|
{
|
||||||
|
result += L"Ctrl-";
|
||||||
|
result += 'A' + (key - NC::Key::Ctrl_A);
|
||||||
|
}
|
||||||
|
else if (key == NC::Key::Ctrl_LeftBracket)
|
||||||
|
result += L"Ctrl-[";
|
||||||
|
else if (key == NC::Key::Ctrl_Backslash)
|
||||||
|
result += L"Ctrl-\\";
|
||||||
|
else if (key == NC::Key::Ctrl_RightBracket)
|
||||||
|
result += L"Ctrl-]";
|
||||||
|
else if (key == NC::Key::Ctrl_Caret)
|
||||||
|
result += L"Ctrl-^";
|
||||||
|
else if (key == NC::Key::Ctrl_Underscore)
|
||||||
|
result += L"Ctrl-_";
|
||||||
|
else if (key & NC::Key::Alt)
|
||||||
|
{
|
||||||
|
result += L"Alt-";
|
||||||
|
result += keyToWString(key & ~NC::Key::Alt);
|
||||||
|
}
|
||||||
|
else if (key & NC::Key::Ctrl)
|
||||||
|
{
|
||||||
|
result += L"Ctrl-";
|
||||||
|
result += keyToWString(key & ~NC::Key::Ctrl);
|
||||||
|
}
|
||||||
|
else if (key & NC::Key::Shift)
|
||||||
|
{
|
||||||
|
result += L"Shift-";
|
||||||
|
result += keyToWString(key & ~NC::Key::Shift);
|
||||||
|
}
|
||||||
|
else if (key == NC::Key::Space)
|
||||||
|
result += L"Space";
|
||||||
|
else if (key == NC::Key::Backspace)
|
||||||
|
result += L"Backspace";
|
||||||
|
else if (key == NC::Key::Insert)
|
||||||
|
result += L"Insert";
|
||||||
|
else if (key == NC::Key::Delete)
|
||||||
|
result += L"Delete";
|
||||||
|
else if (key == NC::Key::Home)
|
||||||
|
result += L"Home";
|
||||||
|
else if (key == NC::Key::End)
|
||||||
|
result += L"End";
|
||||||
|
else if (key == NC::Key::PageUp)
|
||||||
|
result += L"PageUp";
|
||||||
|
else if (key == NC::Key::PageDown)
|
||||||
|
result += L"PageDown";
|
||||||
|
else if (key == NC::Key::Up)
|
||||||
|
result += L"Up";
|
||||||
|
else if (key == NC::Key::Down)
|
||||||
|
result += L"Down";
|
||||||
|
else if (key == NC::Key::Left)
|
||||||
|
result += L"Left";
|
||||||
|
else if (key == NC::Key::Right)
|
||||||
|
result += L"Right";
|
||||||
|
else if (key >= NC::Key::F1 && key <= NC::Key::F9)
|
||||||
|
{
|
||||||
|
result += L"F";
|
||||||
|
result += '1' + (key - NC::Key::F1);
|
||||||
|
}
|
||||||
|
else if (key >= NC::Key::F10 && key <= NC::Key::F12)
|
||||||
|
{
|
||||||
|
result += L"F1";
|
||||||
|
result += '0' + (key - NC::Key::F10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result += std::wstring(1, key);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +320,7 @@ bool BindingsConfiguration::read(const std::string &file)
|
|||||||
Binding::ActionChain actions;
|
Binding::ActionChain actions;
|
||||||
|
|
||||||
// def_key specific variables
|
// def_key specific variables
|
||||||
Key key = Key::noOp;
|
NC::Key::Type key = NC::Key::None;
|
||||||
std::string strkey;
|
std::string strkey;
|
||||||
|
|
||||||
// def_command specific variables
|
// def_command specific variables
|
||||||
@@ -316,7 +411,7 @@ bool BindingsConfiguration::read(const std::string &file)
|
|||||||
in_progress = InProgress::Key;
|
in_progress = InProgress::Key;
|
||||||
strkey = getEnclosedString(line, '"', '"', 0);
|
strkey = getEnclosedString(line, '"', '"', 0);
|
||||||
key = stringToKey(strkey);
|
key = stringToKey(strkey);
|
||||||
if (key == Key::noOp)
|
if (key == NC::Key::None)
|
||||||
{
|
{
|
||||||
error() << "invalid key: '" << strkey << "'\n";
|
error() << "invalid key: '" << strkey << "'\n";
|
||||||
break;
|
break;
|
||||||
@@ -347,7 +442,7 @@ bool BindingsConfiguration::read(const std::string &file)
|
|||||||
|
|
||||||
void BindingsConfiguration::generateDefaults()
|
void BindingsConfiguration::generateDefaults()
|
||||||
{
|
{
|
||||||
Key k = Key::noOp;
|
NC::Key::Type k = NC::Key::None;
|
||||||
if (notBound(k = stringToKey("mouse")))
|
if (notBound(k = stringToKey("mouse")))
|
||||||
bind(k, Actions::Type::MouseEvent);
|
bind(k, Actions::Type::MouseEvent);
|
||||||
if (notBound(k = stringToKey("up")))
|
if (notBound(k = stringToKey("up")))
|
||||||
@@ -608,7 +703,7 @@ const Command *BindingsConfiguration::findCommand(const std::string &name)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BindingsConfiguration::BindingIteratorPair BindingsConfiguration::get(const Key &k)
|
BindingsConfiguration::BindingIteratorPair BindingsConfiguration::get(const NC::Key::Type &k)
|
||||||
{
|
{
|
||||||
std::pair<BindingIterator, BindingIterator> result;
|
std::pair<BindingIterator, BindingIterator> result;
|
||||||
auto it = m_bindings.find(k);
|
auto it = m_bindings.find(k);
|
||||||
|
|||||||
@@ -27,29 +27,8 @@
|
|||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
#include "macro_utilities.h"
|
#include "macro_utilities.h"
|
||||||
|
|
||||||
/// Key for binding actions to it. Supports non-ascii characters.
|
NC::Key::Type readKey(NC::Window &w);
|
||||||
struct Key
|
std::wstring keyToWString(const NC::Key::Type key);
|
||||||
{
|
|
||||||
enum Type { Standard, NCurses };
|
|
||||||
|
|
||||||
Key(wchar_t ch, Type ct) : m_impl(ch, ct) { }
|
|
||||||
|
|
||||||
wchar_t getChar() const { return std::get<0>(m_impl); }
|
|
||||||
Type getType() const { return std::get<1>(m_impl); }
|
|
||||||
|
|
||||||
bool operator< (const Key &rhs) const { return m_impl < rhs.m_impl; }
|
|
||||||
bool operator<=(const Key &rhs) const { return m_impl <= rhs.m_impl; }
|
|
||||||
bool operator> (const Key &rhs) const { return m_impl > rhs.m_impl; }
|
|
||||||
bool operator>=(const Key &rhs) const { return m_impl >= rhs.m_impl; }
|
|
||||||
bool operator==(const Key &rhs) const { return m_impl == rhs.m_impl; }
|
|
||||||
bool operator!=(const Key &rhs) const { return m_impl != rhs.m_impl; }
|
|
||||||
|
|
||||||
static Key read(NC::Window &w);
|
|
||||||
static Key noOp;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::tuple<wchar_t, Type> m_impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Represents either single action or chain of actions bound to a certain key
|
/// Represents either single action or chain of actions bound to a certain key
|
||||||
struct Binding
|
struct Binding
|
||||||
@@ -100,13 +79,8 @@ private:
|
|||||||
/// Keybindings configuration
|
/// Keybindings configuration
|
||||||
class BindingsConfiguration
|
class BindingsConfiguration
|
||||||
{
|
{
|
||||||
struct KeyHash {
|
|
||||||
size_t operator()(const Key &k) const {
|
|
||||||
return (k.getChar() << 1) | (k.getType() == Key::Standard);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef std::unordered_map<std::string, Command> CommandsSet;
|
typedef std::unordered_map<std::string, Command> CommandsSet;
|
||||||
typedef std::unordered_map<Key, std::vector<Binding>, KeyHash> BindingsMap;
|
typedef std::unordered_map<NC::Key::Type, std::vector<Binding>> BindingsMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef BindingsMap::value_type::second_type::iterator BindingIterator;
|
typedef BindingsMap::value_type::second_type::iterator BindingIterator;
|
||||||
@@ -117,18 +91,18 @@ public:
|
|||||||
void generateDefaults();
|
void generateDefaults();
|
||||||
|
|
||||||
const Command *findCommand(const std::string &name);
|
const Command *findCommand(const std::string &name);
|
||||||
BindingIteratorPair get(const Key &k);
|
BindingIteratorPair get(const NC::Key::Type &k);
|
||||||
|
|
||||||
BindingsMap::const_iterator begin() const { return m_bindings.begin(); }
|
BindingsMap::const_iterator begin() const { return m_bindings.begin(); }
|
||||||
BindingsMap::const_iterator end() const { return m_bindings.end(); }
|
BindingsMap::const_iterator end() const { return m_bindings.end(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool notBound(const Key &k) const {
|
bool notBound(const NC::Key::Type &k) const {
|
||||||
return k != Key::noOp && m_bindings.find(k) == m_bindings.end();
|
return k != NC::Key::None && m_bindings.find(k) == m_bindings.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ArgT>
|
template <typename ArgT>
|
||||||
void bind(Key k, ArgT &&t) {
|
void bind(NC::Key::Type k, ArgT &&t) {
|
||||||
m_bindings[k].push_back(std::forward<ArgT>(t));
|
m_bindings[k].push_back(std::forward<ArgT>(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
68
src/help.cpp
68
src/help.cpp
@@ -36,74 +36,36 @@ Help *myHelp;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string key_to_string(const Key &key)
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
if (key == Key(NC::Key::Up, Key::NCurses))
|
|
||||||
result += "Up";
|
|
||||||
else if (key == Key(NC::Key::Down, Key::NCurses))
|
|
||||||
result += "Down";
|
|
||||||
else if (key == Key(NC::Key::PageUp, Key::NCurses))
|
|
||||||
result += "Page Up";
|
|
||||||
else if (key == Key(NC::Key::PageDown, Key::NCurses))
|
|
||||||
result += "Page Down";
|
|
||||||
else if (key == Key(NC::Key::Home, Key::NCurses))
|
|
||||||
result += "Home";
|
|
||||||
else if (key == Key(NC::Key::End, Key::NCurses))
|
|
||||||
result += "End";
|
|
||||||
else if (key == Key(NC::Key::Space, Key::Standard))
|
|
||||||
result += "Space";
|
|
||||||
else if (key == Key(NC::Key::Enter, Key::Standard))
|
|
||||||
result += "Enter";
|
|
||||||
else if (key == Key(NC::Key::Insert, Key::NCurses))
|
|
||||||
result += "Insert";
|
|
||||||
else if (key == Key(NC::Key::Delete, Key::NCurses))
|
|
||||||
result += "Delete";
|
|
||||||
else if (key == Key(NC::Key::Right, Key::NCurses))
|
|
||||||
result += "Right";
|
|
||||||
else if (key == Key(NC::Key::Left, Key::NCurses))
|
|
||||||
result += "Left";
|
|
||||||
else if (key == Key(NC::Key::Tab, Key::Standard))
|
|
||||||
result += "Tab";
|
|
||||||
else if (key == Key(NC::Key::Shift | NC::Key::Tab, Key::NCurses))
|
|
||||||
result += "Shift-Tab";
|
|
||||||
else if (key >= Key(NC::Key::Ctrl_A, Key::Standard) && key <= Key(NC::Key::Ctrl_Z, Key::Standard))
|
|
||||||
{
|
|
||||||
result += "Ctrl-";
|
|
||||||
result += key.getChar()+64;
|
|
||||||
}
|
|
||||||
else if (key >= Key(NC::Key::F1, Key::NCurses) && key <= Key(NC::Key::F12, Key::NCurses))
|
|
||||||
{
|
|
||||||
result += "F";
|
|
||||||
result += boost::lexical_cast<std::string>(key.getChar()-NC::Key::F1+1);
|
|
||||||
}
|
|
||||||
else if (key == Key(NC::Key::Backspace, Key::Standard))
|
|
||||||
result += "Backspace";
|
|
||||||
else
|
|
||||||
result += ToString(std::wstring(1, key.getChar()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string display_keys(const Actions::Type at)
|
std::string display_keys(const Actions::Type at)
|
||||||
{
|
{
|
||||||
std::string result, skey;
|
std::wstring result, skey;
|
||||||
for (auto it = Bindings.begin(); it != Bindings.end(); ++it)
|
for (auto it = Bindings.begin(); it != Bindings.end(); ++it)
|
||||||
{
|
{
|
||||||
for (auto j = it->second.begin(); j != it->second.end(); ++j)
|
for (auto j = it->second.begin(); j != it->second.end(); ++j)
|
||||||
{
|
{
|
||||||
if (j->isSingle() && j->action()->type() == at)
|
if (j->isSingle() && j->action()->type() == at)
|
||||||
{
|
{
|
||||||
skey = key_to_string(it->first);
|
skey = keyToWString(it->first);
|
||||||
if (!skey.empty())
|
if (!skey.empty())
|
||||||
{
|
{
|
||||||
result += std::move(skey);
|
result += std::move(skey);
|
||||||
result += " ";
|
result += ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.resize(16, ' ');
|
size_t i = 0, len = 0;
|
||||||
return result;
|
const size_t max_len = 20;
|
||||||
|
for (; i < result.size(); ++i)
|
||||||
|
{
|
||||||
|
int width = std::max(1, wcwidth(result[i]));
|
||||||
|
if (len+width > max_len)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
len += width;
|
||||||
|
}
|
||||||
|
result.resize(i + max_len - len, ' ');
|
||||||
|
return ToString(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void section(NC::Scrollpad &w, const char *type_, const char *title_)
|
void section(NC::Scrollpad &w, const char *type_, const char *title_)
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ namespace Actions {
|
|||||||
|
|
||||||
struct PushCharacters: BaseAction
|
struct PushCharacters: BaseAction
|
||||||
{
|
{
|
||||||
PushCharacters(NC::Window **w, std::vector<int> &&queue)
|
PushCharacters(NC::Window **w, std::vector<NC::Key::Type> &&queue)
|
||||||
: BaseAction(Type::MacroUtility, ""), m_window(w), m_queue(queue) { }
|
: BaseAction(Type::MacroUtility, ""), m_window(w), m_queue(queue) { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void run() OVERRIDE;
|
virtual void run() OVERRIDE;
|
||||||
|
|
||||||
NC::Window **m_window;
|
NC::Window **m_window;
|
||||||
std::vector<int> m_queue;
|
std::vector<NC::Key::Type> m_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RequireRunnable: BaseAction
|
struct RequireRunnable: BaseAction
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// local variables
|
// local variables
|
||||||
bool key_pressed = false;
|
bool key_pressed = false;
|
||||||
Key input = Key::noOp;
|
auto input = NC::Key::None;
|
||||||
auto connect_attempt = boost::posix_time::from_time_t(0);
|
auto connect_attempt = boost::posix_time::from_time_t(0);
|
||||||
auto past = boost::posix_time::from_time_t(0);
|
auto past = boost::posix_time::from_time_t(0);
|
||||||
|
|
||||||
@@ -210,12 +210,14 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (key_pressed)
|
if (key_pressed)
|
||||||
myScreen->refreshWindow();
|
myScreen->refreshWindow();
|
||||||
input = Key::read(*wFooter);
|
input = readKey(*wFooter);
|
||||||
key_pressed = input != Key::noOp;
|
key_pressed = input != NC::Key::None;
|
||||||
|
|
||||||
if (!key_pressed)
|
if (!key_pressed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Statusbar::print(ToString(keyToWString(input)));
|
||||||
|
|
||||||
// The reason we want to update timer here is that if the timer is updated
|
// The reason we want to update timer here is that if the timer is updated
|
||||||
// in Status::trace, then Key::read usually blocks for 500ms and if key is
|
// in Status::trace, then Key::read usually blocks for 500ms and if key is
|
||||||
// pressed 400ms after Key::read was called, we end up with Timer that is
|
// pressed 400ms after Key::read was called, we end up with Timer that is
|
||||||
|
|||||||
233
src/window.cpp
233
src/window.cpp
@@ -723,9 +723,8 @@ bool Window::FDCallbacksListEmpty() const
|
|||||||
return m_fds.empty();
|
return m_fds.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::getInputChar()
|
Key::Type Window::getInputChar(int key)
|
||||||
{
|
{
|
||||||
int key = wgetch(m_window);
|
|
||||||
if (!m_escape_terminal_sequences || key != Key::Escape)
|
if (!m_escape_terminal_sequences || key != Key::Escape)
|
||||||
return key;
|
return key;
|
||||||
auto define_mouse_event = [this](int type) {
|
auto define_mouse_event = [this](int type) {
|
||||||
@@ -761,6 +760,36 @@ int Window::getInputChar()
|
|||||||
return Key::None;
|
return Key::None;
|
||||||
return Key::Mouse;
|
return Key::Mouse;
|
||||||
};
|
};
|
||||||
|
auto get_xterm_modifier_key = [](int ch) {
|
||||||
|
Key::Type modifier;
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '2':
|
||||||
|
modifier = Key::Shift;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
modifier = Key::Alt;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
modifier = Key::Alt | Key::Shift;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
modifier = Key::Ctrl;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
modifier = Key::Ctrl | Key::Shift;
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
modifier = Key::Alt | Key::Ctrl;
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
modifier = Key::Alt | Key::Ctrl | Key::Shift;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
modifier = Key::None;
|
||||||
|
}
|
||||||
|
return modifier;
|
||||||
|
};
|
||||||
auto parse_number = [this](int &result) {
|
auto parse_number = [this](int &result) {
|
||||||
int x;
|
int x;
|
||||||
while (true)
|
while (true)
|
||||||
@@ -777,31 +806,41 @@ int Window::getInputChar()
|
|||||||
{
|
{
|
||||||
case '\t': // tty
|
case '\t': // tty
|
||||||
return Key::Shift | Key::Tab;
|
return Key::Shift | Key::Tab;
|
||||||
case 'O': // F1 to F4 in xterm
|
case 'O': // ctrl+arrows in rxvt, F1 to F4 in xterm
|
||||||
key = wgetch(m_window);
|
key = wgetch(m_window);
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
case 'a':
|
||||||
|
return Key::Ctrl | Key::Up;
|
||||||
|
case 'b':
|
||||||
|
return Key::Ctrl | Key::Down;
|
||||||
|
case 'c':
|
||||||
|
return Key::Ctrl | Key::Right;
|
||||||
|
case 'd':
|
||||||
|
return Key::Ctrl | Key::Left;
|
||||||
case 'P':
|
case 'P':
|
||||||
key = Key::F1;
|
return Key::F1;
|
||||||
break;
|
|
||||||
case 'Q':
|
case 'Q':
|
||||||
key = Key::F2;
|
return Key::F2;
|
||||||
break;
|
|
||||||
case 'R':
|
case 'R':
|
||||||
key = Key::F3;
|
return Key::F3;
|
||||||
break;
|
|
||||||
case 'S':
|
case 'S':
|
||||||
key = Key::F4;
|
return Key::F4;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
key = Key::None;
|
return Key::None;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return key;
|
|
||||||
case '[':
|
case '[':
|
||||||
key = wgetch(m_window);
|
key = wgetch(m_window);
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
case 'a':
|
||||||
|
return Key::Shift | Key::Up;
|
||||||
|
case 'b':
|
||||||
|
return Key::Shift | Key::Down;
|
||||||
|
case 'c':
|
||||||
|
return Key::Shift | Key::Right;
|
||||||
|
case 'd':
|
||||||
|
return Key::Shift | Key::Left;
|
||||||
case 'A':
|
case 'A':
|
||||||
return Key::Up;
|
return Key::Up;
|
||||||
case 'B':
|
case 'B':
|
||||||
@@ -814,7 +853,7 @@ int Window::getInputChar()
|
|||||||
return Key::End;
|
return Key::End;
|
||||||
case 'H': // xterm
|
case 'H': // xterm
|
||||||
return Key::Home;
|
return Key::Home;
|
||||||
case 'M':
|
case 'M': // standard mouse event
|
||||||
{
|
{
|
||||||
key = wgetch(m_window);
|
key = wgetch(m_window);
|
||||||
int raw_x = wgetch(m_window);
|
int raw_x = wgetch(m_window);
|
||||||
@@ -831,34 +870,78 @@ int Window::getInputChar()
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 'A':
|
case 'A':
|
||||||
key = Key::F1;
|
return Key::F1;
|
||||||
break;
|
|
||||||
case 'B':
|
case 'B':
|
||||||
key = Key::F2;
|
return Key::F2;
|
||||||
break;
|
|
||||||
case 'C':
|
case 'C':
|
||||||
key = Key::F3;
|
return Key::F3;
|
||||||
break;
|
|
||||||
case 'D':
|
case 'D':
|
||||||
key = Key::F4;
|
return Key::F4;
|
||||||
break;
|
|
||||||
case 'E':
|
case 'E':
|
||||||
key = Key::F5;
|
return Key::F5;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
key = Key::None;
|
return Key::None;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return key;
|
|
||||||
case '1': case '2': case '3':
|
case '1': case '2': case '3':
|
||||||
case '4': case '5': case '6':
|
case '4': case '5': case '6':
|
||||||
case '7': case '8': case '9':
|
case '7': case '8': case '9':
|
||||||
{
|
{
|
||||||
key -= '0';
|
key -= '0';
|
||||||
int delim = parse_number(key);
|
int delim = parse_number(key);
|
||||||
|
if (key >= 2 && key <= 8)
|
||||||
|
{
|
||||||
|
Key::Type modifier;
|
||||||
|
switch (delim)
|
||||||
|
{
|
||||||
|
case '~':
|
||||||
|
modifier = Key::Null;
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
modifier = Key::Ctrl;
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
modifier = Key::Shift;
|
||||||
|
break;
|
||||||
|
case '@':
|
||||||
|
modifier = Key::Ctrl | Key::Shift;
|
||||||
|
break;
|
||||||
|
case ';': // xterm insert/delete/page up/page down
|
||||||
|
{
|
||||||
|
int local_key = wgetch(m_window);
|
||||||
|
modifier = get_xterm_modifier_key(local_key);
|
||||||
|
local_key = wgetch(m_window);
|
||||||
|
if (local_key != '~' || (key != 2 && key != 3 && key != 5 && key != 6))
|
||||||
|
return Key::None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return Key::None;
|
||||||
|
}
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
return modifier | Key::Insert;
|
||||||
|
case 3:
|
||||||
|
return modifier | Key::Delete;
|
||||||
|
case 4:
|
||||||
|
return modifier | Key::End;
|
||||||
|
case 5:
|
||||||
|
return modifier | Key::PageUp;
|
||||||
|
case 6:
|
||||||
|
return modifier | Key::PageDown;
|
||||||
|
case 7:
|
||||||
|
return modifier | Key::Home;
|
||||||
|
case 8:
|
||||||
|
return modifier | Key::End;
|
||||||
|
default:
|
||||||
|
std::cerr << "Unreachable code, aborting.\n";
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
switch (delim)
|
switch (delim)
|
||||||
{
|
{
|
||||||
case '~':
|
case '~':
|
||||||
|
{
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 1: // tty
|
case 1: // tty
|
||||||
@@ -879,8 +962,6 @@ int Window::getInputChar()
|
|||||||
return Key::F7;
|
return Key::F7;
|
||||||
case 19:
|
case 19:
|
||||||
return Key::F8;
|
return Key::F8;
|
||||||
case 2:
|
|
||||||
return Key::Insert;
|
|
||||||
case 20:
|
case 20:
|
||||||
return Key::F9;
|
return Key::F9;
|
||||||
case 21:
|
case 21:
|
||||||
@@ -889,33 +970,51 @@ int Window::getInputChar()
|
|||||||
return Key::F11;
|
return Key::F11;
|
||||||
case 24:
|
case 24:
|
||||||
return Key::F12;
|
return Key::F12;
|
||||||
case 3:
|
|
||||||
return Key::Delete;
|
|
||||||
case 4:
|
|
||||||
return Key::End;
|
|
||||||
case 5:
|
|
||||||
return Key::PageUp;
|
|
||||||
case 6:
|
|
||||||
return Key::PageDown;
|
|
||||||
case 7:
|
|
||||||
return Key::Home;
|
|
||||||
case 8:
|
|
||||||
return Key::End;
|
|
||||||
default:
|
default:
|
||||||
return Key::None;
|
return Key::None;
|
||||||
}
|
}
|
||||||
case ';': // urxvt mouse
|
}
|
||||||
m_mouse_event.x = 0;
|
case ';':
|
||||||
delim = parse_number(m_mouse_event.x);
|
switch (key)
|
||||||
if (delim != ';')
|
{
|
||||||
return Key::None;
|
case 1: // xterm
|
||||||
m_mouse_event.y = 0;
|
{
|
||||||
delim = parse_number(m_mouse_event.y);
|
key = wgetch(m_window);
|
||||||
if (delim != 'M')
|
Key::Type modifier = get_xterm_modifier_key(key);
|
||||||
return Key::None;
|
if (modifier == Key::None)
|
||||||
--m_mouse_event.x;
|
return Key::None;
|
||||||
--m_mouse_event.y;
|
key = wgetch(m_window);
|
||||||
return define_mouse_event(key);
|
switch (key)
|
||||||
|
{
|
||||||
|
case 'A':
|
||||||
|
return modifier | Key::Up;
|
||||||
|
case 'B':
|
||||||
|
return modifier | Key::Down;
|
||||||
|
case 'C':
|
||||||
|
return modifier | Key::Right;
|
||||||
|
case 'D':
|
||||||
|
return modifier | Key::Left;
|
||||||
|
case 'F':
|
||||||
|
return modifier | Key::End;
|
||||||
|
case 'H':
|
||||||
|
return modifier | Key::Home;
|
||||||
|
default:
|
||||||
|
return Key::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // urxvt mouse
|
||||||
|
m_mouse_event.x = 0;
|
||||||
|
delim = parse_number(m_mouse_event.x);
|
||||||
|
if (delim != ';')
|
||||||
|
return Key::None;
|
||||||
|
m_mouse_event.y = 0;
|
||||||
|
delim = parse_number(m_mouse_event.y);
|
||||||
|
if (delim != 'M')
|
||||||
|
return Key::None;
|
||||||
|
--m_mouse_event.x;
|
||||||
|
--m_mouse_event.y;
|
||||||
|
return define_mouse_event(key);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return Key::None;
|
return Key::None;
|
||||||
}
|
}
|
||||||
@@ -923,22 +1022,21 @@ int Window::getInputChar()
|
|||||||
default:
|
default:
|
||||||
return Key::None;
|
return Key::None;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case ERR:
|
case ERR:
|
||||||
return Key::Escape;
|
return Key::Escape;
|
||||||
default:
|
default: // alt + something
|
||||||
// this should always succeed as we just got it
|
{
|
||||||
assert(ungetch(key) == OK);
|
auto key_prim = getInputChar(key);
|
||||||
key = getInputChar();
|
if (key_prim != Key::None)
|
||||||
if (key != Key::None)
|
return Key::Alt | key_prim;
|
||||||
m_input_queue.push(key);
|
return Key::None;
|
||||||
return Key::Alt;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::readKey()
|
Key::Type Window::readKey()
|
||||||
{
|
{
|
||||||
int result;
|
Key::Type result;
|
||||||
// if there are characters in input queue,
|
// if there are characters in input queue,
|
||||||
// get them and return immediately.
|
// get them and return immediately.
|
||||||
if (!m_input_queue.empty())
|
if (!m_input_queue.empty())
|
||||||
@@ -963,7 +1061,10 @@ int Window::readKey()
|
|||||||
|
|
||||||
if (select(fd_max+1, &fdset, 0, 0, m_window_timeout < 0 ? 0 : &timeout) > 0)
|
if (select(fd_max+1, &fdset, 0, 0, m_window_timeout < 0 ? 0 : &timeout) > 0)
|
||||||
{
|
{
|
||||||
result = FD_ISSET(STDIN_FILENO, &fdset) ? getInputChar() : Key::None;
|
if (FD_ISSET(STDIN_FILENO, &fdset))
|
||||||
|
result = getInputChar(wgetch(m_window));
|
||||||
|
else
|
||||||
|
result = Key::None;
|
||||||
|
|
||||||
for (FDCallbacks::const_iterator it = m_fds.begin(); it != m_fds.end(); ++it)
|
for (FDCallbacks::const_iterator it = m_fds.begin(); it != m_fds.end(); ++it)
|
||||||
if (FD_ISSET(it->first, &fdset))
|
if (FD_ISSET(it->first, &fdset))
|
||||||
@@ -974,7 +1075,7 @@ int Window::readKey()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::pushChar(int ch)
|
void Window::pushChar(const Key::Type ch)
|
||||||
{
|
{
|
||||||
m_input_queue.push(ch);
|
m_input_queue.push(ch);
|
||||||
}
|
}
|
||||||
|
|||||||
145
src/window.h
145
src/window.h
@@ -49,82 +49,83 @@ namespace NC {
|
|||||||
|
|
||||||
namespace Key {
|
namespace Key {
|
||||||
|
|
||||||
typedef const int Type;
|
typedef uint32_t Type;
|
||||||
|
|
||||||
Type None = -1;
|
const Type None = -1;
|
||||||
|
|
||||||
// modifier masks
|
// modifier masks
|
||||||
Type Alt = 1 << 16;
|
const Type Special = 1 << 31;
|
||||||
Type Ctrl = 1 << 17;
|
const Type Alt = 1 << 30;
|
||||||
Type Shift = 1 << 18;
|
const Type Ctrl = 1 << 29;
|
||||||
|
const Type Shift = 1 << 28;
|
||||||
|
|
||||||
Type Ctrl_A = 1;
|
// useful names
|
||||||
Type Ctrl_B = 2;
|
const Type Null = 0;
|
||||||
Type Ctrl_C = 3;
|
const Type Space = 32;
|
||||||
Type Ctrl_D = 4;
|
const Type Backspace = 127;
|
||||||
Type Ctrl_E = 5;
|
|
||||||
Type Ctrl_F = 6;
|
|
||||||
Type Ctrl_G = 7;
|
|
||||||
Type Ctrl_H = 8;
|
|
||||||
Type Ctrl_I = 9;
|
|
||||||
Type Ctrl_J = 10;
|
|
||||||
Type Ctrl_K = 11;
|
|
||||||
Type Ctrl_L = 12;
|
|
||||||
Type Ctrl_M = 13;
|
|
||||||
Type Ctrl_N = 14;
|
|
||||||
Type Ctrl_O = 15;
|
|
||||||
Type Ctrl_P = 16;
|
|
||||||
Type Ctrl_Q = 17;
|
|
||||||
Type Ctrl_R = 18;
|
|
||||||
Type Ctrl_S = 19;
|
|
||||||
Type Ctrl_T = 20;
|
|
||||||
Type Ctrl_U = 21;
|
|
||||||
Type Ctrl_V = 22;
|
|
||||||
Type Ctrl_W = 23;
|
|
||||||
Type Ctrl_X = 24;
|
|
||||||
Type Ctrl_Y = 25;
|
|
||||||
Type Ctrl_Z = 26;
|
|
||||||
Type Ctrl_LeftBracket = 27;
|
|
||||||
Type Ctrl_Backslash = 28;
|
|
||||||
Type Ctrl_RightBracket = 29;
|
|
||||||
Type Ctrl_Caret = 30;
|
|
||||||
Type Ctrl_Underscore = 31;
|
|
||||||
|
|
||||||
Type Space = 32;
|
// ctrl-?
|
||||||
Type Backspace = 127;
|
const Type Ctrl_A = 1;
|
||||||
|
const Type Ctrl_B = 2;
|
||||||
|
const Type Ctrl_C = 3;
|
||||||
|
const Type Ctrl_D = 4;
|
||||||
|
const Type Ctrl_E = 5;
|
||||||
|
const Type Ctrl_F = 6;
|
||||||
|
const Type Ctrl_G = 7;
|
||||||
|
const Type Ctrl_H = 8;
|
||||||
|
const Type Ctrl_I = 9;
|
||||||
|
const Type Ctrl_J = 10;
|
||||||
|
const Type Ctrl_K = 11;
|
||||||
|
const Type Ctrl_L = 12;
|
||||||
|
const Type Ctrl_M = 13;
|
||||||
|
const Type Ctrl_N = 14;
|
||||||
|
const Type Ctrl_O = 15;
|
||||||
|
const Type Ctrl_P = 16;
|
||||||
|
const Type Ctrl_Q = 17;
|
||||||
|
const Type Ctrl_R = 18;
|
||||||
|
const Type Ctrl_S = 19;
|
||||||
|
const Type Ctrl_T = 20;
|
||||||
|
const Type Ctrl_U = 21;
|
||||||
|
const Type Ctrl_V = 22;
|
||||||
|
const Type Ctrl_W = 23;
|
||||||
|
const Type Ctrl_X = 24;
|
||||||
|
const Type Ctrl_Y = 25;
|
||||||
|
const Type Ctrl_Z = 26;
|
||||||
|
const Type Ctrl_LeftBracket = 27;
|
||||||
|
const Type Ctrl_Backslash = 28;
|
||||||
|
const Type Ctrl_RightBracket = 29;
|
||||||
|
const Type Ctrl_Caret = 30;
|
||||||
|
const Type Ctrl_Underscore = 31;
|
||||||
|
|
||||||
// useful duplicates
|
// useful duplicates
|
||||||
Type Tab = 9;
|
const Type Tab = 9;
|
||||||
Type Enter = 13;
|
const Type Enter = 13;
|
||||||
Type Escape = 27;
|
const Type Escape = 27;
|
||||||
|
|
||||||
// special values, beyond one byte
|
// special values, beyond one byte
|
||||||
Type Insert = 256;
|
const Type Insert = Special | 256;
|
||||||
Type Delete = 257;
|
const Type Delete = Special | 257;
|
||||||
Type Home = 258;
|
const Type Home = Special | 258;
|
||||||
Type End = 259;
|
const Type End = Special | 259;
|
||||||
Type PageUp = 260;
|
const Type PageUp = Special | 260;
|
||||||
Type PageDown = 261;
|
const Type PageDown = Special | 261;
|
||||||
|
const Type Up = Special | 262;
|
||||||
Type Up = 262;
|
const Type Down = Special | 263;
|
||||||
Type Down = 263;
|
const Type Left = Special | 264;
|
||||||
Type Left = 264;
|
const Type Right = Special | 265;
|
||||||
Type Right = 265;
|
const Type F1 = Special | 266;
|
||||||
|
const Type F2 = Special | 267;
|
||||||
Type F1 = 266;
|
const Type F3 = Special | 268;
|
||||||
Type F2 = 267;
|
const Type F4 = Special | 269;
|
||||||
Type F3 = 268;
|
const Type F5 = Special | 270;
|
||||||
Type F4 = 269;
|
const Type F6 = Special | 271;
|
||||||
Type F5 = 270;
|
const Type F7 = Special | 272;
|
||||||
Type F6 = 271;
|
const Type F8 = Special | 273;
|
||||||
Type F7 = 272;
|
const Type F9 = Special | 274;
|
||||||
Type F8 = 273;
|
const Type F10 = Special | 275;
|
||||||
Type F9 = 274;
|
const Type F11 = Special | 276;
|
||||||
Type F10 = 275;
|
const Type F12 = Special | 277;
|
||||||
Type F11 = 276;
|
const Type Mouse = Special | 278;
|
||||||
Type F12 = 277;
|
|
||||||
|
|
||||||
Type Mouse = 278;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,13 +405,13 @@ struct Window
|
|||||||
|
|
||||||
/// Reads key from standard input (or takes it from input queue)
|
/// Reads key from standard input (or takes it from input queue)
|
||||||
/// and writes it into read_key variable
|
/// and writes it into read_key variable
|
||||||
int readKey();
|
Key::Type readKey();
|
||||||
|
|
||||||
/// Push single character into input queue, so it can get consumed by ReadKey
|
/// Push single character into input queue, so it can get consumed by ReadKey
|
||||||
void pushChar(int ch);
|
void pushChar(const NC::Key::Type ch);
|
||||||
|
|
||||||
/// @return const reference to internal input queue
|
/// @return const reference to internal input queue
|
||||||
const std::queue<int> &inputQueue() { return m_input_queue; }
|
const std::queue<NC::Key::Type> &inputQueue() { return m_input_queue; }
|
||||||
|
|
||||||
/// Scrolls the window by amount of lines given in its parameter
|
/// Scrolls the window by amount of lines given in its parameter
|
||||||
/// @param where indicates how many lines it has to scroll
|
/// @param where indicates how many lines it has to scroll
|
||||||
@@ -479,7 +480,7 @@ protected:
|
|||||||
Border m_border;
|
Border m_border;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int getInputChar();
|
Key::Type getInputChar(int key);
|
||||||
|
|
||||||
/// Sets state of bold attribute (internal use only)
|
/// Sets state of bold attribute (internal use only)
|
||||||
/// @param bold_state state of bold attribute
|
/// @param bold_state state of bold attribute
|
||||||
@@ -515,7 +516,7 @@ private:
|
|||||||
/// input queue of a window. you can put characters there using
|
/// input queue of a window. you can put characters there using
|
||||||
/// PushChar and they will be immediately consumed and
|
/// PushChar and they will be immediately consumed and
|
||||||
/// returned by ReadKey
|
/// returned by ReadKey
|
||||||
std::queue<int> m_input_queue;
|
std::queue<Key::Type> m_input_queue;
|
||||||
|
|
||||||
/// containter used for additional file descriptors that have
|
/// containter used for additional file descriptors that have
|
||||||
/// to be polled in ReadKey() and correspondent callbacks that
|
/// to be polled in ReadKey() and correspondent callbacks that
|
||||||
|
|||||||
Reference in New Issue
Block a user