4coder/custom/4coder_command_map.cpp

366 lines
12 KiB
C++

/*
* Mr. 4th Dimention - Allen Webster
*
* 19.08.2015
*
* Command management functions
*
*/
// TOP
internal Command_Map*
mapping__alloc_map(Mapping *mapping){
Command_Map *result = mapping->free_maps;
if (result != 0){
sll_stack_pop(mapping->free_maps);
}
else{
result = push_array(mapping->node_arena, Command_Map, 1);
}
return(result);
}
internal void
mapping__free_map(Mapping *mapping, Command_Map *map){
sll_stack_push(mapping->free_maps, map);
}
internal Command_Modified_Binding*
mapping__alloc_modified_binding(Mapping *mapping){
Command_Modified_Binding *result = mapping->free_bindings;
if (result != 0){
sll_stack_pop(mapping->free_bindings);
}
else{
result = push_array(mapping->node_arena, Command_Modified_Binding, 1);
}
return(result);
}
internal void
mapping__free_modified_binding(Mapping *mapping, Command_Modified_Binding *binding){
sll_stack_push(mapping->free_bindings, binding);
}
internal Command_Binding_List*
mapping__alloc_binding_list(Mapping *mapping){
Command_Binding_List *result = mapping->free_lists;
if (result != 0){
sll_stack_pop(mapping->free_lists);
}
else{
result = push_array(mapping->node_arena, Command_Binding_List, 1);
}
return(result);
}
internal void
mapping__free_binding_list(Mapping *mapping, Command_Binding_List *binding_list){
sll_stack_push(mapping->free_lists, binding_list);
}
internal Command_Binding_List*
map__get_list(Command_Map *map, Key_Code code){
Command_Binding_List *result = 0;
Table_Lookup lookup = table_lookup(&map->key_code_to_binding_list, code);
if (lookup.found_match){
u64 val = 0;
table_read(&map->key_code_to_binding_list, lookup, &val);
result = (Command_Binding_List*)IntAsPtr(val);
}
return(result);
}
internal Command_Binding_List*
map__get_or_make_list(Mapping *mapping, Command_Map *map, Key_Code code){
Command_Binding_List *result = map__get_list(map, code);
if (result == 0){
result = mapping__alloc_binding_list(mapping);
block_zero_struct(result);
sll_queue_push(map->list_first, map->list_last, result);
table_insert(&map->key_code_to_binding_list, code, (u64)PtrAsInt(result));
}
return(result);
}
////////////////////////////////
internal void
mapping_init(Thread_Context *tctx, Mapping *mapping){
block_zero_struct(mapping);
mapping->node_arena = reserve_arena(tctx);
heap_init(&mapping->heap, mapping->node_arena);
mapping->heap_wrapper = base_allocator_on_heap(&mapping->heap);
mapping->id_to_map = make_table_u64_u64(tctx->allocator, 100);
mapping->id_counter = 1;
}
internal void
mapping_release(Thread_Context *tctx, Mapping *mapping){
if (mapping->node_arena != 0){
release_arena(tctx, mapping->node_arena);
table_free(&mapping->id_to_map);
}
}
internal Command_Map*
mapping_begin_new_map(Mapping *mapping){
Command_Map *map = mapping__alloc_map(mapping);
block_zero_struct(map);
map->id = mapping->id_counter;
mapping->id_counter += 1;
map->key_code_to_binding_list = make_table_u64_u64(&mapping->heap_wrapper, 8);
table_insert(&mapping->id_to_map, map->id, (u64)PtrAsInt(map));
return(map);
}
internal Command_Map*
mapping_get_map(Mapping *mapping, Command_Map_ID id){
Command_Map *result = 0;
Table_Lookup lookup = table_lookup(&mapping->id_to_map, id);
if (lookup.found_match){
u64 val = 0;
table_read(&mapping->id_to_map, lookup, &val);
result = (Command_Map*)IntAsPtr(val);
}
return(result);
}
internal Command_Map_ID
mapping_validate_id(Mapping *mapping, Command_Map_ID id){
Table_Lookup lookup = table_lookup(&mapping->id_to_map, id);
if (!lookup.found_match){
id = 0;
}
return(id);
}
internal Command_Map*
mapping_get_or_make_map(Mapping *mapping, Command_Map_ID id){
Command_Map *result = mapping_get_map(mapping, id);
if (result == 0){
result = mapping__alloc_map(mapping);
block_zero_struct(result);
result->id = id;
result->key_code_to_binding_list = make_table_u64_u64(&mapping->heap_wrapper, 8);
table_insert(&mapping->id_to_map, result->id, (u64)PtrAsInt(result));
}
return(result);
}
internal void
mapping_release_map(Mapping *mapping, Command_Map *map){
table_erase(&mapping->id_to_map, map->id);
if (map->binding_last != 0){
map->binding_last->next = mapping->free_bindings;
mapping->free_bindings = map->binding_first;
}
if (map->list_last != 0){
map->list_last->next = mapping->free_lists;
mapping->free_lists = map->list_first;
}
table_free(&map->key_code_to_binding_list);
}
internal Command_Binding
map_get_binding_non_recursive(Command_Map *map, Input_Event *event){
Command_Binding result = {};
if (map != 0){
switch (event->kind){
case InputEventKind_TextInsert:
{
result = map->text_input_command;
}break;
case InputEventKind_KeyStroke:
{
Table_Lookup lookup = table_lookup(&map->key_code_to_binding_list, event->key.code);
if (lookup.found_match){
u64 val = 0;
table_read(&map->key_code_to_binding_list, lookup, &val);
Command_Binding_List *list = (Command_Binding_List*)IntAsPtr(val);
Key_Modifiers *event_mods = &event->key.modifiers;
for (SNode *node = list->first;
node != 0;
node = node->next){
Command_Modified_Binding *mod_binding = CastFromMember(Command_Modified_Binding, order_node, node);
Key_Modifiers *binding_mods = &mod_binding->modifiers;
b32 is_a_match = true;
for (i32 i = 0; i < ArrayCount(binding_mods->modifiers); i += 1){
if (binding_mods->modifiers[i] &&
!event_mods->modifiers[i]){
is_a_match = false;
break;
}
}
if (is_a_match){
result = mod_binding->binding;
break;
}
}
}
}break;
}
}
return(result);
}
internal Command_Binding
map_get_binding_recursive(Mapping *mapping, Command_Map *map, Input_Event *event){
Command_Binding result = {};
for (i32 safety_counter = 0;
map != 0 && safety_counter < 40;
safety_counter += 1){
result = map_get_binding_non_recursive(map, event);
if (result.custom != 0){
break;
}
map = mapping_get_map(mapping, map->parent);
}
return(result);
}
internal void
map_set_parent(Command_Map *map, Command_Map *parent){
if (map != 0 && parent != 0){
map->parent = parent->id;
}
}
internal void
map_null_parent(Command_Map *map){
map->parent = 0;
}
internal void
map_set_binding_text_input(Command_Map *map, Custom_Command_Function *custom){
if (map != 0){
map->text_input_command.custom = custom;
}
}
internal void
map_set_binding_key(Mapping *mapping, Command_Map *map, Custom_Command_Function *custom,
Key_Code code, Key_Modifiers *modifiers){
if (map != 0){
Command_Binding_List *list = map__get_or_make_list(mapping, map, code);
Command_Modified_Binding *mod_binding = mapping__alloc_modified_binding(mapping);
sll_stack_push(map->binding_first, mod_binding);
if (map->binding_last == 0){
map->binding_last = map->binding_first;
}
sll_stack_push(list->first, &mod_binding->order_node);
if (list->last == 0){
list->last= list->first;
}
list->count += 1;
block_copy_struct(&mod_binding->modifiers, modifiers);
mod_binding->binding.custom = custom;
}
}
internal Command_Binding_List*
map_get_binding_list_on_key(Command_Map *map, Key_Code code){
Command_Binding_List *result = 0;
if (map != 0){
result = map__get_list(map, code);
}
return(result);
}
////////////////////////////////
internal void
map_set_parent(Mapping *mapping, Command_Map_ID map_id, Command_Map_ID parent_id){
Command_Map *map = mapping_get_map(mapping, map_id);
Command_Map *parent = mapping_get_map(mapping, parent_id);
map_set_parent(map, parent);
}
internal void
map_set_parent(Mapping *mapping, Command_Map *map, Command_Map_ID parent_id){
Command_Map *parent = mapping_get_map(mapping, parent_id);
map_set_parent(map, parent);
}
internal void
map_null_parent(Mapping *mapping, Command_Map_ID map_id){
Command_Map *map = mapping_get_map(mapping, map_id);
map_null_parent(map);
}
internal void
map_set_binding_text_input(Mapping *mapping, Command_Map_ID map_id, Custom_Command_Function *custom){
Command_Map *map = mapping_get_map(mapping, map_id);
map_set_binding_text_input(map, custom);
}
internal void
map_set_binding_key(Mapping *mapping, Command_Map_ID map_id, Custom_Command_Function *custom,
Key_Code code, Key_Modifiers *modifiers){
Command_Map *map = mapping_get_map(mapping, map_id);
map_set_binding_key(mapping, map, custom, code, modifiers);
}
internal Command_Binding_List*
map_get_binding_list_on_key(Mapping *mapping, Command_Map_ID map_id, Key_Code code){
Command_Map *map = mapping_get_map(mapping, map_id);
return(map_get_binding_list_on_key(map, code));
}
internal Command_Binding
map_get_binding_non_recursive(Mapping *mapping, Command_Map_ID map_id, Input_Event *event){
Command_Map *map = mapping_get_map(mapping, map_id);
return(map_get_binding_non_recursive(map, event));
}
internal Command_Binding
map_get_binding_recursive(Mapping *mapping, Command_Map_ID map_id, Input_Event *event){
Command_Map *map = mapping_get_map(mapping, map_id);
return(map_get_binding_recursive(mapping, map, event));
}
////////////////////////////////
internal void
map_set_binding_key__wrapperv(Mapping *mapping, Command_Map *map,
Custom_Command_Function *custom, Key_Code code, va_list args){
u32 flags = 0;
for (;;){
i32 v = va_arg(args, i32);
if (v <= 0){
break;
}
flags |= v;
}
Key_Modifiers mod = {};
mod.modifiers[MDFR_SHIFT_INDEX] = HasFlag(flags, MDFR_SHIFT);
mod.modifiers[MDFR_CONTROL_INDEX] = HasFlag(flags, MDFR_CTRL);
mod.modifiers[MDFR_ALT_INDEX] = HasFlag(flags, MDFR_ALT);
mod.modifiers[MDFR_COMMAND_INDEX] = HasFlag(flags, MDFR_CMND);
return(map_set_binding_key(mapping, map, custom, code, &mod));
}
internal void
map_set_binding_key__wrapper(Mapping *mapping, Command_Map *map,
Custom_Command_Function *custom, Key_Code code, ...){
va_list args;
va_start(args, code);
map_set_binding_key__wrapperv(mapping, map, custom, code, args);
va_end(args);
}
#define MappingScope() Mapping *m = 0; Command_Map *map = 0
#define SelectMapping(N) m = (N)
#define SelectMap(ID) map = mapping_get_or_make_map(m, (ID))
#define ParentMap(ID) map_set_parent(m, map, (ID))
#define BindTextInput(F) map_set_binding_text_input(map, (F))
// TODO(allen): detect compiler and apply va args extensions correctly
#define Bind(F, K, ...) map_set_binding_key__wrapper(m, map, (F), (K), __VA_ARGS__, 0)
// BOTTOM