diff --git a/src/eval/eval_core.c b/src/eval/eval_core.c index 0adf8c3c..80150fd6 100644 --- a/src/eval/eval_core.c +++ b/src/eval/eval_core.c @@ -1094,7 +1094,7 @@ e_value_eval_from_eval(E_Eval eval) // rjf: manually sign-extend switch(type_kind) { - default: break; + default:{}break; case E_TypeKind_Char8: case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break; case E_TypeKind_Char16: diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 34ed91f3..5e7195d4 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[359] = +RD_VocabInfo rd_vocab_info_table[360] = { {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}, @@ -291,6 +291,7 @@ RD_VocabInfo rd_vocab_info_table[359] = {str8_lit_comp("edit"), str8_lit_comp(""), str8_lit_comp("Edit"), str8_lit_comp(""), RD_IconKind_Pencil}, {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("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}, @@ -436,7 +437,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[26] = {str8_lit_comp("list"), str8_lit_comp("x:\n{\n @description(\"An expression describing the first node in the list.\")\n 'expression': expr_string,\n @order(0) @description(\"The name of the member which encodes the link to the next node.\")\n 'member_name': code_string,\n}\n")}, {str8_lit_comp("text"), str8_lit_comp("@inherit(tab) @expand_commands(@output clear_output) x:\n{\n @description(\"An expression to describe data which should be viewed as text or code.\")\n 'expression': expr_string,\n @description(\"The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.\")\n 'lang': code_string,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers':bool,\n @no_callee_helper @default(1) @display_name('Line Wrapping') @description(\"Splits textual lines into multiple visual lines, so that all text is within the visible area.\")\n 'line_wrapping': bool,\n @no_callee_helper @default(0) @display_name('Scroll To Bottom On Change') @description(\"Scrolls to the bottom if the text is changed.\")\n 'scroll_to_bottom_on_change': bool,\n @no_callee_helper @no_revert @default(0) @display_name('Transient') @description(\"Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.\")\n 'auto': bool,\n}\n")}, {str8_lit_comp("disasm"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe the base address or offset of the disassembly.\")\n 'expression': expr_string,\n 'arch': code_string,\n 'syntax': code_string,\n 'size': expr_string,\n @no_callee_helper @default(1) @description(\"Controls whether or not addresses are shown in the disassembly text.\")\n 'show_addresses': bool,\n @no_callee_helper @default(0) @description(\"Controls whether or not code bytes are shown in the disassembly text.\")\n 'show_code_bytes': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not source lines, corresponding to disassembly instruction ranges, are shown in the disassembly text.\")\n 'show_source_lines': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not disassembly text is decorated with symbol names.\")\n 'show_symbol_names': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers': bool,\n}\n")}, -{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Base Address\") @description(\"An expression which refers to the base address of data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @default(1) @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @expand_if(\"!$.auto_columns\") @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(1) @display_name(\"Track Mark To Cursor\") @description(\"Ensures that the mark always follows the cursor, if the cursor value is updated.\")\n 'track_mark_to_cursor': bool,\n @default(1) @display_name(\"Allow Mutation\") @description(\"Allows operations which mutate memory.\")\n 'allow_mutation': bool,\n @default(0) @display_name(\"Automatically Size Columns\") @description(\"Determines the number of columns based on the available space.\")\n 'auto_columns': bool,\n @display_name(\"Peek Types\") @description(\"A list of types to interpret selected and hovered memory as.\")\n 'peek_types': query,\n}\n")}, +{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Base Address\") @description(\"An expression which refers to the base address of data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @default(1) @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @expand_if(\"!$.auto_columns\") @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(16) @display_name(\"Default Radix\") @description(\"The default radix with which numeric values should be displayed, when peeking.\")\n @or(2, 8, 10, 16)\n 'default_radix': u64,\n @default(1) @display_name(\"Track Mark To Cursor\") @description(\"Ensures that the mark always follows the cursor, if the cursor value is updated.\")\n 'track_mark_to_cursor': bool,\n @default(1) @display_name(\"Allow Mutation\") @description(\"Allows operations which mutate memory.\")\n 'allow_mutation': bool,\n @default(0) @display_name(\"Automatically Size Columns\") @description(\"Determines the number of columns based on the available space.\")\n 'auto_columns': bool,\n @default(1) @display_name(\"Peek As Unsigned\") 'peek_as_unsigned': bool,\n @default(1) @display_name(\"Peek As Signed\") 'peek_as_signed': bool,\n @default(1) @display_name(\"Peek As Float\") 'peek_as_float': bool,\n @display_name(\"Extra Peek Types\") @description(\"A list of types as which to interpret selected memory.\")\n 'peek_types': query,\n}\n")}, {str8_lit_comp("bitmap"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the base address of data which should be viewed as a bitmap.\")\n 'expression': expr_string,\n @description(\"An expression describing the width of the bitmap, in pixels.\") @order(0) 'w': u64,\n @description(\"An expression describing the height of the bitmap, in pixels.\") @order(1) 'h': u64,\n @display_name(\"Bitmap Format\") @description(\"The pixel format that the bitmap data should be interpreted as being within.\")\n 'fmt': code_string,\n}\n")}, {str8_lit_comp("color"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Value\") @description(\"An expression to describe the value or location of the color.\")\n 'expression': expr_string,\n}\n")}, {str8_lit_comp("geo3d"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Expression\") @description(\"An expression to describe the base address of the index buffer.\")\n 'expression': expr_string,\n 'count': expr_string,\n 'vtx': expr_string,\n 'vtx_size': expr_string,\n 'yaw': @range[0, 1] f32,\n 'pitch': @range[-0.5, 0] f32,\n 'zoom': @range[0, 100] f32,\n}\n")}, @@ -561,7 +562,7 @@ Rng1U64 rd_reg_slot_range_table[49] = {OffsetOf(RD_Regs, os_event), OffsetOf(RD_Regs, os_event) + sizeof(OS_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[248] = +RD_CmdKindInfo rd_cmd_kind_info_table[249] = { {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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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"), str8_lit_comp(""), CTRL_EntityKind_Null}}, @@ -679,6 +680,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[248] = { str8_lit_comp("edit"), str8_lit_comp("Edits the current selection."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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("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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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("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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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("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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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("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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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("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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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("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_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(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}}, @@ -813,7 +815,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[248] = { str8_lit_comp("geo3d"), str8_lit_comp("Opens a Geometry (3D) tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, }; -struct {String8 string; CFG_Binding binding;} rd_default_binding_table[117] = +struct {String8 string; CFG_Binding binding;} rd_default_binding_table[118] = { {str8_lit_comp("kill_all"), {OS_Key_F5, 0 |OS_Modifier_Shift }}, {str8_lit_comp("step_into_inst"), {OS_Key_F11, 0 |OS_Modifier_Alt}}, @@ -869,6 +871,7 @@ struct {String8 string; CFG_Binding binding;} rd_default_binding_table[117] = {str8_lit_comp("accept"), {OS_Key_Return, 0 }}, {str8_lit_comp("accept"), {OS_Key_Space, 0 }}, {str8_lit_comp("cancel"), {OS_Key_Esc, 0 }}, +{str8_lit_comp("focus_menu"), {OS_Key_D, 0 |OS_Modifier_Alt}}, {str8_lit_comp("move_left"), {OS_Key_Left, 0 }}, {str8_lit_comp("move_right"), {OS_Key_Right, 0 }}, {str8_lit_comp("move_up"), {OS_Key_Up, 0 }}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index dda99eec..9f2cd81c 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -178,6 +178,7 @@ RD_CmdKind_ProjectSettings, RD_CmdKind_Edit, RD_CmdKind_Accept, RD_CmdKind_Cancel, +RD_CmdKind_FocusMenu, RD_CmdKind_MoveLeft, RD_CmdKind_MoveRight, RD_CmdKind_MoveUp, @@ -601,7 +602,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[359]; +extern RD_VocabInfo rd_vocab_info_table[360]; extern RD_NameSchemaInfo rd_name_schema_info_table[26]; extern String8 rd_reg_slot_code_name_table[49]; extern Rng1U64 rd_reg_slot_range_table[49]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 45e5f582..006362ee 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -550,13 +550,19 @@ RD_VocabTable: 'cursor_size': @range[1, 16] u64, @expand_if("!$.auto_columns") @default(16) @description("The number of columns to build before building new rows.") 'num_columns': @range[1, 64] u64, + @default(16) @display_name("Default Radix") @description("The default radix with which numeric values should be displayed, when peeking.") + @or(2, 8, 10, 16) + 'default_radix': u64, @default(1) @display_name("Track Mark To Cursor") @description("Ensures that the mark always follows the cursor, if the cursor value is updated.") 'track_mark_to_cursor': bool, @default(1) @display_name("Allow Mutation") @description("Allows operations which mutate memory.") 'allow_mutation': bool, @default(0) @display_name("Automatically Size Columns") @description("Determines the number of columns based on the available space.") 'auto_columns': bool, - @display_name("Peek Types") @description("A list of types to interpret selected and hovered memory as.") + @default(1) @display_name("Peek As Unsigned") 'peek_as_unsigned': bool, + @default(1) @display_name("Peek As Signed") 'peek_as_signed': bool, + @default(1) @display_name("Peek As Float") 'peek_as_float': bool, + @display_name("Extra Peek Types") @description("A list of types as which to interpret selected memory.") 'peek_types': query, } ``` @@ -979,6 +985,7 @@ RD_CmdTable: // | | | | {Edit 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Pencil "edit" "Edit" "Edits the current selection." "" "" } {Accept 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckFilled "accept" "Accept" "Accepts current changes, or answers prompts in the affirmative." "" "" } {Cancel 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 X "cancel" "Cancel" "Rejects current changes, exits temporary menus, or answers prompts in the negative." "" "" } + {FocusMenu 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 List "focus_menu" "Focus Menu" "Focuses the menu for the selected interface, if there is one." "" "" } //- rjf: directional movement & text controls {MoveLeft 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_left" "Move Left" "Moves the cursor or selection left." "" "" } @@ -1265,6 +1272,7 @@ RD_DefaultBindingTable: { "accept" Return 0 0 0 } { "accept" Space 0 0 0 } { "cancel" Esc 0 0 0 } + { "focus_menu" D 0 0 alt } //- 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 be59c832..45599767 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -4676,6 +4676,28 @@ rd_view_setting_f32_from_name(String8 name) return result; } +internal U64 +rd_view_setting_addr_from_name(String8 name) +{ + U64 result = 0; + String8 string = rd_view_setting_from_name(name); + E_Eval eval = e_eval_from_string(string); + E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative); + E_TypeKind type_kind = e_type_kind_from_key(type_key); + if(eval.irtree.mode == E_Mode_Offset && + (type_kind == E_TypeKind_Struct || + type_kind == E_TypeKind_Union || + type_kind == E_TypeKind_Class)) + { + result = eval.value.u64; + } + else + { + result = e_value_eval_from_eval(eval).value.u64; + } + return result; +} + //- rjf: evaluation & tag (a view's 'call') parameter extraction internal Rng1U64 @@ -15623,6 +15645,15 @@ rd_frame(void) evt.slot = UI_EventActionSlot_Cancel; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; + case RD_CmdKind_FocusMenu: + { + 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_FocusMenu; + ui_event_list_push(scratch.arena, &ws->ui_events, &evt); + }break; //- rjf: directional movement & text controls // diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 84d3f0ac..cfd8d2ac 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -700,6 +700,7 @@ internal E_Value rd_view_setting_value_from_name(String8 string); internal B32 rd_view_setting_b32_from_name(String8 string); internal U64 rd_view_setting_u64_from_name(String8 string); internal F32 rd_view_setting_f32_from_name(String8 string); +internal U64 rd_view_setting_addr_from_name(String8 string); //- rjf: evaluation & tag (a view's 'call') parameter extraction internal Rng1U64 rd_space_range_from_eval(E_Eval eval); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index a5dad0b5..8cace0af 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -2641,6 +2641,11 @@ struct RD_MemoryViewState B32 snap_scroll; B32 cell_value_edit_in_progress; U8 cell_value_edit_first_digit; + TxtPt addrbar_cursor; + TxtPt addrbar_mark; + U8 addrbar_buffer[1024]; + U64 addrbar_string_size; + B32 addrbar_is_focused; }; EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory) @@ -2698,8 +2703,8 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Vec4F32 main_tx_color_rgba = ui_color_from_name(str8_lit("text")); Vec4F32 main_tx_color_hsva = hsva_from_rgba(main_tx_color_rgba); F32 main_font_size = ui_bottom_font_size(); - U64 cursor_base_vaddr = rd_view_setting_u64_from_name(str8_lit("cursor")); - U64 mark_base_vaddr = rd_view_setting_u64_from_name(str8_lit("mark")); + U64 cursor_base_vaddr = rd_view_setting_addr_from_name(str8_lit("cursor")); + U64 mark_base_vaddr = rd_view_setting_addr_from_name(str8_lit("mark")); U64 cursor_size = rd_view_setting_u64_from_name(str8_lit("cursor_size")); cursor_size = ClampBot(1, cursor_size); U64 initial_cursor_base_vaddr = cursor_base_vaddr; @@ -2763,9 +2768,11 @@ RD_VIEW_UI_FUNCTION_DEF(memory) F32 scroll_bar_dim = floor_f32(main_font_size*1.5f); Vec2F32 panel_dim = dim_2f32(rect); F32 footer_dim = floor_f32(main_font_size*10.f); - Rng2F32 header_rect = r2f32p(0, 0, panel_dim.x, row_height_px); + Rng2F32 addrbar_rect = r2f32p(0, 0, panel_dim.x, main_font_size*3.f); + Rng2F32 peekbar_rect = r2f32p(0, addrbar_rect.y1, panel_dim.x, addrbar_rect.y1 + main_font_size*3.f); + Rng2F32 header_rect = r2f32p(0, peekbar_rect.y1, panel_dim.x, peekbar_rect.y1 + row_height_px); Rng2F32 footer_rect = r2f32p(0, panel_dim.y-footer_dim, panel_dim.x-scroll_bar_dim, panel_dim.y); - Rng2F32 content_rect = r2f32p(0, row_height_px, panel_dim.x-scroll_bar_dim, panel_dim.y); + Rng2F32 content_rect = r2f32p(0, header_rect.y1, panel_dim.x-scroll_bar_dim, panel_dim.y); ////////////////////////////// //- rjf: determine visible range of rows (occluded & non-occluded) @@ -2814,6 +2821,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) ////////////////////////////// //- rjf: loop: compute boundaries, take events, repeat // + B32 focus_addrbar = 0; B32 need_update = 1; Rng1U64 cursor_valid_rng = {0}; for(;;) @@ -2826,7 +2834,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) need_update = 0; //- rjf: take keyboard controls - UI_Focus(UI_FocusKind_On) if(ui_is_focus_active()) + UI_Focus(!mv->addrbar_is_focused ? UI_FocusKind_On : UI_FocusKind_Off) if(ui_is_focus_active()) { U64 next_cursor_base_vaddr = cursor_base_vaddr; U64 next_mark_base_vaddr = mark_base_vaddr; @@ -2836,6 +2844,13 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Vec2S64 cell_delta = {0}; B32 allow_cell_movement = 1; + // rjf: menu bar focuses + if(evt->slot == UI_EventActionSlot_FocusMenu) + { + good_action = 1; + focus_addrbar = 1; + } + // rjf: copies if(evt->flags & UI_EventFlag_Copy) { @@ -3526,9 +3541,9 @@ RD_VIEW_UI_FUNCTION_DEF(memory) UI_Parent(container_box) UI_FontSize(main_font_size) { ui_set_next_fixed_x(content_rect.x1); - ui_set_next_fixed_y(0); + ui_set_next_fixed_y(header_rect.y0); ui_set_next_fixed_width(scroll_bar_dim); - ui_set_next_fixed_height(dim_2f32(rect).y); + ui_set_next_fixed_height(dim_2f32(rect).y - dim_2f32(addrbar_rect).y); { scroll_pos.y = ui_scroll_bar(Axis2_Y, ui_px(scroll_bar_dim, 1.f), @@ -3538,14 +3553,212 @@ RD_VIEW_UI_FUNCTION_DEF(memory) } } + ////////////////////////////// + //- rjf: build address bar + // + B32 commit_addrbar = 0; + UI_Box *addrbar_box = &ui_nil_box; + UI_Parent(container_box) UI_TagF("floating") + { + CFG_Node *view = cfg_node_from_id(rd_regs()->view); + RD_ViewState *view_state = rd_view_state_from_cfg(view); + B32 query_is_open = view_state->query_is_open; + CFG_Node *cursor_addr = cfg_node_child_from_string(view, str8_lit("cursor")); + UI_Signal cell_sig = {0}; + UI_Rect(addrbar_rect) + addrbar_box = ui_build_box_from_stringf(UI_BoxFlag_DrawSideBottom| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawDropShadow| + UI_BoxFlag_DrawBackgroundBlur| + UI_BoxFlag_Floating| + UI_BoxFlag_Clickable, "addrbar_box"); + UI_Parent(addrbar_box) + RD_Font(RD_FontSlot_Code) + UI_FontSize(font_size) + { + UI_Flags(UI_BoxFlag_DrawSideRight) + UI_TextAlignment(UI_TextAlign_Center) + UI_PrefWidth(ui_text_dim(10, 1)) + UI_TagF("weak") + ui_labelf("Cursor Address"); + UI_Focus(!query_is_open && mv->addrbar_is_focused ? UI_FocusKind_On : UI_FocusKind_Off) + { + UI_Key addrbar_edit_key = {0}; + RD_CellParams cell_params = {0}; + { + String8 value_string = cursor_addr->first->string; + DR_FStrList value_fstrs = {0}; + { + DR_FStr value_fstr = + { + value_string, + { + ui_top_font(), + ui_top_text_raster_flags(), + ui_color_from_name(str8_lit("text")), + ui_top_font_size(), + } + }; + dr_fstrs_push(scratch.arena, &value_fstrs, &value_fstr); + } + cell_params.flags = RD_CellFlag_NoBackground|RD_CellFlag_CodeContents|RD_CellFlag_Bindings; + cell_params.pre_edit_value = value_string; + cell_params.value_fstrs = value_fstrs; + cell_params.cursor = &mv->addrbar_cursor; + cell_params.mark = &mv->addrbar_mark; + cell_params.edit_buffer = mv->addrbar_buffer; + cell_params.edit_buffer_size = sizeof(mv->addrbar_buffer); + cell_params.edit_string_size_out = &mv->addrbar_string_size; + cell_params.line_edit_key_out = &addrbar_edit_key; + cell_params.bindings_name = rd_cmd_kind_info_table[RD_CmdKind_FocusMenu].string; + } + cell_sig = rd_cellf(&cell_params, "%S###cursor_addr", cursor_addr->first->string); + if(ui_is_focus_active()) + { + rd_set_autocomp_regs(e_eval_nil, .ui_key = addrbar_edit_key, .string = str8(mv->addrbar_buffer, mv->addrbar_string_size), .cursor = mv->addrbar_cursor); + if(ui_slot_press(UI_EventActionSlot_Cancel)) + { + mv->addrbar_is_focused = 0; + } + if(ui_slot_press(UI_EventActionSlot_Accept)) + { + commit_addrbar = 1; + } + } + } + } + UI_Signal addrbar_sig = ui_signal_from_box(addrbar_box); + if(ui_pressed(addrbar_sig) || ui_pressed(cell_sig)) + { + rd_cmd(RD_CmdKind_FocusPanel); + if(!mv->addrbar_is_focused) + { + ui_kill_action(); + focus_addrbar = 1; + } + } + } + + ////////////////////////////// + //- rjf: build peekbar + // + UI_Box *peekbar_box = &ui_nil_box; + UI_Parent(container_box) UI_FontSize(main_font_size) UI_TagF("floating") + { + ui_set_next_fixed_x(peekbar_rect.x0); + ui_set_next_fixed_y(peekbar_rect.y0); + ui_set_next_fixed_width(dim_2f32(peekbar_rect).x); + ui_set_next_fixed_height(dim_2f32(peekbar_rect).y); + ui_set_next_child_layout_axis(Axis2_Y); + peekbar_box = ui_build_box_from_stringf(UI_BoxFlag_AllowOverflowX|UI_BoxFlag_ViewClampX|UI_BoxFlag_ViewScrollX|UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "footer"); + UI_Parent(peekbar_box) RD_Font(RD_FontSlot_Code) UI_TextAlignment(UI_TextAlign_Center) + { + CFG_Node *view = cfg_node_from_id(rd_regs()->view); + CFG_NodePtrList extra_peek_types = cfg_node_child_list_from_string(scratch.arena, view, str8_lit("peek_type")); + String8List peek_type_list = {0}; + if(rd_view_setting_b32_from_name(str8_lit("peek_as_unsigned"))) + { + str8_list_pushf(scratch.arena, &peek_type_list, "uint8"); + str8_list_pushf(scratch.arena, &peek_type_list, "uint16"); + str8_list_pushf(scratch.arena, &peek_type_list, "uint32"); + str8_list_pushf(scratch.arena, &peek_type_list, "uint64"); + } + if(rd_view_setting_b32_from_name(str8_lit("peek_as_signed"))) + { + str8_list_pushf(scratch.arena, &peek_type_list, "int8"); + str8_list_pushf(scratch.arena, &peek_type_list, "int16"); + str8_list_pushf(scratch.arena, &peek_type_list, "int32"); + str8_list_pushf(scratch.arena, &peek_type_list, "int64"); + } + if(rd_view_setting_b32_from_name(str8_lit("peek_as_float"))) + { + str8_list_pushf(scratch.arena, &peek_type_list, "float32"); + str8_list_pushf(scratch.arena, &peek_type_list, "float64"); + } + for EachNode(n, CFG_NodePtrNode, extra_peek_types.first) + { + str8_list_push(scratch.arena, &peek_type_list, n->v->first->string); + } + ui_set_next_pref_width(ui_children_sum(1)); + ui_row_begin(); + F32 x_off_px = 0; + F32 x_max_px = dim_2f32(rect).x - scroll_bar_dim; + for EachNode(n, String8Node, peek_type_list.first) + { + String8 type_string = n->string; + E_Eval type_eval = e_eval_from_string(type_string); + if(type_eval.msgs.max_kind == E_MsgKind_Null) + { + String8 casted_expr = str8f(scratch.arena, "*(((%S) *)((((uint8 *)(&(%S)) + 0x%I64x))))", + type_string, + eval.string.size ? eval.string : str8_lit("0"), + selection.min - view_range.min); + E_Eval peek_eval = e_eval_from_string(casted_expr); + if(peek_eval.msgs.max_kind == E_MsgKind_Null) + { + EV_StringParams params = + { + .flags = EV_StringFlag_ReadOnlyDisplayRules, + .radix = rd_view_setting_u64_from_name(str8_lit("default_radix")), + }; + String8 value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), ¶ms, ui_top_font(), ui_top_font_size(), ui_top_font_size()*40.f, peek_eval); + F32 type_string_width_px = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, 0, type_string).x + ui_top_font_size()*0.5f; + F32 value_string_width_px = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, 0, value_string).x + ui_top_font_size()*0.5f; + type_string_width_px = Min(type_string_width_px, ui_top_font_size()*10.f); + value_string_width_px = Min(value_string_width_px, ui_top_font_size()*20.f); + F32 padding_px = ui_top_font_size()*0.5f; + x_off_px += type_string_width_px + value_string_width_px + padding_px*2.f; + if(0 && x_off_px >= x_max_px) + { + x_off_px = 0; + ui_row_end(); + ui_row_begin(); + } + UI_PrefWidth(ui_children_sum(1)) UI_TagF(".") UI_TagF("implicit") + { + UI_Box *peek_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawActiveEffects, + "peek_type_%I64x", u64_hash_from_str8(type_string)); + UI_Parent(peek_box) UI_Padding(ui_px(padding_px, 1)) UI_Flags(UI_BoxFlag_DisableTruncatedHover) + { + UI_PrefWidth(ui_px(type_string_width_px, 1)) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), type_string); + UI_PrefWidth(ui_px(value_string_width_px, 1)) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); + } + UI_Signal peek_sig = ui_signal_from_box(peek_box); + if(ui_hovering(peek_sig)) + { + rd_set_hover_eval(v2f32(peek_box->rect.x0, peek_box->rect.y1-2.f), casted_expr); + } + if(ui_clicked(peek_sig)) + { + rd_cmd(RD_CmdKind_PushQuery, .expr = casted_expr); + } + } + } + } + } + ui_row_end(); + } + UI_Signal sig = ui_signal_from_box(peekbar_box); + if(ui_pressed(sig)) + { + rd_cmd(RD_CmdKind_FocusPanel); + commit_addrbar = mv->addrbar_is_focused; + mv->addrbar_is_focused = 0; + } + } + ////////////////////////////// //- rjf: build header // UI_Box *header_box = &ui_nil_box; UI_Parent(container_box) UI_TagF("floating") { - UI_Rect(r2f32p(0, 0, dim_2f32(rect).x - scroll_bar_dim, row_height_px)) + UI_Rect(header_rect) header_box = ui_build_box_from_stringf(UI_BoxFlag_DrawSideBottom| + UI_BoxFlag_DrawSideTop| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawBackgroundBlur| @@ -3570,12 +3783,19 @@ RD_VIEW_UI_FUNCTION_DEF(memory) ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f)); UI_WidthFill ui_labelf("ASCII"); } - ui_signal_from_box(header_box); + UI_Signal sig = ui_signal_from_box(header_box); + if(ui_pressed(sig)) + { + rd_cmd(RD_CmdKind_FocusPanel); + commit_addrbar = mv->addrbar_is_focused; + mv->addrbar_is_focused = 0; + } } ////////////////////////////// //- rjf: build footer // +#if 0 UI_Box *footer_box = &ui_nil_box; UI_Parent(container_box) UI_FontSize(main_font_size) UI_TagF("floating") { @@ -3583,40 +3803,82 @@ RD_VIEW_UI_FUNCTION_DEF(memory) ui_set_next_fixed_y(footer_rect.y0); ui_set_next_fixed_width(dim_2f32(footer_rect).x); ui_set_next_fixed_height(dim_2f32(footer_rect).y); + ui_set_next_child_layout_axis(Axis2_Y); footer_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_DrawDropShadow, "footer"); - UI_Parent(footer_box) RD_Font(RD_FontSlot_Code) + UI_Parent(footer_box) RD_Font(RD_FontSlot_Code) UI_WidthFill UI_TextAlignment(UI_TextAlign_Center) { - UI_PrefWidth(ui_em(7.5f, 1.f)) UI_HeightFill UI_Column UI_TagF("weak") - UI_PrefHeight(ui_em(2.f, 0.f)) + CFG_Node *view = cfg_node_from_id(rd_regs()->view); + CFG_NodePtrList peek_types = cfg_node_child_list_from_string(scratch.arena, view, str8_lit("peek_type")); + ui_row_begin(); + F32 x_off_px = 0; + F32 x_max_px = dim_2f32(rect).x - scroll_bar_dim; + for EachNode(n, CFG_NodePtrNode, peek_types.first) { - ui_labelf("Address:"); - ui_labelf("U8:"); - ui_labelf("U16:"); - ui_labelf("U32:"); - ui_labelf("U64:"); - } - UI_PrefWidth(ui_em(45.f, 1.f)) UI_HeightFill UI_Column - UI_PrefHeight(ui_em(2.f, 0.f)) - { - ui_labelf("%016I64X", cursor_base_vaddr); + String8 type_string = n->v->first->string; + E_Eval type_eval = e_eval_from_string(type_string); + if(type_eval.msgs.max_kind == E_MsgKind_Null) { - U64 as_u8 = 0; - U64 as_u16 = 0; - U64 as_u32 = 0; - U64 as_u64 = 0; - e_space_read(eval.space, &as_u64, r1u64(cursor_base_vaddr, cursor_base_vaddr+1)); - as_u32 = *(U32 *)&as_u64; - as_u16 = *(U16 *)&as_u64; - as_u8 = *(U8 *)&as_u64; - ui_labelf("%02X (%I64u)", as_u8, as_u8); - ui_labelf("%04X (%I64u)", as_u16, as_u16); - ui_labelf("%08X (%I64u)", as_u32, as_u32); - ui_labelf("%016I64X (%I64u)", as_u64, as_u64); + String8 casted_expr = str8f(scratch.arena, "*(((%S) *)((((uint8 *)(&(%S)) + 0x%I64x))))", + type_string, + eval.string.size ? eval.string : str8_lit("0"), + selection.min - view_range.min); + E_Eval peek_eval = e_eval_from_string(casted_expr); + if(peek_eval.msgs.max_kind == E_MsgKind_Null) + { + EV_StringParams params = + { + .flags = EV_StringFlag_ReadOnlyDisplayRules, + .radix = rd_view_setting_u64_from_name(str8_lit("default_radix")), + }; + String8 value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), ¶ms, ui_top_font(), ui_top_font_size(), ui_top_font_size()*40.f, peek_eval); + F32 type_string_width_px = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, 0, type_string).x + ui_top_font_size()*0.5f; + F32 value_string_width_px = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, 0, value_string).x + ui_top_font_size()*0.5f; + type_string_width_px = Min(type_string_width_px, ui_top_font_size()*10.f); + value_string_width_px = Min(value_string_width_px, ui_top_font_size()*20.f); + F32 padding_px = ui_top_font_size()*0.5f; + x_off_px += type_string_width_px + value_string_width_px + padding_px*2.f; + if(x_off_px >= x_max_px) + { + x_off_px = 0; + ui_row_end(); + ui_row_begin(); + } + UI_PrefWidth(ui_children_sum(0)) UI_TagF(".") UI_TagF("implicit") + { + UI_Box *peek_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawActiveEffects, + "peek_type_%I64x", n->v->id); + UI_Parent(peek_box) UI_Padding(ui_px(padding_px, 0)) UI_Flags(UI_BoxFlag_DisableTruncatedHover) + { + UI_PrefWidth(ui_px(type_string_width_px, 0)) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), type_string); + UI_PrefWidth(ui_px(value_string_width_px, 0)) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); + } + UI_Signal peek_sig = ui_signal_from_box(peek_box); + if(ui_hovering(peek_sig)) + { + rd_set_hover_eval(v2f32(peek_box->rect.x0, peek_box->rect.y1-2.f), casted_expr); + } + if(ui_clicked(peek_sig)) + { + rd_cmd(RD_CmdKind_PushQuery, .expr = casted_expr); + } + } + } } } + ui_row_end(); + } + UI_Signal sig = ui_signal_from_box(footer_box); + if(ui_pressed(sig)) + { + rd_cmd(RD_CmdKind_FocusPanel); + commit_addrbar = mv->addrbar_is_focused; + mv->addrbar_is_focused = 0; } - ui_signal_from_box(footer_box); } +#endif ////////////////////////////// //- rjf: build scrollable box @@ -3691,6 +3953,8 @@ RD_VIEW_UI_FUNCTION_DEF(memory) if(ui_pressed(sig)) { rd_cmd(RD_CmdKind_FocusPanel); + commit_addrbar = mv->addrbar_is_focused; + mv->addrbar_is_focused = 0; } // rjf: click & drag -> select @@ -3905,7 +4169,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) } } } - if(annotation_node != 0 && mouse_hover_byte_num == global_byte_num && !byte_is_selected && !dragging_is_active) + if(annotation_node != 0 && mouse_hover_byte_num == global_byte_num && !dragging_is_active) { UI_Tooltip UI_PrefHeight(ui_px(ui_top_font_size()*1.75f, 1.f)) { @@ -3929,38 +4193,6 @@ RD_VIEW_UI_FUNCTION_DEF(memory) } } } - if(mouse_hover_byte_num == global_byte_num && byte_is_selected && !dragging_is_active) - { - UI_Tooltip - { - CFG_Node *view = cfg_node_from_id(rd_regs()->view); - CFG_NodePtrList peek_types = cfg_node_child_list_from_string(scratch.arena, view, str8_lit("peek_type")); - for EachNode(n, CFG_NodePtrNode, peek_types.first) - { - String8 type_string = n->v->first->string; - E_Eval type_size_eval = e_eval_from_stringf("sizeof(%S)", type_string); - if(type_size_eval.msgs.max_kind == E_MsgKind_Null && dim_1u64(selection)+1 >= type_size_eval.value.u64) - { - String8 casted_expr = str8f(scratch.arena, "*(((%S) *)((((uint8 *)(&(%S)) + 0x%I64x))))", - type_string, - eval.string.size ? eval.string : str8_lit("0"), - selection.min - view_range.min); - E_Eval peek_eval = e_eval_from_string(casted_expr); - UI_PrefWidth(ui_children_sum(1)) UI_Row - { - EV_StringParams params = - { - .flags = EV_StringFlag_ReadOnlyDisplayRules, - .radix = 10, - }; - String8 value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), ¶ms, ui_top_font(), ui_top_font_size(), ui_top_font_size()*40.f, peek_eval); - UI_TextAlignment(UI_TextAlign_Left) UI_PrefWidth(ui_em(4.f, 1.f)) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), type_string); - UI_PrefWidth(ui_text_dim(10, 1)) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); - } - } - } - } - } } } } @@ -4023,6 +4255,26 @@ RD_VIEW_UI_FUNCTION_DEF(memory) } } + ////////////////////////////// + //- rjf: commit addrbar changes + // + if(focus_addrbar) + { + CFG_Node *view = cfg_node_from_id(rd_regs()->view); + CFG_Node *cursor_addr = cfg_node_child_from_string(view, str8_lit("cursor")); + mv->addrbar_is_focused = 1; + mv->addrbar_string_size = Min(sizeof(mv->addrbar_buffer), cursor_addr->first->string.size); + MemoryCopy(mv->addrbar_buffer, cursor_addr->first->string.str, mv->addrbar_string_size); + mv->addrbar_cursor = txt_pt(1, mv->addrbar_string_size+1); + mv->addrbar_mark = txt_pt(1, 1); + } + if(commit_addrbar) + { + String8 string = str8(mv->addrbar_buffer, mv->addrbar_string_size); + rd_store_view_param(str8_lit("cursor"), string); + mv->addrbar_is_focused = 0; + } + ////////////////////////////// //- rjf: scroll // diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 9e94c90c..4a99be51 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -3656,6 +3656,11 @@ rd_cell(RD_CellParams *params, String8 string) UI_BoxFlag_Clickable, "%S##revert", rd_icon_kind_text_table[RD_IconKind_Undo]); UI_Signal sig = ui_signal_from_box(revert_box); + if(ui_hovering(sig)) UI_Tooltip RD_Font(RD_FontSlot_Main) + { + ui_state->tooltip_anchor_key = revert_box->key; + ui_label(str8_lit("Revert To Default")); + } if(ui_pressed(sig) && params->revert_out) { params->revert_out[0] = 1; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 79c6f3e9..f5acb805 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -103,6 +103,7 @@ typedef enum UI_EventActionSlot UI_EventActionSlot_Accept, UI_EventActionSlot_Cancel, UI_EventActionSlot_Edit, + UI_EventActionSlot_FocusMenu, UI_EventActionSlot_COUNT } UI_EventActionSlot;