Improvement for keybinding memory management.
I'm not respecting the sorted list anymore, but it's still good.
This commit is contained in:
99
src/keys.cc
99
src/keys.cc
@ -21,17 +21,39 @@
|
||||
#include "utf8.hh"
|
||||
#include "msg.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
/*
|
||||
* Local data types
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
struct KeyBinding_t {
|
||||
std::string name;
|
||||
KeysCommand_t cmd;
|
||||
int modifier, key;
|
||||
} KeyBinding_t;
|
||||
|
||||
auto
|
||||
value_lens() const
|
||||
{
|
||||
return std::tie( key, modifier );
|
||||
}
|
||||
|
||||
friend auto
|
||||
value_lens( const KeyBinding_t &key )
|
||||
{
|
||||
return key.value_lens();
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator < ( const KeyBinding_t &lhs, const KeyBinding_t &rhs );
|
||||
|
||||
friend bool
|
||||
operator == ( const KeyBinding_t &lhs, const KeyBinding_t &rhs );
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
std::string_view name;
|
||||
const int value;
|
||||
} Mapping_t;
|
||||
|
||||
@ -143,7 +165,7 @@ static const KeyBinding_t default_keys[] = {
|
||||
{ "zoom-reset" , KEYS_ZOOM_RESET , FL_CTRL , '0' },
|
||||
};
|
||||
|
||||
static Dlist *bindings;
|
||||
static std::vector< std::unique_ptr< KeyBinding_t > > bindings;
|
||||
|
||||
|
||||
|
||||
@ -152,20 +174,21 @@ static Dlist *bindings;
|
||||
*/
|
||||
void Keys::init()
|
||||
{
|
||||
KeyBinding_t *node;
|
||||
std::unique_ptr< KeyBinding_t > node;
|
||||
|
||||
// Fill our key bindings list
|
||||
bindings = dList_new(32);
|
||||
for (uint_t i = 0; i < sizeof(default_keys) / sizeof(default_keys[0]); i++) {
|
||||
if (default_keys[i].key) {
|
||||
node = dNew(KeyBinding_t, 1);
|
||||
node->name = dStrdup(default_keys[i].name);
|
||||
node = std::make_unique< KeyBinding_t >();
|
||||
node->name = default_keys[i].name;
|
||||
node->cmd = default_keys[i].cmd;
|
||||
node->modifier = default_keys[i].modifier;
|
||||
node->key = default_keys[i].key;
|
||||
dList_insert_sorted(bindings, node, nodeByKeyCmp);
|
||||
bindings.push_back( std::move( node ) );
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( begin( bindings ), end( bindings ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -173,24 +196,23 @@ void Keys::init()
|
||||
*/
|
||||
void Keys::free()
|
||||
{
|
||||
KeyBinding_t *node;
|
||||
|
||||
while ((node = (KeyBinding_t*)dList_nth_data(bindings, 0))) {
|
||||
dFree((char*)node->name);
|
||||
dList_remove_fast(bindings, node);
|
||||
dFree(node);
|
||||
}
|
||||
dList_free(bindings);
|
||||
bindings.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare function by {key,modifier} pairs.
|
||||
*/
|
||||
int Keys::nodeByKeyCmp(const void *node, const void *key)
|
||||
bool
|
||||
operator < (const KeyBinding_t &n, const KeyBinding_t &k)
|
||||
{
|
||||
KeyBinding_t *n = (KeyBinding_t*)node, *k = (KeyBinding_t*)key;
|
||||
_MSG("Keys::nodeByKeyCmp modifier=%d\n", k->modifier);
|
||||
return (n->key != k->key) ? (n->key - k->key) : (n->modifier - k->modifier);
|
||||
return value_lens( n ) < value_lens( k );
|
||||
}
|
||||
|
||||
bool
|
||||
operator == ( const KeyBinding_t &lhs, const KeyBinding_t &rhs )
|
||||
{
|
||||
return value_lens( lhs ) == value_lens( rhs );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,9 +242,10 @@ KeysCommand_t Keys::getKeyCmd()
|
||||
}
|
||||
_MSG("getKeyCmd: evkey=0x%x evtext=\'%s\' key=0x%x, mod=0x%x\n",
|
||||
Fl::event_key(), Fl::event_text(), keyNode.key, keyNode.modifier);
|
||||
void *data = dList_find_sorted(bindings, &keyNode, nodeByKeyCmp);
|
||||
if (data)
|
||||
ret = ((KeyBinding_t*)data)->cmd;
|
||||
auto data= std::find_if( begin( bindings ), end( bindings ),
|
||||
[&]( const auto &node ){ return *node == keyNode; } );
|
||||
if ( data != end( bindings ) )
|
||||
ret = data->get()->cmd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -231,15 +254,14 @@ KeysCommand_t Keys::getKeyCmd()
|
||||
*/
|
||||
void Keys::delKeyCmd(int key, int mod)
|
||||
{
|
||||
KeyBinding_t keyNode, *node;
|
||||
KeyBinding_t keyNode;
|
||||
keyNode.key = key;
|
||||
keyNode.modifier = mod;
|
||||
|
||||
node = (KeyBinding_t*) dList_find_sorted(bindings, &keyNode, nodeByKeyCmp);
|
||||
if (node) {
|
||||
dList_remove(bindings, node);
|
||||
dFree((char*)node->name);
|
||||
dFree(node);
|
||||
auto data= std::find_if( begin( bindings ), end( bindings ),
|
||||
[&]( const auto &node ){ return *node == keyNode; } );
|
||||
if (data != end( bindings )) {
|
||||
bindings.erase( data );
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +274,7 @@ int Keys::getKeyCode(char *keyName)
|
||||
{
|
||||
uint_t i;
|
||||
for (i = 0; i < sizeof(keyNames) / sizeof(keyNames[0]); i++) {
|
||||
if (!dStrAsciiCasecmp(keyNames[i].name, keyName)) {
|
||||
if (!dStrAsciiCasecmp(keyNames[i].name.data(), keyName)) {
|
||||
return keyNames[i].value;
|
||||
}
|
||||
}
|
||||
@ -269,7 +291,7 @@ KeysCommand_t Keys::getCmdCode(const char *commandName)
|
||||
uint_t i;
|
||||
|
||||
for (i = 0; i < sizeof(default_keys) / sizeof(KeyBinding_t); i++) {
|
||||
if (!dStrAsciiCasecmp(default_keys[i].name, commandName))
|
||||
if (!dStrAsciiCasecmp(default_keys[i].name.c_str(), commandName))
|
||||
return default_keys[i].cmd;
|
||||
}
|
||||
return KEYS_INVALID;
|
||||
@ -283,7 +305,7 @@ int Keys::getModifier(char *modifierName)
|
||||
{
|
||||
uint_t i;
|
||||
for (i = 0; i < sizeof(modifierNames) / sizeof(modifierNames[0]); i++) {
|
||||
if (!dStrAsciiCasecmp(modifierNames[i].name, modifierName)) {
|
||||
if (!dStrAsciiCasecmp(modifierNames[i].name.data(), modifierName)) {
|
||||
return modifierNames[i].value;
|
||||
}
|
||||
}
|
||||
@ -297,10 +319,10 @@ int Keys::getModifier(char *modifierName)
|
||||
*/
|
||||
int Keys::getShortcut(KeysCommand_t cmd)
|
||||
{
|
||||
int len = dList_length(bindings);
|
||||
int len = bindings.size();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
KeyBinding_t *node = (KeyBinding_t*)dList_nth_data(bindings, i);
|
||||
const KeyBinding_t *const node = bindings.at( i ).get();
|
||||
if (cmd == node->cmd)
|
||||
return node->modifier + node->key;
|
||||
}
|
||||
@ -362,12 +384,13 @@ void Keys::parseKey(char *key, char *commandName)
|
||||
if (keycode) {
|
||||
delKeyCmd(keycode, keymod);
|
||||
if (symcode != KEYS_NOP) {
|
||||
KeyBinding_t *node = dNew(KeyBinding_t, 1);
|
||||
node->name = dStrdup(commandName);
|
||||
auto node = std::make_unique< KeyBinding_t >();
|
||||
node->name = commandName;
|
||||
node->cmd = symcode;
|
||||
node->modifier = keymod;
|
||||
node->key = keycode;
|
||||
dList_insert_sorted(bindings, node, nodeByKeyCmp);
|
||||
bindings.push_back( std::move( node ) );
|
||||
std::sort( begin( bindings ), end( bindings ) );
|
||||
_MSG("parseKey: Adding key=%d, mod=%d\n", node->key, node->modifier);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user