diff --git a/src/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index a90b39f9..f33189d3 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -1225,9 +1225,26 @@ d_modules_from_dbgi_key(Arena *arena, DI_Key dbgi_key) return list; } +internal D_Entity * +d_process_from_id(U64 id) +{ + // TODO(rjf): @multimachine need machine ID here? + D_Entity *process = &d_entity_nil; + D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process); + for EachIndex(idx, processes.count) + { + if(processes.v[idx]->id == id) + { + process = processes.v[idx]; + } + } + return process; +} + internal D_Entity * d_thread_from_id(U64 id) { + // TODO(rjf): @multimachine need machine ID here? D_Entity *thread = &d_entity_nil; D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); for EachIndex(idx, threads.count) diff --git a/src/dbg_engine/dbg_engine_ctrl.h b/src/dbg_engine/dbg_engine_ctrl.h index c55144e1..4fe1ab95 100644 --- a/src/dbg_engine/dbg_engine_ctrl.h +++ b/src/dbg_engine/dbg_engine_ctrl.h @@ -519,6 +519,7 @@ internal void d_entity_equip_string(D_EntityCtxRWStore *store, D_Entity *entity, internal D_EntityCtxLookupAccel *d_thread_entity_ctx_lookup_accel(void); internal D_EntityArray d_entity_array_from_kind(D_EntityKind kind); internal D_EntityList d_modules_from_dbgi_key(Arena *arena, DI_Key dbgi_key); +internal D_Entity *d_process_from_id(U64 id); internal D_Entity *d_thread_from_id(U64 id); //- rjf: applying events to entity caches diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 23cd64e3..35605bec 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -208,8 +208,6 @@ ev_view_alloc(void) view->arena = arena; view->expand_slots_count = 256; view->expand_slots = push_array(arena, EV_ExpandSlot, view->expand_slots_count); - view->key_view_rule_slots_count = 256; - view->key_view_rule_slots = push_array(arena, EV_KeyViewRuleSlot, view->key_view_rule_slots_count); return view; } @@ -246,36 +244,6 @@ ev_expansion_from_key(EV_View *view, EV_Key key) return (node != 0 && node->expanded); } -internal String8 -ev_view_rule_from_key(EV_View *view, EV_Key key) -{ - String8 result = {0}; - - //- rjf: key -> hash * slot idx * slot - U64 hash = ev_hash_from_key(key); - U64 slot_idx = hash%view->key_view_rule_slots_count; - EV_KeyViewRuleSlot *slot = &view->key_view_rule_slots[slot_idx]; - - //- rjf: slot -> existing node - EV_KeyViewRuleNode *existing_node = 0; - for(EV_KeyViewRuleNode *n = slot->first; n != 0; n = n->hash_next) - { - if(ev_key_match(n->key, key)) - { - existing_node = n; - break; - } - } - - //- rjf: node -> result - if(existing_node != 0) - { - result = str8(existing_node->buffer, existing_node->buffer_string_size); - } - - return result; -} - internal void ev_key_set_expansion(EV_View *view, EV_Key parent_key, EV_Key key, B32 expanded) { @@ -348,44 +316,6 @@ ev_key_set_expansion(EV_View *view, EV_Key parent_key, EV_Key key, B32 expanded) } } -internal void -ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_string) -{ - //- rjf: key -> hash * slot idx * slot - U64 hash = ev_hash_from_key(key); - U64 slot_idx = hash%view->key_view_rule_slots_count; - EV_KeyViewRuleSlot *slot = &view->key_view_rule_slots[slot_idx]; - - //- rjf: slot -> existing node - EV_KeyViewRuleNode *existing_node = 0; - for(EV_KeyViewRuleNode *n = slot->first; n != 0; n = n->hash_next) - { - if(ev_key_match(n->key, key)) - { - existing_node = n; - break; - } - } - - //- rjf: existing node * new node -> node - EV_KeyViewRuleNode *node = existing_node; - if(node == 0) - { - node = push_array(view->arena, EV_KeyViewRuleNode, 1); - DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev); - node->key = key; - node->buffer_cap = 512; - node->buffer = push_array(view->arena, U8, node->buffer_cap); - } - - //- rjf: mutate node - if(node != 0) - { - node->buffer_string_size = ClampTop(view_rule_string.size, node->buffer_cap); - MemoryCopy(node->buffer, view_rule_string.str, node->buffer_string_size); - } -} - //////////////////////////////// //~ rjf: View Rule Info Table Building / Selection / Lookups diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index d3a4d35b..552aa534 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -40,26 +40,6 @@ struct EV_ExpandSlot EV_ExpandNode *last; }; -//- rjf: hash table for view rules - -typedef struct EV_KeyViewRuleNode EV_KeyViewRuleNode; -struct EV_KeyViewRuleNode -{ - EV_KeyViewRuleNode *hash_next; - EV_KeyViewRuleNode *hash_prev; - EV_Key key; - U8 *buffer; - U64 buffer_cap; - U64 buffer_string_size; -}; - -typedef struct EV_KeyViewRuleSlot EV_KeyViewRuleSlot; -struct EV_KeyViewRuleSlot -{ - EV_KeyViewRuleNode *first; - EV_KeyViewRuleNode *last; -}; - //- rjf: view state bundle typedef struct EV_View EV_View; @@ -69,9 +49,6 @@ struct EV_View EV_ExpandSlot *expand_slots; U64 expand_slots_count; EV_ExpandNode *free_expand_node; - EV_KeyViewRuleSlot *key_view_rule_slots; - U64 key_view_rule_slots_count; - EV_KeyViewRuleNode *free_key_view_rule_node; }; //////////////////////////////// @@ -328,9 +305,7 @@ internal void ev_view_release(EV_View *view); //- rjf: lookups / mutations internal EV_ExpandNode *ev_expand_node_from_key(EV_View *view, EV_Key key); internal B32 ev_expansion_from_key(EV_View *view, EV_Key key); -internal String8 ev_view_rule_from_key(EV_View *view, EV_Key key); internal void ev_key_set_expansion(EV_View *view, EV_Key parent_key, EV_Key key, B32 expanded); -internal void ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_string); //////////////////////////////// //~ rjf: View Rule Info Table Building / Selection / Lookups diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 6b9a64e0..7b4e96f5 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -62,7 +62,7 @@ str8_lit_comp(""), str8_lit_comp(""), }; -RD_VocabInfo rd_vocab_info_table[369] = +RD_VocabInfo rd_vocab_info_table[372] = { {str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -300,6 +300,9 @@ RD_VocabInfo rd_vocab_info_table[369] = {str8_lit_comp("accept"), str8_lit_comp(""), str8_lit_comp("Accept"), str8_lit_comp(""), RD_IconKind_CheckFilled}, {str8_lit_comp("cancel"), str8_lit_comp(""), str8_lit_comp("Cancel"), str8_lit_comp(""), RD_IconKind_X}, {str8_lit_comp("focus_menu"), str8_lit_comp(""), str8_lit_comp("Focus Menu"), str8_lit_comp(""), RD_IconKind_List}, +{str8_lit_comp("lock"), str8_lit_comp(""), str8_lit_comp("Lock"), str8_lit_comp(""), RD_IconKind_Locked}, +{str8_lit_comp("unlock"), str8_lit_comp(""), str8_lit_comp("Unlock"), str8_lit_comp(""), RD_IconKind_Unlocked}, +{str8_lit_comp("toggle_lock"), str8_lit_comp(""), str8_lit_comp("Toggle Lock"), str8_lit_comp(""), RD_IconKind_Locked}, {str8_lit_comp("move_left"), str8_lit_comp(""), str8_lit_comp("Move Left"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_right"), str8_lit_comp(""), str8_lit_comp("Move Right"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up"), str8_lit_comp(""), str8_lit_comp("Move Up"), str8_lit_comp(""), RD_IconKind_Null}, @@ -594,7 +597,7 @@ Rng1U64 rd_reg_slot_range_table[54] = {OffsetOf(RD_Regs, wm_event), OffsetOf(RD_Regs, wm_event) + sizeof(WM_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[256] = +RD_CmdKindInfo rd_cmd_kind_info_table[259] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets")}}, @@ -719,6 +722,9 @@ RD_CmdKindInfo rd_cmd_kind_info_table[256] = { str8_lit_comp("accept"), str8_lit_comp("Accepts current changes, or answers prompts in the affirmative."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("cancel"), str8_lit_comp("Rejects current changes, exits temporary menus, or answers prompts in the negative."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("focus_menu"), str8_lit_comp("Focuses the menu for the selected interface, if there is one."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("lock"), str8_lit_comp("Locks the current selection, if applicable."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("unlock"), str8_lit_comp("Unlocks the current selection, if applicable."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, +{ str8_lit_comp("toggle_lock"), str8_lit_comp("Toggles the lock state of the current selection, if applicable."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("move_left"), str8_lit_comp("Moves the cursor or selection left."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("move_right"), str8_lit_comp("Moves the cursor or selection right."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, { str8_lit_comp("move_up"), str8_lit_comp("Moves the cursor or selection up."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("")}}, @@ -854,7 +860,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[256] = { str8_lit_comp("geo3d"), str8_lit_comp("Opens a Geometry (3D) tab."), {0}, str8_lit_comp("{tab_commands}"), RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs}, }; -struct {String8 string; CFG_Binding binding;} rd_default_binding_table[116] = +struct {String8 string; CFG_Binding binding;} rd_default_binding_table[117] = { {str8_lit_comp("kill_all"), {WM_Key_F5, 0 |WM_Modifier_Shift }}, {str8_lit_comp("step_into_inst"), {WM_Key_F11, 0 |WM_Modifier_Alt}}, @@ -907,6 +913,7 @@ struct {String8 string; CFG_Binding binding;} rd_default_binding_table[116] = {str8_lit_comp("accept"), {WM_Key_Space, 0 }}, {str8_lit_comp("cancel"), {WM_Key_Esc, 0 }}, {str8_lit_comp("focus_menu"), {WM_Key_D, 0 |WM_Modifier_Alt}}, +{str8_lit_comp("toggle_lock"), {WM_Key_L, 0 |WM_Modifier_Ctrl }}, {str8_lit_comp("move_left"), {WM_Key_Left, 0 }}, {str8_lit_comp("move_right"), {WM_Key_Right, 0 }}, {str8_lit_comp("move_up"), {WM_Key_Up, 0 }}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 744003f2..1b22d152 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -190,6 +190,9 @@ RD_CmdKind_Edit, RD_CmdKind_Accept, RD_CmdKind_Cancel, RD_CmdKind_FocusMenu, +RD_CmdKind_Lock, +RD_CmdKind_Unlock, +RD_CmdKind_ToggleLock, RD_CmdKind_MoveLeft, RD_CmdKind_MoveRight, RD_CmdKind_MoveUp, @@ -623,7 +626,7 @@ Z(getting_started)\ C_LINKAGE_BEGIN extern String8 rd_tab_fast_path_view_name_table[25]; extern String8 rd_tab_fast_path_query_name_table[25]; -extern RD_VocabInfo rd_vocab_info_table[369]; +extern RD_VocabInfo rd_vocab_info_table[372]; extern RD_NameSchemaInfo rd_name_schema_info_table[39]; extern String8 rd_reg_slot_code_name_table[54]; extern Rng1U64 rd_reg_slot_range_table[54]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 4355bb5b..0d9817f2 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -1087,6 +1087,9 @@ RD_CmdTable: // | | | | {Accept 0 1 1 "" Null 0 0 0 0 0 0 0 CheckFilled "accept" "Accept" "Accepts current changes, or answers prompts in the affirmative." "" "" } {Cancel 0 1 1 "" Null 0 0 0 0 0 0 0 X "cancel" "Cancel" "Rejects current changes, exits temporary menus, or answers prompts in the negative." "" "" } {FocusMenu 0 1 1 "" Null 0 0 0 0 0 0 0 List "focus_menu" "Focus Menu" "Focuses the menu for the selected interface, if there is one." "" "" } + {Lock 0 1 1 "" Null 0 0 0 0 0 0 0 Locked "lock" "Lock" "Locks the current selection, if applicable." "" "" } + {Unlock 0 1 1 "" Null 0 0 0 0 0 0 0 Unlocked "unlock" "Unlock" "Unlocks the current selection, if applicable." "" "" } + {ToggleLock 0 1 1 "" Null 0 0 0 0 0 0 0 Locked "toggle_lock" "Toggle Lock" "Toggles the lock state of the current selection, if applicable." "" "" } //- rjf: directional movement & text controls {MoveLeft 0 1 1 "" Null 0 0 0 0 0 0 0 Null "move_left" "Move Left" "Moves the cursor or selection left." "" "" } @@ -1373,6 +1376,7 @@ RD_DefaultBindingTable: { "accept" Space 0 0 0 } { "cancel" Esc 0 0 0 } { "focus_menu" D 0 0 alt } + { "toggle_lock" L ctrl 0 0 } //- rjf: directional movement & text controls { "move_left" Left 0 0 0 } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index ed39fd8e..b9e644eb 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -2049,6 +2049,35 @@ rd_view_ui(Rng2F32 rect) ewv->text_edit_arena = rd_push_view_arena(); } + ////////////////////////////// + //- rjf: adjust locked expressions which have been invalidated + // + for(CFG_Node *child = view->first; child != &cfg_nil_node; child = child->next) + { + if(str8_match(child->string, s("watch_expression"), 0)) + { + CFG_Node *locked = cfg_node_child_from_string(child, s("locked")); + if(locked != &cfg_nil_node) + { + CFG_Node *pid_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, locked, s("pid")); + U64 pid = u64_from_str8(pid_cfg->first->string, 10); + D_Entity *process = d_process_from_id(pid); + if(process == &d_entity_nil) + { + D_Entity *current_process = d_entity_from_handle(rd_regs()->process); + if(current_process != &d_entity_nil) + { + cfg_node_new_replacef(rd_state->cfg, pid_cfg, "%I64u", current_process->id); + } + else + { + cfg_node_release(rd_state->cfg, locked); + } + } + } + } + } + ////////////////////////////// //- rjf: unpack arguments // @@ -2694,6 +2723,79 @@ rd_view_ui(Rng2F32 rect) } } + ////////////////////////// + //- rjf: [table] do cell-granularity lock operations + // + if(!ewv->text_editing && + (evt->slot == UI_EventActionSlot_Lock || + evt->slot == UI_EventActionSlot_Unlock || + evt->slot == UI_EventActionSlot_ToggleLock) && + (selection_tbl.min.y != 0 || selection_tbl.max.y != 0)) + { + EV_WindowedRowList rows = ev_rows_from_num_range(scratch.arena, eval_view, &block_ranges, r1u64(selection_tbl.min.y, selection_tbl.max.y+1)); + EV_WindowedRowNode *row_node = rows.first; + if(row_node != 0) + { + taken = 1; + B32 next_locked = 0; + B32 found_next_locked = 0; + for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row_node != 0; y += 1, row_node = row_node->next) + { + // rjf: unpack row info + EV_Row *row = &row_node->row; + RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); + CFG_Node *cfg = row_info.group_cfg_child; + + // rjf: determine if row can be locked + B32 row_can_be_locked = 0; + if(str8_match(row_info.group_cfg_name, s("watch_expression"), 0) && + cfg != &cfg_nil_node && + row->eval.string.size != 0) + { + E_Space space = row->eval.space; + D_Entity *entity = rd_ctrl_entity_from_eval_space(space); + B32 is_memory_eval = (space.kind == D_EvalSpaceKind_Entity && entity->kind == D_EntityKind_Process); + row_can_be_locked = (is_memory_eval && + (row->eval.irtree.mode == E_Mode_Offset) || + (row->eval.irtree.mode == E_Mode_Value && + e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(row->eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative))))); + } + + // rjf: determine if row is locked + B32 row_is_locked = (cfg_node_child_from_string(cfg, s("locked")) != &cfg_nil_node); + if(row_can_be_locked && !found_next_locked) + { + found_next_locked = 1; + next_locked = !row_is_locked; + } + + // rjf: toggle lock on row + if(row_can_be_locked) + { + if(next_locked) + { + E_Space space = row->eval.space; + D_Entity *entity = rd_ctrl_entity_from_eval_space(space); + CFG_Node *locked = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, s("locked")); + cfg_node_release_all_children(rd_state->cfg, locked); + CFG_Node *mid = cfg_node_new(rd_state->cfg, locked, s("mid")); + cfg_node_newf(rd_state->cfg, mid, "%I64u", entity->handle.machine_id); + CFG_Node *pid = cfg_node_new(rd_state->cfg, locked, s("pid")); + cfg_node_newf(rd_state->cfg, pid, "%I64u", entity->id); + CFG_Node *addr = cfg_node_new(rd_state->cfg, locked, s("addr")); + cfg_node_newf(rd_state->cfg, addr, "0x%I64x", row->eval.value.u64); + CFG_Node *type = cfg_node_new(rd_state->cfg, locked, s("type")); + cfg_node_new(rd_state->cfg, type, e_type_string_from_key(scratch.arena, row->eval.irtree.type_key)); + } + else + { + cfg_node_release(rd_state->cfg, cfg_node_child_from_string(cfg, s("locked"))); + } + } + } + } + } + ////////////////////////// //- rjf: [text] apply textual edits // @@ -4027,11 +4129,14 @@ rd_view_ui(Rng2F32 rect) // rjf: determine if this cell can be locked B32 cell_can_be_locked = 0; if(str8_match(row_info->group_cfg_name, s("watch_expression"), 0) && - cell_info.flags & RD_WatchCellFlag_Expr && - cell->eval.string.size != 0 && - cell->eval.msgs.count == 0) + !(cell_info.flags & RD_WatchCellFlag_Expr) && + cell->eval.string.size != 0) { - cell_can_be_locked = ((cell->eval.irtree.mode == E_Mode_Offset) || + E_Space space = row->eval.space; + D_Entity *entity = rd_ctrl_entity_from_eval_space(space); + B32 is_memory_eval = (space.kind == D_EvalSpaceKind_Entity && entity->kind == D_EntityKind_Process); + cell_can_be_locked = (is_memory_eval && + (cell->eval.irtree.mode == E_Mode_Offset) || (cell->eval.irtree.mode == E_Mode_Value && e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(cell->eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative))))); } @@ -4264,14 +4369,24 @@ rd_view_ui(Rng2F32 rect) } // rjf: apply locks - if(next_cell_is_locked != cell_is_locked) { CFG_Node *cfg = row_info->group_cfg_child; - if(cfg != &cfg_nil_node) + if(next_cell_is_locked != cell_is_locked && cfg != &cfg_nil_node) { if(next_cell_is_locked) { - cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, s("locked")); + E_Space space = row->eval.space; + D_Entity *entity = rd_ctrl_entity_from_eval_space(space); + CFG_Node *locked = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, s("locked")); + cfg_node_release_all_children(rd_state->cfg, locked); + CFG_Node *mid = cfg_node_new(rd_state->cfg, locked, s("mid")); + cfg_node_newf(rd_state->cfg, mid, "%I64u", entity->handle.machine_id); + CFG_Node *pid = cfg_node_new(rd_state->cfg, locked, s("pid")); + cfg_node_newf(rd_state->cfg, pid, "%I64u", entity->id); + CFG_Node *addr = cfg_node_new(rd_state->cfg, locked, s("addr")); + cfg_node_newf(rd_state->cfg, addr, "0x%I64x", row->eval.value.u64); + CFG_Node *type = cfg_node_new(rd_state->cfg, locked, s("type")); + cfg_node_new(rd_state->cfg, type, e_type_string_from_key(scratch.arena, row->eval.irtree.type_key)); } else { @@ -12338,12 +12453,17 @@ rd_frame(void) } if(kind == D_EntityKind_Process && d_handle_match(rd_base_regs()->process, entity->handle)) { - e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("current_process"), expr); + e_string2expr_map_insert(scratch.arena, macro_map, s("current_process"), expr); } if(kind == D_EntityKind_Module && d_handle_match(rd_base_regs()->module, entity->handle)) { e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("current_module"), expr); } + if(kind == D_EntityKind_Process) + { + String8 pid_string = str8f(scratch.arena, "process_%I64u", entity->id); + e_string2expr_map_insert(scratch.arena, macro_map, pid_string, expr); + } } } @@ -16876,6 +16996,33 @@ rd_frame(void) evt.slot = UI_EventActionSlot_FocusMenu; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; + case RD_CmdKind_Lock: + { + CFG_Node *window = cfg_node_from_id(rd_regs()->window); + RD_WindowState *ws = rd_window_state_from_cfg(window); + UI_Event evt = zero_struct; + evt.kind = UI_EventKind_Press; + evt.slot = UI_EventActionSlot_Lock; + ui_event_list_push(scratch.arena, &ws->ui_events, &evt); + }break; + case RD_CmdKind_Unlock: + { + CFG_Node *window = cfg_node_from_id(rd_regs()->window); + RD_WindowState *ws = rd_window_state_from_cfg(window); + UI_Event evt = zero_struct; + evt.kind = UI_EventKind_Press; + evt.slot = UI_EventActionSlot_Unlock; + ui_event_list_push(scratch.arena, &ws->ui_events, &evt); + }break; + case RD_CmdKind_ToggleLock: + { + CFG_Node *window = cfg_node_from_id(rd_regs()->window); + RD_WindowState *ws = rd_window_state_from_cfg(window); + UI_Event evt = zero_struct; + evt.kind = UI_EventKind_Press; + evt.slot = UI_EventActionSlot_ToggleLock; + ui_event_list_push(scratch.arena, &ws->ui_events, &evt); + }break; //- rjf: directional movement & text controls // diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c index ea0f0d62..ab9f89e2 100644 --- a/src/raddbg/raddbg_eval.c +++ b/src/raddbg/raddbg_eval.c @@ -1462,7 +1462,24 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(watches) { CFG_Node *cfg = accel->cfgs.v[cfg_idx]; CFG_Node *expr = cfg_node_child_from_string(cfg, s("expression")); - evals_out[idx] = e_eval_from_string(expr->first->string); + CFG_Node *locked = cfg_node_child_from_string(cfg, s("locked")); + if(locked->first->string.size != 0) + { + String8 pid = cfg_node_child_from_string(locked, s("pid"))->first->string; + String8 type = cfg_node_child_from_string(locked, s("type"))->first->string; + String8 addr = cfg_node_child_from_string(locked, s("addr"))->first->string; + String8 lock_expr = str8f(arena, "*(cast(%S *)(process_%S.memory + %S))", type, pid, addr); + evals_out[idx] = e_eval_from_string(lock_expr); + evals_out[idx].string = expr->first->string; + if(evals_out[idx].msgs.count != 0) + { + evals_out[idx] = e_eval_from_string(expr->first->string); + } + } + else + { + evals_out[idx] = e_eval_from_string(expr->first->string); + } } } } diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 7ccdc1a6..a1e797c4 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -3417,6 +3417,52 @@ rd_cell(RD_CellParams *params, String8 string) } } + ////////////////////////////// + //- rjf: build lock + // + if(params->flags & RD_CellFlag_Lock && !is_focus_active && !is_focus_active_disabled) UI_Parent(box) UI_Focus(UI_FocusKind_Off) + { + // TODO(rjf): @hack + { + ui_spacer(ui_em(0.5f, 1.f)); + } + B32 is_locked = (params->lock_out && params->lock_out[0]); + UI_PrefWidth(ui_em(2.f, 1.f)) + UI_TagF(".") + UI_TagF(is_locked ? "pop" : "weak") + UI_TagF("implicit") + UI_Column + UI_Padding(ui_pct(1, 0)) + UI_PrefHeight(ui_em(2.f, 1.f)) + UI_CornerRadius(ui_top_font_size()*0.5f) + RD_Font(RD_FontSlot_Icons) + UI_TextAlignment(UI_TextAlign_Center) + { + UI_Box *lock_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DisableFocusOverlay| + UI_BoxFlag_DisableFocusBorder| + UI_BoxFlag_Clickable, + "%S###lock", rd_icon_kind_text_table[is_locked ? RD_IconKind_Locked : RD_IconKind_Unlocked]); + UI_Signal sig = ui_signal_from_box(lock_box); + if(ui_hovering(sig)) UI_Tooltip RD_Font(RD_FontSlot_Main) + { + ui_state->tooltip_anchor_key = lock_box->key; + UI_PrefWidth(ui_children_sum(1)) UI_Row + { + UI_PrefWidth(ui_text_dim(10, 1)) ui_label(is_locked ? s("Unlock Location") : s("Lock Location")); + rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_ToggleLock].string, s(""), 1, RD_CmdBindingButtonFlag_NoEdit); + } + } + if(ui_pressed(sig) && params->lock_out) + { + params->lock_out[0] ^= 1; + } + } + } + ////////////////////////////// //- rjf: build left-hand-side container box // @@ -3607,47 +3653,6 @@ rd_cell(RD_CellParams *params, String8 string) } } - ////////////////////////////// - //- rjf: build lock - // - if(params->flags & RD_CellFlag_Lock && !is_focus_active && !is_focus_active_disabled) UI_Parent(box) UI_Focus(UI_FocusKind_Off) - { - UI_PrefWidth(ui_em(2.f, 1.f)) - UI_TagF(".") - UI_TagF("weak") - UI_TagF("implicit") - UI_Column - UI_Padding(ui_pct(1, 0)) - UI_PrefHeight(ui_em(2.f, 1.f)) - UI_CornerRadius(ui_top_font_size()*0.5f) - RD_Font(RD_FontSlot_Icons) - UI_TextAlignment(UI_TextAlign_Center) - { - UI_Box *lock_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| - UI_BoxFlag_DrawHotEffects| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawBackground| - UI_BoxFlag_DisableFocusOverlay| - UI_BoxFlag_DisableFocusBorder| - UI_BoxFlag_Clickable, - "%S###lock", rd_icon_kind_text_table[(params->lock_out && params->lock_out[0]) ? RD_IconKind_Locked : RD_IconKind_Unlocked]); - UI_Signal sig = ui_signal_from_box(lock_box); - if(ui_hovering(sig)) UI_Tooltip RD_Font(RD_FontSlot_Main) - { - ui_state->tooltip_anchor_key = lock_box->key; - ui_label((params->lock_out && params->lock_out[0]) ? s("Unlock Evaluated Location") : s("Lock Evaluated Location")); - } - if(ui_pressed(sig) && params->lock_out) - { - params->lock_out[0] ^= 1; - } - } - // TODO(rjf): @hack - { - ui_spacer(ui_em(0.5f, 1.f)); - } - } - ////////////////////////////// //- rjf: build toggle-switch // diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 5d2352ba..b5aaa508 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -104,6 +104,9 @@ typedef enum UI_EventActionSlot UI_EventActionSlot_Cancel, UI_EventActionSlot_Edit, UI_EventActionSlot_FocusMenu, + UI_EventActionSlot_Lock, + UI_EventActionSlot_Unlock, + UI_EventActionSlot_ToggleLock, UI_EventActionSlot_COUNT } UI_EventActionSlot;