Improvement for keybinding memory management.

I'm not respecting the sorted list anymore, but it's still good.
This commit is contained in:
2025-03-04 01:03:18 -05:00
parent a3ae87e90b
commit 5f1fa36890

View File

@ -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);
}
}