diff --git a/src/hover.cpp b/src/hover.cpp index 04df6f7..8811157 100644 --- a/src/hover.cpp +++ b/src/hover.cpp @@ -55,6 +55,7 @@ String8_Node *hover_display_datetime_str(Arena *arena, String8_Node *prev, const return push_str8_node_child(arena, prev, "%s%u/%02u/%02u %02u:%02u:%02u", fmt_pre, year, month, day, hour, min, sec); } +// Returns null is `src` doesn't point to a zipped block internal String8_Node *display_val_rootzip(Arena *arena, String8_Node *prev, const char *fmt, const u8 *src) { @@ -89,6 +90,11 @@ String8_Node *display_val_rootzip(Arena *arena, String8_Node *prev, const char * template using Display_Fn = String8_Node *(*)(Arena *, String8_Node *, const char *, T); +enum Hover_Section_Flags { + HoverSec_None = 0, + HoverSec_HideIfNotHovered = 1, +}; + // Functor used by get_section_hover_info to describe the structure of a section and print data about it. struct Sec_Hover_Fn { u64 start; // the start of the section (including the pre_size, e.g. the TKey) @@ -99,34 +105,42 @@ struct Sec_Hover_Fn { Sec_Hover_Info &info; u64 &cur_field_off; b8 display_grouped; - b8 hovered = false; b8 ended = false; + u8 cur_section_nesting = 0; + u8 innermost_section_highlighted = 0; template - void titled_section(const char *title, F &&fn) + void titled_section(const char *title, F &&sec_body_fn, u64 flags = 0) { - if (ended) - return; + // if (ended) + // return; + ++cur_section_nesting; String8_Node *prev_desc = info.desc; info.desc = push_str8_node_child(arena, prev_desc, title); u64 sec_start = cur_field_off; - fn(); - if (!hovered) { - // the entire section was not hovered: don't display its description. + sec_body_fn(); + + assert(cur_field_off >= sec_start); + b8 hovered = roff >= sec_start && roff <= cur_field_off; + + if (!hovered & (flags & HoverSec_HideIfNotHovered)) { pop_str8_node_child(prev_desc, info.desc); } else if (display_grouped) { // if we're in display_grouped mode, we want to highlight the entire range of the section; - assert(sec_start <= cur_field_off); u64 sec_len = cur_field_off - sec_start; - hovered = roff >= sec_start && roff < sec_start + sec_len; - if (hovered) { - info.rng = { start + sec_start, sec_len }; - ended = true; - } + info.rng = { start + sec_start, sec_len }; + // In case of nested sections, only highlight the innermost + // FIXME! + info.desc->selected = innermost_section_highlighted < cur_section_nesting; + innermost_section_highlighted = max(cur_section_nesting, innermost_section_highlighted); + // ended = true; } + + --cur_section_nesting; + info.desc = prev_desc; return; } @@ -136,30 +150,33 @@ struct Sec_Hover_Fn { b8 field(const char *desc_fmt, Display_Fn display_val, T *val_read = nullptr) { static_assert(!std::is_same_v, "use field_str8 instead."); - if (ended) - return false; + // if (ended) + // return false; u64 field_len = sizeof(T); - if (display_grouped || roff < cur_field_off + field_len) { + b8 hovered = cur_field_off <= roff && roff < cur_field_off + field_len; + + T val; + memcpy(&val, (u8 *)data + start + cur_field_off, field_len); + String8_Node *desc = display_val(arena, info.desc, desc_fmt, val); + desc->selected = hovered && !display_grouped; + if (val_read) + *val_read = val; + + if (display_grouped || hovered) { info.rng = { start + cur_field_off, field_len }; - T val; - memcpy(&val, (u8 *)data + start + cur_field_off, field_len); - display_val(arena, info.desc, desc_fmt, val); - if (val_read) - *val_read = val; - hovered = true; // truncate the hovered section here if we're not in display_grouped mode. - ended = !display_grouped; + // ended = !display_grouped; } cur_field_off += field_len; - return hovered; + return true; } template void field_str8(const char *desc_fmt, Display_Fn display_val = hover_display_val_str8) { - if (ended) - return; + // if (ended) + // return; // String size can be stored as different types, like u8 (by ROOT I/O) or u32 (by RNTuple). TStrSize str_size; @@ -167,19 +184,22 @@ struct Sec_Hover_Fn { // DEBUG if (str_size > 1000) { printf("read str_size = %u at offset 0x%lX!\n", str_size, start + cur_field_off); - ended = true; + // ended = true; return; } u64 field_len = sizeof(TStrSize) + (u64)str_size; - if (display_grouped || roff < cur_field_off + field_len) { + b8 hovered = cur_field_off <= roff && roff < cur_field_off + field_len; + + u8 *buf = arena_push_array_nozero(arena, str_size + 1); + memcpy(buf, data + start + cur_field_off + sizeof(TStrSize), str_size); + buf[str_size] = 0; + String8 s = { buf, str_size }; + String8_Node *desc = display_val(arena, info.desc, desc_fmt, s); + desc->selected = hovered && !display_grouped; + + if (display_grouped || hovered) { info.rng = { start + cur_field_off, field_len }; - u8 *buf = arena_push_array_nozero(arena, str_size + 1); - memcpy(buf, data + start + cur_field_off + sizeof(TStrSize), str_size); - buf[str_size] = 0; - String8 s = { buf, str_size }; - display_val(arena, info.desc, desc_fmt, s); - hovered = true; - ended = !display_grouped; + // ended = !display_grouped; } cur_field_off += field_len; } @@ -199,14 +219,15 @@ struct Sec_Hover_Fn { // An unspecified range of bytes void range(const char *desc, u64 range_len, Display_Fn display_val = hover_display_generic_range) { - if (ended) - return; + // if (ended) + // return; - if (display_grouped || roff < cur_field_off + range_len) { + b8 hovered = cur_field_off <= roff && roff < cur_field_off + range_len; + String8_Node *dsc = display_val(arena, info.desc, desc, data + start + cur_field_off); + dsc->selected = hovered && !display_grouped; + if (display_grouped || hovered) { info.rng = { start + cur_field_off, range_len }; - display_val(arena, info.desc, desc, data + start + cur_field_off); - hovered = true; - ended = !display_grouped; + // ended = !display_grouped; } cur_field_off += range_len; } @@ -214,17 +235,19 @@ struct Sec_Hover_Fn { // Returns true if `was_zipped` was read. b8 maybe_rootzip(b8 *was_zipped = nullptr) { - if (ended) - return false; + // if (ended) + // return false; // TODO boundary checks const u64 range_len = 9; + b8 hovered = cur_field_off <= roff && roff < cur_field_off + range_len; if (display_val_rootzip(arena, info.desc, "Zipped Block", data + start + cur_field_off)) { - if (was_zipped) *was_zipped = true; - if (display_grouped || roff < cur_field_off + range_len) { + if (display_grouped || hovered) { + if (was_zipped) + *was_zipped = true; info.rng = { start + cur_field_off, range_len }; - hovered = true; - ended = !display_grouped; + info.desc->selected = hovered; + // ended = !display_grouped; } cur_field_off += range_len; } else if (was_zipped) { @@ -342,7 +365,7 @@ struct Sec_Hover_Fn { // DEBUG if (size > 100000) { printf("read field_frame_size = %lu at offset 0x%lX!\n", size, start + cur_field_off); - ended = true; + // ended = true; return; } field_le("Field version: %u"); @@ -372,7 +395,7 @@ struct Sec_Hover_Fn { u64 extra_size = size - (cur_field_off - start_off); if (extra_size > 0) range("Unknown", extra_size); - }); + }, HoverSec_HideIfNotHovered); } void column_desc(const char *title) @@ -387,7 +410,7 @@ struct Sec_Hover_Fn { // DEBUG if (size > 100000) { printf("read column_desc_size = %lu at offset 0x%lX!\n", size, start + cur_field_off); - ended = true; + // ended = true; return; } @@ -421,7 +444,7 @@ struct Sec_Hover_Fn { printf("extra size: %lu - %lu = %lu\n", size, cur_field_off - start_off, extra_size); if (extra_size > 0) range("Unknown", extra_size); - }); + }, HoverSec_HideIfNotHovered); } template @@ -439,7 +462,7 @@ struct Sec_Hover_Fn { // DEBUG if (n_elems > 100000) { printf("read n_elems = %u at offset 0x%lX!\n", n_elems, start + cur_field_off); - ended = true; + // ended = true; return; } for (u32 i = 0; i < n_elems; ++i) { diff --git a/src/render.cpp b/src/render.cpp index 99ec8f4..bd296b5 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -225,7 +225,10 @@ void imgui_render_string_tree(Arena *arena, String8_Node *root, u16 indent = 0) } for (String8_Node *node = root; node; node = node->next) { - ImGui::Text("%s%s", indent_str.c(), node->str.c()); + if (node->selected) + ImGui::TextColored(ImColor(1.0f, 1.0f, 0.0f), "%s%s", indent_str.c(), node->str.c()); + else + ImGui::Text("%s%s", indent_str.c(), node->str.c()); if (node->first_child) imgui_render_string_tree(arena, node->first_child, indent + 2); diff --git a/src/str.h b/src/str.h index e2cdaba..25e9a0c 100644 --- a/src/str.h +++ b/src/str.h @@ -15,4 +15,6 @@ struct String8_Node { String8_Node *next, *prev, *head; String8_Node *first_child, *last_child; String8 str; + // @Cleanup: only used by hover.cpp, it should not belong in here... + b8 selected; };