diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index dfaf7e46..a36cd7c4 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -667,11 +667,31 @@ ev_resolved_from_expr(Arena *arena, E_Expr *expr, EV_ViewRuleList *view_rules) return expr; } +//////////////////////////////// +//~ rjf: Column List Building + +internal EV_Col * +ev_col_list_push(Arena *arena, EV_ColList *list) +{ + EV_Col *col = push_array(arena, EV_Col, 1); + SLLQueuePush(list->first, list->last, col); + list->count += 1; + return col; +} + +internal EV_Col * +ev_col_list_push_new(Arena *arena, EV_ColList *list, String8 key) +{ + EV_Col *col = ev_col_list_push(arena, list); + col->key = push_str8_copy(arena, key); + return col; +} + //////////////////////////////// //~ rjf: Block Building internal EV_BlockTree -ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules) +ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules, EV_ColList *cols) { ProfBeginFunction(); EV_BlockTree tree = {&ev_nil_block}; @@ -691,6 +711,7 @@ ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 str tree.root = push_array(arena, EV_Block, 1); MemoryCopyStruct(tree.root, &ev_nil_block); tree.root->key = ev_key_root(); + tree.root->cols = *cols; tree.root->string = string; tree.root->expr = ev_resolved_from_expr(arena, expr, top_level_view_rules); tree.root->view_rules = top_level_view_rules; @@ -758,6 +779,7 @@ ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 str expansion_block->parent = t->parent_block; expansion_block->key = key; expansion_block->split_relative_idx = t->split_relative_idx; + expansion_block->cols = *cols; expansion_block->expr = t->expr; expansion_block->view_rules = t->view_rules; expansion_block->expand_view_rule_info = expand_view_rule_info; @@ -885,7 +907,7 @@ ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 str } internal EV_BlockTree -ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 string, EV_ViewRuleList *view_rules) +ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 string, EV_ViewRuleList *view_rules, EV_ColList *cols) { ProfBeginFunction(); EV_BlockTree tree = {0}; @@ -896,7 +918,7 @@ ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 s EV_ViewRuleList *fastpath_view_rules = ev_view_rule_list_from_expr_fastpaths(arena, string); EV_ViewRuleList *all_view_rules = ev_view_rule_list_copy(arena, view_rules); ev_view_rule_list_concat_in_place(all_view_rules, &fastpath_view_rules); - tree = ev_block_tree_from_expr(arena, view, filter, string, parse.expr, all_view_rules); + tree = ev_block_tree_from_expr(arena, view, filter, string, parse.expr, all_view_rules, cols); } scratch_end(scratch); ProfEnd(); diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index 41b9d403..164ca077 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -187,6 +187,24 @@ struct EV_ViewRuleInfoTable U64 slots_count; }; +//////////////////////////////// +//~ rjf: Columns + +typedef struct EV_Col EV_Col; +struct EV_Col +{ + EV_Col *next; + String8 key; +}; + +typedef struct EV_ColList EV_ColList; +struct EV_ColList +{ + EV_Col *first; + EV_Col *last; + U64 count; +}; + //////////////////////////////// //~ rjf: Blocks @@ -206,6 +224,9 @@ struct EV_Block // rjf: split index, relative to parent's space U64 split_relative_idx; + // rjf: columns + EV_ColList cols; + // rjf: expression / visualization info String8 string; E_Expr *expr; @@ -351,7 +372,7 @@ global read_only EV_ViewRuleInfo ev_nil_view_rule_info = thread_static EV_ViewRuleInfoTable *ev_view_rule_info_table = 0; global read_only EV_ViewRuleList ev_nil_view_rule_list = {0}; thread_static EV_AutoViewRuleTable *ev_auto_view_rule_table = 0; -global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, &e_expr_nil, &ev_nil_view_rule_list, &ev_nil_view_rule_info}; +global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, {0}, &e_expr_nil, &ev_nil_view_rule_list, &ev_nil_view_rule_info}; //////////////////////////////// //~ rjf: Key Functions @@ -415,11 +436,17 @@ internal void ev_view_rule_list_concat_in_place(EV_ViewRuleList *dst, EV_ViewRul internal E_Expr *ev_resolved_from_expr(Arena *arena, E_Expr *expr, EV_ViewRuleList *view_rules); +//////////////////////////////// +//~ rjf: Column List Building + +internal EV_Col *ev_col_list_push(Arena *arena, EV_ColList *list); +internal EV_Col *ev_col_list_push_new(Arena *arena, EV_ColList *list, String8 key); + //////////////////////////////// //~ rjf: Block Building -internal EV_BlockTree ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules); -internal EV_BlockTree ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 string, EV_ViewRuleList *view_rules); +internal EV_BlockTree ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules, EV_ColList *cols); +internal EV_BlockTree ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 string, EV_ViewRuleList *view_rules, EV_ColList *cols); internal U64 ev_depth_from_block(EV_Block *block); //////////////////////////////// diff --git a/src/os/gfx/win32/os_gfx_win32.c b/src/os/gfx/win32/os_gfx_win32.c index 99d73deb..fdcac746 100644 --- a/src/os/gfx/win32/os_gfx_win32.c +++ b/src/os/gfx/win32/os_gfx_win32.c @@ -715,9 +715,10 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) // of the top hit area so manually checking that. F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f; S32 frame_y = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME); - S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER); + // NOTE(rjf): it seems incorrect to apply this padding here... + // S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER); - B32 is_over_top_resize = pos_client.y >= 0 && pos_client.y < frame_y + padding; + B32 is_over_top_resize = pos_client.y >= 0 && pos_client.y < frame_y; // + padding; B32 is_over_title_bar = pos_client.y >= 0 && pos_client.y < window->custom_border_title_thickness; //- rjf: check against title bar client areas diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index c232a9a1..75dea353 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -54,12 +54,12 @@ RD_VocabularyInfo rd_vocabulary_info_table[39] = {str8_lit_comp("stdout_path"), str8_lit_comp("stdout_paths"), str8_lit_comp("Standard Output Path"), str8_lit_comp("Standard Output Paths"), RD_IconKind_Null}, {str8_lit_comp("stderr_path"), str8_lit_comp("stderr_paths"), str8_lit_comp("Standard Error Path"), str8_lit_comp("Standard Error Paths"), RD_IconKind_Null}, {str8_lit_comp("stdin_path"), str8_lit_comp("stdin_paths"), str8_lit_comp("Standard Input Path"), str8_lit_comp("Standard Input Paths"), RD_IconKind_Null}, -{str8_lit_comp("window"), str8_lit_comp("windows"), str8_lit_comp("Window"), str8_lit_comp("Windows"), RD_IconKind_Null}, +{str8_lit_comp("window"), str8_lit_comp("windows"), str8_lit_comp("Window"), str8_lit_comp("Windows"), RD_IconKind_Window}, {str8_lit_comp("panel"), str8_lit_comp("panels"), str8_lit_comp("Panel"), str8_lit_comp("Panels"), RD_IconKind_Null}, {str8_lit_comp("view"), str8_lit_comp("views"), str8_lit_comp("View"), str8_lit_comp("Views"), RD_IconKind_Null}, {str8_lit_comp("tab"), str8_lit_comp("tabs"), str8_lit_comp("Tab"), str8_lit_comp("Tabs"), RD_IconKind_Null}, -{str8_lit_comp("recent_project"), str8_lit_comp("recent_projects"), str8_lit_comp("Recent Project"), str8_lit_comp("Recent Projects"), RD_IconKind_Null}, -{str8_lit_comp("recent_file"), str8_lit_comp("recent_files"), str8_lit_comp("Recent File"), str8_lit_comp("Recent Files"), RD_IconKind_Null}, +{str8_lit_comp("recent_project"), str8_lit_comp("recent_projects"), str8_lit_comp("Recent Project"), str8_lit_comp("Recent Projects"), RD_IconKind_Briefcase}, +{str8_lit_comp("recent_file"), str8_lit_comp("recent_files"), str8_lit_comp("Recent File"), str8_lit_comp("Recent Files"), RD_IconKind_FileOutline}, {str8_lit_comp("src"), str8_lit_comp("srcs"), str8_lit_comp("Source"), str8_lit_comp("Sources"), RD_IconKind_Null}, {str8_lit_comp("dst"), str8_lit_comp("dsts"), str8_lit_comp("Destination"), str8_lit_comp("Destinations"), RD_IconKind_Null}, {str8_lit_comp("conversion_task"), str8_lit_comp("conversion_tasks"), str8_lit_comp("Conversion Task"), str8_lit_comp("Conversion Tasks"), RD_IconKind_Null}, @@ -863,7 +863,7 @@ EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(types), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(procedures), }; -RD_ViewRuleInfo rd_view_rule_kind_info_table[35] = +RD_ViewRuleInfo rd_view_rule_kind_info_table[29] = { {{0}, {0}, {0}, {0}, RD_IconKind_Null, 0, EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(null)}, {str8_lit_comp("empty"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), RD_IconKind_Null, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(empty)}, @@ -871,12 +871,6 @@ RD_ViewRuleInfo rd_view_rule_kind_info_table[35] = {str8_lit_comp("exception_filters"), str8_lit_comp("An interface which controls whether or not the debugger will halt attached processes upon encountering specific exception codes for the first time."), str8_lit_comp("Exception Filters"), str8_lit_comp(""), RD_IconKind_Gear, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(exception_filters)}, {str8_lit_comp("settings"), str8_lit_comp("An interface to modify general settings for the debugger's appearance and behavior."), str8_lit_comp("Settings"), str8_lit_comp(""), RD_IconKind_Gear, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(settings)}, {str8_lit_comp("pending_file"), str8_lit_comp(""), str8_lit_comp("Pending File"), str8_lit_comp(""), RD_IconKind_FileOutline, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(pending_file)}, -{str8_lit_comp("commands"), str8_lit_comp(""), str8_lit_comp("Commands"), str8_lit_comp(""), RD_IconKind_List, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(commands)}, -{str8_lit_comp("file_system"), str8_lit_comp(""), str8_lit_comp("File System"), str8_lit_comp(""), RD_IconKind_FileOutline, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(file_system)}, -{str8_lit_comp("system_processes"), str8_lit_comp(""), str8_lit_comp("System Processes"), str8_lit_comp(""), RD_IconKind_Null, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(system_processes)}, -{str8_lit_comp("entity_lister"), str8_lit_comp(""), str8_lit_comp("Entities"), str8_lit_comp(""), RD_IconKind_Null, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(entity_lister)}, -{str8_lit_comp("ctrl_entity_lister"), str8_lit_comp(""), str8_lit_comp("Control Entities"), str8_lit_comp(""), RD_IconKind_Null, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(ctrl_entity_lister)}, -{str8_lit_comp("symbol_lister"), str8_lit_comp(""), str8_lit_comp("Symbols"), str8_lit_comp(""), RD_IconKind_Null, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(symbol_lister)}, {str8_lit_comp("watch"), str8_lit_comp("The familiar 'watch window' debugger interface. Allows the inputting of a number of expressions. Each expression in the table is evaluated within the context of the selected thread's selected call stack frame. If applicable (depending on visualization rules and the expression's type), these expressions may be hierarchically expanded, which displays children as more rows in the table. The values of these expressions may also be edited, and if possible, can be used to write to registers or memory in attached processes. Also contains a new *view rule* column, not found in other major debuggers, which allows per-row specification of various visualization rules. These view rules may be used to visualize and inspect the evaluation of expressions in a variety of ways. To learn more, read the 'View Rules' section."), str8_lit_comp("Watch"), str8_lit_comp(""), RD_IconKind_Binoculars, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*1|RD_ViewRuleInfoFlag_FilterIsCode*1|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*1|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(watch)}, {str8_lit_comp("locals"), str8_lit_comp("Nearly identical to `Watch`, but automatically filled with local variables found within the selected call stack frame of the selected thread, according to the associated debug info. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table."), str8_lit_comp("Locals"), str8_lit_comp(""), RD_IconKind_Binoculars, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*1|RD_ViewRuleInfoFlag_FilterIsCode*1|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*1|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(locals)}, {str8_lit_comp("registers"), str8_lit_comp("Nearly identical to `Watch`, but automatically filled with all register names according to the selected thread's architecture. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table."), str8_lit_comp("Registers"), str8_lit_comp(""), RD_IconKind_Binoculars, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*1|RD_ViewRuleInfoFlag_FilterIsCode*1|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*1|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(registers)}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index a2b0eb95..b1e7a936 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -252,14 +252,14 @@ RD_CmdKind_ToggleWatchExpressionAtMouse, RD_CmdKind_SetColumns, RD_CmdKind_ToggleAddressVisibility, RD_CmdKind_ToggleCodeBytesVisibility, -RD_CmdKind_EnableEntity, -RD_CmdKind_DisableEntity, -RD_CmdKind_SelectEntity, -RD_CmdKind_RemoveEntity, -RD_CmdKind_NameEntity, -RD_CmdKind_ConditionEntity, -RD_CmdKind_DuplicateEntity, -RD_CmdKind_RelocateEntity, +RD_CmdKind_EnableCfg, +RD_CmdKind_DisableCfg, +RD_CmdKind_SelectCfg, +RD_CmdKind_RemoveCfg, +RD_CmdKind_NameCfg, +RD_CmdKind_ConditionCfg, +RD_CmdKind_DuplicateCfg, +RD_CmdKind_RelocateCfg, RD_CmdKind_AddBreakpoint, RD_CmdKind_AddAddressBreakpoint, RD_CmdKind_AddFunctionBreakpoint, @@ -395,12 +395,6 @@ RD_ViewRuleKind_GettingStarted, RD_ViewRuleKind_ExceptionFilters, RD_ViewRuleKind_Settings, RD_ViewRuleKind_PendingFile, -RD_ViewRuleKind_Commands, -RD_ViewRuleKind_FileSystem, -RD_ViewRuleKind_SystemProcesses, -RD_ViewRuleKind_EntityLister, -RD_ViewRuleKind_CtrlEntityLister, -RD_ViewRuleKind_SymbolLister, RD_ViewRuleKind_Watch, RD_ViewRuleKind_Locals, RD_ViewRuleKind_Registers, @@ -757,12 +751,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(getting_started); RD_VIEW_RULE_UI_FUNCTION_DEF(exception_filters); RD_VIEW_RULE_UI_FUNCTION_DEF(settings); RD_VIEW_RULE_UI_FUNCTION_DEF(pending_file); -RD_VIEW_RULE_UI_FUNCTION_DEF(commands); -RD_VIEW_RULE_UI_FUNCTION_DEF(file_system); -RD_VIEW_RULE_UI_FUNCTION_DEF(system_processes); -RD_VIEW_RULE_UI_FUNCTION_DEF(entity_lister); -RD_VIEW_RULE_UI_FUNCTION_DEF(ctrl_entity_lister); -RD_VIEW_RULE_UI_FUNCTION_DEF(symbol_lister); RD_VIEW_RULE_UI_FUNCTION_DEF(watch); RD_VIEW_RULE_UI_FUNCTION_DEF(locals); RD_VIEW_RULE_UI_FUNCTION_DEF(registers); @@ -809,7 +797,7 @@ extern EV_ViewRuleExprExpandInfoHookFunctionType * rd_collection_expr_expand_inf extern EV_ViewRuleExprExpandRangeInfoHookFunctionType * rd_collection_expr_expand_range_info_hook_function_table[18]; extern EV_ViewRuleExprExpandIDFromNumHookFunctionType * rd_collection_expr_expand_id_from_num_hook_function_table[18]; extern EV_ViewRuleExprExpandIDFromNumHookFunctionType * rd_collection_expr_expand_num_from_id_hook_function_table[18]; -extern RD_ViewRuleInfo rd_view_rule_kind_info_table[35]; +extern RD_ViewRuleInfo rd_view_rule_kind_info_table[29]; extern RD_IconKind rd_entity_kind_icon_kind_table[27]; extern String8 rd_theme_preset_display_string_table[9]; extern String8 rd_theme_preset_code_string_table[9]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 0c40c45d..a41ca1a1 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -72,12 +72,12 @@ RD_VocabularyMap: {stdout_path _ "Standard Output Path" _ Null } {stderr_path _ "Standard Error Path" _ Null } {stdin_path _ "Standard Input Path" _ Null } - {window _ "Window" _ Null } + {window _ "Window" _ Window } {panel _ "Panel" _ Null } {view _ "View" _ Null } {tab _ "Tab" _ Null } - {recent_project _ "Recent Project" _ Null } - {recent_file _ "Recent File" _ Null } + {recent_project _ "Recent Project" _ Briefcase } + {recent_file _ "Recent File" _ FileOutline } {src _ "Source" _ Null } {dst _ "Destination" _ Null } {conversion_task _ "Conversion Task" _ Null } @@ -478,15 +478,15 @@ RD_CmdTable: // | | | | {ToggleAddressVisibility 1 1 Null null Nil Null 0 0 0 0 0 0 Thumbnails "toggle_address_visibility" "Toggle Address Visibility" "Toggles the visibility of addresses in a disassembly view." "" "$disasm," } {ToggleCodeBytesVisibility 1 1 Null null Nil Null 0 0 0 0 0 0 Thumbnails "toggle_code_bytes_visibility""Toggle Code Bytes Visibility" "Toggles the visibility of machine code bytes in a disassembly view." "" "$disasm," } - //- rjf: general entity operations - {EnableEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "enable_entity" "Enable Entity" "Enables an entity." "" "" } - {DisableEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "disable_entity" "Disable Entity" "Disables an entity." "" "" } - {SelectEntity 0 0 Null null Nil Null 0 0 0 0 0 0 CheckHollow "select_entity" "Select Entity" "Selects an entity, disabling all others of the same kind." "" "" } - {RemoveEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Trash "remove_entity" "Remove Entity" "Removes an entity." "" "" } - {NameEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "name_entity" "Name Entity" "Equips an entity with a name." "" "" } - {ConditionEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "condition_entity" "Condition Entity" "Equips an entity with a condition string." "" "" } - {DuplicateEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "duplicate_entity" "Duplicate Entity" "Duplicates an entity." "" "" } - {RelocateEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "relocate_entity" "Relocate Entity" "Relocates an entity." "" "" } + //- rjf: general config operations + {EnableCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Null "enable_entity" "Enable Entity" "Enables an entity." "" "" } + {DisableCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Null "disable_entity" "Disable Entity" "Disables an entity." "" "" } + {SelectCfg 0 0 Null null Nil Null 0 0 0 0 0 0 CheckHollow "select_entity" "Select Entity" "Selects an entity, disabling all others of the same kind." "" "" } + {RemoveCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Trash "remove_entity" "Remove Entity" "Removes an entity." "" "" } + {NameCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Null "name_entity" "Name Entity" "Equips an entity with a name." "" "" } + {ConditionCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Null "condition_entity" "Condition Entity" "Equips an entity with a condition string." "" "" } + {DuplicateCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Null "duplicate_entity" "Duplicate Entity" "Duplicates an entity." "" "" } + {RelocateCfg 0 0 Null null Nil Null 0 0 0 0 0 0 Null "relocate_entity" "Relocate Entity" "Relocates an entity." "" "" } //- rjf: breakpoints {AddBreakpoint 1 1 Null null Nil Null 0 0 0 0 0 0 CircleFilled "add_breakpoint" "Add Breakpoint" "Places a breakpoint at a given location (file path and line number, address, or symbol name)." "" "" } @@ -980,14 +980,6 @@ RD_ViewRuleTable: //- rjf: temporary view for loading files - must analyze file before picking viewer { PendingFile pending_file "Pending File" "" FileOutline 0 0 0 0 0 0 0 "" } - //- rjf: query listers - { Commands commands "Commands" "" List 0 0 0 0 0 0 0 "" } - { FileSystem file_system "File System" "" FileOutline 0 0 0 0 0 0 0 "" } - { SystemProcesses system_processes "System Processes" "" Null 0 0 0 0 0 0 0 "" } - { EntityLister entity_lister "Entities" "" Null 0 0 0 0 0 0 0 "" } - { CtrlEntityLister ctrl_entity_lister "Control Entities" "" Null 0 0 0 0 0 0 0 "" } - { SymbolLister symbol_lister "Symbols" "" Null 0 0 0 0 0 0 0 "" } - //- rjf: watch or watch-style tables { Watch watch "Watch" "" Binoculars 1 1 1 0 0 0 1 "The familiar 'watch window' debugger interface. Allows the inputting of a number of expressions. Each expression in the table is evaluated within the context of the selected thread's selected call stack frame. If applicable (depending on visualization rules and the expression's type), these expressions may be hierarchically expanded, which displays children as more rows in the table. The values of these expressions may also be edited, and if possible, can be used to write to registers or memory in attached processes. Also contains a new *view rule* column, not found in other major debuggers, which allows per-row specification of various visualization rules. These view rules may be used to visualize and inspect the evaluation of expressions in a variety of ways. To learn more, read the 'View Rules' section." } { Locals locals "Locals" "" Binoculars 1 1 1 0 0 0 1 "Nearly identical to `Watch`, but automatically filled with local variables found within the selected call stack frame of the selected thread, according to the associated debug info. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 41c55c85..5e8ef63e 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -579,6 +579,16 @@ rd_cfg_release(RD_Cfg *cfg) scratch_end(scratch); } +internal void +rd_cfg_release_all_children(RD_Cfg *cfg) +{ + for(RD_Cfg *child = cfg->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) + { + next = child->next; + rd_cfg_release(child); + } +} + internal RD_Handle rd_handle_from_cfg(RD_Cfg *cfg) { @@ -1294,38 +1304,7 @@ rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg, Vec4F32 secondary_color, F32 { rgba = ui_top_palette()->text; } - - //- rjf: name -> icon table - local_persist struct - { - String8 name; - RD_IconKind icon_kind; - } - name2icon_map[] = - { - {str8_lit_comp("target"), RD_IconKind_Target}, - {str8_lit_comp("breakpoint"), RD_IconKind_CircleFilled}, - {str8_lit_comp("auto_view_rule"), RD_IconKind_Binoculars}, - {str8_lit_comp("file_path_map"), RD_IconKind_FileOutline}, - {str8_lit_comp("watch_pin"), RD_IconKind_Pin}, - {str8_lit_comp("watch"), RD_IconKind_Binoculars}, - {str8_lit_comp("window"), RD_IconKind_Window}, - {str8_lit_comp("recent_project"), RD_IconKind_Briefcase}, - {str8_lit_comp("recent_file"), RD_IconKind_FileOutline}, - }; - - //- rjf: map cfg -> icon - RD_IconKind icon_kind = RD_IconKind_Null; - for EachElement(idx, name2icon_map) - { - if(str8_match(cfg->string, name2icon_map[idx].name, 0)) - { - icon_kind = name2icon_map[idx].icon_kind; - break; - } - } - - //- rjf: map icon -> is-from-command-line + RD_IconKind icon_kind = rd_icon_kind_from_code_name(cfg->string); B32 is_from_command_line = 0; { RD_Cfg *cmd_line_root = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("command_line")); @@ -1947,28 +1926,6 @@ rd_entity_from_name_and_kind(String8 string, RD_EntityKind kind) //////////////////////////////// //~ rjf: Frontend Entity Info Extraction -internal D_Target -rd_d_target_from_entity(RD_Entity *entity) -{ - RD_Entity *src_target_exe = rd_entity_child_from_kind(entity, RD_EntityKind_Executable); - RD_Entity *src_target_args = rd_entity_child_from_kind(entity, RD_EntityKind_Arguments); - RD_Entity *src_target_wdir = rd_entity_child_from_kind(entity, RD_EntityKind_WorkingDirectory); - RD_Entity *src_target_stdo = rd_entity_child_from_kind(entity, RD_EntityKind_StdoutPath); - RD_Entity *src_target_stde = rd_entity_child_from_kind(entity, RD_EntityKind_StderrPath); - RD_Entity *src_target_stdi = rd_entity_child_from_kind(entity, RD_EntityKind_StdinPath); - RD_Entity *src_target_entry = rd_entity_child_from_kind(entity, RD_EntityKind_EntryPoint); - D_Target target = {0}; - target.exe = src_target_exe->string; - target.args = src_target_args->string; - target.working_directory = src_target_wdir->string; - target.custom_entry_point_name = src_target_entry->string; - target.stdout_path = src_target_stdo->string; - target.stderr_path = src_target_stde->string; - target.stdin_path = src_target_stdi->string; - target.debug_subprocesses = entity->debug_subprocesses; - return target; -} - internal DR_FancyStringList rd_title_fstrs_from_entity(Arena *arena, RD_Entity *entity, Vec4F32 secondary_color, F32 size) { @@ -3290,11 +3247,7 @@ rd_store_view_expr_string(String8 string) { RD_Cfg *view = rd_cfg_from_handle(rd_regs()->view); RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression")); - for(RD_Cfg *child = expr->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) - { - next = child->next; - rd_cfg_release(child); - } + rd_cfg_release_all_children(expr); rd_cfg_new(expr, string); } @@ -3303,11 +3256,7 @@ rd_store_view_filter(String8 string) { RD_Cfg *view = rd_cfg_from_handle(rd_regs()->view); RD_Cfg *filter = rd_cfg_child_from_string_or_alloc(view, str8_lit("filter")); - for(RD_Cfg *child = filter->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) - { - next = child->next; - rd_cfg_release(child); - } + rd_cfg_release_all_children(filter); rd_cfg_new(filter, string); } @@ -3334,13 +3283,7 @@ rd_store_view_param(String8 key, String8 value) { RD_Cfg *view = rd_cfg_from_handle(rd_regs()->view); RD_Cfg *child = rd_cfg_child_from_string_or_alloc(view, key); - for(RD_Cfg *val_child = child->first, *next = &rd_nil_cfg; - val_child != &rd_nil_cfg; - val_child = next) - { - next = val_child->next; - rd_cfg_release(val_child); - } + rd_cfg_release_all_children(child); rd_cfg_new(child, value); } @@ -5236,71 +5179,6 @@ rd_window_frame(void) } #endif }break; - - ////////////////////// - //- rjf: frontend entities - // - case RD_RegSlot_Entity: - { - RD_Entity *entity = rd_entity_from_handle(regs->entity); - RD_EntityKindFlags kind_flags = rd_entity_kind_flags_table[entity->kind]; - - //- rjf: title - UI_Row - UI_PrefWidth(ui_text_dim(5, 1)) - UI_TextAlignment(UI_TextAlign_Center) - UI_TextPadding(ui_top_font_size()*1.5f) - { - DR_FancyStringList fstrs = rd_title_fstrs_from_entity(scratch.arena, entity, ui_top_palette()->text_weak, ui_top_font_size()); - UI_Box *title_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); - ui_box_equip_display_fancy_strings(title_box, &fstrs); - if(ctrl_entity->kind == CTRL_EntityKind_Thread) - { - ui_spacer(ui_em(0.5f, 1.f)); - UI_FontSize(ui_top_font_size() - 1.f) - UI_CornerRadius(ui_top_font_size()*0.5f) - RD_Palette(RD_PaletteCode_NeutralPopButton) - UI_TextPadding(ui_top_font_size()*0.5f) - { - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak|UI_BoxFlag_DrawBorder) ui_label(string_from_arch(ctrl_entity->arch)); - ui_spacer(ui_em(0.5f, 1.f)); - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak|UI_BoxFlag_DrawBorder) ui_labelf("TID: %i", (U32)ctrl_entity->id); - } - } - } - - RD_Palette(RD_PaletteCode_Floating) ui_divider(ui_em(1.f, 1.f)); - - //- rjf: name editor - if(kind_flags & RD_EntityKindFlag_CanRename) RD_Font(RD_FontSlot_Code) UI_TextPadding(ui_top_font_size()*1.5f) - { - UI_Signal sig = rd_line_editf(RD_LineEditFlag_Border|RD_LineEditFlag_CodeContents, 0, 0, &ws->ctx_menu_input_cursor, &ws->ctx_menu_input_mark, ws->ctx_menu_input_buffer, ws->ctx_menu_input_buffer_size, &ws->ctx_menu_input_string_size, 0, entity->string, "Name###entity_string_edit_%p", ctrl_entity); - if(ui_committed(sig)) - { - rd_cmd(RD_CmdKind_NameEntity, .entity = regs->entity, .string = str8(ws->ctx_menu_input_buffer, ws->ctx_menu_input_string_size)); - } - } - - //- rjf: condition editor - if(kind_flags & RD_EntityKindFlag_CanCondition) RD_Font(RD_FontSlot_Code) UI_TextPadding(ui_top_font_size()*1.5f) - { - UI_Signal sig = rd_line_editf(RD_LineEditFlag_Border|RD_LineEditFlag_CodeContents, 0, 0, &ws->ctx_menu_input_cursor, &ws->ctx_menu_input_mark, ws->ctx_menu_input_buffer, ws->ctx_menu_input_buffer_size, &ws->ctx_menu_input_string_size, 0, rd_entity_child_from_kind(entity, RD_EntityKind_Condition)->string, "Condition###entity_condition_edit_%p", entity); - if(ui_committed(sig)) - { - rd_cmd(RD_CmdKind_ConditionEntity, .entity = regs->entity, .string = str8(ws->ctx_menu_input_buffer, ws->ctx_menu_input_string_size)); - } - } - - //- rjf: name editor - if(entity->cfg_src == RD_CfgSrc_CommandLine) - { - if(ui_clicked(rd_icon_buttonf(RD_IconKind_Save, 0, "Save To Project"))) - { - rd_entity_equip_cfg_src(entity, RD_CfgSrc_Project); - } - } - }break; - } } @@ -5839,13 +5717,14 @@ rd_window_frame(void) RD_Palette(RD_PaletteCode_NeutralPopButton) { Temp scratch = scratch_begin(0, 0); - RD_EntityList tasks = rd_query_cached_entity_list_with_kind(RD_EntityKind_ConversionTask); - for(RD_EntityNode *n = tasks.first; n != 0; n = n->next) + RD_CfgList tasks = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("conversion_task")); + for(RD_CfgNode *n = tasks.first; n != 0; n = n->next) { - RD_Entity *task = n->entity; - if(task->alloc_time_us + 500000 < os_now_microseconds()) + RD_Cfg *task = n->v; + F32 task_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "task_anim_%p_%I64u", task, task->gen), 1.f); + if(task_t > 0.5f) { - String8 rdi_path = task->string; + String8 rdi_path = task->first->string; String8 rdi_name = str8_skip_last_slash(rdi_path); String8 task_text = push_str8f(scratch.arena, "Creating %S...", rdi_name); UI_Key key = ui_key_from_stringf(ui_key_zero(), "task_%p", task); @@ -6397,6 +6276,7 @@ rd_window_frame(void) String8 expr = ws->hover_eval_string; E_Eval eval = e_eval_from_string(scratch.arena, expr); EV_ViewRuleList top_level_view_rules = {0}; + EV_ColList top_level_cols = {0}; //- rjf: build if good if(!e_type_key_match(eval.type_key, e_type_key_zero()) && !ui_any_ctx_menu_is_open()) @@ -6410,7 +6290,7 @@ rd_window_frame(void) EV_View *ev_view = rd_ev_view_from_key(d_hash_from_string(ev_view_key_string)); EV_Key parent_key = ev_key_make(5381, 1); EV_Key key = ev_key_make(ev_hash_from_key(parent_key), 1); - EV_BlockTree block_tree = ev_block_tree_from_string(scratch.arena, ev_view, str8_zero(), expr, &top_level_view_rules); + EV_BlockTree block_tree = ev_block_tree_from_string(scratch.arena, ev_view, str8_zero(), expr, &top_level_view_rules, &top_level_cols); EV_BlockRangeList block_ranges = ev_block_range_list_from_tree(scratch.arena, &block_tree); // EV_BlockList viz_blocks = ev_block_list_from_view_expr_keys(scratch.arena, ev_view, str8_zero(), &top_level_view_rules, expr, parent_key, key, 0); CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); @@ -12839,14 +12719,12 @@ rd_frame(void) { ev_auto_view_rule_table_push_new(scratch.arena, auto_view_rule_table, collection_type_keys[idx], rd_collection_name_table[idx], 1); } - RD_EntityList auto_view_rules = rd_query_cached_entity_list_with_kind(RD_EntityKind_AutoViewRule); - for(RD_EntityNode *n = auto_view_rules.first; n != 0; n = n->next) + RD_CfgList auto_view_rules = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("auto_view_rule")); + for(RD_CfgNode *n = auto_view_rules.first; n != 0; n = n->next) { - RD_Entity *rule = n->entity; - RD_Entity *src = rd_entity_child_from_kind(rule, RD_EntityKind_Source); - RD_Entity *dst = rd_entity_child_from_kind(rule, RD_EntityKind_Dest); - String8 type_string = src->string; - String8 view_rule_string = dst->string; + RD_Cfg *rule = n->v; + String8 type_string = rd_cfg_child_from_string(rule, str8_lit("source"))->first->string; + String8 view_rule_string = rd_cfg_child_from_string(rule, str8_lit("dest"))->first->string; E_TokenArray tokens = e_token_array_from_text(scratch.arena, type_string); E_Parse type_parse = e_parse_type_from_text_tokens(scratch.arena, type_string, &tokens); E_TypeKey type_key = e_type_from_expr(type_parse.expr); @@ -12917,10 +12795,12 @@ rd_frame(void) CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process); if(processes.count == 0 || kind == RD_CmdKind_Restart) { - RD_EntityList bps = rd_query_cached_entity_list_with_kind(RD_EntityKind_Breakpoint); - for(RD_EntityNode *n = bps.first; n != 0; n = n->next) + RD_CfgList bps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); + for(RD_CfgNode *n = bps.first; n != 0; n = n->next) { - n->entity->u64 = 0; + RD_Cfg *hit_count = rd_cfg_child_from_string_or_alloc(n->v, str8_lit("hit_count")); + rd_cfg_release_all_children(hit_count); + rd_cfg_new(hit_count, str8_lit("0")); } } } // fallthrough @@ -13325,66 +13205,28 @@ rd_frame(void) //- rjf: keep track of recent projects if(src == RD_CfgSrc_Project) { - //- TODO(rjf): @cfg keep track of recent projects + RD_Cfg *user = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("user")); + RD_CfgList recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); + RD_Cfg *recent_project = &rd_nil_cfg; + for(RD_CfgNode *n = recent_projects.first; n != 0; n = n->next) { - RD_Cfg *user = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("user")); - RD_CfgList recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); - RD_Cfg *recent_project = &rd_nil_cfg; - for(RD_CfgNode *n = recent_projects.first; n != 0; n = n->next) + if(path_match_normalized(n->v->string, cfg_path)) { - if(path_match_normalized(n->v->string, cfg_path)) - { - recent_project = n->v; - break; - } - } - if(recent_project == &rd_nil_cfg) - { - recent_project = rd_cfg_new(user, str8_lit("recent_project")); - rd_cfg_new(recent_project, path_normalized_from_string(scratch.arena, cfg_path)); - } - rd_cfg_unhook(user, recent_project); - rd_cfg_insert_child(user, &rd_nil_cfg, recent_project); - recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); - if(recent_projects.count > 32) - { - rd_cfg_release(recent_projects.last->v); - } - } - RD_EntityList recent_projects = rd_query_cached_entity_list_with_kind(RD_EntityKind_RecentProject); - RD_Entity *recent_project = &rd_nil_entity; - for(RD_EntityNode *n = recent_projects.first; n != 0; n = n->next) - { - if(path_match_normalized(cfg_path, n->entity->string)) - { - recent_project = n->entity; + recent_project = n->v; break; } } - if(rd_entity_is_nil(recent_project)) + if(recent_project == &rd_nil_cfg) { - recent_project = rd_entity_alloc(rd_entity_root(), RD_EntityKind_RecentProject); - rd_entity_equip_name(recent_project, path_normalized_from_string(scratch.arena, cfg_path)); - rd_entity_equip_cfg_src(recent_project, RD_CfgSrc_User); + recent_project = rd_cfg_new(user, str8_lit("recent_project")); + rd_cfg_new(recent_project, path_normalized_from_string(scratch.arena, cfg_path)); } - } - - //- rjf: eliminate all existing entities which are derived from config - { - for EachEnumVal(RD_EntityKind, k) + rd_cfg_unhook(user, recent_project); + rd_cfg_insert_child(user, &rd_nil_cfg, recent_project); + recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); + if(recent_projects.count > 32) { - RD_EntityKindFlags k_flags = rd_entity_kind_flags_table[k]; - if(k_flags & RD_EntityKindFlag_IsSerializedToConfig) - { - RD_EntityList entities = rd_query_cached_entity_list_with_kind(k); - for(RD_EntityNode *n = entities.first; n != 0; n = n->next) - { - if(n->entity->cfg_src == src) - { - rd_entity_mark_for_deletion(n->entity); - } - } - } + rd_cfg_release(recent_projects.last->v); } } @@ -14070,11 +13912,7 @@ rd_frame(void) F32 new_font_size = clamp_1f32(r1f32(6, 72), current_font_size+1); RD_Cfg *window = rd_cfg_from_handle(rd_regs()->window); RD_Cfg *main_font_size = rd_cfg_child_from_string_or_alloc(window, str8_lit("main_font_size")); - for(RD_Cfg *child = main_font_size->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) - { - next = child->next; - rd_cfg_release(child); - } + rd_cfg_release_all_children(main_font_size); rd_cfg_newf(main_font_size, "%f", new_font_size); }break; case RD_CmdKind_DecUIFontScale: @@ -14084,11 +13922,7 @@ rd_frame(void) F32 new_font_size = clamp_1f32(r1f32(6, 72), current_font_size-1); RD_Cfg *window = rd_cfg_from_handle(rd_regs()->window); RD_Cfg *main_font_size = rd_cfg_child_from_string_or_alloc(window, str8_lit("main_font_size")); - for(RD_Cfg *child = main_font_size->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) - { - next = child->next; - rd_cfg_release(child); - } + rd_cfg_release_all_children(main_font_size); rd_cfg_newf(main_font_size, "%f", new_font_size); }break; case RD_CmdKind_IncCodeFontScale: @@ -14098,11 +13932,7 @@ rd_frame(void) F32 new_font_size = clamp_1f32(r1f32(6, 72), current_font_size+1); RD_Cfg *window = rd_cfg_from_handle(rd_regs()->window); RD_Cfg *code_font_size = rd_cfg_child_from_string_or_alloc(window, str8_lit("code_font_size")); - for(RD_Cfg *child = code_font_size->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) - { - next = child->next; - rd_cfg_release(child); - } + rd_cfg_release_all_children(code_font_size); rd_cfg_newf(code_font_size, "%f", new_font_size); }break; case RD_CmdKind_DecCodeFontScale: @@ -14112,11 +13942,7 @@ rd_frame(void) F32 new_font_size = clamp_1f32(r1f32(6, 72), current_font_size-1); RD_Cfg *window = rd_cfg_from_handle(rd_regs()->window); RD_Cfg *code_font_size = rd_cfg_child_from_string_or_alloc(window, str8_lit("code_font_size")); - for(RD_Cfg *child = code_font_size->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) - { - next = child->next; - rd_cfg_release(child); - } + rd_cfg_release_all_children(code_font_size); rd_cfg_newf(code_font_size, "%f", new_font_size); }break; @@ -14433,21 +14259,13 @@ rd_frame(void) String8 map_src = str8_list_join(scratch.arena, &map_src_parts, &map_join); String8 map_dst = str8_list_join(scratch.arena, &map_dst_parts, &map_join); - //- rjf: store as file path map entity - //- TODO(rjf): @cfg store as file path map entity - { - RD_Cfg *user = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("user")); - RD_Cfg *map = rd_cfg_new(user, str8_lit("file_path_map")); - RD_Cfg *src = rd_cfg_new(map, str8_lit("source")); - RD_Cfg *dst = rd_cfg_new(map, str8_lit("dest")); - rd_cfg_new(src, map_src); - rd_cfg_new(dst, map_dst); - } - RD_Entity *map = rd_entity_alloc(rd_entity_root(), RD_EntityKind_FilePathMap); - RD_Entity *src = rd_entity_alloc(map, RD_EntityKind_Source); - RD_Entity *dst = rd_entity_alloc(map, RD_EntityKind_Dest); - rd_entity_equip_name(src, map_src); - rd_entity_equip_name(dst, map_dst); + //- rjf: store as file path map cfg + RD_Cfg *user = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("user")); + RD_Cfg *map = rd_cfg_new(user, str8_lit("file_path_map")); + RD_Cfg *src = rd_cfg_new(map, str8_lit("source")); + RD_Cfg *dst = rd_cfg_new(map, str8_lit("dest")); + rd_cfg_new(src, map_src); + rd_cfg_new(dst, map_dst); }break; //- rjf: panel removal @@ -14680,17 +14498,13 @@ rd_frame(void) }break; case RD_CmdKind_TabBarTop: { -#if 0 // TODO(rjf): @cfg - RD_Panel *panel = rd_panel_from_handle(rd_regs()->panel); - panel->tab_side = Side_Min; -#endif + RD_Cfg *panel = rd_cfg_from_handle(rd_regs()->panel); + rd_cfg_release(rd_cfg_child_from_string(panel, str8_lit("tabs_on_bottom"))); }break; case RD_CmdKind_TabBarBottom: { -#if 0 // TODO(rjf): @cfg - RD_Panel *panel = rd_panel_from_handle(rd_regs()->panel); - panel->tab_side = Side_Max; -#endif + RD_Cfg *panel = rd_cfg_from_handle(rd_regs()->panel); + rd_cfg_child_from_string_or_alloc(panel, str8_lit("tabs_on_bottom")); }break; //- rjf: files @@ -14808,57 +14622,28 @@ rd_frame(void) if(rd_regs()->file_path.size != 0) { String8 path = path_normalized_from_string(scratch.arena, rd_regs()->file_path); - - //- TODO(rjf): @cfg record file in project + RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); + RD_CfgList recent_files = rd_cfg_child_list_from_string(scratch.arena, project, str8_lit("recent_files")); + RD_Cfg *recent_file = &rd_nil_cfg; + for(RD_CfgNode *n = recent_files.first; n != 0; n = n->next) { - RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); - RD_CfgList recent_files = rd_cfg_child_list_from_string(scratch.arena, project, str8_lit("recent_files")); - RD_Cfg *recent_file = &rd_nil_cfg; - for(RD_CfgNode *n = recent_files.first; n != 0; n = n->next) + if(path_match_normalized(n->v->string, path)) { - if(path_match_normalized(n->v->string, path)) - { - recent_file = n->v; - break; - } - } - if(recent_file == &rd_nil_cfg) - { - recent_file = rd_cfg_new(project, str8_lit("recent_file")); - rd_cfg_new(recent_file, path); - } - rd_cfg_unhook(project, recent_file); - rd_cfg_insert_child(project, &rd_nil_cfg, recent_file); - recent_files = rd_cfg_child_list_from_string(scratch.arena, project, str8_lit("recent_files")); - if(recent_files.count > 256) - { - rd_cfg_release(recent_files.last->v); - } - } - - RD_EntityList recent_files = rd_query_cached_entity_list_with_kind(RD_EntityKind_RecentFile); - if(recent_files.count >= 256) - { - rd_entity_mark_for_deletion(recent_files.first->entity); - } - RD_Entity *existing_recent_file = &rd_nil_entity; - for(RD_EntityNode *n = recent_files.first; n != 0; n = n->next) - { - if(str8_match(n->entity->string, path, StringMatchFlag_CaseInsensitive)) - { - existing_recent_file = n->entity; + recent_file = n->v; break; } } - if(rd_entity_is_nil(existing_recent_file)) + if(recent_file == &rd_nil_cfg) { - RD_Entity *recent_file = rd_entity_alloc(rd_entity_root(), RD_EntityKind_RecentFile); - rd_entity_equip_name(recent_file, path); - rd_entity_equip_cfg_src(recent_file, RD_CfgSrc_Project); + recent_file = rd_cfg_new(project, str8_lit("recent_file")); + rd_cfg_new(recent_file, path); } - else + rd_cfg_unhook(project, recent_file); + rd_cfg_insert_child(project, &rd_nil_cfg, recent_file); + recent_files = rd_cfg_child_list_from_string(scratch.arena, project, str8_lit("recent_files")); + if(recent_files.count > 256) { - rd_entity_change_parent(existing_recent_file, rd_entity_root(), rd_entity_root(), rd_entity_root()->last); + rd_cfg_release(recent_files.last->v); } }break; case RD_CmdKind_ShowFileInExplorer: @@ -16145,124 +15930,95 @@ X(getting_started) }break; //- rjf: general entity operations - case RD_CmdKind_SelectEntity: + case RD_CmdKind_SelectCfg: case RD_CmdKind_SelectTarget: { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - RD_EntityList all_of_the_same_kind = rd_query_cached_entity_list_with_kind(entity->kind); - B32 is_selected = !entity->disabled; - for(RD_EntityNode *n = all_of_the_same_kind.first; n != 0; n = n->next) + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + RD_CfgList all_of_the_same_kind = rd_cfg_top_level_list_from_string(scratch.arena, cfg->string); + B32 is_selected = rd_disabled_from_cfg(cfg); + for(RD_CfgNode *n = all_of_the_same_kind.first; n != 0; n = n->next) { - RD_Entity *e = n->entity; - rd_entity_equip_disabled(e, 1); + RD_Cfg *c = n->v; + rd_cfg_child_from_string_or_alloc(c, str8_lit("disabled")); } if(!is_selected) { - rd_entity_equip_disabled(entity, 0); + rd_cfg_release(rd_cfg_child_from_string(cfg, str8_lit("disabled"))); } }break; - case RD_CmdKind_EnableEntity: + case RD_CmdKind_EnableCfg: case RD_CmdKind_EnableBreakpoint: case RD_CmdKind_EnableTarget: { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - rd_entity_equip_disabled(entity, 0); + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + rd_cfg_release(rd_cfg_child_from_string(cfg, str8_lit("disabled"))); }break; - case RD_CmdKind_DisableEntity: + case RD_CmdKind_DisableCfg: case RD_CmdKind_DisableBreakpoint: case RD_CmdKind_DisableTarget: { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - rd_entity_equip_disabled(entity, 1); + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + rd_cfg_child_from_string_or_alloc(cfg, str8_lit("disabled")); }break; - case RD_CmdKind_RemoveEntity: + case RD_CmdKind_RemoveCfg: { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - RD_EntityKindFlags kind_flags = rd_entity_kind_flags_table[entity->kind]; - if(kind_flags & RD_EntityKindFlag_CanDelete) + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + rd_cfg_release(cfg); + }break; + case RD_CmdKind_NameCfg: + { + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + if(rd_regs()->string.size != 0) { - rd_entity_mark_for_deletion(entity); - } - }break; - case RD_CmdKind_NameEntity: - { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - String8 string = rd_regs()->string; - rd_entity_equip_name(entity, string); - }break; - case RD_CmdKind_ConditionEntity: - { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - String8 string = rd_regs()->string; - if(string.size != 0) - { - RD_Entity *child = rd_entity_child_from_kind_or_alloc(entity, RD_EntityKind_Condition); - rd_entity_equip_name(child, string); + RD_Cfg *label = rd_cfg_child_from_string_or_alloc(cfg, str8_lit("label")); + rd_cfg_new(label, rd_regs()->string); } else { - RD_Entity *child = rd_entity_child_from_kind(entity, RD_EntityKind_Condition); - rd_entity_mark_for_deletion(child); + rd_cfg_release(rd_cfg_child_from_string(cfg, str8_lit("label"))); } }break; - case RD_CmdKind_DuplicateEntity: + case RD_CmdKind_ConditionCfg: { - RD_Entity *src = rd_entity_from_handle(rd_regs()->entity); - if(!rd_entity_is_nil(src)) + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + if(rd_regs()->string.size != 0) { - typedef struct Task Task; - struct Task - { - Task *next; - RD_Entity *src_n; - RD_Entity *dst_parent; - }; - Task starter_task = {0, src, src->parent}; - Task *first_task = &starter_task; - Task *last_task = &starter_task; - for(Task *task = first_task; task != 0; task = task->next) - { - RD_Entity *src_n = task->src_n; - RD_Entity *dst_n = rd_entity_alloc(task->dst_parent, task->src_n->kind); - if(src_n->flags & RD_EntityFlag_HasTextPoint) {rd_entity_equip_txt_pt(dst_n, src_n->text_point);} - if(src_n->flags & RD_EntityFlag_HasU64) {rd_entity_equip_u64(dst_n, src_n->u64);} - if(src_n->flags & RD_EntityFlag_HasColor) {rd_entity_equip_color_hsva(dst_n, rd_hsva_from_entity(src_n));} - if(src_n->flags & RD_EntityFlag_HasVAddr) {rd_entity_equip_vaddr(dst_n, src_n->vaddr);} - if(src_n->disabled) {rd_entity_equip_disabled(dst_n, 1);} - if(src_n->string.size != 0) {rd_entity_equip_name(dst_n, src_n->string);} - dst_n->cfg_src = src_n->cfg_src; - for(RD_Entity *src_child = task->src_n->first; !rd_entity_is_nil(src_child); src_child = src_child->next) - { - Task *child_task = push_array(scratch.arena, Task, 1); - child_task->src_n = src_child; - child_task->dst_parent = dst_n; - SLLQueuePush(first_task, last_task, child_task); - } - } + RD_Cfg *cnd = rd_cfg_child_from_string_or_alloc(cfg, str8_lit("condition")); + rd_cfg_new(cnd, rd_regs()->string); + } + else + { + rd_cfg_release(rd_cfg_child_from_string(cfg, str8_lit("condition"))); } }break; - case RD_CmdKind_RelocateEntity: + case RD_CmdKind_DuplicateCfg: { - RD_Entity *entity = rd_entity_from_handle(rd_regs()->entity); - RD_Entity *location = rd_entity_child_from_kind(entity, RD_EntityKind_Location); - if(rd_entity_is_nil(location)) + RD_Cfg *src = rd_cfg_from_handle(rd_regs()->cfg); + RD_Cfg *dst = rd_cfg_deep_copy(src); + rd_cfg_insert_child(src->parent, src, dst); + }break; + case RD_CmdKind_RelocateCfg: + { + RD_Cfg *cfg = rd_cfg_from_handle(rd_regs()->cfg); + RD_Cfg *loc = rd_cfg_child_from_string_or_alloc(cfg, str8_lit("location")); + for(RD_Cfg *child = loc->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next) { - location = rd_entity_alloc(entity, RD_EntityKind_Location); + next = child->next; + rd_cfg_release(child); } - location->flags &= ~RD_EntityFlag_HasTextPoint; - location->flags &= ~RD_EntityFlag_HasVAddr; if(rd_regs()->cursor.line != 0) { - rd_entity_equip_txt_pt(location, rd_regs()->cursor); + RD_Cfg *file = rd_cfg_new(loc, rd_regs()->file_path); + RD_Cfg *line = rd_cfg_newf(file, "%I64d", rd_regs()->cursor.line); + rd_cfg_newf(line, "%I64d", rd_regs()->cursor.column); } - if(rd_regs()->vaddr != 0) + else if(rd_regs()->vaddr != 0) { - rd_entity_equip_vaddr(location, rd_regs()->vaddr); - rd_entity_equip_name(location, str8_zero()); + rd_cfg_newf(loc, "0x%I64x", rd_regs()->vaddr); } - if(rd_regs()->file_path.size != 0) + else if(rd_regs()->string.size != 0) { - rd_entity_equip_name(location, rd_regs()->file_path); + rd_cfg_new(loc, rd_regs()->string); } }break; @@ -16276,62 +16032,22 @@ X(getting_started) U64 vaddr = rd_regs()->vaddr; if(file_path.size != 0 || string.size != 0 || vaddr != 0) { - //- TODO(rjf): @cfg add/toggle breakpoint - { - B32 removed_already_existing = 0; - if(kind == RD_CmdKind_ToggleBreakpoint) - { - RD_CfgList bps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); - for(RD_CfgNode *n = bps.first; n != 0; n = n->next) - { - RD_Cfg *bp = n->v; - RD_Cfg *loc = rd_cfg_child_from_string(bp, str8_lit("location")); - S64 loc_line = 0; - U64 loc_vaddr = 0; - B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line); - B32 loc_matches_string = (string.size != 0 && str8_match(loc->first->string, string, 0)); - B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr); - if(loc_matches_file_pt || loc_matches_string || loc_matches_vaddr) - { - rd_cfg_release(bp); - removed_already_existing = 1; - break; - } - } - } - if(!removed_already_existing) - { - RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); - RD_Cfg *bp = rd_cfg_new(project, str8_lit("breakpoint")); - RD_Cfg *loc = rd_cfg_new(bp, str8_lit("location")); - if(vaddr != 0) - { - rd_cfg_newf(loc, "0x%I64x", vaddr); - } - else if(string.size != 0) - { - rd_cfg_new(loc, string); - } - else if(file_path.size != 0) - { - RD_Cfg *file_path_cfg = rd_cfg_new(loc, file_path); - rd_cfg_newf(file_path_cfg, "%I64d", pt.line); - } - } - } B32 removed_already_existing = 0; if(kind == RD_CmdKind_ToggleBreakpoint) { - RD_EntityList bps = rd_query_cached_entity_list_with_kind(RD_EntityKind_Breakpoint); - for(RD_EntityNode *n = bps.first; n != 0; n = n->next) + RD_CfgList bps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); + for(RD_CfgNode *n = bps.first; n != 0; n = n->next) { - RD_Entity *bp = n->entity; - RD_Entity *loc = rd_entity_child_from_kind(bp, RD_EntityKind_Location); - if((loc->flags & RD_EntityFlag_HasTextPoint && path_match_normalized(loc->string, file_path) && loc->text_point.line == pt.line) || - (loc->flags & RD_EntityFlag_HasVAddr && loc->vaddr == vaddr) || - (!(loc->flags & RD_EntityFlag_HasTextPoint) && str8_match(loc->string, string, 0))) + RD_Cfg *bp = n->v; + RD_Cfg *loc = rd_cfg_child_from_string(bp, str8_lit("location")); + S64 loc_line = 0; + U64 loc_vaddr = 0; + B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line); + B32 loc_matches_string = (string.size != 0 && str8_match(loc->first->string, string, 0)); + B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr); + if(loc_matches_file_pt || loc_matches_string || loc_matches_vaddr) { - rd_entity_mark_for_deletion(bp); + rd_cfg_release(bp); removed_already_existing = 1; break; } @@ -16339,21 +16055,21 @@ X(getting_started) } if(!removed_already_existing) { - RD_Entity *bp = rd_entity_alloc(rd_entity_root(), RD_EntityKind_Breakpoint); - rd_entity_equip_cfg_src(bp, RD_CfgSrc_Project); - RD_Entity *loc = rd_entity_alloc(bp, RD_EntityKind_Location); + RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); + RD_Cfg *bp = rd_cfg_new(project, str8_lit("breakpoint")); + RD_Cfg *loc = rd_cfg_new(bp, str8_lit("location")); if(vaddr != 0) { - rd_entity_equip_vaddr(loc, vaddr); + rd_cfg_newf(loc, "0x%I64x", vaddr); } else if(string.size != 0) { - rd_entity_equip_name(loc, string); + rd_cfg_new(loc, string); } - else if(file_path.size != 0 && pt.line != 0) + else if(file_path.size != 0) { - rd_entity_equip_name(loc, file_path); - rd_entity_equip_txt_pt(loc, pt); + RD_Cfg *file_path_cfg = rd_cfg_new(loc, file_path); + rd_cfg_newf(file_path_cfg, "%I64d", pt.line); } } } @@ -16375,61 +16091,23 @@ X(getting_started) TxtPt pt = rd_regs()->cursor; String8 string = rd_regs()->string; U64 vaddr = rd_regs()->vaddr; - //- TODO(rjf): @cfg add/toggle watch pin - { - B32 removed_already_existing = 0; - if(kind == RD_CmdKind_ToggleWatchPin) - { - RD_CfgList wps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("watch_pin")); - for(RD_CfgNode *n = wps.first; n != 0; n = n->next) - { - RD_Cfg *wp = n->v; - RD_Cfg *expr = rd_cfg_child_from_string(wp, str8_lit("expression")); - RD_Cfg *loc = rd_cfg_child_from_string(wp, str8_lit("location")); - S64 loc_line = 0; - U64 loc_vaddr = 0; - B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line); - B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr); - B32 loc_matches_expr = (string.size != 0 && str8_match(expr->first->string, string, 0)); - if(loc_matches_expr && (loc_matches_file_pt || loc_matches_vaddr)) - { - rd_cfg_release(wp); - removed_already_existing = 1; - break; - } - } - } - if(!removed_already_existing) - { - RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); - RD_Cfg *wp = rd_cfg_new(project, str8_lit("watch_pin")); - RD_Cfg *expr = rd_cfg_new(wp, str8_lit("expression")); - RD_Cfg *loc = rd_cfg_new(wp, str8_lit("location")); - rd_cfg_new(expr, string); - if(vaddr != 0) - { - rd_cfg_newf(loc, "0x%I64x", vaddr); - } - else if(file_path.size != 0) - { - RD_Cfg *file_path_cfg = rd_cfg_new(loc, file_path); - rd_cfg_newf(file_path_cfg, "%I64d", pt.line); - } - } - } B32 removed_already_existing = 0; if(kind == RD_CmdKind_ToggleWatchPin) { - RD_EntityList wps = rd_query_cached_entity_list_with_kind(RD_EntityKind_WatchPin); - for(RD_EntityNode *n = wps.first; n != 0; n = n->next) + RD_CfgList wps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("watch_pin")); + for(RD_CfgNode *n = wps.first; n != 0; n = n->next) { - RD_Entity *wp = n->entity; - RD_Entity *loc = rd_entity_child_from_kind(wp, RD_EntityKind_Location); - if(str8_match(wp->string, string, 0) && - ((loc->flags & RD_EntityFlag_HasTextPoint && path_match_normalized(loc->string, file_path) && loc->text_point.line == pt.line) || - (loc->flags & RD_EntityFlag_HasVAddr && loc->vaddr == vaddr))) + RD_Cfg *wp = n->v; + RD_Cfg *expr = rd_cfg_child_from_string(wp, str8_lit("expression")); + RD_Cfg *loc = rd_cfg_child_from_string(wp, str8_lit("location")); + S64 loc_line = 0; + U64 loc_vaddr = 0; + B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line); + B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr); + B32 loc_matches_expr = (string.size != 0 && str8_match(expr->first->string, string, 0)); + if(loc_matches_expr && (loc_matches_file_pt || loc_matches_vaddr)) { - rd_entity_mark_for_deletion(wp); + rd_cfg_release(wp); removed_already_existing = 1; break; } @@ -16437,18 +16115,19 @@ X(getting_started) } if(!removed_already_existing) { - RD_Entity *wp = rd_entity_alloc(rd_entity_root(), RD_EntityKind_WatchPin); - rd_entity_equip_name(wp, string); - rd_entity_equip_cfg_src(wp, RD_CfgSrc_Project); - RD_Entity *loc = rd_entity_alloc(wp, RD_EntityKind_Location); - if(file_path.size != 0 && pt.line != 0) + RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); + RD_Cfg *wp = rd_cfg_new(project, str8_lit("watch_pin")); + RD_Cfg *expr = rd_cfg_new(wp, str8_lit("expression")); + RD_Cfg *loc = rd_cfg_new(wp, str8_lit("location")); + rd_cfg_new(expr, string); + if(vaddr != 0) { - rd_entity_equip_name(loc, file_path); - rd_entity_equip_txt_pt(loc, pt); + rd_cfg_newf(loc, "0x%I64x", vaddr); } - else if(vaddr != 0) + else if(file_path.size != 0) { - rd_entity_equip_vaddr(loc, vaddr); + RD_Cfg *file_path_cfg = rd_cfg_new(loc, file_path); + rd_cfg_newf(file_path_cfg, "%I64d", pt.line); } } }break; @@ -16526,37 +16205,18 @@ X(getting_started) //- rjf: targets case RD_CmdKind_AddTarget: { - //- TODO(rjf): @cfg add new target + String8 file_path = rd_regs()->file_path; + RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); + RD_Cfg *target = rd_cfg_new(project, str8_lit("target")); + RD_Cfg *exe = rd_cfg_new(target, str8_lit("executable")); + rd_cfg_new(exe, file_path); + String8 working_directory = str8_chop_last_slash(file_path); + if(working_directory.size != 0) { - String8 file_path = rd_regs()->file_path; - RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); - RD_Cfg *target = rd_cfg_new(project, str8_lit("target")); - RD_Cfg *exe = rd_cfg_new(target, str8_lit("executable")); - rd_cfg_new(exe, file_path); - String8 working_directory = str8_chop_last_slash(file_path); - if(working_directory.size != 0) - { - RD_Cfg *wdir = rd_cfg_new(target, str8_lit("working_directory")); - rd_cfg_newf(wdir, "%S/", working_directory); - } - // TODO(rjf): (select target here) + RD_Cfg *wdir = rd_cfg_new(target, str8_lit("working_directory")); + rd_cfg_newf(wdir, "%S/", working_directory); } - - // rjf: build target - RD_Entity *entity = &rd_nil_entity; - entity = rd_entity_alloc(rd_entity_root(), RD_EntityKind_Target); - rd_entity_equip_disabled(entity, 1); - rd_entity_equip_cfg_src(entity, RD_CfgSrc_Project); - RD_Entity *exe = rd_entity_alloc(entity, RD_EntityKind_Executable); - rd_entity_equip_name(exe, rd_regs()->file_path); - String8 working_dir = str8_chop_last_slash(rd_regs()->file_path); - if(working_dir.size != 0) - { - String8 working_dir_path = push_str8f(scratch.arena, "%S/", working_dir); - RD_Entity *execution_path = rd_entity_alloc(entity, RD_EntityKind_WorkingDirectory); - rd_entity_equip_name(execution_path, working_dir_path); - } - rd_cmd(RD_CmdKind_SelectTarget, .entity = rd_handle_from_entity(entity)); + rd_cmd(RD_CmdKind_SelectCfg, .cfg = rd_handle_from_cfg(target)); }break; //- rjf: jit-debugger registration @@ -17222,20 +16882,21 @@ X(getting_started) U64 meval_count = 0; MetaEvalNode *first_meval = 0; MetaEvalNode *last_meval = 0; - RD_EntityList bp_entities = rd_query_cached_entity_list_with_kind(RD_EntityKind_Breakpoint); - breakpoints.count = bp_entities.count; + RD_CfgList bp_cfgs = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); + breakpoints.count = bp_cfgs.count; breakpoints.v = push_array(scratch.arena, D_Breakpoint, breakpoints.count); U64 idx = 0; - for(RD_EntityNode *n = bp_entities.first; n != 0; n = n->next) + for(RD_CfgNode *n = bp_cfgs.first; n != 0; n = n->next) { - RD_Entity *src_bp = n->entity; - if(src_bp->disabled) + RD_Cfg *src_bp = n->v; + B32 src_bp_is_disabled = rd_disabled_from_cfg(src_bp); + if(src_bp_is_disabled) { breakpoints.count -= 1; continue; } - RD_Entity *src_bp_loc = rd_entity_child_from_kind(src_bp, RD_EntityKind_Location); - RD_Entity *src_bp_cnd = rd_entity_child_from_kind(src_bp, RD_EntityKind_Condition); + RD_Location src_bp_loc = rd_location_from_cfg(src_bp); + String8 src_bp_cnd = rd_cfg_child_from_string(src_bp, str8_lit("condition"))->first->string; //- rjf: walk conditional breakpoint expression tree - for each leaf identifier, // determine if it resolves to a meta-evaluation. if it does, compute the meta @@ -17248,7 +16909,7 @@ X(getting_started) // or not it is 'static', w.r.t. the control thread. // B32 is_static_for_ctrl_thread = 0; - if(src_bp_cnd->string.size != 0) + if(src_bp_cnd.size != 0) { typedef struct ExprWalkTask ExprWalkTask; struct ExprWalkTask @@ -17256,7 +16917,7 @@ X(getting_started) ExprWalkTask *next; E_Expr *expr; }; - E_Expr *expr = e_parse_expr_from_text(scratch.arena, src_bp_cnd->string); + E_Expr *expr = e_parse_expr_from_text(scratch.arena, src_bp_cnd); ExprWalkTask start_task = {0, expr}; ExprWalkTask *first_task = &start_task; for(ExprWalkTask *t = first_task; t != 0; t = t->next) @@ -17302,7 +16963,7 @@ X(getting_started) B32 is_statically_disqualified = 0; if(is_static_for_ctrl_thread) { - E_Eval eval = e_eval_from_string(scratch.arena, src_bp_cnd->string); + E_Eval eval = e_eval_from_string(scratch.arena, src_bp_cnd); E_Eval value_eval = e_value_eval_from_eval(eval); if(value_eval.value.u64 == 0) { @@ -17319,11 +16980,11 @@ X(getting_started) //- rjf: fill breakpoint D_Breakpoint *dst_bp = &breakpoints.v[idx]; - dst_bp->file_path = src_bp_loc->string; - dst_bp->pt = src_bp_loc->text_point; - dst_bp->symbol_name = src_bp_loc->string; - dst_bp->vaddr = src_bp_loc->vaddr; - dst_bp->condition = src_bp_cnd->string; + dst_bp->file_path = src_bp_loc.file_path; + dst_bp->pt = src_bp_loc.pt; + dst_bp->symbol_name = src_bp_loc.name; + dst_bp->vaddr = src_bp_loc.vaddr; + dst_bp->condition = src_bp_cnd; idx += 1; } @@ -17345,15 +17006,15 @@ X(getting_started) // D_PathMapArray path_maps = {0}; { - RD_EntityList maps = rd_query_cached_entity_list_with_kind(RD_EntityKind_FilePathMap); + RD_CfgList maps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("file_path_map")); path_maps.count = maps.count; path_maps.v = push_array(scratch.arena, D_PathMap, path_maps.count); U64 idx = 0; - for(RD_EntityNode *n = maps.first; n != 0; n = n->next, idx += 1) + for(RD_CfgNode *n = maps.first; n != 0; n = n->next, idx += 1) { - RD_Entity *map = n->entity; - path_maps.v[idx].src = rd_entity_child_from_kind(map, RD_EntityKind_Source)->string; - path_maps.v[idx].dst = rd_entity_child_from_kind(map, RD_EntityKind_Dest)->string; + RD_Cfg *map = n->v; + path_maps.v[idx].src = rd_cfg_child_from_string(map, str8_lit("source"))->first->string; + path_maps.v[idx].dst = rd_cfg_child_from_string(map, str8_lit("dest"))->first->string; } } @@ -17428,35 +17089,40 @@ X(getting_started) // rjf: increment breakpoint hit counts if(evt->cause == D_EventCause_UserBreakpoint) { - RD_EntityList user_bps = rd_query_cached_entity_list_with_kind(RD_EntityKind_Breakpoint); - for(RD_EntityNode *n = user_bps.first; n != 0; n = n->next) + RD_CfgList bps = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); + for(RD_CfgNode *n = bps.first; n != 0; n = n->next) { - RD_Entity *bp = n->entity; - RD_Entity *loc = rd_entity_child_from_kind(bp, RD_EntityKind_Location); - D_LineList loc_lines = d_lines_from_file_path_line_num(scratch.arena, loc->string, loc->text_point.line); + RD_Cfg *bp = n->v; + RD_Cfg *hit_count_root = rd_cfg_child_from_string_or_alloc(bp, str8_lit("hit_count")); + U64 hit_count = 0; + try_u64_from_str8_c_rules(hit_count_root->first->string, &hit_count); + RD_Location loc = rd_location_from_cfg(bp); + D_LineList loc_lines = d_lines_from_file_path_line_num(scratch.arena, loc.file_path, loc.pt.line); if(loc_lines.first != 0) { for(D_LineNode *n = loc_lines.first; n != 0; n = n->next) { if(contains_1u64(n->v.voff_range, voff)) { - bp->u64 += 1; + hit_count += 1; break; } } } - else if(loc->flags & RD_EntityFlag_HasVAddr && vaddr == loc->vaddr) + else if(loc.vaddr != 0 && vaddr == loc.vaddr) { - bp->u64 += 1; + hit_count += 1; } - else if(loc->string.size != 0) + else if(loc.name.size != 0) { - U64 symb_voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, loc->string); + U64 symb_voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, loc.name); if(symb_voff == voff) { - bp->u64 += 1; + hit_count += 1; } } + rd_cfg_release_all_children(hit_count_root); + rd_cfg_newf(hit_count_root, "%I64u", hit_count); } } diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index a2421f7d..fc8e2169 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -1138,6 +1138,7 @@ internal void rd_name_release(String8 string); internal RD_Cfg *rd_cfg_alloc(void); internal void rd_cfg_release(RD_Cfg *cfg); +internal void rd_cfg_release_all_children(RD_Cfg *cfg); internal RD_Handle rd_handle_from_cfg(RD_Cfg *cfg); internal RD_Cfg *rd_cfg_from_handle(RD_Handle handle); internal RD_Cfg *rd_cfg_new(RD_Cfg *parent, String8 string); @@ -1218,7 +1219,6 @@ internal RD_Entity *rd_entity_from_name_and_kind(String8 string, RD_EntityKind k //////////////////////////////// //~ rjf: Frontend Entity Info Extraction -internal D_Target rd_d_target_from_entity(RD_Entity *entity); internal DR_FancyStringList rd_title_fstrs_from_entity(Arena *arena, RD_Entity *entity, Vec4F32 secondary_color, F32 size); //////////////////////////////// diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 1430e47d..2ab0280b 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1274,6 +1274,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo //- rjf: unpack arguments // EV_ViewRuleList *top_level_view_rules = ev_view_rule_list_from_string(scratch.arena, root_view_rule); + EV_ColList top_level_cols = {0}; String8 eval_view_key_string = push_str8f(scratch.arena, "eval_view_watch_%p", ewv); EV_View *eval_view = rd_ev_view_from_key(d_hash_from_string(eval_view_key_string)); String8 filter = rd_view_filter(); @@ -1285,6 +1286,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo { string_flags |= EV_StringFlag_PrettyNames; } +#if 0 // TODO(rjf): @cfg RD_WatchViewRowCtrl row_ctrls_[] = { {RD_EntityKind_Target, CTRL_EntityKind_Null, RD_CmdKind_LaunchAndRun }, @@ -1303,6 +1305,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo }; RD_WatchViewRowCtrl *row_ctrls = row_ctrls_; U64 row_ctrls_count = ArrayCount(row_ctrls_); +#endif ////////////////////////////// //- rjf: root-level view rule which has a ui hook? call into that to build the UI @@ -1371,7 +1374,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo MemoryZeroStruct(&block_tree); MemoryZeroStruct(&block_ranges); ev_key_set_expansion(eval_view, ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); - block_tree = ev_block_tree_from_string(scratch.arena, eval_view, filter, root_expr, top_level_view_rules); + block_tree = ev_block_tree_from_string(scratch.arena, eval_view, filter, root_expr, top_level_view_rules, &top_level_cols); block_ranges = ev_block_range_list_from_tree(scratch.arena, &block_tree); } @@ -1467,6 +1470,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo if(row_kind == RD_WatchViewRowKind_PrettyEntityControls) { U64 row_ctrl_count = 0; +#if 0 // TODO(rjf): @cfg for EachIndex(idx, row_ctrls_count) { if(row_ctrls[idx].entity_kind == row_info.collection_entity->kind && @@ -1475,6 +1479,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo row_ctrl_count += 1; } } +#endif cursor_x_range = r1s64(1, 1+row_ctrl_count); } } @@ -2725,6 +2730,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo } if(ui_double_clicked(sig)) { +#if 0 // TODO(rjf): @cfg if(entity->kind == RD_EntityKind_Target) { rd_cmd(sig.event_flags & OS_Modifier_Ctrl && entity->disabled ? RD_CmdKind_EnableEntity : @@ -2744,6 +2750,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo .cursor = loc->text_point, .vaddr = loc->vaddr); } +#endif } } } @@ -2751,6 +2758,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo //- rjf: build extra entity controls UI_PrefWidth(ui_em(3.f, 1.f)) { +#if 0 // TODO(rjf): @cfg U64 ctrl_idx = 1; for EachIndex(idx, row_ctrls_count) { @@ -2818,6 +2826,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo ctrl_idx += 1; } } +#endif } } }break; @@ -3592,1811 +3601,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(getting_started) ProfEnd(); } -//////////////////////////////// -//~ rjf: commands @view_hook_impl - -typedef struct RD_CmdListerItem RD_CmdListerItem; -struct RD_CmdListerItem -{ - String8 cmd_name; - U64 registrar_idx; - U64 ordering_idx; - FuzzyMatchRangeList name_match_ranges; - FuzzyMatchRangeList desc_match_ranges; - FuzzyMatchRangeList tags_match_ranges; -}; - -typedef struct RD_CmdListerItemNode RD_CmdListerItemNode; -struct RD_CmdListerItemNode -{ - RD_CmdListerItemNode *next; - RD_CmdListerItem item; -}; - -typedef struct RD_CmdListerItemList RD_CmdListerItemList; -struct RD_CmdListerItemList -{ - RD_CmdListerItemNode *first; - RD_CmdListerItemNode *last; - U64 count; -}; - -typedef struct RD_CmdListerItemArray RD_CmdListerItemArray; -struct RD_CmdListerItemArray -{ - RD_CmdListerItem *v; - U64 count; -}; - -internal RD_CmdListerItemList -rd_cmd_lister_item_list_from_needle(Arena *arena, String8 needle) -{ - Temp scratch = scratch_begin(&arena, 1); - RD_CmdListerItemList result = {0}; - // TODO(rjf): extend this with dynamically-registered command info - for EachNonZeroEnumVal(RD_CmdKind, k) - { - RD_CmdKindInfo *info = &rd_cmd_kind_info_table[k]; - if(info->flags & RD_CmdKindFlag_ListInUI) - { - String8 cmd_display_name = info->display_name; - String8 cmd_desc = info->description; - String8 cmd_tags = info->search_tags; - FuzzyMatchRangeList name_matches = fuzzy_match_find(arena, needle, cmd_display_name); - FuzzyMatchRangeList desc_matches = fuzzy_match_find(arena, needle, cmd_desc); - FuzzyMatchRangeList tags_matches = fuzzy_match_find(arena, needle, cmd_tags); - if(name_matches.count == name_matches.needle_part_count || - desc_matches.count == name_matches.needle_part_count || - tags_matches.count > 0 || - name_matches.needle_part_count == 0) - { - RD_CmdListerItemNode *node = push_array(arena, RD_CmdListerItemNode, 1); - node->item.cmd_name = info->string; - node->item.registrar_idx = (U64)k; - node->item.ordering_idx = (U64)k; - node->item.name_match_ranges = name_matches; - node->item.desc_match_ranges = desc_matches; - node->item.tags_match_ranges = tags_matches; - SLLQueuePush(result.first, result.last, node); - result.count += 1; - } - } - } - scratch_end(scratch); - return result; -} - -internal RD_CmdListerItemArray -rd_cmd_lister_item_array_from_list(Arena *arena, RD_CmdListerItemList list) -{ - RD_CmdListerItemArray result = {0}; - result.count = list.count; - result.v = push_array(arena, RD_CmdListerItem, result.count); - U64 idx = 0; - for(RD_CmdListerItemNode *n = list.first; n != 0; n = n->next, idx += 1) - { - result.v[idx] = n->item; - } - return result; -} - -internal int -rd_qsort_compare_cmd_lister__strength(RD_CmdListerItem *a, RD_CmdListerItem *b) -{ - int result = 0; - if(a->name_match_ranges.count > b->name_match_ranges.count) - { - result = -1; - } - else if(a->name_match_ranges.count < b->name_match_ranges.count) - { - result = +1; - } - else if(a->desc_match_ranges.count > b->desc_match_ranges.count) - { - result = -1; - } - else if(a->desc_match_ranges.count < b->desc_match_ranges.count) - { - result = +1; - } - else if(a->tags_match_ranges.count > b->tags_match_ranges.count) - { - result = -1; - } - else if(a->tags_match_ranges.count < b->tags_match_ranges.count) - { - result = +1; - } - else if(a->registrar_idx < b->registrar_idx) - { - result = -1; - } - else if(a->registrar_idx > b->registrar_idx) - { - result = +1; - } - else if(a->ordering_idx < b->ordering_idx) - { - result = -1; - } - else if(a->ordering_idx > b->ordering_idx) - { - result = +1; - } - return result; -} - -internal void -rd_cmd_lister_item_array_sort_by_strength__in_place(RD_CmdListerItemArray array) -{ - quick_sort(array.v, array.count, sizeof(RD_CmdListerItem), rd_qsort_compare_cmd_lister__strength); -} - -RD_VIEW_RULE_UI_FUNCTION_DEF(commands) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); - - //- rjf: grab state - typedef struct RD_CmdsViewState RD_CmdsViewState; - struct RD_CmdsViewState - { - U64 selected_cmd_hash; - }; - UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); - RD_CmdsViewState *cv = rd_view_state(RD_CmdsViewState); - - //- rjf: build filtered array of commands - RD_CmdListerItemList cmd_list = rd_cmd_lister_item_list_from_needle(scratch.arena, string); - RD_CmdListerItemArray cmd_array = rd_cmd_lister_item_array_from_list(scratch.arena, cmd_list); - rd_cmd_lister_item_array_sort_by_strength__in_place(cmd_array); - - //- rjf: submit best match when hitting enter w/ no selection - if(cv->selected_cmd_hash == 0 && ui_slot_press(UI_EventActionSlot_Accept)) - { - rd_cmd(RD_CmdKind_CompleteQuery, .cmd_name = (cmd_array.count > 0 ? cmd_array.v[0].cmd_name : str8_zero())); - } - - //- rjf: selected kind -> cursor - Vec2S64 cursor = {0}; - { - for(U64 idx = 0; idx < cmd_array.count; idx += 1) - { - if(d_hash_from_string(cmd_array.v[idx].cmd_name) == cv->selected_cmd_hash) - { - cursor.y = (S64)idx+1; - break; - } - } - } - - //- rjf: build contents - Rng1S64 visible_row_range = {0}; - UI_ScrollListParams scroll_list_params = {0}; - { - scroll_list_params.flags = UI_ScrollListFlag_All; - scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*6.5f); - scroll_list_params.dim_px = dim_2f32(rect); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, cmd_array.count)); - scroll_list_params.item_range = r1s64(0, cmd_array.count); - scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; - } - UI_ScrollListSignal scroll_list_sig = {0}; - UI_Focus(UI_FocusKind_On) - UI_ScrollList(&scroll_list_params, - &scroll_pos.y, - &cursor, - 0, - &visible_row_range, - &scroll_list_sig) - UI_Focus(UI_FocusKind_Null) - { - //- rjf: build buttons - for(S64 row_idx = visible_row_range.min; - row_idx <= visible_row_range.max && row_idx < cmd_array.count; - row_idx += 1) - { - RD_CmdListerItem *item = &cmd_array.v[row_idx]; - RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(item->cmd_name); - - //- rjf: build row contents - ui_set_next_hover_cursor(OS_Cursor_HandPoint); - ui_set_next_child_layout_axis(Axis2_X); - UI_Box *box = &ui_nil_box; - UI_Focus(cursor.y == row_idx+1 ? UI_FocusKind_On : UI_FocusKind_Off) - { - box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawBackground| - UI_BoxFlag_DrawHotEffects| - UI_BoxFlag_DrawActiveEffects, - "###cmd_button_%S", item->cmd_name); - } - UI_Parent(box) UI_PrefHeight(ui_em(1.65f, 1.f)) - { - //- rjf: icon - UI_PrefWidth(ui_em(3.f, 1.f)) - UI_HeightFill - UI_Column - RD_Font(RD_FontSlot_Icons) - UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Icons)) - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - UI_HeightFill - UI_TextAlignment(UI_TextAlign_Center) - { - RD_IconKind icon = info->icon_kind; - if(icon != RD_IconKind_Null) - { - ui_label(rd_icon_kind_text_table[icon]); - } - } - - //- rjf: name + description - ui_set_next_pref_height(ui_pct(1, 0)); - UI_Column UI_Padding(ui_pct(1, 0)) - { - FNT_Tag font = ui_top_font(); - F32 font_size = ui_top_font_size(); - FNT_Metrics font_metrics = fnt_metrics_from_tag_size(font, font_size); - F32 font_line_height = fnt_line_height_from_metrics(&font_metrics); - String8 cmd_display_name = info->display_name; - String8 cmd_desc = info->description; - UI_Box *name_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "%S##name_%S", cmd_display_name, info->string); - UI_Box *desc_box = &ui_nil_box; - UI_PrefHeight(ui_em(1.8f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - { - desc_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "%S##desc_%S", cmd_desc, info->string); - } - ui_box_equip_fuzzy_match_ranges(name_box, &item->name_match_ranges); - ui_box_equip_fuzzy_match_ranges(desc_box, &item->desc_match_ranges); - } - - //- rjf: bindings - ui_set_next_flags(UI_BoxFlag_Clickable); - UI_PrefWidth(ui_children_sum(1.f)) UI_HeightFill UI_NamedColumn(str8_lit("binding_column")) UI_Padding(ui_em(1.5f, 1.f)) - { - ui_set_next_flags(UI_BoxFlag_Clickable); - UI_NamedRow(str8_lit("binding_row")) UI_Padding(ui_em(1.f, 1.f)) - { - rd_cmd_binding_buttons(item->cmd_name); - } - } - } - - //- rjf: interact - UI_Signal sig = ui_signal_from_box(box); - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_CompleteQuery, .cmd_name = item->cmd_name); - } - } - } - - //- rjf: map selected num -> selected kind - if(1 <= cursor.y && cursor.y <= cmd_array.count) - { - cv->selected_cmd_hash = d_hash_from_string(cmd_array.v[cursor.y-1].cmd_name); - } - else - { - cv->selected_cmd_hash = 0; - } - - rd_store_view_scroll_pos(scroll_pos); - scratch_end(scratch); - ProfEnd(); -} - -//////////////////////////////// -//~ rjf: file_system @view_hook_impl - -typedef enum RD_FileSortKind -{ - RD_FileSortKind_Null, - RD_FileSortKind_Filename, - RD_FileSortKind_LastModified, - RD_FileSortKind_Size, - RD_FileSortKind_COUNT -} -RD_FileSortKind; - -typedef struct RD_FileInfo RD_FileInfo; -struct RD_FileInfo -{ - String8 filename; - FileProperties props; - FuzzyMatchRangeList match_ranges; -}; - -typedef struct RD_FileInfoNode RD_FileInfoNode; -struct RD_FileInfoNode -{ - RD_FileInfoNode *next; - RD_FileInfo file_info; -}; - -typedef struct RD_FileSystemViewPathState RD_FileSystemViewPathState; -struct RD_FileSystemViewPathState -{ - RD_FileSystemViewPathState *hash_next; - String8 normalized_path; - Vec2S64 cursor; -}; - -typedef struct RD_FileSystemViewState RD_FileSystemViewState; -struct RD_FileSystemViewState -{ - B32 initialized; - U64 path_state_table_size; - RD_FileSystemViewPathState **path_state_table; - RD_FileSortKind sort_kind; - Side sort_side; - Arena *cached_files_arena; - String8 cached_files_path; - RD_FileSortKind cached_files_sort_kind; - Side cached_files_sort_side; - U64 cached_file_count; - RD_FileInfo *cached_files; - F32 col_pcts[3]; -}; - -typedef struct RD_PathQuery RD_PathQuery; -struct RD_PathQuery -{ - String8 prefix; - String8 path; - String8 search; -}; - -internal RD_PathQuery -rd_path_query_from_string(String8 string) -{ - String8 dir_str_in_input = {0}; - for(U64 i = 0; i < string.size; i += 1) - { - String8 substr1 = str8_substr(string, r1u64(i, i+1)); - String8 substr2 = str8_substr(string, r1u64(i, i+2)); - String8 substr3 = str8_substr(string, r1u64(i, i+3)); - if(str8_match(substr1, str8_lit("/"), StringMatchFlag_SlashInsensitive)) - { - dir_str_in_input = str8_substr(string, r1u64(i, string.size)); - } - else if(i != 0 && str8_match(substr2, str8_lit(":/"), StringMatchFlag_SlashInsensitive)) - { - dir_str_in_input = str8_substr(string, r1u64(i-1, string.size)); - } - else if(str8_match(substr2, str8_lit("./"), StringMatchFlag_SlashInsensitive)) - { - dir_str_in_input = str8_substr(string, r1u64(i, string.size)); - } - else if(str8_match(substr3, str8_lit("../"), StringMatchFlag_SlashInsensitive)) - { - dir_str_in_input = str8_substr(string, r1u64(i, string.size)); - } - if(dir_str_in_input.size != 0) - { - break; - } - } - - RD_PathQuery path_query = {0}; - if(dir_str_in_input.size != 0) - { - String8 dir = dir_str_in_input; - String8 search = {0}; - U64 one_past_last_slash = dir.size; - for(U64 i = 0; i < dir_str_in_input.size; i += 1) - { - if(dir_str_in_input.str[i] == '/' || dir_str_in_input.str[i] == '\\') - { - one_past_last_slash = i+1; - } - } - dir.size = one_past_last_slash; - search = str8_substr(dir_str_in_input, r1u64(one_past_last_slash, dir_str_in_input.size)); - path_query.path = dir; - path_query.search = search; - path_query.prefix = str8_substr(string, r1u64(0, path_query.path.str - string.str)); - } - return path_query; -} - -internal int -rd_qsort_compare_file_info__filename(RD_FileInfo *a, RD_FileInfo *b) -{ - return strncmp((char *)a->filename.str, (char *)b->filename.str, Min(a->filename.size, b->filename.size)); -} - -internal int -rd_qsort_compare_file_info__default(RD_FileInfo *a, RD_FileInfo *b) -{ - int result = 0; - if(a->props.flags & FilePropertyFlag_IsFolder && !(b->props.flags & FilePropertyFlag_IsFolder)) - { - result = -1; - } - else if(b->props.flags & FilePropertyFlag_IsFolder && !(a->props.flags & FilePropertyFlag_IsFolder)) - { - result = +1; - } - else - { - result = rd_qsort_compare_file_info__filename(a, b); - } - return result; -} - -internal int -rd_qsort_compare_file_info__default_filtered(RD_FileInfo *a, RD_FileInfo *b) -{ - int result = 0; - if(a->filename.size < b->filename.size) - { - result = -1; - } - else if(a->filename.size > b->filename.size) - { - result = +1; - } - return result; -} - -internal int -rd_qsort_compare_file_info__last_modified(RD_FileInfo *a, RD_FileInfo *b) -{ - return ((a->props.modified < b->props.modified) ? -1 : - (a->props.modified > b->props.modified) ? +1 : - 0); -} - -internal int -rd_qsort_compare_file_info__size(RD_FileInfo *a, RD_FileInfo *b) -{ - return ((a->props.size < b->props.size) ? -1 : - (a->props.size > b->props.size) ? +1 : - 0); -} - -RD_VIEW_RULE_UI_FUNCTION_DEF(file_system) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); - String8 query = string; - String8 query_normalized = path_normalized_from_string(scratch.arena, query); - B32 query_has_slash = (query.size != 0 && char_to_correct_slash(query.str[query.size-1]) == '/'); - String8 query_normalized_with_opt_slash = push_str8f(scratch.arena, "%S%s", query_normalized, query_has_slash ? "/" : ""); - RD_PathQuery path_query = rd_path_query_from_string(query_normalized_with_opt_slash); - F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); - F32 scroll_bar_dim = floor_f32(ui_top_font_size()*1.5f); -#if 0 // TODO(rjf): @cfg - RD_Window *window = rd_window_from_handle(rd_regs()->window); - RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(window->query_cmd_name); -#endif - B32 file_selection = 1;// !!(cmd_kind_info->query.flags & RD_QueryFlag_AllowFiles); - B32 dir_selection = 1;// !!(cmd_kind_info->query.flags & RD_QueryFlag_AllowFolders); - - //- rjf: get extra state for this view - UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); - RD_FileSystemViewState *fs = rd_view_state(RD_FileSystemViewState); - if(fs->initialized == 0) - { - fs->initialized = 1; - fs->path_state_table_size = 256; - fs->path_state_table = push_array(rd_view_arena(), RD_FileSystemViewPathState *, fs->path_state_table_size); - fs->cached_files_arena = rd_push_view_arena(); - fs->col_pcts[0] = 0.60f; - fs->col_pcts[1] = 0.20f; - fs->col_pcts[2] = 0.20f; - } - - //- rjf: grab state for the current path - RD_FileSystemViewPathState *ps = 0; - { - String8 key = query_normalized; - U64 hash = d_hash_from_string(key); - U64 slot = hash % fs->path_state_table_size; - for(RD_FileSystemViewPathState *p = fs->path_state_table[slot]; p != 0; p = p->hash_next) - { - if(str8_match(p->normalized_path, key, 0)) - { - ps = p; - break; - } - } - if(ps == 0) - { - ps = push_array(rd_view_arena(), RD_FileSystemViewPathState, 1); - ps->hash_next = fs->path_state_table[slot]; - fs->path_state_table[slot] = ps; - ps->normalized_path = push_str8_copy(rd_view_arena(), key); - } - } - - //- rjf: get file array from the current path - U64 file_count = fs->cached_file_count; - RD_FileInfo *files = fs->cached_files; - if(!str8_match(fs->cached_files_path, query_normalized_with_opt_slash, 0) || - fs->cached_files_sort_kind != fs->sort_kind || - fs->cached_files_sort_side != fs->sort_side) - { - arena_clear(fs->cached_files_arena); - - //- rjf: store off path that we're gathering from - fs->cached_files_path = push_str8_copy(fs->cached_files_arena, query_normalized_with_opt_slash); - fs->cached_files_sort_kind = fs->sort_kind; - fs->cached_files_sort_side = fs->sort_side; - - //- rjf: use stored path as the new browse path for the whole frontend - // (multiple file system views may conflict here. that's okay. we'll just always - // choose the most recent change to a file browser path, and live with the - // consequences). - { - rd_cmd(RD_CmdKind_SetCurrentPath, .file_path = path_query.path); - } - - //- rjf: get files, filtered - U64 new_file_count = 0; - RD_FileInfoNode *first_file = 0; - RD_FileInfoNode *last_file = 0; - { - OS_FileIter *it = os_file_iter_begin(scratch.arena, path_query.path, 0); - for(OS_FileInfo info = {0}; os_file_iter_next(scratch.arena, it, &info);) - { - FuzzyMatchRangeList match_ranges = fuzzy_match_find(fs->cached_files_arena, path_query.search, info.name); - B32 fits_search = (path_query.search.size == 0 || match_ranges.count == match_ranges.needle_part_count); - B32 fits_dir_only = !!(info.props.flags & FilePropertyFlag_IsFolder) || !dir_selection; - if(fits_search && fits_dir_only) - { - RD_FileInfoNode *node = push_array(scratch.arena, RD_FileInfoNode, 1); - node->file_info.filename = push_str8_copy(fs->cached_files_arena, info.name); - node->file_info.props = info.props; - node->file_info.match_ranges = match_ranges; - SLLQueuePush(first_file, last_file, node); - new_file_count += 1; - } - } - os_file_iter_end(it); - } - - //- rjf: convert list to array - RD_FileInfo *new_files = push_array(fs->cached_files_arena, RD_FileInfo, new_file_count); - { - U64 idx = 0; - for(RD_FileInfoNode *n = first_file; n != 0; n = n->next, idx += 1) - { - new_files[idx] = n->file_info; - } - } - - //- rjf: apply sort - switch(fs->sort_kind) - { - default: - { - if(path_query.search.size != 0) - { - quick_sort(new_files, new_file_count, sizeof(RD_FileInfo), rd_qsort_compare_file_info__default_filtered); - } - else - { - quick_sort(new_files, new_file_count, sizeof(RD_FileInfo), rd_qsort_compare_file_info__default); - } - }break; - case RD_FileSortKind_Filename: - { - quick_sort(new_files, new_file_count, sizeof(RD_FileInfo), rd_qsort_compare_file_info__filename); - }break; - case RD_FileSortKind_LastModified: - { - quick_sort(new_files, new_file_count, sizeof(RD_FileInfo), rd_qsort_compare_file_info__last_modified); - }break; - case RD_FileSortKind_Size: - { - quick_sort(new_files, new_file_count, sizeof(RD_FileInfo), rd_qsort_compare_file_info__size); - }break; - } - - //- rjf: apply reverse - if(fs->sort_kind != RD_FileSortKind_Null && fs->sort_side == Side_Max) - { - for(U64 idx = 0; idx < new_file_count/2; idx += 1) - { - U64 rev_idx = new_file_count - idx - 1; - Swap(RD_FileInfo, new_files[idx], new_files[rev_idx]); - } - } - - fs->cached_file_count = file_count = new_file_count; - fs->cached_files = files = new_files; - } - - //- rjf: submit best match when hitting enter w/ no selection - if(ps->cursor.y == 0 && ui_slot_press(UI_EventActionSlot_Accept)) - { - FileProperties query_normalized_with_opt_slash_props = os_properties_from_file_path(query_normalized_with_opt_slash); - FileProperties path_query_path_props = os_properties_from_file_path(path_query.path); - - // rjf: command search part is empty, but directory matches some file: - if(path_query_path_props.created != 0 && path_query.search.size == 0) - { - rd_cmd(RD_CmdKind_CompleteQuery, .file_path = query_normalized_with_opt_slash); - } - - // rjf: command argument exactly matches some file: - else if(query_normalized_with_opt_slash_props.created != 0 && path_query.search.size != 0) - { - // rjf: is a folder -> autocomplete to slash - if(query_normalized_with_opt_slash_props.flags & FilePropertyFlag_IsFolder) - { - String8 new_path = push_str8f(scratch.arena, "%S%S/", path_query.path, path_query.search); - rd_store_view_filter(new_path); - } - - // rjf: is a file -> complete view - else - { - rd_cmd(RD_CmdKind_CompleteQuery, .file_path = query_normalized_with_opt_slash); - } - } - - // rjf: command argument is empty, picking folders -> use current folder - else if(path_query.search.size == 0 && dir_selection) - { - rd_cmd(RD_CmdKind_CompleteQuery, .file_path = path_query.path); - } - - // rjf: command argument does not exactly match any file, but lister results are in: - else if(file_count != 0) - { - String8 filename = files[0].filename; - if(files[0].props.flags & FilePropertyFlag_IsFolder) - { - String8 existing_path = str8_chop_last_slash(path_query.path); - String8 new_path = push_str8f(scratch.arena, "%S/%S/", existing_path, files[0].filename); - rd_store_view_filter(new_path); - } - else - { - String8 file_path = push_str8f(scratch.arena, "%S%S", path_query.path, filename); - rd_cmd(RD_CmdKind_CompleteQuery, .file_path = file_path); - } - } - - // rjf: command argument does not match any file, and lister is empty (new file) - else - { - rd_cmd(RD_CmdKind_CompleteQuery, .file_path = query); - } - } - - //- rjf: build non-scrolled table header - U64 row_num = 1; - F32 **col_pcts = push_array(scratch.arena, F32 *, ArrayCount(fs->col_pcts)); - for(U64 idx = 0; idx < ArrayCount(fs->col_pcts); idx += 1) - { - col_pcts[idx] = &fs->col_pcts[idx]; - } - UI_PrefHeight(ui_px(row_height_px, 1)) UI_Focus(UI_FocusKind_Off) UI_TableF(ArrayCount(fs->col_pcts), col_pcts, "###fs_tbl") - { - UI_TableVector - { - struct - { - RD_FileSortKind kind; - String8 string; - } - kinds[] = - { - { RD_FileSortKind_Filename, str8_lit_comp("Filename") }, - { RD_FileSortKind_LastModified, str8_lit_comp("Last Modified") }, - { RD_FileSortKind_Size, str8_lit_comp("Size") }, - }; - for(U64 idx = 0; idx < ArrayCount(kinds); idx += 1) - { - B32 sorting = (fs->sort_kind == kinds[idx].kind); - UI_TableCell UI_FlagsAdd(sorting ? 0 : UI_BoxFlag_DrawTextWeak) - { - UI_Signal sig = ui_sort_header(sorting, - fs->cached_files_sort_side == Side_Min, - kinds[idx].string); - if(ui_clicked(sig)) - { - if(fs->sort_kind != kinds[idx].kind) - { - fs->sort_kind = kinds[idx].kind; - fs->sort_side = Side_Max; - } - else if(fs->sort_kind == kinds[idx].kind && fs->sort_side == Side_Max) - { - fs->sort_side = Side_Min; - } - else if(fs->sort_kind == kinds[idx].kind && fs->sort_side == Side_Min) - { - fs->sort_kind = RD_FileSortKind_Null; - } - } - } - } - } - } - - //- rjf: build file list - Rng1S64 visible_row_range = {0}; - UI_ScrollListParams scroll_list_params = {0}; - { - Vec2F32 content_dim = dim_2f32(rect); - scroll_list_params.flags = UI_ScrollListFlag_All; - scroll_list_params.row_height_px = row_height_px; - scroll_list_params.dim_px = v2f32(content_dim.x, content_dim.y-row_height_px); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, file_count+1)); - scroll_list_params.item_range = r1s64(0, file_count+1); - scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; - } - UI_ScrollListSignal scroll_list_sig = {0}; - UI_Focus(UI_FocusKind_On) - UI_ScrollList(&scroll_list_params, - &scroll_pos.y, - &ps->cursor, - 0, - &visible_row_range, - &scroll_list_sig) - UI_Focus(UI_FocusKind_Null) - { - // rjf: up-one-directory button (at idx 0) - if(visible_row_range.min == 0) - { - // rjf: build - UI_Signal sig = {0}; - UI_FocusHot(ps->cursor.y == row_num ? UI_FocusKind_On : UI_FocusKind_Off) - { - sig = ui_buttonf("###up_one"); - } - - // rjf: make content - UI_Parent(sig.box) - { - // rjf: icons - RD_Font(RD_FontSlot_Icons) - UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Icons)) - UI_PrefWidth(ui_em(3.f, 1.f)) - UI_TextAlignment(UI_TextAlign_Center) - { - ui_label(rd_icon_kind_text_table[RD_IconKind_LeftArrow]); - } - - // rjf: text - { - ui_label(str8_lit("Up One Directory")); - } - - row_num += 1; - } - - // rjf: click => up one directory - if(ui_clicked(sig)) - { - String8 new_path = str8_chop_last_slash(str8_chop_last_slash(path_query.path)); - new_path = path_normalized_from_string(scratch.arena, new_path); - String8 new_cmd = push_str8f(scratch.arena, "%S%s", new_path, new_path.size != 0 ? "/" : ""); - rd_store_view_filter(new_cmd); - } - } - - // rjf: file buttons - for(U64 row_idx = Max(visible_row_range.min, 1); - row_idx <= visible_row_range.max && row_idx <= file_count; - row_idx += 1, row_num += 1) - { - U64 file_idx = row_idx-1; - RD_FileInfo *file = &files[file_idx]; - B32 file_kb_focus = (ps->cursor.y == (row_idx+1)); - - // rjf: make button - UI_Signal file_sig = {0}; - UI_FocusHot(file_kb_focus ? UI_FocusKind_On : UI_FocusKind_Off) - { - file_sig = ui_buttonf("##%S", file->filename); - } - - // rjf: make content - UI_Parent(file_sig.box) - { - UI_PrefWidth(ui_pct(fs->col_pcts[0], 1)) UI_Row - { - // rjf: icon to signify directory - RD_Font(RD_FontSlot_Icons) - UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Icons)) - UI_PrefWidth(ui_em(3.f, 1.f)) - UI_TextAlignment(UI_TextAlign_Center) - { - if(file->props.flags & FilePropertyFlag_IsFolder) - { - ui_label((ui_key_match(ui_hot_key(), file_sig.box->key) || file_kb_focus) - ? rd_icon_kind_text_table[RD_IconKind_FolderOpenFilled] - : rd_icon_kind_text_table[RD_IconKind_FolderClosedFilled]); - } - else - { - ui_label(rd_icon_kind_text_table[RD_IconKind_FileOutline]); - } - } - - // rjf: filename - UI_PrefWidth(ui_pct(1, 0)) - { - UI_Box *box = ui_build_box_from_string(UI_BoxFlag_DrawText|UI_BoxFlag_DisableIDString, file->filename); - ui_box_equip_fuzzy_match_ranges(box, &file->match_ranges); - } - } - - // rjf: last-modified time - UI_PrefWidth(ui_pct(fs->col_pcts[1], 1)) UI_Row - UI_PrefWidth(ui_pct(1, 0)) - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - { - DateTime time = date_time_from_dense_time(file->props.modified); - DateTime time_local = os_local_time_from_universal(&time); - String8 string = push_date_time_string(scratch.arena, &time_local); - ui_label(string); - } - - // rjf: file size - UI_PrefWidth(ui_pct(fs->col_pcts[2], 1)) UI_Row - UI_PrefWidth(ui_pct(1, 0)) - { - if(file->props.size != 0) - { - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_label(str8_from_memory_size(scratch.arena, file->props.size)); - } - } - } - - // rjf: click => activate this file - if(ui_clicked(file_sig)) - { - String8 existing_path = str8_chop_last_slash(path_query.path); - String8 new_path = push_str8f(scratch.arena, "%S%s%S/", existing_path, existing_path.size != 0 ? "/" : "", file->filename); - new_path = path_normalized_from_string(scratch.arena, new_path); - if(file->props.flags & FilePropertyFlag_IsFolder) - { - String8 new_cmd = push_str8f(scratch.arena, "%S%s", new_path, new_path.size != 0 ? "/" : ""); - rd_store_view_filter(new_cmd); - } - else - { - rd_cmd(RD_CmdKind_CompleteQuery, .file_path = new_path); - } - } - } - } - - rd_store_view_scroll_pos(scroll_pos); - scratch_end(scratch); - ProfEnd(); -} - -//////////////////////////////// -//~ rjf: system_processes @view_hook_impl - -typedef struct RD_ProcessInfo RD_ProcessInfo; -struct RD_ProcessInfo -{ - DMN_ProcessInfo info; - B32 is_attached; - FuzzyMatchRangeList attached_match_ranges; - FuzzyMatchRangeList name_match_ranges; - FuzzyMatchRangeList pid_match_ranges; -}; - -typedef struct RD_ProcessInfoNode RD_ProcessInfoNode; -struct RD_ProcessInfoNode -{ - RD_ProcessInfoNode *next; - RD_ProcessInfo info; -}; - -typedef struct RD_ProcessInfoList RD_ProcessInfoList; -struct RD_ProcessInfoList -{ - RD_ProcessInfoNode *first; - RD_ProcessInfoNode *last; - U64 count; -}; - -typedef struct RD_ProcessInfoArray RD_ProcessInfoArray; -struct RD_ProcessInfoArray -{ - RD_ProcessInfo *v; - U64 count; -}; - -internal RD_ProcessInfoList -rd_process_info_list_from_query(Arena *arena, String8 query) -{ - Temp scratch = scratch_begin(&arena, 1); - - //- rjf: gather PIDs that we're currently attached to - U64 attached_process_count = 0; - U32 *attached_process_pids = 0; - { - CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process); - attached_process_count = processes.count; - attached_process_pids = push_array(scratch.arena, U32, attached_process_count); - U64 idx = 0; - for(CTRL_EntityNode *n = processes.first; n != 0; n = n->next, idx += 1) - { - CTRL_Entity *process = n->v; - attached_process_pids[idx] = process->id; - } - } - - //- rjf: build list - RD_ProcessInfoList list = {0}; - { - DMN_ProcessIter iter = {0}; - dmn_process_iter_begin(&iter); - for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &iter, &info);) - { - // rjf: skip root-level or otherwise 0-pid processes - if(info.pid == 0) - { - continue; - } - - // rjf: determine if this process is attached - B32 is_attached = 0; - for(U64 attached_idx = 0; attached_idx < attached_process_count; attached_idx += 1) - { - if(attached_process_pids[attached_idx] == info.pid) - { - is_attached = 1; - break; - } - } - - // rjf: gather fuzzy matches - FuzzyMatchRangeList attached_match_ranges = {0}; - FuzzyMatchRangeList name_match_ranges = fuzzy_match_find(arena, query, info.name); - FuzzyMatchRangeList pid_match_ranges = fuzzy_match_find(arena, query, push_str8f(scratch.arena, "%i", info.pid)); - if(is_attached) - { - attached_match_ranges = fuzzy_match_find(arena, query, str8_lit("[attached]")); - } - - // rjf: determine if this item is filtered out - B32 matches_query = (query.size == 0 || - (attached_match_ranges.needle_part_count != 0 && attached_match_ranges.count >= attached_match_ranges.needle_part_count) || - (name_match_ranges.count != 0 && name_match_ranges.count >= name_match_ranges.needle_part_count) || - (pid_match_ranges.count != 0 && pid_match_ranges.count >= pid_match_ranges.needle_part_count)); - - // rjf: push if unfiltered - if(matches_query) - { - RD_ProcessInfoNode *n = push_array(arena, RD_ProcessInfoNode, 1); - n->info.info = info; - n->info.info.name = push_str8_copy(arena, info.name); - n->info.is_attached = is_attached; - n->info.attached_match_ranges = attached_match_ranges; - n->info.name_match_ranges = name_match_ranges; - n->info.pid_match_ranges = pid_match_ranges; - SLLQueuePush(list.first, list.last, n); - list.count += 1; - } - } - dmn_process_iter_end(&iter); - } - - scratch_end(scratch); - return list; -} - -internal RD_ProcessInfoArray -rd_process_info_array_from_list(Arena *arena, RD_ProcessInfoList list) -{ - RD_ProcessInfoArray array = {0}; - array.count = list.count; - array.v = push_array(arena, RD_ProcessInfo, array.count); - U64 idx = 0; - for(RD_ProcessInfoNode *n = list.first; n != 0; n = n->next, idx += 1) - { - array.v[idx] = n->info; - } - return array; -} - -internal int -rd_qsort_compare_process_info(RD_ProcessInfo *a, RD_ProcessInfo *b) -{ - int result = 0; - if(a->pid_match_ranges.count > b->pid_match_ranges.count) - { - result = -1; - } - else if(a->pid_match_ranges.count < b->pid_match_ranges.count) - { - result = +1; - } - else if(a->name_match_ranges.count < b->name_match_ranges.count) - { - result = -1; - } - else if(a->name_match_ranges.count > b->name_match_ranges.count) - { - result = +1; - } - else if(a->attached_match_ranges.count < b->attached_match_ranges.count) - { - result = -1; - } - else if(a->attached_match_ranges.count > b->attached_match_ranges.count) - { - result = +1; - } - return result; -} - -internal void -rd_process_info_array_sort_by_strength__in_place(RD_ProcessInfoArray array) -{ - quick_sort(array.v, array.count, sizeof(RD_ProcessInfo), rd_qsort_compare_process_info); -} - -RD_VIEW_RULE_UI_FUNCTION_DEF(system_processes) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); - F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); - - //- rjf: grab state - typedef struct RD_SystemProcessesViewState RD_SystemProcessesViewState; - struct RD_SystemProcessesViewState - { - B32 initialized; - B32 need_initial_gather; - U32 selected_pid; - Arena *cached_process_arena; - String8 cached_process_arg; - RD_ProcessInfoArray cached_process_array; - }; - UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); - RD_SystemProcessesViewState *sp = rd_view_state(RD_SystemProcessesViewState); - if(sp->initialized == 0) - { - sp->initialized = 1; - sp->need_initial_gather = 1; - sp->cached_process_arena = rd_push_view_arena(); - } - - //- rjf: gather list of filtered process infos - String8 query = string; - RD_ProcessInfoArray process_info_array = sp->cached_process_array; - if(sp->need_initial_gather || !str8_match(sp->cached_process_arg, query, 0)) - { - arena_clear(sp->cached_process_arena); - sp->need_initial_gather = 0; - sp->cached_process_arg = push_str8_copy(sp->cached_process_arena, query); - RD_ProcessInfoList list = rd_process_info_list_from_query(sp->cached_process_arena, query); - sp->cached_process_array = rd_process_info_array_from_list(sp->cached_process_arena, list); - process_info_array = sp->cached_process_array; - rd_process_info_array_sort_by_strength__in_place(process_info_array); - } - - //- rjf: submit best match when hitting enter w/ no selection - if(sp->selected_pid == 0 && process_info_array.count > 0 && ui_slot_press(UI_EventActionSlot_Accept)) - { - RD_ProcessInfo *info = &process_info_array.v[0]; - rd_cmd(RD_CmdKind_CompleteQuery, .pid = info->info.pid); - } - - //- rjf: selected PID -> cursor - Vec2S64 cursor = {0}; - { - for(U64 idx = 0; idx < process_info_array.count; idx += 1) - { - if(process_info_array.v[idx].info.pid == sp->selected_pid) - { - cursor.y = idx+1; - break; - } - } - } - - //- rjf: build contents - Rng1S64 visible_row_range = {0}; - UI_ScrollListParams scroll_list_params = {0}; - { - Vec2F32 content_dim = dim_2f32(rect); - scroll_list_params.flags = UI_ScrollListFlag_All; - scroll_list_params.row_height_px = row_height_px; - scroll_list_params.dim_px = v2f32(content_dim.x, content_dim.y); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, process_info_array.count)); - scroll_list_params.item_range = r1s64(0, process_info_array.count); - scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; - } - UI_ScrollListSignal scroll_list_sig = {0}; - UI_Focus(UI_FocusKind_On) - UI_ScrollList(&scroll_list_params, - &scroll_pos.y, - &cursor, - 0, - &visible_row_range, - &scroll_list_sig) - UI_Focus(UI_FocusKind_Null) - { - //- rjf: build rows - for(U64 idx = visible_row_range.min; - idx <= visible_row_range.max && idx < process_info_array.count; - idx += 1) - { - RD_ProcessInfo *info = &process_info_array.v[idx]; - B32 is_attached = info->is_attached; - UI_Signal sig = {0}; - UI_FocusHot(cursor.y == idx+1 ? UI_FocusKind_On : UI_FocusKind_Off) - { - sig = ui_buttonf("###proc_%i", info->info.pid); - } - UI_Parent(sig.box) - { - // rjf: icon - RD_Font(RD_FontSlot_Icons) - UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Icons)) - UI_PrefWidth(ui_em(3.f, 1.f)) - UI_TextAlignment(UI_TextAlign_Center) - { - ui_label(rd_icon_kind_text_table[RD_IconKind_Threads]); - } - - // rjf: attached indicator - if(is_attached) UI_PrefWidth(ui_text_dim(10, 1)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - { - UI_Box *attached_label = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "[attached]##attached_label_%i", (int)info->info.pid); - ui_box_equip_fuzzy_match_ranges(attached_label, &info->attached_match_ranges); - } - - // rjf: process name - UI_PrefWidth(ui_text_dim(10, 1)) - { - UI_Box *name_label = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "%S##name_label_%i", info->info.name, (int)info->info.pid); - ui_box_equip_fuzzy_match_ranges(name_label, &info->name_match_ranges); - } - - // rjf: process number - UI_PrefWidth(ui_text_dim(1, 1)) UI_TextAlignment(UI_TextAlign_Center) UI_TextPadding(0) - { - ui_labelf("[PID: "); - UI_Box *pid_label = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "%i##pid_label", info->info.pid); - ui_box_equip_fuzzy_match_ranges(pid_label, &info->pid_match_ranges); - ui_labelf("]"); - } - } - - // rjf: click => activate this specific process - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_CompleteQuery, .pid = info->info.pid); - } - } - } - - //- rjf: selected num -> selected PID - { - if(1 <= cursor.y && cursor.y <= process_info_array.count) - { - sp->selected_pid = process_info_array.v[cursor.y-1].info.pid; - } - else - { - sp->selected_pid = 0; - } - } - - rd_store_view_scroll_pos(scroll_pos); - scratch_end(scratch); - ProfEnd(); -} - -//////////////////////////////// -//~ rjf: entity_lister @view_hook_impl - -typedef struct RD_EntityListerItem RD_EntityListerItem; -struct RD_EntityListerItem -{ - RD_Entity *entity; - FuzzyMatchRangeList name_match_ranges; -}; - -typedef struct RD_EntityListerItemNode RD_EntityListerItemNode; -struct RD_EntityListerItemNode -{ - RD_EntityListerItemNode *next; - RD_EntityListerItem item; -}; - -typedef struct RD_EntityListerItemList RD_EntityListerItemList; -struct RD_EntityListerItemList -{ - RD_EntityListerItemNode *first; - RD_EntityListerItemNode *last; - U64 count; -}; - -typedef struct RD_EntityListerItemArray RD_EntityListerItemArray; -struct RD_EntityListerItemArray -{ - RD_EntityListerItem *v; - U64 count; -}; - -internal RD_EntityListerItemList -rd_entity_lister_item_list_from_needle(Arena *arena, RD_EntityKind kind, RD_EntityFlags omit_flags, String8 needle) -{ - Temp scratch = scratch_begin(&arena, 1); - RD_EntityListerItemList result = {0}; - RD_EntityList ent_list = rd_query_cached_entity_list_with_kind(kind); - for(RD_EntityNode *n = ent_list.first; n != 0; n = n->next) - { - RD_Entity *entity = n->entity; - if(!(entity->flags & omit_flags)) - { - DR_FancyStringList title_fstrs = rd_title_fstrs_from_entity(scratch.arena, entity, v4f32(0, 0, 0, 0), 0); - String8 title_string = dr_string_from_fancy_string_list(scratch.arena, &title_fstrs); - FuzzyMatchRangeList match_rngs = fuzzy_match_find(arena, needle, title_string); - if(match_rngs.count != 0 || needle.size == 0) - { - RD_EntityListerItemNode *item_n = push_array(arena, RD_EntityListerItemNode, 1); - item_n->item.entity = entity; - item_n->item.name_match_ranges = match_rngs; - SLLQueuePush(result.first, result.last, item_n); - result.count += 1; - } - } - } - scratch_end(scratch); - return result; -} - -internal RD_EntityListerItemArray -rd_entity_lister_item_array_from_list(Arena *arena, RD_EntityListerItemList list) -{ - RD_EntityListerItemArray result = {0}; - result.count = list.count; - result.v = push_array(arena, RD_EntityListerItem, result.count); - { - U64 idx = 0; - for(RD_EntityListerItemNode *n = list.first; n != 0; n = n->next, idx += 1) - { - result.v[idx] = n->item; - } - } - return result; -} - -internal int -rd_qsort_compare_entity_lister__strength(RD_EntityListerItem *a, RD_EntityListerItem *b) -{ - int result = 0; - if(a->name_match_ranges.count > b->name_match_ranges.count) - { - result = -1; - } - else if(a->name_match_ranges.count < b->name_match_ranges.count) - { - result = +1; - } - return result; -} - -internal void -rd_entity_lister_item_array_sort_by_strength__in_place(RD_EntityListerItemArray array) -{ - quick_sort(array.v, array.count, sizeof(RD_EntityListerItem), rd_qsort_compare_entity_lister__strength); -} - -RD_VIEW_RULE_UI_FUNCTION_DEF(entity_lister) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); -#if 0 // TODO(rjf): @cfg - RD_Window *window = rd_window_from_handle(rd_regs()->window); - RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(window->query_cmd_name); -#endif - RD_EntityKind entity_kind = RD_EntityKind_Nil; // cmd_kind_info->query.entity_kind; - F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); - F32 scroll_bar_dim = floor_f32(ui_top_font_size()*1.5f); - - //- rjf: grab state - typedef struct RD_EntityListerViewState RD_EntityListerViewState; - struct RD_EntityListerViewState - { - RD_Handle selected_entity_handle; - }; - UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); - RD_EntityListerViewState *fev = rd_view_state(RD_EntityListerViewState); - RD_Handle selected_entity_handle = fev->selected_entity_handle; - RD_Entity *selected_entity = rd_entity_from_handle(selected_entity_handle); - - //- rjf: build filtered array of entities - RD_EntityListerItemList ent_list = rd_entity_lister_item_list_from_needle(scratch.arena, entity_kind, 0, string); - RD_EntityListerItemArray ent_arr = rd_entity_lister_item_array_from_list(scratch.arena, ent_list); - rd_entity_lister_item_array_sort_by_strength__in_place(ent_arr); - - //- rjf: submit best match when hitting enter w/ no selection - if(rd_entity_is_nil(rd_entity_from_handle(fev->selected_entity_handle)) && ent_arr.count != 0 && ui_slot_press(UI_EventActionSlot_Accept)) - { - RD_Entity *ent = ent_arr.v[0].entity; - rd_cmd(RD_CmdKind_CompleteQuery, .entity = rd_handle_from_entity(ent)); - } - - //- rjf: selected entity -> cursor - Vec2S64 cursor = {0}; - { - for(U64 idx = 0; idx < ent_arr.count; idx += 1) - { - if(ent_arr.v[idx].entity == selected_entity) - { - cursor.y = (S64)(idx+1); - break; - } - } - } - - //- rjf: build list - Rng1S64 visible_row_range = {0}; - UI_ScrollListParams scroll_list_params = {0}; - { - Vec2F32 content_dim = dim_2f32(rect); - scroll_list_params.flags = UI_ScrollListFlag_All; - scroll_list_params.row_height_px = row_height_px; - scroll_list_params.dim_px = v2f32(content_dim.x, content_dim.y); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, ent_arr.count)); - scroll_list_params.item_range = r1s64(0, ent_arr.count); - scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; - } - UI_ScrollListSignal scroll_list_sig = {0}; - UI_Focus(UI_FocusKind_On) - UI_ScrollList(&scroll_list_params, - &scroll_pos.y, - &cursor, - 0, - &visible_row_range, - &scroll_list_sig) - UI_Focus(UI_FocusKind_Null) - { - for(S64 idx = visible_row_range.min; - idx <= visible_row_range.max && idx < ent_arr.count; - idx += 1) - { - RD_EntityListerItem item = ent_arr.v[idx]; - RD_Entity *ent = item.entity; - ui_set_next_hover_cursor(OS_Cursor_HandPoint); - ui_set_next_child_layout_axis(Axis2_X); - UI_Box *box = &ui_nil_box; - UI_FocusHot(idx+1 == cursor.y ? UI_FocusKind_On : UI_FocusKind_Off) - { - box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawBackground| - UI_BoxFlag_DrawHotEffects| - UI_BoxFlag_DrawActiveEffects, - "###ent_btn_%p", ent); - } - UI_Parent(box) UI_WidthFill UI_Padding(ui_em(1.f, 1.f)) - { - DR_FancyStringList title_fstrs = rd_title_fstrs_from_entity(scratch.arena, ent, ui_top_palette()->text_weak, ui_top_font_size()); - UI_Box *title_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); - ui_box_equip_display_fancy_strings(title_box, &title_fstrs); - ui_box_equip_fuzzy_match_ranges(title_box, &item.name_match_ranges); - } - if(ui_clicked(ui_signal_from_box(box))) - { - rd_cmd(RD_CmdKind_CompleteQuery, .entity = rd_handle_from_entity(ent)); - } - } - } - - //- rjf: selected entity num -> handle - { - fev->selected_entity_handle = (1 <= cursor.y && cursor.y <= ent_arr.count) ? rd_handle_from_entity(ent_arr.v[cursor.y-1].entity) : rd_handle_zero(); - } - - rd_store_view_scroll_pos(scroll_pos); - scratch_end(scratch); - ProfEnd(); -} - -//////////////////////////////// -//~ rjf: ctrl_entity_lister @view_hook_impl - -typedef struct RD_CtrlEntityListerItem RD_CtrlEntityListerItem; -struct RD_CtrlEntityListerItem -{ - CTRL_Entity *entity; - FuzzyMatchRangeList name_match_ranges; -}; - -typedef struct RD_CtrlEntityListerItemNode RD_CtrlEntityListerItemNode; -struct RD_CtrlEntityListerItemNode -{ - RD_CtrlEntityListerItemNode *next; - RD_CtrlEntityListerItem item; -}; - -typedef struct RD_CtrlEntityListerItemList RD_CtrlEntityListerItemList; -struct RD_CtrlEntityListerItemList -{ - RD_CtrlEntityListerItemNode *first; - RD_CtrlEntityListerItemNode *last; - U64 count; -}; - -typedef struct RD_CtrlEntityListerItemArray RD_CtrlEntityListerItemArray; -struct RD_CtrlEntityListerItemArray -{ - RD_CtrlEntityListerItem *v; - U64 count; -}; - -internal RD_CtrlEntityListerItemList -rd_ctrl_entity_lister_item_list_from_needle(Arena *arena, CTRL_EntityKind kind, String8 needle) -{ - Temp scratch = scratch_begin(&arena, 1); - RD_CtrlEntityListerItemList result = {0}; - CTRL_EntityList ent_list = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, kind); - for(CTRL_EntityNode *n = ent_list.first; n != 0; n = n->next) - { - CTRL_Entity *entity = n->v; - DR_FancyStringList title_fstrs = rd_title_fstrs_from_ctrl_entity(scratch.arena, entity, v4f32(0, 0, 0, 0), 0, 0); - String8 title_fstrs_text = dr_string_from_fancy_string_list(scratch.arena, &title_fstrs); - FuzzyMatchRangeList match_rngs = fuzzy_match_find(arena, needle, title_fstrs_text); - if(match_rngs.count == match_rngs.needle_part_count || needle.size == 0) - { - RD_CtrlEntityListerItemNode *item_n = push_array(arena, RD_CtrlEntityListerItemNode, 1); - item_n->item.entity = entity; - item_n->item.name_match_ranges = match_rngs; - SLLQueuePush(result.first, result.last, item_n); - result.count += 1; - } - } - scratch_end(scratch); - return result; -} - -internal RD_CtrlEntityListerItemArray -rd_ctrl_entity_lister_item_array_from_list(Arena *arena, RD_CtrlEntityListerItemList list) -{ - RD_CtrlEntityListerItemArray result = {0}; - result.count = list.count; - result.v = push_array(arena, RD_CtrlEntityListerItem, result.count); - { - U64 idx = 0; - for(RD_CtrlEntityListerItemNode *n = list.first; n != 0; n = n->next, idx += 1) - { - result.v[idx] = n->item; - } - } - return result; -} - -internal int -rd_qsort_compare_ctrl_entity_lister__strength(RD_CtrlEntityListerItem *a, RD_CtrlEntityListerItem *b) -{ - int result = 0; - if(a->name_match_ranges.count > b->name_match_ranges.count) - { - result = -1; - } - else if(a->name_match_ranges.count < b->name_match_ranges.count) - { - result = +1; - } - return result; -} - -internal void -rd_ctrl_entity_lister_item_array_sort_by_strength__in_place(RD_CtrlEntityListerItemArray array) -{ - quick_sort(array.v, array.count, sizeof(RD_CtrlEntityListerItem), rd_qsort_compare_ctrl_entity_lister__strength); -} - -RD_VIEW_RULE_UI_FUNCTION_DEF(ctrl_entity_lister) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); -#if 0 // TODO(rjf): @cfg - RD_Window *window = rd_window_from_handle(rd_regs()->window); - RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(window->query_cmd_name); -#endif - CTRL_EntityKind entity_kind = CTRL_EntityKind_Null; // cmd_kind_info->query.ctrl_entity_kind; - F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); - F32 scroll_bar_dim = floor_f32(ui_top_font_size()*1.5f); - - //- rjf: grab state - typedef struct RD_CtrlEntityListerViewState RD_CtrlEntityListerViewState; - struct RD_CtrlEntityListerViewState - { - CTRL_Handle selected_entity_handle; - }; - UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); - RD_CtrlEntityListerViewState *fev = rd_view_state(RD_CtrlEntityListerViewState); - CTRL_Handle selected_entity_handle = fev->selected_entity_handle; - CTRL_Entity *selected_entity = ctrl_entity_from_handle(d_state->ctrl_entity_store, selected_entity_handle); - - //- rjf: build filtered array of entities - RD_CtrlEntityListerItemList ent_list = rd_ctrl_entity_lister_item_list_from_needle(scratch.arena, entity_kind, string); - RD_CtrlEntityListerItemArray ent_arr = rd_ctrl_entity_lister_item_array_from_list(scratch.arena, ent_list); - rd_ctrl_entity_lister_item_array_sort_by_strength__in_place(ent_arr); - - //- rjf: submit best match when hitting enter w/ no selection - if(ctrl_entity_from_handle(d_state->ctrl_entity_store, fev->selected_entity_handle) == &ctrl_entity_nil && ent_arr.count != 0 && ui_slot_press(UI_EventActionSlot_Accept)) - { - CTRL_Entity *ent = ent_arr.v[0].entity; - RD_RegsScope() - { - switch(ent->kind) - { - default:{}break; - case CTRL_EntityKind_Machine:{rd_regs()->machine = ent->handle;}break; - case CTRL_EntityKind_Process:{rd_regs()->process = ent->handle;}break; - case CTRL_EntityKind_Thread: {rd_regs()->thread = ent->handle;}break; - case CTRL_EntityKind_Module: {rd_regs()->module = ent->handle;}break; - } - rd_cmd(RD_CmdKind_CompleteQuery, .ctrl_entity = ent->handle); - } - } - - //- rjf: selected entity -> cursor - Vec2S64 cursor = {0}; - { - for(U64 idx = 0; idx < ent_arr.count; idx += 1) - { - if(ent_arr.v[idx].entity == selected_entity) - { - cursor.y = (S64)(idx+1); - break; - } - } - } - - //- rjf: build list - Rng1S64 visible_row_range = {0}; - UI_ScrollListParams scroll_list_params = {0}; - { - Vec2F32 content_dim = dim_2f32(rect); - scroll_list_params.flags = UI_ScrollListFlag_All; - scroll_list_params.row_height_px = row_height_px; - scroll_list_params.dim_px = v2f32(content_dim.x, content_dim.y); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, ent_arr.count)); - scroll_list_params.item_range = r1s64(0, ent_arr.count); - scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; - } - UI_ScrollListSignal scroll_list_sig = {0}; - UI_Focus(UI_FocusKind_On) - UI_ScrollList(&scroll_list_params, - &scroll_pos.y, - &cursor, - 0, - &visible_row_range, - &scroll_list_sig) - UI_Focus(UI_FocusKind_Null) - { - for(S64 idx = visible_row_range.min; - idx <= visible_row_range.max && idx < ent_arr.count; - idx += 1) - { - RD_CtrlEntityListerItem item = ent_arr.v[idx]; - CTRL_Entity *ent = item.entity; - ui_set_next_hover_cursor(OS_Cursor_HandPoint); - ui_set_next_child_layout_axis(Axis2_X); - UI_Box *box = &ui_nil_box; - UI_FocusHot(idx+1 == cursor.y ? UI_FocusKind_On : UI_FocusKind_Off) - { - box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawBackground| - UI_BoxFlag_DrawHotEffects| - UI_BoxFlag_DrawActiveEffects, - "###ent_btn_%p", ent); - } - UI_Parent(box) UI_WidthFill UI_Padding(ui_em(1.f, 1.f)) - { - DR_FancyStringList title_fstrs = rd_title_fstrs_from_ctrl_entity(scratch.arena, ent, ui_top_palette()->text_weak, ui_top_font_size(), 1); - UI_Box *title_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); - ui_box_equip_display_fancy_strings(title_box, &title_fstrs); - ui_box_equip_fuzzy_match_ranges(title_box, &item.name_match_ranges); - } - if(ui_clicked(ui_signal_from_box(box))) - { - RD_RegsScope() - { - switch(ent->kind) - { - default:{}break; - case CTRL_EntityKind_Machine:{rd_regs()->machine = ent->handle;}break; - case CTRL_EntityKind_Process:{rd_regs()->process = ent->handle;}break; - case CTRL_EntityKind_Thread: {rd_regs()->thread = ent->handle;}break; - case CTRL_EntityKind_Module: {rd_regs()->module = ent->handle;}break; - } - rd_cmd(RD_CmdKind_CompleteQuery, .ctrl_entity = ent->handle); - } - } - } - } - - //- rjf: selected entity num -> handle - { - fev->selected_entity_handle = (1 <= cursor.y && cursor.y <= ent_arr.count) ? (ent_arr.v[cursor.y-1].entity->handle) : ctrl_handle_zero(); - } - - rd_store_view_scroll_pos(scroll_pos); - scratch_end(scratch); - ProfEnd(); -} - -//////////////////////////////// -//~ rjf: symbol_lister @view_hook_impl - -RD_VIEW_RULE_UI_FUNCTION_DEF(symbol_lister) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); - DI_Scope *di_scope = di_scope_open(); - F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); - DI_KeyList dbgi_keys_list = d_push_active_dbgi_key_list(scratch.arena); - DI_KeyArray dbgi_keys = di_key_array_from_list(scratch.arena, &dbgi_keys_list); - DI_SearchParams search_params = {RDI_SectionKind_Procedures, dbgi_keys}; - U64 endt_us = os_now_microseconds()+200; - - //- rjf: grab rdis - U64 rdis_count = dbgi_keys.count; - RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count); - { - for(U64 idx = 0; idx < rdis_count; idx += 1) - { - RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_keys.v[idx], endt_us); - RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); - rdis[idx] = rdi; - } - } - - //- rjf: grab state - typedef struct RD_SymbolListerViewState RD_SymbolListerViewState; - struct RD_SymbolListerViewState - { - Vec2S64 cursor; - }; - UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); - RD_SymbolListerViewState *slv = rd_view_state(RD_SymbolListerViewState); - - //- rjf: query -> raddbg, filtered items - U128 search_key = {rd_regs()->view.u64[0], rd_regs()->view.u64[1]}; - B32 items_stale = 0; - DI_SearchItemArray items = di_search_items_from_key_params_query(di_scope, search_key, &search_params, string, endt_us, &items_stale); - if(items_stale) - { - rd_request_frame(); - } - - //- rjf: submit best match when hitting enter w/ no selection - if(slv->cursor.y == 0 && items.count != 0 && ui_slot_press(UI_EventActionSlot_Accept)) - { - DI_SearchItem *item = &items.v[0]; - if(item->dbgi_idx < rdis_count) - { - RDI_Parsed *rdi = rdis[item->dbgi_idx]; - U64 rdi_procedures_count = 0; - rdi_section_raw_table_from_kind(rdi, RDI_SectionKind_Procedures, &rdi_procedures_count); - if(item->idx < rdi_procedures_count) - { - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, item->idx); - U64 name_size = 0; - U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - String8 name = str8(name_base, name_size); - if(name.size != 0) - { - rd_cmd(RD_CmdKind_CompleteQuery, .string = name); - } - } - } - } - - //- rjf: build contents - Rng1S64 visible_row_range = {0}; - UI_ScrollListParams scroll_list_params = {0}; - { - Vec2F32 content_dim = dim_2f32(rect); - scroll_list_params.flags = UI_ScrollListFlag_All; - scroll_list_params.row_height_px = row_height_px; - scroll_list_params.dim_px = v2f32(content_dim.x, content_dim.y); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, items.count)); - scroll_list_params.item_range = r1s64(0, items.count); - scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; - } - UI_ScrollListSignal scroll_list_sig = {0}; - UI_Focus(UI_FocusKind_On) - UI_ScrollList(&scroll_list_params, - &scroll_pos.y, - &slv->cursor, - 0, - &visible_row_range, - &scroll_list_sig) - UI_Focus(UI_FocusKind_Null) - UI_TextRasterFlags(rd_raster_flags_from_slot(RD_FontSlot_Code)) - { - //- rjf: build rows - for(U64 idx = visible_row_range.min; - idx <= visible_row_range.max && idx < items.count; - idx += 1) - UI_Focus((slv->cursor.y == idx+1) ? UI_FocusKind_On : UI_FocusKind_Off) - { - DI_SearchItem *item = &items.v[idx]; - if(item->dbgi_idx >= rdis_count) {continue;} - DI_Key dbgi_key = dbgi_keys.v[item->dbgi_idx]; - RDI_Parsed *rdi = rdis[item->dbgi_idx]; - - //- rjf: unpack this item's info - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, item->idx); - U64 name_size = 0; - U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - String8 name = str8(name_base, name_size); - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); - E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, e_parse_ctx_module_idx_from_rdi(rdi)); - - //- rjf: build item button - ui_set_next_hover_cursor(OS_Cursor_HandPoint); - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| - UI_BoxFlag_DrawBackground| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawText| - UI_BoxFlag_DrawHotEffects| - UI_BoxFlag_DrawActiveEffects, - "###procedure_%I64x", item->idx); - UI_Parent(box) UI_PrefWidth(ui_text_dim(10, 1)) RD_Font(RD_FontSlot_Code) - { - UI_Box *box = rd_code_label(1.f, 0, rd_rgba_from_theme_color(RD_ThemeColor_CodeSymbol), name); - ui_box_equip_fuzzy_match_ranges(box, &item->match_ranges); - if(!e_type_key_match(e_type_key_zero(), type_key)) - { - String8 type_string = e_type_string_from_key(scratch.arena, type_key); - rd_code_label(0.5f, 0, rd_rgba_from_theme_color(RD_ThemeColor_TextWeak), type_string); - } - } - - //- rjf: interact - UI_Signal sig = ui_signal_from_box(box); - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_CompleteQuery, .string = name); - } - if(ui_hovering(sig)) UI_Tooltip - { - RD_Font(RD_FontSlot_Code) rd_code_label(1.f, 0, rd_rgba_from_theme_color(RD_ThemeColor_CodeSymbol), name); - RD_Font(RD_FontSlot_Main) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - ui_labelf("Procedure #%I64u", idx); - U64 binary_voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, name); - D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, binary_voff); - if(lines.first != 0 && lines.first->v.file_path.size != 0 && lines.first->v.pt.line != 0) - { - String8 file_path = lines.first->v.file_path; - S64 line_num = lines.first->v.pt.line; - RD_Font(RD_FontSlot_Main) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - ui_labelf("%S:%I64d", file_path, line_num); - } - else - { - RD_Font(RD_FontSlot_Main) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - ui_label(str8_lit("(No source code location found)")); - } - } - } - } - - rd_store_view_scroll_pos(scroll_pos); - di_scope_close(di_scope); - scratch_end(scratch); - ProfEnd(); -} - //////////////////////////////// //~ rjf: targets @view_hook_impl diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 2d11258e..ce58c58e 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -1016,13 +1016,13 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe // rjf: shift+click => enable breakpoint if(ui_clicked(bp_sig) && bp_sig.event_flags & OS_Modifier_Shift) { - rd_cmd(bp_is_disabled ? RD_CmdKind_EnableEntity : RD_CmdKind_DisableEntity, .cfg = rd_handle_from_cfg(bp)); + rd_cmd(bp_is_disabled ? RD_CmdKind_EnableCfg : RD_CmdKind_DisableCfg, .cfg = rd_handle_from_cfg(bp)); } // rjf: click => remove breakpoint if(ui_clicked(bp_sig) && bp_sig.event_flags == 0) { - rd_cmd(RD_CmdKind_RemoveEntity, .cfg = rd_handle_from_cfg(bp)); + rd_cmd(RD_CmdKind_RemoveCfg, .cfg = rd_handle_from_cfg(bp)); } // rjf: drag start @@ -1077,7 +1077,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe // rjf: click => remove pin if(ui_clicked(pin_sig)) { - rd_cmd(RD_CmdKind_RemoveEntity, .cfg = rd_handle_from_cfg(pin)); + rd_cmd(RD_CmdKind_RemoveCfg, .cfg = rd_handle_from_cfg(pin)); } // rjf: drag start @@ -1403,7 +1403,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe UI_Signal catchall_margin_container_sig = ui_signal_from_box(catchall_margin_container_box); UI_Signal text_container_sig = ui_signal_from_box(text_container_box); B32 line_drag_drop = 0; - RD_Entity *line_drag_entity = &rd_nil_entity; + RD_Cfg *line_drag_cfg = &rd_nil_cfg; CTRL_Entity *line_drag_ctrl_entity = &ctrl_entity_nil; Vec4F32 line_drag_drop_color = rd_rgba_from_theme_color(RD_ThemeColor_DropSiteOverlay); { @@ -1479,17 +1479,18 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe if(rd_drag_is_active() && contains_2f32(clipped_top_container_rect, ui_mouse())) { CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_state->drag_drop_regs->thread); - RD_Entity *entity = rd_entity_from_handle(rd_state->drag_drop_regs->entity); - if(rd_state->drag_drop_regs_slot == RD_RegSlot_Entity && - (entity->kind == RD_EntityKind_WatchPin || - entity->kind == RD_EntityKind_Breakpoint)) + RD_Cfg *cfg = rd_cfg_from_handle(rd_state->drag_drop_regs->cfg); + if(rd_state->drag_drop_regs_slot == RD_RegSlot_Cfg && + (str8_match(cfg->string, str8_lit("breakpoint"), 0) || + str8_match(cfg->string, str8_lit("watch_pin"), 0))) { line_drag_drop = 1; - line_drag_entity = entity; - if(entity->flags & RD_EntityFlag_HasColor) + line_drag_cfg = cfg; + line_drag_drop_color = rd_rgba_from_cfg(cfg); + line_drag_drop_color.w *= 0.5f; + if(line_drag_drop_color.w == 0) { - line_drag_drop_color = rd_rgba_from_entity(entity); - line_drag_drop_color.w *= 0.5f; + line_drag_drop_color = rd_rgba_from_theme_color(RD_ThemeColor_DropSiteOverlay); } } if(rd_state->drag_drop_regs_slot == RD_RegSlot_Thread) @@ -1503,14 +1504,14 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe //- rjf: drop target is dropped -> process { - if(!rd_entity_is_nil(line_drag_entity) && rd_drag_drop() && contains_1s64(params->line_num_range, mouse_pt.line)) + if(line_drag_cfg != &rd_nil_cfg && rd_drag_drop() && contains_1s64(params->line_num_range, mouse_pt.line)) { - RD_Entity *dropped_entity = line_drag_entity; + RD_Cfg *dropped_cfg = line_drag_cfg; S64 line_num = mouse_pt.line; U64 line_idx = line_num - params->line_num_range.min; U64 line_vaddr = params->line_vaddrs[line_idx]; - rd_cmd(RD_CmdKind_RelocateEntity, - .entity = rd_handle_from_entity(dropped_entity), + rd_cmd(RD_CmdKind_RelocateCfg, + .cfg = rd_handle_from_cfg(dropped_cfg), .file_path = line_vaddr == 0 ? rd_regs()->file_path : str8_zero(), .cursor = line_vaddr == 0 ? txt_pt(line_num, 1) : txt_pt(0, 0), .vaddr = line_vaddr);