diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index fac3994b..1bdd54e4 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -317,7 +317,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[12] = {str8_lit_comp("thread"), str8_lit_comp("x:{'label':code_string, 'id':u64, 'frozen':bool, 'call_stack':query}")}, }; -Rng1U64 rd_reg_slot_range_table[38] = +Rng1U64 rd_reg_slot_range_table[40] = { {0}, {OffsetOf(RD_Regs, machine), OffsetOf(RD_Regs, machine) + sizeof(CTRL_Handle)}, @@ -345,6 +345,8 @@ Rng1U64 rd_reg_slot_range_table[38] = {OffsetOf(RD_Regs, voff), OffsetOf(RD_Regs, voff) + sizeof(U64)}, {OffsetOf(RD_Regs, vaddr_range), OffsetOf(RD_Regs, vaddr_range) + sizeof(Rng1U64)}, {OffsetOf(RD_Regs, voff_range), OffsetOf(RD_Regs, voff_range) + sizeof(Rng1U64)}, +{OffsetOf(RD_Regs, expr), OffsetOf(RD_Regs, expr) + sizeof(String8)}, +{OffsetOf(RD_Regs, view_rule), OffsetOf(RD_Regs, view_rule) + sizeof(String8)}, {OffsetOf(RD_Regs, ui_key), OffsetOf(RD_Regs, ui_key) + sizeof(UI_Key)}, {OffsetOf(RD_Regs, off_px), OffsetOf(RD_Regs, off_px) + sizeof(Vec2F32)}, {OffsetOf(RD_Regs, lister_flags), OffsetOf(RD_Regs, lister_flags) + sizeof(RD_ListerFlags)}, @@ -531,8 +533,8 @@ RD_CmdKindInfo rd_cmd_kind_info_table[213] = { str8_lit_comp("toggle_breakpoint"), str8_lit_comp("Places or removes a breakpoint at a given location (file path and line number, address, or symbol name)."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (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(""), CTRL_EntityKind_Null}}, { str8_lit_comp("enable_breakpoint"), str8_lit_comp("Enables a breakpoint."), 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*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("disable_breakpoint"), str8_lit_comp("Disables a breakpoint."), 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*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}}, -{ str8_lit_comp("add_watch_pin"), str8_lit_comp("Places a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp("$watch_pins,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, -{ str8_lit_comp("toggle_watch_pin"), str8_lit_comp("Places or removes a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, +{ str8_lit_comp("add_watch_pin"), str8_lit_comp("Places a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp("$watch_pins,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, +{ str8_lit_comp("toggle_watch_pin"), str8_lit_comp("Places or removes a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_auto_view_rule"), str8_lit_comp("Adds a new auto view rule."), str8_lit_comp(""), str8_lit_comp("$auto_view_rules,"), (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_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_next_statement"), str8_lit_comp("Sets the selected thread's instruction pointer to the cursor's position."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (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(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_target"), str8_lit_comp("Adds a new target."), str8_lit_comp("application,executable,debug"), str8_lit_comp("$targets,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*1)|(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_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 348bb4fc..0ec59375 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -34,6 +34,8 @@ RD_RegSlot_Vaddr, RD_RegSlot_Voff, RD_RegSlot_VaddrRange, RD_RegSlot_VoffRange, +RD_RegSlot_Expr, +RD_RegSlot_ViewRule, RD_RegSlot_UIKey, RD_RegSlot_OffPx, RD_RegSlot_ListerFlags, @@ -550,6 +552,8 @@ U64 vaddr; U64 voff; Rng1U64 vaddr_range; Rng1U64 voff_range; +String8 expr; +String8 view_rule; UI_Key ui_key; Vec2F32 off_px; RD_ListerFlags lister_flags; @@ -611,6 +615,8 @@ RD_Query query; .voff = rd_regs()->voff,\ .vaddr_range = rd_regs()->vaddr_range,\ .voff_range = rd_regs()->voff_range,\ +.expr = rd_regs()->expr,\ +.view_rule = rd_regs()->view_rule,\ .ui_key = rd_regs()->ui_key,\ .off_px = rd_regs()->off_px,\ .lister_flags = rd_regs()->lister_flags,\ @@ -627,7 +633,7 @@ RD_Query query; C_LINKAGE_BEGIN extern RD_VocabInfo rd_vocab_info_table[293]; extern RD_NameSchemaInfo rd_name_schema_info_table[12]; -extern Rng1U64 rd_reg_slot_range_table[38]; +extern Rng1U64 rd_reg_slot_range_table[40]; extern String8 rd_binding_version_remap_old_name_table[8]; extern String8 rd_binding_version_remap_new_name_table[8]; extern String8 rd_icon_kind_text_table[69]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index b1124a51..38125746 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -297,6 +297,10 @@ RD_RegTable: {Rng1U64 vaddr_range VaddrRange } {Rng1U64 voff_range VoffRange } + // rjf: evaluation + {String8 expr Expr } + {String8 view_rule ViewRule } + // rjf: ui context {UI_Key ui_key UIKey } {Vec2F32 off_px OffPx } @@ -545,8 +549,8 @@ RD_CmdTable: // | | | | {DisableBreakpoint 1 1 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 0 0 1 CheckHollow "disable_breakpoint" "Disable Breakpoint" "Disables a breakpoint." "" "" } //- rjf: watch pins - {AddWatchPin 1 1 "" String null Nil Null 0 0 0 0 1 1 1 Pin "add_watch_pin" "Add Watch Pin" "Places a watch pin at a given location (file path and line number or address)." "" "$watch_pins," } - {ToggleWatchPin 1 0 "" String null Nil Null 0 0 0 0 1 1 1 Binoculars "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin at a given location (file path and line number or address)." "" "" } + {AddWatchPin 1 1 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "add_watch_pin" "Add Watch Pin" "Places a watch pin at a given location (file path and line number or address)." "" "$watch_pins," } + {ToggleWatchPin 1 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Binoculars "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin at a given location (file path and line number or address)." "" "" } //- rjf: auto view rule {AddAutoViewRule 1 1 "" String null Nil Null 0 0 0 0 0 0 0 Binoculars "add_auto_view_rule" "Add Auto View Rule" "Adds a new auto view rule." "" "$auto_view_rules," } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 19182ee8..74186fc7 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -1051,6 +1051,8 @@ rd_regs_copy_contents(Arena *arena, RD_Regs *dst, RD_Regs *src) dst->file_path = push_str8_copy(arena, src->file_path); dst->lines = d_line_list_copy(arena, &src->lines); dst->dbgi_key = di_key_copy(arena, &src->dbgi_key); + dst->expr = push_str8_copy(arena, src->expr); + dst->view_rule = push_str8_copy(arena, src->view_rule); dst->string = push_str8_copy(arena, src->string); dst->cmd_name = push_str8_copy(arena, src->cmd_name); dst->params_tree = md_tree_copy(arena, src->params_tree); @@ -5259,6 +5261,12 @@ rd_view_ui(Rng2F32 rect) case CTRL_EntityKind_Thread:{RD_RegsScope(.thread = cell_info.entity->handle) rd_drag_begin(RD_RegSlot_Thread);}break; } } + else + { + RD_RegsScope(.expr = e_string_from_expr(scratch.arena, row_info->eval.exprs.last), + .view_rule = ev_view_rule_from_key(rd_view_eval_view(), row->key)) + rd_drag_begin(RD_RegSlot_Expr); + } } // rjf: (normally) single-click -> move selection here @@ -6267,7 +6275,6 @@ rd_window_frame(void) //- rjf: build UI // UI_Box *lister_box = &ui_nil_box; - UI_Box *hover_eval_box = &ui_nil_box; ProfScope("build UI") { //////////////////////////// @@ -6500,6 +6507,26 @@ rd_window_frame(void) di_scope_close(di_scope); }break; + + //////////////////////// + //- rjf: expression tooltips + // + case RD_RegSlot_Expr: + UI_Tooltip RD_Font(RD_FontSlot_Code) + { + ui_set_next_pref_width(ui_children_sum(1)); + UI_Row + { + rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), rd_state->drag_drop_regs->expr); + ui_spacer(ui_em(2.f, 1.f)); + E_Eval eval = e_eval_from_string(scratch.arena, rd_state->drag_drop_regs->expr); + if(eval.mode != E_Mode_Null) + { + String8 value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), EV_StringFlag_ReadOnlyDisplayRules, 10, ui_top_font(), ui_top_font_size(), ui_top_font_size()*20.f, eval); + rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); + } + } + }break; } scratch_end(scratch); } @@ -8031,6 +8058,8 @@ rd_window_frame(void) } U64 needed_row_count = Min(max_row_count, predicted_block_tree.total_row_count); F32 num_rows_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "hover_eval_num_rows_t"), (F32)needed_row_count); + + // rjf: build container UI_Focus(ws->hover_eval_focused ? UI_FocusKind_On : UI_FocusKind_Off) UI_PrefHeight(ui_px(row_height_px, 1.f)) { @@ -9305,33 +9334,6 @@ rd_window_frame(void) ui_end_build(); } - ////////////////////////////// - //- rjf: ensure hover eval is in-bounds - // - if(!ui_box_is_nil(hover_eval_box)) - { - UI_Box *root = hover_eval_box; - Rng2F32 window_rect = os_client_rect_from_window(ui_window()); - Rng2F32 root_rect = root->rect; - Vec2F32 shift = - { - -ClampBot(0, root_rect.x1 - window_rect.x1), - -ClampBot(0, root_rect.y1 - window_rect.y1), - }; - Rng2F32 new_root_rect = shift_2f32(root_rect, shift); - root->fixed_position = new_root_rect.p0; - root->fixed_size = dim_2f32(new_root_rect); - root->rect = new_root_rect; - for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis + 1)) - { - ui_calc_sizes_standalone__in_place_rec(root, axis); - ui_calc_sizes_upwards_dependent__in_place_rec(root, axis); - ui_calc_sizes_downwards_dependent__in_place_rec(root, axis); - ui_layout_enforce_constraints__in_place_rec(root, axis); - ui_layout_position__in_place_rec(root, axis); - } - } - ////////////////////////////// //- rjf: attach lister boxes to root, or hide if it has not been renewed // @@ -15896,7 +15898,8 @@ Z(getting_started) { String8 file_path = rd_regs()->file_path; TxtPt pt = rd_regs()->cursor; - String8 string = rd_regs()->string; + String8 expr_string = rd_regs()->expr; + String8 view_rule_string = rd_regs()->view_rule; U64 vaddr = rd_regs()->vaddr; B32 removed_already_existing = 0; if(kind == RD_CmdKind_ToggleWatchPin) @@ -15911,7 +15914,7 @@ Z(getting_started) U64 loc_vaddr = 0; B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line); B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr); - B32 loc_matches_expr = (string.size != 0 && str8_match(expr->first->string, string, 0)); + B32 loc_matches_expr = (expr_string.size != 0 && str8_match(expr->first->string, expr_string, 0)); if(loc_matches_expr && (loc_matches_file_pt || loc_matches_vaddr)) { rd_cfg_release(wp); @@ -15925,8 +15928,10 @@ Z(getting_started) RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); RD_Cfg *wp = rd_cfg_new(project, str8_lit("watch_pin")); RD_Cfg *expr = rd_cfg_new(wp, str8_lit("expression")); + RD_Cfg *view_rule = rd_cfg_new(wp, str8_lit("view_rule")); RD_Cfg *loc = rd_cfg_new(wp, str8_lit("location")); - rd_cfg_new(expr, string); + rd_cfg_new(expr, expr_string); + rd_cfg_new(view_rule, view_rule_string); if(vaddr != 0) { rd_cfg_newf(loc, "0x%I64x", vaddr); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 3202b4c0..0d2e47d7 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1543,16 +1543,6 @@ rd_watch_view_text_edit_state_from_pt(RD_WatchViewState *wv, RD_WatchPt pt) return result; } -//- rjf: watch view main hooks - -internal void -rd_watch_view_build(RD_WatchViewState *ewv, Rng2F32 rect) -{ - ProfBeginFunction(); - - ProfEnd(); -} - //////////////////////////////// //~ rjf: null @view_hook_impl diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 566b3095..0e3f87b7 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -234,7 +234,7 @@ rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg) } //- rjf: cfg has expression attached -> use that - else if(expr_string.size != 0 && !str8_match(cfg->string, str8_lit("watch"), 0)) + else if(expr_string.size != 0 && !is_within_window) { dr_fstrs_push_new(arena, &result, ¶ms, expr_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code)); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); @@ -1829,7 +1829,8 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe RD_Cfg *pin = n->v; String8 pin_expr = rd_expr_from_cfg(pin); String8 pin_view_rule = rd_view_rule_from_cfg(pin); - E_Eval eval = e_eval_from_string(scratch.arena, pin_expr); + String8 full_pin_expr = push_str8f(scratch.arena, "%S => %S", pin_expr, pin_view_rule); + E_Eval eval = e_eval_from_string(scratch.arena, full_pin_expr); String8 eval_string = {0}; if(!e_type_key_match(e_type_key_zero(), eval.type_key)) { @@ -2042,6 +2043,12 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe line_drag_drop_color = pop_color; } } + if(rd_state->drag_drop_regs_slot == RD_RegSlot_Expr) + { + line_drag_drop = 1; + line_drag_cfg = cfg; + line_drag_drop_color = pop_color; + } if(rd_state->drag_drop_regs_slot == RD_RegSlot_Thread) { line_drag_drop = 1; @@ -2055,8 +2062,21 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe } //- rjf: drop target is dropped -> process + if(contains_1s64(params->line_num_range, mouse_pt.line) && contains_2f32(clipped_top_container_rect, ui_mouse())) { - if(line_drag_cfg != &rd_nil_cfg && rd_drag_drop() && contains_1s64(params->line_num_range, mouse_pt.line)) + if(rd_state->drag_drop_regs_slot == RD_RegSlot_Expr && rd_drag_drop()) + { + S64 line_num = mouse_pt.line; + U64 line_idx = line_num - params->line_num_range.min; + U64 line_vaddr = params->line_vaddrs[line_idx]; + rd_cmd(RD_CmdKind_AddWatchPin, + .expr = rd_state->drag_drop_regs->expr, + .view_rule = rd_state->drag_drop_regs->view_rule, + .file_path = line_vaddr == 0 ? rd_regs()->file_path : str8_zero(), + .cursor = line_vaddr == 0 ? txt_pt(line_num, 1) : txt_pt(0, 0), + .vaddr = line_vaddr); + } + if(rd_state->drag_drop_regs_slot == RD_RegSlot_Cfg && line_drag_cfg != &rd_nil_cfg && rd_drag_drop()) { RD_Cfg *dropped_cfg = line_drag_cfg; S64 line_num = mouse_pt.line; @@ -2068,7 +2088,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe .cursor = line_vaddr == 0 ? txt_pt(line_num, 1) : txt_pt(0, 0), .vaddr = line_vaddr); } - if(line_drag_ctrl_entity != &ctrl_entity_nil && rd_drag_drop() && contains_1s64(params->line_num_range, mouse_pt.line)) + if(line_drag_ctrl_entity != &ctrl_entity_nil && rd_drag_drop()) { S64 line_num = mouse_pt.line; U64 line_idx = line_num - params->line_num_range.min;