checkpoint on unified code ctx menu & all of its operations

This commit is contained in:
Ryan Fleury
2024-06-25 16:31:31 -07:00
parent 010d5609c6
commit 6fa8af5e1a
11 changed files with 947 additions and 513 deletions
+278 -232
View File
@@ -1029,6 +1029,7 @@ df_window_open(Vec2F32 size, OS_Handle preferred_monitor, DF_CfgSrc cfg_src)
window->code_ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_code_ctx_menu_"));
window->entity_ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_entity_ctx_menu_"));
window->tab_ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_tab_ctx_menu_"));
window->code_ctx_menu_arena = arena_alloc();
window->hover_eval_arena = arena_alloc();
window->autocomp_lister_params_arena = arena_alloc();
window->free_panel = &df_g_nil_panel;
@@ -2585,13 +2586,25 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
DI_Key dbgi_key = df_dbgi_key_from_module(module);
RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, inline_unwind_index);
DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
DF_Line line = {0};
{
U64 idx = 0;
for(DF_LineNode *n = lines.first; n != 0; n = n->next, idx += 1)
{
line = n->v;
if(idx == inline_unwind_index)
{
break;
}
}
}
// rjf: snap to resolved line
B32 missing_rip = (rip_vaddr == 0);
B32 dbgi_missing = (dbgi_key.min_timestamp == 0 || dbgi_key.path.size == 0);
B32 dbgi_pending = !dbgi_missing && rdi == &di_rdi_parsed_nil;
B32 has_line_info = (line_info.voff_range.max != line_info.voff_range.min);
B32 has_line_info = (line.voff_range.max != line.voff_range.min);
B32 has_module = !df_entity_is_nil(module);
B32 has_dbg_info = has_module && !dbgi_missing;
if(!dbgi_pending && (has_line_info || has_module))
@@ -2599,8 +2612,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
DF_CmdParams params = df_cmd_params_from_window(ws);
if(has_line_info)
{
params.file_path = df_full_path_from_entity(scratch.arena, line_info.file);
params.text_point = line_info.pt;
params.file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(line.file));
params.text_point = line.pt;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_FilePath);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_TextPoint);
}
@@ -2783,28 +2796,31 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
// rjf: name resolved to voff * dbg info
if(name_resolved != 0 && voff != 0)
{
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff, 0);
DF_CmdParams p = params;
DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &voff_dbgi_key, voff);
if(lines.first != 0)
{
p.file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file);
p.text_point = dasm2src_info.pt;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_FilePath);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_TextPoint);
if(voff_dbgi_key.path.size != 0)
DF_CmdParams p = params;
{
DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &voff_dbgi_key);
DF_Entity *module = df_first_entity_from_list(&modules);
DF_Entity *process = df_entity_ancestor_from_kind(module, DF_EntityKind_Process);
if(!df_entity_is_nil(process))
p.file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file));
p.text_point = lines.first->v.pt;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_FilePath);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_TextPoint);
if(voff_dbgi_key.path.size != 0)
{
p.entity = df_handle_from_entity(process);
p.vaddr = module->vaddr_rng.min + dasm2src_info.voff_range.min;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_VirtualAddr);
DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &voff_dbgi_key);
DF_Entity *module = df_first_entity_from_list(&modules);
DF_Entity *process = df_entity_ancestor_from_kind(module, DF_EntityKind_Process);
if(!df_entity_is_nil(process))
{
p.entity = df_handle_from_entity(process);
p.vaddr = module->vaddr_rng.min + lines.first->v.voff_range.min;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_VirtualAddr);
}
}
}
df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
}
df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
}
// rjf: name resolved to a file
@@ -3694,9 +3710,154 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
UI_PrefWidth(ui_em(30.f, 1.f))
DF_Palette(DF_PaletteCode_ImplicitButton)
{
ui_buttonf("Foo");
ui_buttonf("Bar");
ui_buttonf("Baz");
TXT_Scope *txt_scope = txt_scope_open();
HS_Scope *hs_scope = hs_scope_open();
DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_window(ws);
TxtRng range = ws->code_ctx_menu_range;
DF_LineList lines = ws->code_ctx_menu_lines;
if(!txt_pt_match(range.min, range.max) && ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Copy))))
{
U128 hash = {0};
TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, ws->code_ctx_menu_text_key, ws->code_ctx_menu_lang_kind, &hash);
String8 data = hs_data_from_hash(hs_scope, hash);
String8 copy_data = txt_string_from_info_data_txt_rng(&info, data, ws->code_ctx_menu_range);
os_set_clipboard_text(copy_data);
ui_ctx_menu_close();
}
if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_RightArrow, 0, "Move Thread Here")))
{
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
U64 new_rip_vaddr = ws->code_ctx_menu_vaddr;
if(!df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file)))
{
for(DF_LineNode *n = lines.first; n != 0; n = n->next)
{
DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &n->v.dbgi_key);
DF_Entity *module = df_module_from_thread_candidates(thread, &modules);
if(!df_entity_is_nil(module))
{
new_rip_vaddr = df_vaddr_from_voff(module, n->v.voff_range.min);
break;
}
}
}
DF_CmdParams p = df_cmd_params_from_window(ws);
p.entity = df_handle_from_entity(thread);
p.vaddr = new_rip_vaddr;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetThreadIP));
ui_ctx_menu_close();
}
if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_Play, 0, "Run To Line")))
{
if(!df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file)))
{
DF_CmdParams p = df_cmd_params_from_window(ws);
p.entity = ws->code_ctx_menu_file;
p.text_point = range.min;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_RunToLine));
}
else
{
DF_CmdParams p = df_cmd_params_from_window(ws);
p.vaddr = ws->code_ctx_menu_vaddr;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_RunToAddress));
}
ui_ctx_menu_close();
}
if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_Null, 0, "Go To Name")))
{
U128 hash = {0};
TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, ws->code_ctx_menu_text_key, ws->code_ctx_menu_lang_kind, &hash);
String8 data = hs_data_from_hash(hs_scope, hash);
Rng1U64 expr_off_range = {0};
if(range.min.column != range.max.column)
{
expr_off_range = r1u64(txt_off_from_info_pt(&info, range.min), txt_off_from_info_pt(&info, range.max));
}
else
{
expr_off_range = txt_expr_off_range_from_info_data_pt(&info, data, range.min);
}
String8 expr = str8_substr(data, expr_off_range);
DF_CmdParams p = df_cmd_params_from_window(ws);
p.string = expr;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_GoToName));
ui_ctx_menu_close();
}
if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_CircleFilled, 0, "Toggle Breakpoint")))
{
if(ws->code_ctx_menu_vaddr != 0)
{
DF_CmdParams p = df_cmd_params_from_window(ws);
p.vaddr = ws->code_ctx_menu_vaddr;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_AddressBreakpoint));
}
else
{
DF_CmdParams p = df_cmd_params_from_window(ws);
p.entity = ws->code_ctx_menu_file;
p.text_point = range.min;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_TextBreakpoint));
}
ui_ctx_menu_close();
}
if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_Binoculars, 0, "Toggle Watch Expression")))
{
U128 hash = {0};
TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, ws->code_ctx_menu_text_key, ws->code_ctx_menu_lang_kind, &hash);
String8 data = hs_data_from_hash(hs_scope, hash);
Rng1U64 expr_off_range = {0};
if(range.min.column != range.max.column)
{
expr_off_range = r1u64(txt_off_from_info_pt(&info, range.min), txt_off_from_info_pt(&info, range.max));
}
else
{
expr_off_range = txt_expr_off_range_from_info_data_pt(&info, data, range.min);
}
String8 expr = str8_substr(data, expr_off_range);
DF_CmdParams p = df_cmd_params_from_window(ws);
p.string = expr;
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ToggleWatchExpression));
ui_ctx_menu_close();
}
if(df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file)) && range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_FileOutline, 0, "Go To Source")))
{
if(lines.first != 0)
{
DF_CmdParams params = df_cmd_params_from_window(ws);
params.file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file));
params.text_point = lines.first->v.pt;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_FilePath);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_TextPoint);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
}
ui_ctx_menu_close();
}
if(!df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file)) && range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_FileOutline, 0, "Go To Disassembly")))
{
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
U64 vaddr = 0;
for(DF_LineNode *n = lines.first; n != 0; n = n->next)
{
DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &n->v.dbgi_key);
DF_Entity *module = df_module_from_thread_candidates(thread, &modules);
if(!df_entity_is_nil(module))
{
vaddr = df_vaddr_from_voff(module, n->v.voff_range.min);
break;
}
}
DF_CmdParams params = df_cmd_params_from_window(ws);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_VirtualAddr);
params.entity = df_handle_from_entity(thread);
params.vaddr = vaddr;
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
ui_ctx_menu_close();
}
hs_scope_close(hs_scope);
txt_scope_close(txt_scope);
}
//- rjf: entity menu
@@ -10607,7 +10768,7 @@ internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions)
}
internal DF_CodeSliceSignal
df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string)
df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string)
{
DF_CodeSliceSignal result = {0};
ProfBeginFunction();
@@ -10674,82 +10835,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
}
}
//////////////////////////////
//- rjf: build per-line context menus
//
UI_Key *ctx_menu_keys = push_array(scratch.arena, UI_Key, dim_1s64(params->line_num_range)+1);
{
U64 line_idx = 0;
for(S64 line_num = params->line_num_range.min;
line_num < params->line_num_range.max;
line_num += 1, line_idx += 1)
{
ctx_menu_keys[line_idx] = ui_key_from_stringf(top_container_box->key, "line_ctx_%I64d", line_num);
DF_Palette(DF_PaletteCode_Floating)
UI_CtxMenu(ctx_menu_keys[line_idx])
DF_Palette(DF_PaletteCode_ImplicitButton)
UI_PrefWidth(ui_em(37.f, 1.f))
{
DF_TextLineSrc2DasmInfoList *line_src2dasm_list = &params->line_src2dasm[line_idx];
DF_TextLineDasm2SrcInfoList *line_dasm2src_list = &params->line_dasm2src[line_idx];
//- rjf: copy selection
if(!txt_pt_match(*cursor, *mark) && ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Copy))))
{
result.copy_range = txt_rng(*cursor, *mark);
ui_ctx_menu_close();
}
//- rjf: watch selection
if(ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ToggleWatchExpressionAtCursor))))
{
result.toggle_cursor_watch = 1;
ui_ctx_menu_close();
}
//- rjf: set-next-statement
if(ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetNextStatement))))
{
result.set_next_statement_line_num = line_num;
ui_ctx_menu_close();
}
//- rjf: run-to-line
if(ui_clicked(df_icon_buttonf(DF_IconKind_Play, 0, "Run To Line")))
{
result.run_to_line_num = line_num;
ui_ctx_menu_close();
}
//- rjf: breakpoint placing
if((params->line_bps[line_idx].count == 0 &&
ui_clicked(df_icon_buttonf(DF_IconKind_CircleFilled, 0, "Place Breakpoint"))) ||
(params->line_bps[line_idx].count != 0 &&
ui_clicked(df_icon_buttonf(DF_IconKind_CircleFilled, 0, "Remove Breakpoint"))))
{
result.clicked_margin_line_num = line_num;
ui_ctx_menu_close();
}
//- rjf: go from src -> disasm
if(line_src2dasm_list->first != 0 &&
ui_clicked(df_icon_buttonf(DF_IconKind_Find, 0, "Go To Disassembly")))
{
result.goto_disasm_line_num = line_num;
ui_ctx_menu_close();
}
//- rjf: go from disasm -> src
if(line_dasm2src_list->first != 0 &&
ui_clicked(df_icon_buttonf(DF_IconKind_Find, 0, "Go To Source")))
{
result.goto_src_line_num = line_num;
ui_ctx_menu_close();
}
}
}
}
//////////////////////////////
//- rjf: build priority margin
//
@@ -10851,23 +10936,21 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
// rjf: fill out progress t (progress into range of current line's
// voff range)
if(params->line_src2dasm[line_idx].first != 0)
if(params->line_infos[line_idx].first != 0)
{
DF_TextLineSrc2DasmInfoList *line_info_list = &params->line_src2dasm[line_idx];
DF_TextLineSrc2DasmInfo *line_info = 0;
for(DF_TextLineSrc2DasmInfoNode *n = line_info_list->first;
n != 0;
n = n->next)
DF_LineList *lines = &params->line_infos[line_idx];
DF_Line *line = 0;
for(DF_LineNode *n = lines->first; n != 0; n = n->next)
{
if(di_key_match(&n->v.dbgi_key, &dbgi_key))
{
line_info = &n->v;
line = &n->v;
break;
}
}
if(line_info != 0)
if(line != 0)
{
Rng1U64 line_voff_rng = line_info->voff_range;
Rng1U64 line_voff_rng = line->voff_range;
Vec4F32 weak_thread_color = color;
weak_thread_color.w *= 0.4f;
F32 progress_t = (line_voff_rng.max != line_voff_rng.min) ? ((F32)(thread_rip_voff - line_voff_rng.min) / (F32)(line_voff_rng.max - line_voff_rng.min)) : 0;
@@ -11008,23 +11091,21 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
// rjf: fill out progress t (progress into range of current line's
// voff range)
if(params->line_src2dasm[line_idx].first != 0)
if(code_ctx->file != &df_g_nil_entity && params->line_infos[line_idx].first != 0)
{
DF_TextLineSrc2DasmInfoList *line_info_list = &params->line_src2dasm[line_idx];
DF_TextLineSrc2DasmInfo *line_info = 0;
for(DF_TextLineSrc2DasmInfoNode *n = line_info_list->first;
n != 0;
n = n->next)
DF_LineList *lines = &params->line_infos[line_idx];
DF_Line *line = 0;
for(DF_LineNode *n = lines->first; n != 0; n = n->next)
{
if(di_key_match(&n->v.dbgi_key, &dbgi_key))
{
line_info = &n->v;
line = &n->v;
break;
}
}
if(line_info != 0)
if(line != 0)
{
Rng1U64 line_voff_rng = line_info->voff_range;
Rng1U64 line_voff_rng = line->voff_range;
Vec4F32 weak_thread_color = color;
weak_thread_color.w *= 0.4f;
F32 progress_t = (line_voff_rng.max != line_voff_rng.min) ? ((F32)(thread_rip_voff - line_voff_rng.min) / (F32)(line_voff_rng.max - line_voff_rng.min)) : 0;
@@ -11086,17 +11167,20 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
DF_BreakpointBoxDrawExtData *bp_draw = push_array(ui_build_arena(), DF_BreakpointBoxDrawExtData, 1);
{
bp_draw->color = bp_color;
DF_TextLineSrc2DasmInfoList *src2dasm_list = &params->line_src2dasm[line_idx];
for(DF_TextLineSrc2DasmInfoNode *n = src2dasm_list->first; n != 0; n = n->next)
bp_draw->alive_t = bp->alive_t;
if(code_ctx->file != &df_g_nil_entity)
{
S64 remap_line = (S64)n->v.remap_line;
if(remap_line != line_num)
DF_LineList *lines = &params->line_infos[line_idx];
for(DF_LineNode *n = lines->first; n != 0; n = n->next)
{
bp_draw->remap_px_delta = (remap_line - line_num) * params->line_height_px;
break;
S64 remap_line = n->v.pt.line;
if(remap_line != line_num)
{
bp_draw->remap_px_delta = (remap_line - line_num) * params->line_height_px;
break;
}
}
}
bp_draw->alive_t = bp->alive_t;
}
// rjf: build box for breakpoint
@@ -11248,33 +11332,17 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
// rjf: line info on this line -> adjust bg color to visualize
B32 has_line_info = 0;
{
U64 best_stamp = 0;
S64 line_info_line_num = 0;
F32 line_info_t = 0;
DF_TextLineSrc2DasmInfoList *src2dasm_list = &params->line_src2dasm[line_idx];
DF_TextLineDasm2SrcInfoList *dasm2src_list = &params->line_dasm2src[line_idx];
if(src2dasm_list->first != 0)
F32 line_info_t = selected_thread_module->alive_t;
DF_LineList *lines = &params->line_infos[line_idx];
for(DF_LineNode *n = lines->first; n != 0; n = n->next)
{
has_line_info = (src2dasm_list->first->v.remap_line == line_num);
line_info_line_num = line_num;
line_info_t = selected_thread_module->alive_t;
}
if(dasm2src_list->first != 0)
{
DF_TextLineDasm2SrcInfo *dasm2src_info = 0;
U64 best_stamp = 0;
for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next)
if(n->v.dbgi_key.min_timestamp >= best_stamp)
{
if(n->v.file->timestamp > best_stamp)
{
dasm2src_info = &n->v;
best_stamp = n->v.file->timestamp;
}
}
if(dasm2src_info != 0)
{
has_line_info = 1;
line_info_line_num = dasm2src_info->pt.line;
line_info_t = selected_thread_module->alive_t;
has_line_info = (n->v.pt.line == line_num || code_ctx->file == &df_g_nil_entity);
line_info_line_num = n->v.pt.line;
best_stamp = n->v.dbgi_key.min_timestamp;
}
}
if(has_line_info)
@@ -11575,42 +11643,26 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
*preferred_column = cursor->column;
}
//- rjf: right-click => active context menu for line
//- rjf: right-click => code context menu
if(ui_right_clicked(text_container_sig))
{
S64 line_idx = mouse_pt.line-params->line_num_range.min;
if(0 <= line_idx && line_idx < dim_1s64(params->line_num_range))
if(txt_pt_match(*cursor, *mark))
{
ui_ctx_menu_open(ctx_menu_keys[line_idx], ui_key_zero(), sub_2f32(ui_mouse(), v2f32(2, 2)));
if(txt_pt_match(*cursor, *mark))
{
*cursor = *mark = mouse_pt;
}
*cursor = *mark = mouse_pt;
}
}
//- rjf: hovering text container & ctrl+scroll -> change font size
if(ui_hovering(text_container_sig))
{
UI_EventList *events = ui_events();
for(UI_EventNode *n = events->first, *next = 0; n != 0; n = next)
ui_ctx_menu_open(ws->code_ctx_menu_key, ui_key_zero(), sub_2f32(ui_mouse(), v2f32(2, 2)));
arena_clear(ws->code_ctx_menu_arena);
ws->code_ctx_menu_file = df_handle_from_entity(code_ctx->file);
ws->code_ctx_menu_text_key = code_ctx->text_key;
ws->code_ctx_menu_lang_kind = code_ctx->lang_kind;
ws->code_ctx_menu_range = txt_rng(*cursor, *mark);
if(params->line_num_range.min <= cursor->line && cursor->line < params->line_num_range.max)
{
next = n->next;
UI_Event *event = &n->v;
if(event->kind == UI_EventKind_Scroll && event->modifiers & OS_EventFlag_Ctrl)
{
ui_eat_event(events, n);
if(event->delta_2f32.y < 0)
{
DF_CmdParams params = df_cmd_params_from_window(ws);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_IncCodeFontScale));
}
else if(event->delta_2f32.y > 0)
{
DF_CmdParams params = df_cmd_params_from_window(ws);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_DecCodeFontScale));
}
}
ws->code_ctx_menu_vaddr = params->line_vaddrs[cursor->line - params->line_num_range.min];
}
if(params->line_num_range.min <= cursor->line && cursor->line < params->line_num_range.max)
{
ws->code_ctx_menu_lines = df_line_list_copy(ws->code_ctx_menu_arena, &params->line_infos[cursor->line - params->line_num_range.min]);
}
}
@@ -11629,6 +11681,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
}
//- rjf: drop target is dropped -> process
// TODO(rjf): @src_collapse
#if 0
{
DF_DragDropPayload payload = {0};
if(!df_entity_is_nil(line_drag_entity) && df_drag_drop(&payload))
@@ -11637,6 +11691,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
result.dropped_entity_line_num = mouse_pt.line;
}
}
#endif
//- rjf: commit text container signal to main output
result.base = text_container_sig;
@@ -11645,6 +11700,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
//////////////////////////////
//- rjf: mouse -> expression range info
//
TxtRng mouse_expr_rng = {0};
Vec2F32 mouse_expr_baseline_pos = {0};
if(ui_hovering(text_container_sig) && contains_1s64(params->line_num_range, mouse_pt.line)) ProfScope("mouse -> expression range")
{
TxtRng selected_rng = txt_rng(*cursor, *mark);
@@ -11655,9 +11712,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
U64 line_slice_idx = mouse_pt.line-params->line_num_range.min;
String8 line_text = params->line_text[line_slice_idx];
F32 expr_hoff_px = params->line_num_width_px + f_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_text, selected_rng.min.column-1)).x;
result.mouse_expr_rng = selected_rng;
result.mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px,
text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f);
result.mouse_expr_rng = mouse_expr_rng = selected_rng;
result.mouse_expr_baseline_pos = mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px,
text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f);
}
else
{
@@ -11670,9 +11727,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
if(expr_off_rng.max != expr_off_rng.min)
{
F32 expr_hoff_px = params->line_num_width_px + f_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_text, expr_off_rng.min-line_range.min)).x;
result.mouse_expr_rng = txt_rng(txt_pt(mouse_pt.line, 1+(expr_off_rng.min-line_range.min)), txt_pt(mouse_pt.line, 1+(expr_off_rng.max-line_range.min)));
result.mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px,
text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f);
result.mouse_expr_rng = mouse_expr_rng = txt_rng(txt_pt(mouse_pt.line, 1+(expr_off_rng.min-line_range.min)), txt_pt(mouse_pt.line, 1+(expr_off_rng.max-line_range.min)));
result.mouse_expr_baseline_pos = mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px,
text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f);
}
}
}
@@ -11683,29 +11740,38 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
if(ui_hovering(text_container_sig) && contains_1s64(params->line_num_range, mouse_pt.line) && (ui_mouse().x - text_container_box->rect.x0 < params->line_num_width_px + line_num_padding_px))
{
U64 line_slice_idx = mouse_pt.line-params->line_num_range.min;
if(params->line_src2dasm[line_slice_idx].first != 0 &&
params->line_src2dasm[line_slice_idx].first->v.remap_line == mouse_pt.line)
DF_LineList *lines = &params->line_infos[line_slice_idx];
if(lines->first != 0 && (code_ctx->file == &df_g_nil_entity || lines->first->v.pt.line == mouse_pt.line))
{
DF_RichHoverInfo info = {0};
info.process = df_handle_from_entity(selected_thread_process);
info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_src2dasm[line_slice_idx].first->v.voff_range);
info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, lines->first->v.voff_range);
info.module = df_handle_from_entity(selected_thread_module);
info.dbgi_key = params->line_src2dasm[line_slice_idx].first->v.dbgi_key;
info.voff_range = params->line_src2dasm[line_slice_idx].first->v.voff_range;
df_set_rich_hover_info(&info);
}
if(params->line_dasm2src[line_slice_idx].first != 0)
{
DF_RichHoverInfo info = {0};
info.process = df_handle_from_entity(selected_thread_process);
info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_dasm2src[line_slice_idx].first->v.voff_range);
info.module = df_handle_from_entity(selected_thread_module);
info.dbgi_key = params->line_dasm2src[line_slice_idx].first->v.dbgi_key;
info.voff_range = params->line_dasm2src[line_slice_idx].first->v.voff_range;
info.dbgi_key = lines->first->v.dbgi_key;
info.voff_range = lines->first->v.voff_range;
df_set_rich_hover_info(&info);
}
}
//////////////////////////////
//- rjf: hover eval
//
#if 0
if(!ui_dragging(text_container_sig) && sig.mouse_expr_rng.min.line != 0 && sig.base.event_flags == 0)
{
TxtRng expr_rng = mouse_expr_rng;
String8 expr = txt_string_from_info_data_txt_rng(&text_info, data, expr_rng);
if(expr.size != 0)
{
DF_Eval eval = df_eval_from_string(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
if(eval.mode != EVAL_EvalMode_NULL)
{
df_set_hover_eval(ws, mouse_expr_baseline_pos, ctrl_ctx, entity, sig.mouse_pt, 0, expr);
}
}
}
#endif
//////////////////////////////
//- rjf: dragging entity which applies to lines over this slice -> visualize
//
@@ -12048,37 +12114,16 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
{
B32 matches = 0;
S64 line_info_line_num = 0;
DF_TextLineSrc2DasmInfoList *src2dasm_list = &params->line_src2dasm[line_idx];
DF_TextLineDasm2SrcInfoList *dasm2src_list = &params->line_dasm2src[line_idx];
// rjf: check src2dasm
if(src2dasm_list->first != 0)
DF_LineList *lines = &params->line_infos[line_idx];
for(DF_LineNode *n = lines->first; n != 0; n = n->next)
{
for(DF_TextLineSrc2DasmInfoNode *n = src2dasm_list->first; n != 0; n = n->next)
if((n->v.pt.line == line_num || code_ctx->file == &df_g_nil_entity) &&
di_key_match(&n->v.dbgi_key, &hovered_line_dbgi_key) &&
n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max)
{
if(n->v.remap_line == line_num &&
di_key_match(&n->v.dbgi_key, &hovered_line_dbgi_key) &&
n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max)
{
matches = 1;
line_info_line_num = line_num;
break;
}
}
}
// rjf: check dasm2src
if(dasm2src_list->first != 0)
{
for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next)
{
if(n->v.voff_range.min <= hovered_line_voff &&
hovered_line_voff < n->v.voff_range.max)
{
line_info_line_num = n->v.pt.line;
matches = 1;
break;
}
matches = 1;
line_info_line_num = n->v.pt.line;
break;
}
}
@@ -12108,13 +12153,13 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
}
internal DF_CodeSliceSignal
df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...)
df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, params, cursor, mark, preferred_column, string);
DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, code_ctx, params, cursor, mark, preferred_column, string);
va_end(args);
scratch_end(scratch);
return sig;
@@ -13414,6 +13459,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
r_window_unequip(ws->os, ws->r);
os_window_close(ws->os);
arena_release(ws->query_cmd_arena);
arena_release(ws->code_ctx_menu_arena);
arena_release(ws->hover_eval_arena);
arena_release(ws->autocomp_lister_params_arena);
arena_release(ws->arena);
+18 -5
View File
@@ -432,6 +432,14 @@ enum
DF_CodeSliceFlag_LineNums = (1<<3),
};
typedef struct DF_CodeCtx DF_CodeCtx;
struct DF_CodeCtx
{
DF_Entity *file; // the source file, if any, from which the code was derived
U128 text_key; // the text info cache key for the backing textual data
TXT_LangKind lang_kind; // the language for which the text is parsed/analyzed
};
typedef struct DF_CodeSliceParams DF_CodeSliceParams;
struct DF_CodeSliceParams
{
@@ -444,8 +452,8 @@ struct DF_CodeSliceParams
DF_EntityList *line_bps;
DF_EntityList *line_ips;
DF_EntityList *line_pins;
DF_TextLineDasm2SrcInfoList *line_dasm2src;
DF_TextLineSrc2DasmInfoList *line_src2dasm;
U64 *line_vaddrs;
DF_LineList *line_infos;
DI_KeyList relevant_dbgi_keys;
// rjf: visual parameters
@@ -570,10 +578,14 @@ struct DF_Window
B32 menu_bar_focus_press_started;
// rjf: code context menu state
Arena *code_ctx_menu_arena;
UI_Key code_ctx_menu_key;
DF_Handle code_ctx_menu_entity;
DF_Handle code_ctx_menu_file;
U128 code_ctx_menu_text_key;
TXT_LangKind code_ctx_menu_lang_kind;
TxtRng code_ctx_menu_range;
U64 code_ctx_menu_vaddr;
DF_LineList code_ctx_menu_lines;
// rjf: entity context menu state
UI_Key entity_ctx_menu_key;
@@ -620,6 +632,7 @@ struct DF_Window
Vec2F32 hover_eval_spawn_pos;
String8 hover_eval_string;
// rjf: hover eval timer
U64 hover_eval_first_frame_idx;
U64 hover_eval_last_frame_idx;
@@ -1071,8 +1084,8 @@ internal void df_entity_src_loc_button(DF_Window *ws, DF_Entity *entity, TxtPt p
internal UI_BOX_CUSTOM_DRAW(df_thread_box_draw_extensions);
internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions);
internal DF_CodeSliceSignal df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string);
internal DF_CodeSliceSignal df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...);
internal DF_CodeSliceSignal df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string);
internal DF_CodeSliceSignal df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...);
internal B32 df_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column);
internal B32 df_do_txti_controls(TXTI_Handle handle, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column);
+12 -8
View File
@@ -537,9 +537,10 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
String8 data = {0};
TXT_TextInfo info = {0};
TXT_LineTokensSlice line_tokens_slice = {0};
U128 text_key = {0};
{
U128 text_hash = {0};
U128 text_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1);
text_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1);
info = txt_text_info_from_key_lang(txt_scope, text_key, top.lang, &text_hash);
data = hs_data_from_hash(hs_scope, text_hash);
line_tokens_slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, &info, data, r1s64(1, info.lines_count));
@@ -558,8 +559,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, info.lines_count);
code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, info.lines_count);
code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, info.lines_count);
code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, info.lines_count);
code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, info.lines_count);
code_slice_params.line_vaddrs = push_array(scratch.arena, U64, info.lines_count);
code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, info.lines_count);
for(U64 line_idx = 0; line_idx < info.lines_count; line_idx += 1)
{
code_slice_params.line_text[line_idx] = str8_substr(data, info.lines_ranges[line_idx]);
@@ -591,7 +592,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
//- rjf: build code slice
UI_WidthFill UI_HeightFill UI_Parent(container)
{
DF_CodeSliceSignal slice_sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###slice"));
DF_CodeCtx code_ctx = {&df_g_nil_entity, text_key, top.lang};
DF_CodeSliceSignal slice_sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###slice"));
}
}
@@ -697,11 +699,12 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm)
DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &data_hash);
String8 dasm_text_data = {0};
TXT_TextInfo dasm_text_info = {0};
TXT_LangKind lang_kind = TXT_LangKind_DisasmX64Intel;
for(U64 rewind_idx = 0; rewind_idx < 2; rewind_idx += 1)
{
U128 dasm_text_hash = hs_hash_from_key(dasm_info.text_key, rewind_idx);
dasm_text_data = hs_data_from_hash(hs_scope, dasm_text_hash);
dasm_text_info = txt_text_info_from_hash_lang(txt_scope, dasm_text_hash, TXT_LangKind_DisasmX64Intel);
dasm_text_info = txt_text_info_from_hash_lang(txt_scope, dasm_text_hash, lang_kind);
if(dasm_text_info.lines_count != 0)
{
break;
@@ -720,8 +723,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm)
code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, dasm_text_info.lines_count);
code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, dasm_text_info.lines_count);
code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, dasm_text_info.lines_count);
code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, dasm_text_info.lines_count);
code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, dasm_text_info.lines_count);
code_slice_params.line_vaddrs = push_array(scratch.arena, U64, dasm_text_info.lines_count);
code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, dasm_text_info.lines_count);
for(U64 line_idx = 0; line_idx < dasm_text_info.lines_count; line_idx += 1)
{
code_slice_params.line_text[line_idx] = str8_substr(dasm_text_data, dasm_info.insts.v[line_idx].text_range);
@@ -742,7 +745,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm)
if(dasm_info.insts.count != 0 && dasm_text_info.lines_count != 0)
UI_Padding(ui_pct(1, 0)) UI_PrefWidth(ui_px(dasm_text_info.lines_max_size*ui_top_font_size()*1.2f, 1.f)) UI_Column UI_Padding(ui_pct(1, 0))
{
DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###code_slice"));
DF_CodeCtx code_ctx = {&df_g_nil_entity, dasm_info.text_key, lang_kind};
DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###code_slice"));
}
}
dasm_scope_close(dasm_scope);
+238 -58
View File
@@ -387,7 +387,7 @@ df_code_view_init(DF_CodeViewState *cv, DF_View *view)
}
internal void
df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info)
df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx)
{
for(DF_CmdNode *n = cmds->first; n != 0; n = n->next)
{
@@ -499,7 +499,7 @@ df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewStat
}
internal void
df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info)
df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
@@ -603,8 +603,8 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, visible_line_count);
code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, visible_line_count);
code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count);
code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, visible_line_count);
code_slice_params.font = code_font;
code_slice_params.font_size = code_font_size;
code_slice_params.tab_size = code_tab_size;
@@ -627,6 +627,73 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
code_slice_params.line_tokens[visible_line_idx] = slice.line_tokens[visible_line_idx];
}
}
// rjf: find visible breakpoints
ProfScope("find visible breakpoints")
{
for(DF_Entity *bp = code_ctx->file->first; !df_entity_is_nil(bp); bp = bp->next)
{
if(bp->deleted || bp->kind != DF_EntityKind_Breakpoint) { continue; }
if(visible_line_num_range.min <= bp->text_point.line && bp->text_point.line <= visible_line_num_range.max)
{
U64 slice_line_idx = (bp->text_point.line-visible_line_num_range.min);
df_entity_list_push(scratch.arena, &code_slice_params.line_bps[slice_line_idx], bp);
}
}
}
// rjf: find live threads mapping to this file
ProfScope("find live threads mapping to this file")
{
DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread);
DF_EntityList threads = df_query_cached_entity_list_with_kind(DF_EntityKind_Thread);
for(DF_EntityNode *thread_n = threads.first; thread_n != 0; thread_n = thread_n->next)
{
DF_Entity *thread = thread_n->entity;
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
U64 base_unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0;
U64 inline_unwind_count = (thread == selected_thread) ? ctrl_ctx.inline_unwind_count : 0;
U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
U64 last_inst_on_unwound_rip_vaddr = rip_vaddr - !!unwind_count;
DF_Entity *module = df_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr);
U64 rip_voff = df_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
for(DF_LineNode *n = lines.first; n != 0; n = n->next)
{
if(df_entity_from_handle(n->v.file) == code_ctx->file && visible_line_num_range.min <= n->v.pt.line && n->v.pt.line <= visible_line_num_range.max)
{
U64 slice_line_idx = lines.first->v.pt.line-visible_line_num_range.min;
df_entity_list_push(scratch.arena, &code_slice_params.line_ips[slice_line_idx], thread);
}
}
}
}
// rjf: find visible watch pins
ProfScope("find visible watch pins")
{
for(DF_Entity *wp = code_ctx->file->first; !df_entity_is_nil(wp); wp = wp->next)
{
if(wp->deleted || wp->kind != DF_EntityKind_WatchPin) { continue; }
if(visible_line_num_range.min <= wp->text_point.line && wp->text_point.line <= visible_line_num_range.max)
{
U64 slice_line_idx = (wp->text_point.line-visible_line_num_range.min);
df_entity_list_push(scratch.arena, &code_slice_params.line_pins[slice_line_idx], wp);
}
}
}
// rjf: find all src -> dasm info
ProfScope("find all src -> dasm info")
{
DF_LineListArray lines_array = df_lines_array_from_file_line_range(scratch.arena, code_ctx->file, visible_line_num_range);
if(lines_array.count != 0)
{
MemoryCopy(code_slice_params.line_infos, lines_array.v, sizeof(DF_LineList)*lines_array.count);
}
code_slice_params.relevant_dbgi_keys = lines_array.dbgi_keys;
}
}
//////////////////////////////
@@ -819,7 +886,7 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
DF_CodeSliceSignal sig = {0};
UI_Focus(UI_FocusKind_On)
{
sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, &code_slice_params, &cv->cursor, &cv->mark, &cv->preferred_column, "txt_view_%p", view);
sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, code_ctx, &code_slice_params, &cv->cursor, &cv->mark, &cv->preferred_column, "txt_view_%p", view);
}
//- rjf: press code slice? -> focus panel
@@ -852,13 +919,6 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_GoToName));
}
//- rjf: copy text
if(!txt_pt_match(sig.copy_range.min, sig.copy_range.max))
{
String8 text = txt_string_from_info_data_txt_rng(info, data, sig.copy_range);
os_set_clipboard_text(text);
}
//- rjf: selected text on single line, no query? -> set search text
if(!txt_pt_match(cv->cursor, cv->mark) && cv->cursor.line == cv->mark.line && search_query.size == 0)
{
@@ -866,22 +926,9 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
df_set_search_string(text);
}
//- rjf: toggle cursor watch
if(sig.toggle_cursor_watch)
{
DF_CmdParams params = df_cmd_params_from_view(ws, panel, view);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ToggleWatchExpressionAtCursor));
}
//- rjf: set next statement
if(sig.set_next_statement_line_num != 0 && contains_1s64(visible_line_num_range, sig.set_next_statement_line_num))
{
DF_CmdParams params = df_cmd_params_from_view(ws, panel, view);
params.text_point = txt_pt(sig.set_next_statement_line_num, 1);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetNextStatement));
}
//- rjf: go to disasm
// TODO(rjf): @src_collapse
#if 0
if(sig.goto_disasm_line_num != 0 && contains_1s64(visible_line_num_range, sig.goto_disasm_line_num))
{
U64 line_idx = (sig.goto_disasm_line_num-visible_line_num_range.min);
@@ -911,6 +958,7 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
}
}
}
#endif
}
//////////////////////////////
@@ -1038,6 +1086,29 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta
}
ui_scroll_pt_clamp_idx(&view->scroll_pos.x, scroll_idx_rng[Axis2_X]);
ui_scroll_pt_clamp_idx(&view->scroll_pos.y, scroll_idx_rng[Axis2_Y]);
if(ui_mouse_over(sig))
{
UI_EventList *events = ui_events();
for(UI_EventNode *n = events->first, *next = 0; n != 0; n = next)
{
next = n->next;
UI_Event *event = &n->v;
if(event->kind == UI_EventKind_Scroll && event->modifiers & OS_EventFlag_Ctrl)
{
ui_eat_event(events, n);
if(event->delta_2f32.y < 0)
{
DF_CmdParams params = df_cmd_params_from_window(ws);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_IncCodeFontScale));
}
else if(event->delta_2f32.y > 0)
{
DF_CmdParams params = df_cmd_params_from_window(ws);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_DecCodeFontScale));
}
}
}
}
}
txt_scope_close(txt_scope);
@@ -4076,15 +4147,15 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
}
if(ui_hovering(sig)) UI_Tooltip
{
U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name);
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff, 0);
String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file);
S64 line_num = dasm2src_info.pt.line;
df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeSymbol), name);
UI_Font(df_font_from_slot(DF_FontSlot_Main)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak)
ui_labelf("Procedure #%I64u", item->idx);
if(!df_entity_is_nil(dasm2src_info.file))
U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name);
DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, binary_voff);
if(lines.first != 0)
{
String8 file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file));
S64 line_num = lines.first->v.pt.line;
UI_Font(df_font_from_slot(DF_FontSlot_Main)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak)
ui_labelf("%S:%I64d", file_path, line_num);
}
@@ -5460,10 +5531,14 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler)
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, 0);
if(!df_entity_is_nil(line_info.file))
DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
if(lines.first != 0)
{
UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, line_info.file, line_info.pt);
DF_Entity *file = df_entity_from_handle(lines.first->v.file);
if(!df_entity_is_nil(file))
{
UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, file, lines.first->v.pt);
}
}
}
}break;
@@ -6191,7 +6266,7 @@ DF_VIEW_UI_FUNCTION_DEF(PendingEntity)
////////////////////////////////
//~ rjf: Code @view_hook_impl
#if 0
#if 1
DF_VIEW_SETUP_FUNCTION_DEF(Code)
{
// rjf: set up state
@@ -6229,13 +6304,15 @@ DF_VIEW_CMD_FUNCTION_DEF(Code)
Temp scratch = scratch_begin(0, 0);
HS_Scope *hs_scope = hs_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
String8 path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(view->entity));
DF_Entity *entity = df_entity_from_handle(view->entity);
String8 path = df_full_path_from_entity(scratch.arena, entity);
TXT_LangKind lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(path));
U128 key = fs_key_from_path(path);
U128 hash = {0};
TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash);
String8 data = hs_data_from_hash(hs_scope, hash);
df_code_view_cmds(ws, panel, view, cv, cmds, data, &info);
DF_CodeCtx code_ctx = {entity, key, lang_kind};
df_code_view_cmds(ws, panel, view, cv, cmds, data, &info, &code_ctx);
txt_scope_close(txt_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
@@ -6321,7 +6398,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
//
if(!entity_is_missing && key_has_data)
{
df_code_view_build(ws, panel, view, cv, code_area_rect, data, &info);
DF_CodeCtx code_ctx = {entity, key, lang_kind};
df_code_view_build(ws, panel, view, cv, code_area_rect, data, &info, &code_ctx);
}
//////////////////////////////
@@ -6377,9 +6455,9 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
}
#endif
//~ TODO(rjf): OLD vvvvvvvv
//~ TODO(rjf): OLD vvvvvvvv @src_collapse
#if 1
#if 0
DF_VIEW_SETUP_FUNCTION_DEF(Code)
{
// rjf: set up state
@@ -6744,6 +6822,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count);
code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, visible_line_count);
code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, visible_line_count);
code_slice_params.font = code_font;
@@ -7761,8 +7840,9 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
dasm_params.dbgi_key = dasm_dbgi_key;
}
DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &dasm_data_hash);
TXT_LangKind lang_kind = txt_lang_kind_from_architecture(arch);
U128 dasm_text_hash = {0};
TXT_TextInfo dasm_text_info = txt_text_info_from_key_lang(txt_scope, dasm_info.text_key, txt_lang_kind_from_architecture(arch), &dasm_text_hash);
TXT_TextInfo dasm_text_info = txt_text_info_from_key_lang(txt_scope, dasm_info.text_key, lang_kind, &dasm_text_hash);
String8 dasm_text_data = hs_data_from_hash(hs_scope, dasm_text_hash);
B32 has_disasm = (dasm_info.insts.count != 0 && dasm_text_info.lines_count != 0);
B32 is_loading = (!has_disasm && !df_entity_is_nil(process) && dim_1u64(dasm_vaddr_range) != 0);
@@ -7846,8 +7926,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, visible_line_count);
code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, visible_line_count);
code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, visible_line_count);
code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count);
code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, visible_line_count);
code_slice_params.font = code_font;
code_slice_params.font_size = code_font_size;
code_slice_params.tab_size = code_tab_size;
@@ -7858,7 +7938,6 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
code_slice_params.line_num_width_px = line_num_width_px;
code_slice_params.line_text_max_width_px = (F32)line_size_x;
code_slice_params.margin_float_off_px = view->scroll_pos.x.idx + view->scroll_pos.x.off;
di_key_list_push(scratch.arena, &code_slice_params.relevant_dbgi_keys, &dbgi_key);
// rjf: fill text info
@@ -7947,10 +8026,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
U64 vaddr = dasm_vaddr_range.min + dasm_inst_array_code_off_from_idx(&dasm_info.insts, line_num-1);
U64 voff = df_voff_from_vaddr(module, vaddr);
U64 slice_idx = line_num-visible_line_num_range.min;
DF_TextLineDasm2SrcInfoNode *dasm2src_n = push_array(scratch.arena, DF_TextLineDasm2SrcInfoNode, 1);
SLLQueuePush(code_slice_params.line_dasm2src[slice_idx].first, code_slice_params.line_dasm2src[slice_idx].last, dasm2src_n);
code_slice_params.line_dasm2src[slice_idx].count += 1;
dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0);
code_slice_params.line_vaddrs[slice_idx] = vaddr;
code_slice_params.line_infos[slice_idx] = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff);
}
}
}
@@ -8010,7 +8087,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
DF_CodeSliceSignal sig = {0};
UI_Focus(UI_FocusKind_On)
{
sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, &code_slice_params, &dv->cursor, &dv->mark, &dv->preferred_column, "dasm_slice_%p", view);
DF_CodeCtx code_ctx = {&df_g_nil_entity, dasm_info.text_key, lang_kind};
sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, &code_ctx, &code_slice_params, &dv->cursor, &dv->mark, &dv->preferred_column, "dasm_slice_%p", view);
}
//- rjf: hover eval
@@ -8129,14 +8207,17 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
DF_Entity *module = df_module_from_process_vaddr(process, vaddr);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
U64 voff = df_voff_from_vaddr(module, vaddr);
DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0);
String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src.file);
DF_CmdParams params = df_cmd_params_from_view(ws, panel, view);
params.text_point = dasm2src.pt;
params.file_path = file_path;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_TextPoint);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_FilePath);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff);
if(lines.first != 0)
{
String8 file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file));
DF_CmdParams params = df_cmd_params_from_view(ws, panel, view);
params.text_point = lines.first->v.pt;
params.file_path = file_path;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_TextPoint);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_FilePath);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
}
}
}
@@ -8485,6 +8566,103 @@ DF_VIEW_UI_FUNCTION_DEF(Procedures)
////////////////////////////////
//~ rjf: Output @view_hook_impl
#if 1
DF_VIEW_SETUP_FUNCTION_DEF(Output)
{
DF_CodeViewState *cv = df_view_user_state(view, DF_CodeViewState);
df_code_view_init(cv, view);
}
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Output)
{
return str8_zero();
}
DF_VIEW_CMD_FUNCTION_DEF(Output)
{
DF_CodeViewState *cv = df_view_user_state(view, DF_CodeViewState);
Temp scratch = scratch_begin(0, 0);
HS_Scope *hs_scope = hs_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
U128 key = df_state->output_log_key;
TXT_LangKind lang_kind = TXT_LangKind_Null;
U128 hash = {0};
TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash);
String8 data = hs_data_from_hash(hs_scope, hash);
DF_CodeCtx code_ctx = {&df_g_nil_entity, key, lang_kind};
df_code_view_cmds(ws, panel, view, cv, cmds, data, &info, &code_ctx);
txt_scope_close(txt_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
}
DF_VIEW_UI_FUNCTION_DEF(Output)
{
DF_CodeViewState *cv = df_view_user_state(view, DF_CodeViewState);
Temp scratch = scratch_begin(0, 0);
HS_Scope *hs_scope = hs_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
//////////////////////////////
//- rjf: set up invariants
//
F32 bottom_bar_height = ui_top_font_size()*2.f;
Rng2F32 code_area_rect = r2f32p(rect.x0, rect.y0, rect.x1, rect.y1 - bottom_bar_height);
Rng2F32 bottom_bar_rect = r2f32p(rect.x0, rect.y1 - bottom_bar_height, rect.x1, rect.y1);
//////////////////////////////
//- rjf: unpack text info
//
U128 key = df_state->output_log_key;
TXT_LangKind lang_kind = TXT_LangKind_Null;
U128 hash = {0};
TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash);
String8 data = hs_data_from_hash(hs_scope, hash);
Rng1U64 empty_range = {0};
if(info.lines_count == 0)
{
info.lines_count = 1;
info.lines_ranges = &empty_range;
}
//////////////////////////////
//- rjf: build code contents
//
{
DF_CodeCtx code_ctx = {&df_g_nil_entity, key, lang_kind};
df_code_view_build(ws, panel, view, cv, code_area_rect, data, &info, &code_ctx);
}
//////////////////////////////
//- rjf: build bottom bar
//
{
ui_set_next_rect(shift_2f32(bottom_bar_rect, scale_2f32(rect.p0, -1.f)));
ui_set_next_flags(UI_BoxFlag_DrawBackground);
UI_Row
UI_TextAlignment(UI_TextAlign_Center)
UI_PrefWidth(ui_text_dim(10, 1))
UI_FlagsAdd(UI_BoxFlag_DrawTextWeak)
{
UI_Font(df_font_from_slot(DF_FontSlot_Code))
{
ui_labelf("(Debug String Output)");
ui_spacer(ui_em(1.5f, 1));
ui_labelf("Line: %I64d, Column: %I64d", cv->cursor.line, cv->cursor.column);
ui_spacer(ui_pct(1, 0));
ui_labelf("(read only)");
}
}
}
txt_scope_close(txt_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
}
#endif
//~ TODO(rjf): OLD vvvvvvvvvvvvvvvvvvvv @src_collapse
#if 0
DF_VIEW_SETUP_FUNCTION_DEF(Output)
{
// rjf: set up state
@@ -8692,6 +8870,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output)
code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, slice.line_count);
code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, slice.line_count);
code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, slice.line_count);
code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count);
code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, slice.line_count);
code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, slice.line_count);
code_slice_params.font = code_font;
@@ -9097,6 +9276,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output)
scratch_end(scratch);
ProfEnd();
}
#endif
////////////////////////////////
//~ rjf: Memory @view_hook_impl
+3 -3
View File
@@ -359,7 +359,7 @@ struct DF_WatchViewState
};
////////////////////////////////
//~ rjf: Code @view_types
//~ rjf: Code, Output @view_types
typedef struct DF_CodeViewState DF_CodeViewState;
struct DF_CodeViewState
@@ -471,8 +471,8 @@ internal void df_entity_lister_item_array_sort_by_strength__in_place(DF_EntityLi
//~ rjf: Code Views
internal void df_code_view_init(DF_CodeViewState *cv, DF_View *view);
internal void df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info);
internal void df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info);
internal void df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx);
internal void df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx);
////////////////////////////////
//~ rjf: Watch Views