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 "utf8.hh"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local data types
|
* Local data types
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
struct KeyBinding_t {
|
||||||
const char *name;
|
std::string name;
|
||||||
KeysCommand_t cmd;
|
KeysCommand_t cmd;
|
||||||
int modifier, key;
|
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 {
|
typedef struct {
|
||||||
const char *name;
|
std::string_view name;
|
||||||
const int value;
|
const int value;
|
||||||
} Mapping_t;
|
} Mapping_t;
|
||||||
|
|
||||||
@ -143,7 +165,7 @@ static const KeyBinding_t default_keys[] = {
|
|||||||
{ "zoom-reset" , KEYS_ZOOM_RESET , FL_CTRL , '0' },
|
{ "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()
|
void Keys::init()
|
||||||
{
|
{
|
||||||
KeyBinding_t *node;
|
std::unique_ptr< KeyBinding_t > node;
|
||||||
|
|
||||||
// Fill our key bindings list
|
// Fill our key bindings list
|
||||||
bindings = dList_new(32);
|
|
||||||
for (uint_t i = 0; i < sizeof(default_keys) / sizeof(default_keys[0]); i++) {
|
for (uint_t i = 0; i < sizeof(default_keys) / sizeof(default_keys[0]); i++) {
|
||||||
if (default_keys[i].key) {
|
if (default_keys[i].key) {
|
||||||
node = dNew(KeyBinding_t, 1);
|
node = std::make_unique< KeyBinding_t >();
|
||||||
node->name = dStrdup(default_keys[i].name);
|
node->name = default_keys[i].name;
|
||||||
node->cmd = default_keys[i].cmd;
|
node->cmd = default_keys[i].cmd;
|
||||||
node->modifier = default_keys[i].modifier;
|
node->modifier = default_keys[i].modifier;
|
||||||
node->key = default_keys[i].key;
|
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()
|
void Keys::free()
|
||||||
{
|
{
|
||||||
KeyBinding_t *node;
|
bindings.clear();
|
||||||
|
|
||||||
while ((node = (KeyBinding_t*)dList_nth_data(bindings, 0))) {
|
|
||||||
dFree((char*)node->name);
|
|
||||||
dList_remove_fast(bindings, node);
|
|
||||||
dFree(node);
|
|
||||||
}
|
|
||||||
dList_free(bindings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare function by {key,modifier} pairs.
|
* 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);
|
_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",
|
_MSG("getKeyCmd: evkey=0x%x evtext=\'%s\' key=0x%x, mod=0x%x\n",
|
||||||
Fl::event_key(), Fl::event_text(), keyNode.key, keyNode.modifier);
|
Fl::event_key(), Fl::event_text(), keyNode.key, keyNode.modifier);
|
||||||
void *data = dList_find_sorted(bindings, &keyNode, nodeByKeyCmp);
|
auto data= std::find_if( begin( bindings ), end( bindings ),
|
||||||
if (data)
|
[&]( const auto &node ){ return *node == keyNode; } );
|
||||||
ret = ((KeyBinding_t*)data)->cmd;
|
if ( data != end( bindings ) )
|
||||||
|
ret = data->get()->cmd;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,15 +254,14 @@ KeysCommand_t Keys::getKeyCmd()
|
|||||||
*/
|
*/
|
||||||
void Keys::delKeyCmd(int key, int mod)
|
void Keys::delKeyCmd(int key, int mod)
|
||||||
{
|
{
|
||||||
KeyBinding_t keyNode, *node;
|
KeyBinding_t keyNode;
|
||||||
keyNode.key = key;
|
keyNode.key = key;
|
||||||
keyNode.modifier = mod;
|
keyNode.modifier = mod;
|
||||||
|
|
||||||
node = (KeyBinding_t*) dList_find_sorted(bindings, &keyNode, nodeByKeyCmp);
|
auto data= std::find_if( begin( bindings ), end( bindings ),
|
||||||
if (node) {
|
[&]( const auto &node ){ return *node == keyNode; } );
|
||||||
dList_remove(bindings, node);
|
if (data != end( bindings )) {
|
||||||
dFree((char*)node->name);
|
bindings.erase( data );
|
||||||
dFree(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +274,7 @@ int Keys::getKeyCode(char *keyName)
|
|||||||
{
|
{
|
||||||
uint_t i;
|
uint_t i;
|
||||||
for (i = 0; i < sizeof(keyNames) / sizeof(keyNames[0]); 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;
|
return keyNames[i].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,7 +291,7 @@ KeysCommand_t Keys::getCmdCode(const char *commandName)
|
|||||||
uint_t i;
|
uint_t i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(default_keys) / sizeof(KeyBinding_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 default_keys[i].cmd;
|
||||||
}
|
}
|
||||||
return KEYS_INVALID;
|
return KEYS_INVALID;
|
||||||
@ -283,7 +305,7 @@ int Keys::getModifier(char *modifierName)
|
|||||||
{
|
{
|
||||||
uint_t i;
|
uint_t i;
|
||||||
for (i = 0; i < sizeof(modifierNames) / sizeof(modifierNames[0]); 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;
|
return modifierNames[i].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,10 +319,10 @@ int Keys::getModifier(char *modifierName)
|
|||||||
*/
|
*/
|
||||||
int Keys::getShortcut(KeysCommand_t cmd)
|
int Keys::getShortcut(KeysCommand_t cmd)
|
||||||
{
|
{
|
||||||
int len = dList_length(bindings);
|
int len = bindings.size();
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
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)
|
if (cmd == node->cmd)
|
||||||
return node->modifier + node->key;
|
return node->modifier + node->key;
|
||||||
}
|
}
|
||||||
@ -362,12 +384,13 @@ void Keys::parseKey(char *key, char *commandName)
|
|||||||
if (keycode) {
|
if (keycode) {
|
||||||
delKeyCmd(keycode, keymod);
|
delKeyCmd(keycode, keymod);
|
||||||
if (symcode != KEYS_NOP) {
|
if (symcode != KEYS_NOP) {
|
||||||
KeyBinding_t *node = dNew(KeyBinding_t, 1);
|
auto node = std::make_unique< KeyBinding_t >();
|
||||||
node->name = dStrdup(commandName);
|
node->name = commandName;
|
||||||
node->cmd = symcode;
|
node->cmd = symcode;
|
||||||
node->modifier = keymod;
|
node->modifier = keymod;
|
||||||
node->key = keycode;
|
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);
|
_MSG("parseKey: Adding key=%d, mod=%d\n", node->key, node->modifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user