diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 535a1db4..d6d331af 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -1143,6 +1143,48 @@ rd_cfg_is_project_filtered(RD_Cfg *cfg) return result; } +internal RD_KeyMapNodePtrList +rd_key_map_node_ptr_list_from_name(Arena *arena, String8 string) +{ + RD_KeyMapNodePtrList list = {0}; + { + U64 hash = d_hash_from_string(string); + U64 slot_idx = hash%rd_state->key_map->name_slots_count; + for(RD_KeyMapNode *n = rd_state->key_map->name_slots[slot_idx].first; n != 0; n = n->name_hash_next) + { + if(str8_match(n->name, string, 0)) + { + RD_KeyMapNodePtr *ptr = push_array(arena, RD_KeyMapNodePtr, 1); + ptr->v = n; + SLLQueuePush(list.first, list.last, ptr); + list.count += 1; + } + } + } + return list; +} + +internal RD_KeyMapNodePtrList +rd_key_map_node_ptr_list_from_binding(Arena *arena, RD_Binding binding) +{ + RD_KeyMapNodePtrList list = {0}; + { + U64 hash = d_hash_from_string(str8_struct(&binding)); + U64 slot_idx = hash%rd_state->key_map->binding_slots_count; + for(RD_KeyMapNode *n = rd_state->key_map->binding_slots[slot_idx].first; n != 0; n = n->binding_hash_next) + { + if(MemoryMatchStruct(&binding, &n->binding)) + { + RD_KeyMapNodePtr *ptr = push_array(arena, RD_KeyMapNodePtr, 1); + ptr->v = n; + SLLQueuePush(list.first, list.last, ptr); + list.count += 1; + } + } + } + return list; +} + //////////////////////////////// //~ rjf: Entity State Functions @@ -4231,7 +4273,8 @@ rd_window_frame(void) .display_name__matches = name_matches, .description = cmd_desc, .description__matches = desc_matches, - .is_non_code = 1); + .is_non_code = 1, + .can_have_bindings = 1); } } } @@ -4391,9 +4434,17 @@ rd_window_frame(void) } // rjf: bindings - if(0) UI_Column + if(item->can_have_bindings) { - + ui_set_next_flags(UI_BoxFlag_Clickable); + UI_PrefWidth(ui_children_sum(1.f)) UI_HeightFill UI_NamedColumn(str8_lit("binding_column")) UI_Padding(ui_em(1.5f, 1.f)) + { + ui_set_next_flags(UI_BoxFlag_Clickable); + UI_NamedRow(str8_lit("binding_row")) UI_Padding(ui_em(1.f, 1.f)) + { + rd_cmd_binding_buttons(item->string); + } + } } } @@ -9997,123 +10048,6 @@ rd_push_search_string(Arena *arena) //////////////////////////////// //~ rjf: Colors, Fonts, Config -//- rjf: keybindings - -internal OS_Key -rd_os_key_from_cfg_string(String8 string) -{ - OS_Key result = OS_Key_Null; - { - for(OS_Key key = OS_Key_Null; key < OS_Key_COUNT; key = (OS_Key)(key+1)) - { - if(str8_match(string, os_g_key_cfg_string_table[key], StringMatchFlag_CaseInsensitive)) - { - result = key; - break; - } - } - } - return result; -} - -internal void -rd_clear_bindings(void) -{ - arena_clear(rd_state->key_map_arena); - rd_state->key_map_table_size = 1024; - rd_state->key_map_table = push_array(rd_state->key_map_arena, RD_KeyMapSlot, rd_state->key_map_table_size); - rd_state->key_map_total_count = 0; -} - -internal RD_BindingList -rd_bindings_from_name(Arena *arena, String8 name) -{ - RD_BindingList result = {0}; - U64 hash = d_hash_from_string(name); - U64 slot = hash%rd_state->key_map_table_size; - for(RD_KeyMapNode *n = rd_state->key_map_table[slot].first; n != 0; n = n->hash_next) - { - if(str8_match(n->name, name, 0)) - { - RD_BindingNode *node = push_array(arena, RD_BindingNode, 1); - node->binding = n->binding; - SLLQueuePush(result.first, result.last, node); - result.count += 1; - } - } - return result; -} - -internal void -rd_bind_name(String8 name, RD_Binding binding) -{ - if(binding.key != OS_Key_Null) - { - U64 hash = d_hash_from_string(name); - U64 slot = hash%rd_state->key_map_table_size; - RD_KeyMapNode *existing_node = 0; - for(RD_KeyMapNode *n = rd_state->key_map_table[slot].first; n != 0; n = n->hash_next) - { - if(str8_match(n->name, name, 0) && n->binding.key == binding.key && n->binding.modifiers == binding.modifiers) - { - existing_node = n; - break; - } - } - if(existing_node == 0) - { - RD_KeyMapNode *n = rd_state->free_key_map_node; - if(n == 0) - { - n = push_array(rd_state->arena, RD_KeyMapNode, 1); - } - else - { - rd_state->free_key_map_node = rd_state->free_key_map_node->hash_next; - } - n->name = push_str8_copy(rd_state->arena, name); - n->binding = binding; - DLLPushBack_NP(rd_state->key_map_table[slot].first, rd_state->key_map_table[slot].last, n, hash_next, hash_prev); - rd_state->key_map_total_count += 1; - } - } -} - -internal void -rd_unbind_name(String8 name, RD_Binding binding) -{ - U64 hash = d_hash_from_string(name); - U64 slot = hash%rd_state->key_map_table_size; - for(RD_KeyMapNode *n = rd_state->key_map_table[slot].first, *next = 0; n != 0; n = next) - { - next = n->hash_next; - if(str8_match(n->name, name, 0) && n->binding.key == binding.key && n->binding.modifiers == binding.modifiers) - { - DLLRemove_NP(rd_state->key_map_table[slot].first, rd_state->key_map_table[slot].last, n, hash_next, hash_prev); - n->hash_next = rd_state->free_key_map_node; - rd_state->free_key_map_node = n; - rd_state->key_map_total_count -= 1; - } - } -} - -internal String8List -rd_cmd_name_list_from_binding(Arena *arena, RD_Binding binding) -{ - String8List result = {0}; - for(U64 idx = 0; idx < rd_state->key_map_table_size; idx += 1) - { - for(RD_KeyMapNode *n = rd_state->key_map_table[idx].first; n != 0; n = n->hash_next) - { - if(n->binding.key == binding.key && n->binding.modifiers == binding.modifiers) - { - str8_list_push(arena, &result, n->name); - } - } - } - return result; -} - //- rjf: colors internal Vec4F32 @@ -11335,7 +11269,7 @@ rd_cmd_kind_info_from_string(String8 string) { RD_CmdKindInfo *info = &rd_nil_cmd_kind_info; { - // TODO(rjf): extend this by looking up into dynamically-registered commands by views + // TODO(rjf): @dynamic_cmds extend this by looking up into dynamically-registered commands by views RD_CmdKind kind = rd_cmd_kind_from_string(string); if(kind != RD_CmdKind_Null) { @@ -11419,7 +11353,6 @@ rd_init(CmdLine *cmdln) rd_state->entities_base = push_array(rd_state->entities_arena, RD_Entity, 0); rd_state->entities_count = 0; rd_state->entities_root = rd_entity_alloc(&rd_nil_entity, RD_EntityKind_Root); - rd_state->key_map_arena = arena_alloc(); rd_state->popup_arena = arena_alloc(); rd_state->ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("top_level_ctx_menu")); rd_state->drop_completion_key = ui_key_from_string(ui_key_zero(), str8_lit("drop_completion_ctx_menu")); @@ -11432,7 +11365,6 @@ rd_init(CmdLine *cmdln) rd_state->drag_drop_arena = arena_alloc(); rd_state->drag_drop_regs = push_array(rd_state->drag_drop_arena, RD_Regs, 1); rd_state->top_regs = &rd_state->base_regs; - rd_clear_bindings(); // rjf: set up top-level config entity trees { @@ -11704,6 +11636,109 @@ rd_frame(void) } } + ////////////////////////////// + //- rjf: build key map from config + // + { + //- rjf: set up table + rd_state->key_map = push_array(rd_frame_arena(), RD_KeyMap, 1); + RD_KeyMap *key_map = rd_state->key_map; + key_map->name_slots_count = 4096; + key_map->name_slots = push_array(rd_frame_arena(), RD_KeyMapSlot, key_map->name_slots_count); + key_map->binding_slots_count = 4096; + key_map->binding_slots = push_array(rd_frame_arena(), RD_KeyMapSlot, key_map->binding_slots_count); + + //- rjf: gather & parse all explicitly stored keybinding sets + RD_CfgList keybindings_cfg_list = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("keybindings")); + for(RD_CfgNode *n = keybindings_cfg_list.first; n != 0; n = n->next) + { + RD_Cfg *keybindings_root = n->v; + for(RD_Cfg *keybinding = keybindings_root->first; keybinding != &rd_nil_cfg; keybinding = keybinding->next) + { + String8 name = {0}; + RD_Binding binding = {0}; + for(RD_Cfg *child = keybinding->first; child != &rd_nil_cfg; child = child->next) + { + if(0){} + else if(str8_match(child->string, str8_lit("ctrl"), 0)) { binding.modifiers |= OS_Modifier_Ctrl; } + else if(str8_match(child->string, str8_lit("alt"), 0)) { binding.modifiers |= OS_Modifier_Alt; } + else if(str8_match(child->string, str8_lit("shift"), 0)) { binding.modifiers |= OS_Modifier_Shift; } + else + { + OS_Key key = OS_Key_Null; + for EachEnumVal(OS_Key, k) + { + if(str8_match(child->string, os_g_key_cfg_string_table[k], StringMatchFlag_CaseInsensitive)) + { + key = k; + break; + } + } + if(key != OS_Key_Null) + { + binding.key = key; + } + else + { + name = child->string; + for(U64 idx = 0; idx < ArrayCount(rd_binding_version_remap_old_name_table); idx += 1) + { + if(str8_match(rd_binding_version_remap_old_name_table[idx], name, StringMatchFlag_CaseInsensitive)) + { + name = rd_binding_version_remap_new_name_table[idx]; + } + } + } + } + } + if(name.size != 0) + { + U64 name_hash = d_hash_from_string(name); + U64 binding_hash = d_hash_from_string(str8_struct(&binding)); + U64 name_slot_idx = name_hash%key_map->name_slots_count; + U64 binding_slot_idx = binding_hash%key_map->binding_slots_count; + RD_KeyMapNode *n = push_array(rd_frame_arena(), RD_KeyMapNode, 1); + n->cfg = keybinding; + n->name = push_str8_copy(rd_frame_arena(), name); + n->binding = binding; + SLLQueuePush_N(key_map->name_slots[name_slot_idx].first, key_map->name_slots[name_slot_idx].last, n, name_hash_next); + SLLQueuePush_N(key_map->binding_slots[binding_slot_idx].first, key_map->binding_slots[binding_slot_idx].last, n, binding_hash_next); + } + } + } + + //- rjf: iterate all commands - if they are not found in the map, then use + // the default binding. + // TODO(rjf): @dynamic_cmds + for EachElement(idx, rd_default_binding_table) + { + String8 name = rd_default_binding_table[idx].string; + B32 name_was_mapped = 0; + U64 name_hash = d_hash_from_string(name); + U64 name_slot_idx = name_hash%key_map->name_slots_count; + for(RD_KeyMapNode *n = key_map->name_slots[name_slot_idx].first; n != 0; n = n->name_hash_next) + { + if(str8_match(n->name, name, 0)) + { + name_was_mapped = 1; + break; + } + } + if(!name_was_mapped) + { + RD_Binding binding = rd_default_binding_table[idx].binding; + U64 binding_hash = d_hash_from_string(str8_struct(&binding)); + U64 binding_slot_idx = binding_hash%key_map->binding_slots_count; + RD_KeyMapNode *n = push_array(rd_frame_arena(), RD_KeyMapNode, 1); + n->cfg = &rd_nil_cfg; + n->name = push_str8_copy(rd_frame_arena(), name); + n->binding = binding; + SLLQueuePush_N(key_map->name_slots[name_slot_idx].first, key_map->name_slots[name_slot_idx].last, n, name_hash_next); + SLLQueuePush_N(key_map->binding_slots[binding_slot_idx].first, key_map->binding_slots[binding_slot_idx].last, n, binding_hash_next); + } + } + } + ////////////////////////////// //- rjf: get events from the OS // @@ -11774,7 +11809,7 @@ rd_frame(void) if(os_key_press(&events, os_handle_zero(), 0, OS_Key_Delete)) { rd_request_frame(); - rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding); + // TODO(rjf): @cfg rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding); rd_state->bind_change_active = 0; rd_cmd(rd_cfg_src_write_cmd_kind_table[RD_CfgSrc_User]); } @@ -11798,8 +11833,8 @@ rd_frame(void) binding.key = event->key; binding.modifiers = event->modifiers; } - rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding); - rd_bind_name(rd_state->bind_change_cmd_name, binding); + // TODO(rjf): @cfg rd_unbind_name(rd_state->bind_change_cmd_name, rd_state->bind_change_binding); + // TODO(rjf): @cfg rd_bind_name(rd_state->bind_change_cmd_name, binding); U32 codepoint = os_codepoint_from_modifiers_and_key(event->modifiers, event->key); os_text(&events, event->window, codepoint); os_eat_event(&events, event); @@ -11887,13 +11922,13 @@ rd_frame(void) if(!take && event->kind == OS_EventKind_Press) { RD_Binding binding = {event->key, event->modifiers}; - String8List spec_candidates = rd_cmd_name_list_from_binding(scratch.arena, binding); - if(spec_candidates.first != 0) + RD_KeyMapNodePtrList key_map_nodes = rd_key_map_node_ptr_list_from_binding(scratch.arena, binding); + if(key_map_nodes.first != 0) { U32 hit_char = os_codepoint_from_modifiers_and_key(event->modifiers, event->key); if(hit_char == 0 || allow_text_hotkeys) { - rd_cmd(RD_CmdKind_RunCommand, .cmd_name = spec_candidates.first->string); + rd_cmd(RD_CmdKind_RunCommand, .cmd_name = key_map_nodes.first->v->name); if(allow_text_hotkeys) { os_text(&events, event->window, hit_char); @@ -13118,6 +13153,7 @@ rd_frame(void) } //- rjf: apply keybindings +#if 0 // TODO(rjf): @cfg if(src == RD_CfgSrc_User) { rd_clear_bindings(); @@ -13150,7 +13186,15 @@ rd_frame(void) } else { - OS_Key k = rd_os_key_from_cfg_string(child->string); + OS_Key k = OS_Key_Null; + for EachEnumVal(OS_Key, key) + { + if(str8_match(child->string, os_g_key_cfg_string_table[key], StringMatchFlag_CaseInsensitive)) + { + k = key; + break; + } + } if(k != OS_Key_Null) { key = k; @@ -13180,6 +13224,7 @@ rd_frame(void) } } } +#endif //- rjf: reset theme to default MemoryCopy(rd_state->cfg_theme_target.colors, rd_theme_preset_colors__default_dark, sizeof(rd_theme_preset_colors__default_dark)); @@ -13362,6 +13407,7 @@ rd_frame(void) #endif //- rjf: if config bound 0 keys, we need to do some sensible default +#if 0 // TODO(rjf): @cfg if(src == RD_CfgSrc_User && rd_state->key_map_total_count == 0) { for(U64 idx = 0; idx < ArrayCount(rd_default_binding_table); idx += 1) @@ -13370,8 +13416,10 @@ rd_frame(void) rd_bind_name(pair->string, pair->binding); } } +#endif //- rjf: always ensure that the meta controls have bindings +#if 0 // TODO(rjf): @cfg if(src == RD_CfgSrc_User) { struct @@ -13395,6 +13443,7 @@ rd_frame(void) } } } +#endif }break; //- rjf: writing config changes diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 3e77d6cf..09bcb823 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -29,6 +29,38 @@ struct RD_HandleList U64 count; }; +//////////////////////////////// +//~ rjf: Binding Types + +typedef struct RD_Binding RD_Binding; +struct RD_Binding +{ + OS_Key key; + OS_Modifiers modifiers; +}; + +typedef struct RD_BindingNode RD_BindingNode; +struct RD_BindingNode +{ + RD_BindingNode *next; + RD_Binding binding; +}; + +typedef struct RD_BindingList RD_BindingList; +struct RD_BindingList +{ + RD_BindingNode *first; + RD_BindingNode *last; + U64 count; +}; + +typedef struct RD_StringBindingPair RD_StringBindingPair; +struct RD_StringBindingPair +{ + String8 string; + RD_Binding binding; +}; + //////////////////////////////// //~ rjf: Evaluation Spaces @@ -84,57 +116,6 @@ enum RD_EntityFlag_MarkedForDeletion = (1<<31), }; -//////////////////////////////// -//~ rjf: Binding Types - -typedef struct RD_Binding RD_Binding; -struct RD_Binding -{ - OS_Key key; - OS_Modifiers modifiers; -}; - -typedef struct RD_BindingNode RD_BindingNode; -struct RD_BindingNode -{ - RD_BindingNode *next; - RD_Binding binding; -}; - -typedef struct RD_BindingList RD_BindingList; -struct RD_BindingList -{ - RD_BindingNode *first; - RD_BindingNode *last; - U64 count; -}; - -typedef struct RD_StringBindingPair RD_StringBindingPair; -struct RD_StringBindingPair -{ - String8 string; - RD_Binding binding; -}; - -//////////////////////////////// -//~ rjf: Key Map Types - -typedef struct RD_KeyMapNode RD_KeyMapNode; -struct RD_KeyMapNode -{ - RD_KeyMapNode *hash_next; - RD_KeyMapNode *hash_prev; - String8 name; - RD_Binding binding; -}; - -typedef struct RD_KeyMapSlot RD_KeyMapSlot; -struct RD_KeyMapSlot -{ - RD_KeyMapNode *first; - RD_KeyMapNode *last; -}; - //////////////////////////////// //~ rjf: Setting Types @@ -330,6 +311,50 @@ struct RD_CfgRec S32 pop_count; }; +//////////////////////////////// +//~ rjf: Key Map Types + +typedef struct RD_KeyMapNode RD_KeyMapNode; +struct RD_KeyMapNode +{ + RD_KeyMapNode *name_hash_next; + RD_KeyMapNode *binding_hash_next; + RD_Cfg *cfg; + String8 name; + RD_Binding binding; +}; + +typedef struct RD_KeyMapNodePtr RD_KeyMapNodePtr; +struct RD_KeyMapNodePtr +{ + RD_KeyMapNodePtr *next; + RD_KeyMapNode *v; +}; + +typedef struct RD_KeyMapNodePtrList RD_KeyMapNodePtrList; +struct RD_KeyMapNodePtrList +{ + RD_KeyMapNodePtr *first; + RD_KeyMapNodePtr *last; + U64 count; +}; + +typedef struct RD_KeyMapSlot RD_KeyMapSlot; +struct RD_KeyMapSlot +{ + RD_KeyMapNode *first; + RD_KeyMapNode *last; +}; + +typedef struct RD_KeyMap RD_KeyMap; +struct RD_KeyMap +{ + U64 name_slots_count; + RD_KeyMapSlot *name_slots; + U64 binding_slots_count; + RD_KeyMapSlot *binding_slots; +}; + //////////////////////////////// //~ rjf: New Panel Types (Queried From Config) @@ -550,6 +575,7 @@ struct RD_ListerItem FuzzyMatchRangeList description__matches; U64 group; B32 is_non_code; + B32 can_have_bindings; }; typedef struct RD_ListerItemChunkNode RD_ListerItemChunkNode; @@ -789,10 +815,13 @@ struct RD_State // rjf: dbgi match store DI_MatchStore *match_store; - // rjf: ambiguous path table + // rjf: ambiguous path table (constructed from-scratch each frame) U64 ambiguous_path_slots_count; RD_AmbiguousPathNode **ambiguous_path_slots; + // rjf: key map (constructed from-scratch each frame) + RD_KeyMap *key_map; + // rjf: registers stack RD_RegsNode base_regs; RD_RegsNode *top_regs; @@ -890,11 +919,13 @@ struct RD_State RD_EntityListCache kind_caches[RD_EntityKind_COUNT]; // rjf: key map table +#if 0 // TODO(rjf): @cfg Arena *key_map_arena; U64 key_map_table_size; RD_KeyMapSlot *key_map_table; RD_KeyMapNode *free_key_map_node; U64 key_map_total_count; +#endif // rjf: bind change Arena *bind_change_arena; @@ -1121,6 +1152,9 @@ internal Rng2F32 rd_target_rect_from_panel_node(Rng2F32 root_rect, RD_PanelNode internal B32 rd_cfg_is_project_filtered(RD_Cfg *cfg); +internal RD_KeyMapNodePtrList rd_key_map_node_ptr_list_from_name(Arena *arena, String8 string); +internal RD_KeyMapNodePtrList rd_key_map_node_ptr_list_from_binding(Arena *arena, RD_Binding binding); + //////////////////////////////// //~ rjf: Entity Stateful Functions @@ -1303,14 +1337,6 @@ internal String8 rd_push_search_string(Arena *arena); //////////////////////////////// //~ rjf: Colors, Fonts, Config -//- rjf: keybindings -internal OS_Key rd_os_key_from_cfg_string(String8 string); -internal void rd_clear_bindings(void); -internal RD_BindingList rd_bindings_from_name(Arena *arena, String8 name); -internal void rd_bind_name(String8 name, RD_Binding binding); -internal void rd_unbind_name(String8 name, RD_Binding binding); -internal String8List rd_cmd_name_list_from_binding(Arena *arena, RD_Binding binding); - //- rjf: colors internal Vec4F32 rd_rgba_from_theme_color(RD_ThemeColor color); internal RD_ThemeColor rd_theme_color_from_txt_token_kind(TXT_TokenKind kind); diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 52e6df14..29e4915f 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -25,6 +25,8 @@ // etc., all need to be merged, and optionally contextualized/filtered. // right-clicking a tab should be equivalent to spawning a command lister, // but only with commands that are directly +// +// [ ] r8 bitmap view rule seems incorrect? //////////////////////////////// //~ rjf: post-0.9.12 TODO notes diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 99cb299b..209bf857 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -95,26 +95,28 @@ internal void rd_cmd_binding_buttons(String8 name) { Temp scratch = scratch_begin(0, 0); - RD_BindingList bindings = rd_bindings_from_name(scratch.arena, name); + RD_KeyMapNodePtrList key_map_nodes = rd_key_map_node_ptr_list_from_name(scratch.arena, name); //- rjf: build buttons for each binding - for(RD_BindingNode *n = bindings.first; n != 0; n = n->next) + for(RD_KeyMapNodePtr *n = key_map_nodes.first; n != 0; n = n->next) { - RD_Binding binding = n->binding; + RD_Binding binding = n->v->binding; B32 rebinding_active_for_this_binding = (rd_state->bind_change_active && str8_match(rd_state->bind_change_cmd_name, name, 0) && rd_state->bind_change_binding.key == binding.key && rd_state->bind_change_binding.modifiers == binding.modifiers); //- rjf: grab all conflicts - String8List specs_with_binding = rd_cmd_name_list_from_binding(scratch.arena, binding); B32 has_conflicts = 0; - for(String8Node *n = specs_with_binding.first; n != 0; n = n->next) + RD_KeyMapNodePtrList nodes_with_this_binding = rd_key_map_node_ptr_list_from_binding(scratch.arena, binding); { - if(!str8_match(n->string, name, 0)) + for(RD_KeyMapNodePtr *n2 = nodes_with_this_binding.first; n2 != 0; n2 = n2->next) { - has_conflicts = 1; - break; + if(!str8_match(n->v->name, n2->v->name, 0)) + { + has_conflicts = 1; + break; + } } } @@ -196,11 +198,11 @@ rd_cmd_binding_buttons(String8 name) if(ui_hovering(sig) && has_conflicts) UI_Tooltip { UI_PrefWidth(ui_children_sum(1)) rd_error_label(str8_lit("This binding conflicts with those for:")); - for(String8Node *n = specs_with_binding.first; n != 0; n = n->next) + for(RD_KeyMapNodePtr *n2 = nodes_with_this_binding.first; n2 != 0; n2 = n2->next) { - if(!str8_match(n->string, name, 0)) + if(!str8_match(n2->v->name, n->v->name, 0)) { - RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(n->string); + RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(n2->v->name); ui_labelf("%S", info->display_name); } } @@ -219,7 +221,7 @@ rd_cmd_binding_buttons(String8 name) UI_Signal sig = rd_icon_button(RD_IconKind_X, 0, str8_lit("###delete_binding")); if(ui_clicked(sig)) { - rd_unbind_name(name, binding); + // TODO(rjf): @cfg rd_unbind_name(name, binding); rd_state->bind_change_active = 0; } }