checkpoint on memory view improvements; bugfixes, improved visualizations, & mutation controls

This commit is contained in:
Ryan Fleury
2026-04-09 11:07:00 -07:00
parent be270a8f8d
commit 9aa63bc86c
5 changed files with 147 additions and 33 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
- Fixed the debugger incorrectly evaluating pointer casts of registers in - Fixed the debugger incorrectly evaluating pointer casts of registers in
register space, rather than promoting them to process address space register space, rather than promoting them to process address space
evaluations. This fixes cases where expressions like `(int *)rax` were not evaluations. This fixes cases where expressions like `(int *)rax` were not
displaying correctly. evaluating correctly.
- Fixed the debugger incorrectly requiring multiple step operations when source - Fixed the debugger incorrectly requiring multiple step operations when source
lines mapped to multiple discontiguous ranges of instructions. This most lines mapped to multiple discontiguous ranges of instructions. This most
notably showed up with certain styles of `for`-loops, especially with Clang notably showed up with certain styles of `for`-loops, especially with Clang
+1 -1
View File
@@ -435,7 +435,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("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("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}\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}\n")},
{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @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 @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @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}\n")}, {str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @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 @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(0) @display_name(\"Edit Mode\") @description(\"Enables editing operations on memory contents.\")\n 'edit_mode': bool,\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("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("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")}, {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")},
+3 -1
View File
@@ -546,12 +546,14 @@ RD_VocabTable:
'size': expr_string, 'size': expr_string,
@display_name("Cursor Address") @description("The address of the cursor.") @display_name("Cursor Address") @description("The address of the cursor.")
'cursor': expr_string, 'cursor': expr_string,
@display_name("Cursor Size") @description("The size, in bytes, of the cursor.") @default(1) @display_name("Cursor Size") @description("The size, in bytes, of the cursor.")
'cursor_size': @range[1, 16] u64, 'cursor_size': @range[1, 16] u64,
@default(16) @description("The number of columns to build before building new rows.") @default(16) @description("The number of columns to build before building new rows.")
'num_columns': @range[1, 64] u64, 'num_columns': @range[1, 64] u64,
@default(1) @display_name("Track Mark To Cursor") @description("Ensures that the mark always follows the cursor, if the cursor value is updated.") @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, 'track_mark_to_cursor': bool,
@default(0) @display_name("Edit Mode") @description("Enables editing operations on memory contents.")
'edit_mode': bool,
} }
``` ```
} }
+1 -1
View File
@@ -11,7 +11,7 @@
// [ ] make address editable; specialized version of the cursor address editor in tab right-click menu // [ ] make address editable; specialized version of the cursor address editor in tab right-click menu
// [ ] simplified default layout // [ ] simplified default layout
// [ ] memory view deserves larger spot, in default layout // [ ] memory view deserves larger spot, in default layout
// [ ] fix for-loop stepping oddities, likely single-line for-loop stepping // [x] fix for-loop stepping oddities, likely single-line for-loop stepping
// [x] `foo, x` needs to correctly match `hex(foo)`, e.g. in application to expansions // [x] `foo, x` needs to correctly match `hex(foo)`, e.g. in application to expansions
// [x] eval: pointer casts of register space should promote to process space // [x] eval: pointer casts of register space should promote to process space
// [x] more control over string visualization; specifically, when *not* to do it, even when using e.g. char *s // [x] more control over string visualization; specifically, when *not* to do it, even when using e.g. char *s
+141 -29
View File
@@ -2637,6 +2637,8 @@ struct RD_MemoryViewState
B32 center_cursor; B32 center_cursor;
B32 contain_cursor; B32 contain_cursor;
B32 snap_scroll; B32 snap_scroll;
B32 cell_value_edit_in_progress;
U8 cell_value_edit_first_digit;
}; };
EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory) EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory)
@@ -2652,6 +2654,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
ProfBeginFunction(); ProfBeginFunction();
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
RD_MemoryViewState *mv = rd_view_state(RD_MemoryViewState); RD_MemoryViewState *mv = rd_view_state(RD_MemoryViewState);
B32 edit_mode = rd_view_setting_b32_from_name(str8_lit("edit_mode"));
////////////////////////////// //////////////////////////////
//- rjf: if memory views are parameterized by a register-space evaluation, //- rjf: if memory views are parameterized by a register-space evaluation,
@@ -2821,16 +2824,83 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
U64 next_mark_base_vaddr = mark_base_vaddr; U64 next_mark_base_vaddr = mark_base_vaddr;
for(UI_Event *evt = 0; ui_next_event(&evt);) for(UI_Event *evt = 0; ui_next_event(&evt);)
{ {
B32 good_action = 0;
Vec2S64 cell_delta = {0}; Vec2S64 cell_delta = {0};
switch(evt->delta_unit) B32 allow_cell_movement = 1;
// rjf: edit mode toggling
if(evt->slot == UI_EventActionSlot_Edit)
{
rd_store_view_param_s64(str8_lit("edit_mode"), !edit_mode);
edit_mode ^= 1;
good_action = 1;
}
// rjf: cell-granularity deletions
if(edit_mode && !mv->cell_value_edit_in_progress && evt->flags & UI_EventFlag_Delete)
{
Rng1U64 range = union_1u64(r1u64(cursor_base_vaddr, cursor_base_vaddr+cursor_size),
r1u64(mark_base_vaddr, mark_base_vaddr+cursor_size));
U8 *data = push_array(scratch.arena, U8, dim_1u64(range));
if(!e_space_write(eval.space, data, range))
{
log_user_errorf("Could not successfully write to memory.");
}
good_action = 1;
}
// rjf: in-progress cell value edit deletions -> delete existing cell half-byte
if(edit_mode && mv->cell_value_edit_in_progress && evt->flags & UI_EventFlag_Delete)
{
mv->cell_value_edit_in_progress = 0;
allow_cell_movement = 0;
good_action = 1;
}
// rjf: byte digit -> cell value insertion. if first digit, store, if 2nd, commit
if(edit_mode && evt->string.size != 0 && evt->kind == UI_EventKind_Text)
{
good_action = 1;
if(!mv->cell_value_edit_in_progress)
{
mv->cell_value_edit_in_progress = 1;
mv->cell_value_edit_first_digit = evt->string.str[0];
}
else
{
U8 digits[] = {mv->cell_value_edit_first_digit, evt->string.str[0]};
String8 byte_string = str8(digits, 2);
U8 byte_value = (U8)u64_from_str8(byte_string, 16);
if(!e_space_write(eval.space, &byte_value, r1u64(cursor_base_vaddr, cursor_base_vaddr+1)))
{
log_user_errorf("Could not successfully write to memory.");
}
cell_delta.x = 1;
mv->cell_value_edit_in_progress = 0;
}
}
// rjf: determine cell movement delta from cell-granularity operations
if(allow_cell_movement) switch(evt->delta_unit)
{ {
default:{}break; default:{}break;
case UI_EventDeltaUnit_Char: case UI_EventDeltaUnit_Char:
{ {
cell_delta.x = (S64)evt->delta_2s32.x; cell_delta.x = (S64)evt->delta_2s32.x * cursor_size;
cell_delta.y = (S64)evt->delta_2s32.y; cell_delta.y = (S64)evt->delta_2s32.y;
}break; }break;
case UI_EventDeltaUnit_Word: case UI_EventDeltaUnit_Word:
{
if(evt->delta_2s32.x < 0)
{
cell_delta.x = -cursor_size;
}
else if(evt->delta_2s32.x > 0)
{
cell_delta.x = +cursor_size;
}
}break;
case UI_EventDeltaUnit_Line:
case UI_EventDeltaUnit_Page: case UI_EventDeltaUnit_Page:
{ {
if(evt->delta_2s32.x < 0) if(evt->delta_2s32.x < 0)
@@ -2851,37 +2921,48 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
} }
}break; }break;
} }
B32 good_action = 0;
if(evt->delta_2s32.x != 0 || evt->delta_2s32.y != 0) // rjf: apply movements
{ {
good_action = 1; if(evt->delta_2s32.x != 0 || evt->delta_2s32.y != 0)
}
if(good_action && evt->flags & UI_EventFlag_ZeroDeltaOnSelect && cursor_base_vaddr != mark_base_vaddr)
{
MemoryZeroStruct(&cell_delta);
}
if(good_action)
{
cell_delta.x = ClampBot(cell_delta.x, (S64)-next_cursor_base_vaddr);
cell_delta.y = ClampBot(cell_delta.y, (S64)-(next_cursor_base_vaddr/num_columns));
next_cursor_base_vaddr += cell_delta.x;
next_cursor_base_vaddr += cell_delta.y*num_columns;
}
if(good_action && evt->flags & UI_EventFlag_PickSelectSide && cursor_base_vaddr != mark_base_vaddr)
{
if(evt->delta_2s32.x < 0 || evt->delta_2s32.y < 0)
{ {
next_cursor_base_vaddr = Min(cursor_base_vaddr, mark_base_vaddr); good_action = 1;
} }
else if(good_action && evt->flags & UI_EventFlag_ZeroDeltaOnSelect && cursor_base_vaddr != mark_base_vaddr)
{ {
next_cursor_base_vaddr = Max(cursor_base_vaddr, mark_base_vaddr); MemoryZeroStruct(&cell_delta);
}
if(good_action)
{
cell_delta.x = ClampBot(cell_delta.x, (S64)-next_cursor_base_vaddr);
cell_delta.y = ClampBot(cell_delta.y, (S64)-(next_cursor_base_vaddr/num_columns));
next_cursor_base_vaddr += cell_delta.x;
next_cursor_base_vaddr += cell_delta.y*num_columns;
}
if(good_action && evt->flags & UI_EventFlag_PickSelectSide && cursor_base_vaddr != mark_base_vaddr)
{
if(evt->delta_2s32.x < 0 || evt->delta_2s32.y < 0)
{
next_cursor_base_vaddr = Min(cursor_base_vaddr, mark_base_vaddr);
}
else
{
next_cursor_base_vaddr = Max(cursor_base_vaddr, mark_base_vaddr);
}
}
if(good_action && !(evt->flags & UI_EventFlag_KeepMark))
{
next_mark_base_vaddr = next_cursor_base_vaddr;
} }
} }
if(good_action && !(evt->flags & UI_EventFlag_KeepMark))
// rjf: abort cell editing on address changes
if(next_cursor_base_vaddr != cursor_base_vaddr)
{ {
next_mark_base_vaddr = next_cursor_base_vaddr; mv->cell_value_edit_in_progress = 0;
} }
// rjf: take event
if(good_action) if(good_action)
{ {
need_update = 1; need_update = 1;
@@ -2999,12 +3080,19 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
// //
DR_FStrList byte_fstrs[256] = {0}; DR_FStrList byte_fstrs[256] = {0};
DR_FStrList byte_fstrs_selected[256] = {0}; DR_FStrList byte_fstrs_selected[256] = {0};
DR_FStrList byte_fstrs_changed[256] = {0};
{ {
Vec4F32 selected_color = ui_color_from_name(str8_lit("text")); Vec4F32 selected_color = ui_color_from_name(str8_lit("text"));
if(edit_mode) UI_TagF("bad")
{
selected_color = ui_color_from_name(str8_lit("text"));
}
Vec4F32 full_color = {0}; Vec4F32 full_color = {0};
UI_TagF("neutral") full_color = ui_color_from_name(str8_lit("text")); UI_TagF("neutral") full_color = ui_color_from_name(str8_lit("text"));
Vec4F32 zero_color = full_color; Vec4F32 zero_color = full_color;
UI_TagF("weak") zero_color = ui_color_from_name(str8_lit("text")); UI_TagF("weak") zero_color = ui_color_from_name(str8_lit("text"));
Vec4F32 changed_color = full_color;
UI_TagF("neutral") changed_color = ui_color_from_name(str8_lit("text"));
for(U64 idx = 0; idx < ArrayCount(byte_fstrs); idx += 1) for(U64 idx = 0; idx < ArrayCount(byte_fstrs); idx += 1)
{ {
U8 byte = (U8)idx; U8 byte = (U8)idx;
@@ -3022,6 +3110,10 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, selected_color, font_size, 0, 0}}; DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, selected_color, font_size, 0, 0}};
dr_fstrs_push(scratch.arena, &byte_fstrs_selected[idx], &fstr); dr_fstrs_push(scratch.arena, &byte_fstrs_selected[idx], &fstr);
} }
{
DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, changed_color, font_size, 0, 0}};
dr_fstrs_push(scratch.arena, &byte_fstrs_changed[idx], &fstr);
}
} }
} }
@@ -3387,7 +3479,8 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBackground|
UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawDropShadow|
UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_DrawBackgroundBlur|
UI_BoxFlag_Floating, "table_header"); UI_BoxFlag_Floating|
UI_BoxFlag_Clickable, "table_header");
UI_Parent(header_box) UI_Parent(header_box)
RD_Font(RD_FontSlot_Code) RD_Font(RD_FontSlot_Code)
UI_FontSize(font_size) UI_FontSize(font_size)
@@ -3406,6 +3499,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f)); ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f));
UI_WidthFill ui_labelf("ASCII"); UI_WidthFill ui_labelf("ASCII");
} }
ui_signal_from_box(header_box);
} }
////////////////////////////// //////////////////////////////
@@ -3418,7 +3512,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
ui_set_next_fixed_y(footer_rect.y0); ui_set_next_fixed_y(footer_rect.y0);
ui_set_next_fixed_width(dim_2f32(footer_rect).x); ui_set_next_fixed_width(dim_2f32(footer_rect).x);
ui_set_next_fixed_height(dim_2f32(footer_rect).y); ui_set_next_fixed_height(dim_2f32(footer_rect).y);
footer_box = ui_build_box_from_stringf(UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_DrawDropShadow, "footer"); 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_PrefWidth(ui_em(7.5f, 1.f)) UI_HeightFill UI_Column UI_TagF("weak") UI_PrefWidth(ui_em(7.5f, 1.f)) UI_HeightFill UI_Column UI_TagF("weak")
@@ -3450,6 +3544,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
} }
} }
} }
ui_signal_from_box(footer_box);
} }
////////////////////////////// //////////////////////////////
@@ -3629,6 +3724,10 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
UI_BoxFlags cell_flags = 0; UI_BoxFlags cell_flags = 0;
Vec4F32 cell_bg_rgba = {0}; Vec4F32 cell_bg_rgba = {0};
Vec4F32 cell_bd_rgba = ui_color_from_name(str8_lit("text")); Vec4F32 cell_bd_rgba = ui_color_from_name(str8_lit("text"));
if(edit_mode) UI_TagF("bad")
{
cell_bd_rgba = ui_color_from_name(str8_lit("text"));
}
if(global_byte_num == mouse_hover_byte_num) if(global_byte_num == mouse_hover_byte_num)
{ {
cell_flags |= UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawDropShadow; cell_flags |= UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawDropShadow;
@@ -3676,10 +3775,23 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
if(cell_bd_rgba.w != 0) { ui_set_next_border_color(cell_bd_rgba); } if(cell_bd_rgba.w != 0) { ui_set_next_border_color(cell_bd_rgba); }
if(cell_bg_rgba.w != 0) { ui_set_next_background_color(cell_bg_rgba); } if(cell_bg_rgba.w != 0) { ui_set_next_background_color(cell_bg_rgba); }
UI_Box *cell_box = ui_build_box_from_key(UI_BoxFlag_DrawText|cell_flags, ui_key_zero()); UI_Box *cell_box = ui_build_box_from_key(UI_BoxFlag_DrawText|cell_flags, ui_key_zero());
if(byte_is_selected || byte_is_changed) if(global_byte_idx == cursor_base_vaddr && mv->cell_value_edit_in_progress)
{
Vec4F32 color = {0};
UI_TagF("bad") color = ui_color_from_name(str8_lit("text"));
DR_FStrList fstrs = {0};
DR_FStr fstr = {str8f(scratch.arena, "%c", mv->cell_value_edit_first_digit), {font, font_raster_flags, color, font_size, 0, 0}};
dr_fstrs_push(scratch.arena, &fstrs, &fstr);
ui_box_equip_display_fstrs(cell_box, &fstrs);
}
else if(byte_is_selected)
{ {
ui_box_equip_display_fstrs(cell_box, &byte_fstrs_selected[byte_value]); ui_box_equip_display_fstrs(cell_box, &byte_fstrs_selected[byte_value]);
} }
else if(byte_is_changed)
{
ui_box_equip_display_fstrs(cell_box, &byte_fstrs_changed[byte_value]);
}
else else
{ {
ui_box_equip_display_fstrs(cell_box, &byte_fstrs[byte_value]); ui_box_equip_display_fstrs(cell_box, &byte_fstrs[byte_value]);
@@ -3748,7 +3860,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
} }
} }
ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f)); ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f));
UI_WidthFill UI_WidthFill UI_TextPadding(0)
{ {
MemoryZero(row_ascii_buffer, num_columns); MemoryZero(row_ascii_buffer, num_columns);
U64 num_bytes_this_row = 0; U64 num_bytes_this_row = 0;