1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#pragma once
#include "core/result.h"
#include "ui/macro_expander.h"
#include <cstdint>
#include <filesystem>
#include <optional>
#include <string>
#include <unordered_set>
#include <vector>
struct ImDrawList;
struct ImFont;
namespace Hsdbg
{
class Debugger;
// one coloured run inside a source line; start and length index into the
// line's own string so the spans stay valid as long as the line does
enum class SyntaxKind : uint8_t
{
Default,
Keyword,
Type,
String,
Number,
Comment,
Preprocessor,
Macro,
};
struct SourceSpan
{
uint32_t start;
uint32_t length;
SyntaxKind kind;
};
class SourceView
{
public:
auto open(const std::filesystem::path& file_path) -> Result<void>;
auto close() -> void;
auto draw(Debugger& debugger) -> void;
auto set_highlighted_line(uint32_t line) -> void;
// the lines of the function the selected frame is in (zero for unknown):
// live values are only annotated inside it
auto set_frame_extent(uint32_t first, uint32_t last) -> void;
// names of locals that moved since the previous stop; their annotations
// take the accent. the set is owned by the caller and read each frame
auto set_changed_locals(const std::unordered_set<std::string>* names) -> void { m_changed_locals = names; }
auto set_highlighting(bool enabled) -> void { m_highlighting_enabled = enabled; }
auto set_line_numbers(bool enabled) -> void { m_line_numbers = enabled; }
auto set_highlight_current_line(bool enabled) -> void { m_highlight_current_line = enabled; }
// packed ImU32 (0xAABBGGRR) colours, one per SyntaxKind, index 0 unused
auto set_syntax_color(size_t kind, unsigned int color) -> void { m_syntax_colors[kind] = color; }
auto set_current_line_color(unsigned int color) -> void { m_current_line_color = color; }
// the monospace face the code (and its gutter) is rendered in, and its
// size in px before ui scaling: cmd/ctrl + wheel over the code nudges the
// size, and the ui reads it back to persist it
auto set_mono_font(ImFont* font) -> void { m_mono_font = font; }
auto set_font_size(float size) -> void { m_font_size = size; }
auto font_size() const -> float { return m_font_size; }
auto path() const -> const std::filesystem::path& { return m_path; }
auto line_count() const -> size_t { return m_lines.size(); }
auto is_open() const -> bool { return !m_lines.empty(); }
// the #defines visible in the open file, so a panel can expand the same
// macros the source view is highlighting
auto macros() const -> const MacroTable& { return m_macros; }
// when the user clicks a highlighted macro, the invocation as written
// (name plus any argument list) is stashed here for the ui to pick up and
// hand to the macros panel; cleared once taken
auto take_macro_request() -> std::optional<std::string>;
// right-clicking a name in the source stashes it here for the ui to add to
// the watch list; cleared once taken
auto take_watch_request() -> std::optional<std::string>;
private:
auto draw_open_bar() -> void;
auto draw_lines(Debugger& debugger) -> void;
auto handle_zoom() -> void;
// renders a highlighted macro name: hovering previews its expansion,
// clicking records the invocation for the macros panel to open
auto draw_macro_span(ImDrawList* draw_list, const std::string& line,
const SourceSpan& span) -> void;
ImFont* m_mono_font = nullptr;
std::filesystem::path m_path;
std::vector<std::string> m_lines;
std::vector<std::vector<SourceSpan>> m_spans;
MacroTable m_macros;
std::optional<std::string> m_macro_request;
std::optional<std::string> m_watch_request;
bool m_highlight = false;
bool m_highlighting_enabled = true;
bool m_line_numbers = true;
bool m_highlight_current_line = true;
// indexed by SyntaxKind; the defaults match the built-in dark palette.
// the macro colour (last) is warm on purpose so expandable names read as
// clickable against the rest of the syntax
unsigned int m_syntax_colors[8] = {
0, 0xFFD69C56, 0xFFB0C94E, 0xFF7891CE, 0xFFA8CEB5, 0xFF55996A, 0xFFC086C5,
0xFF4FA3E0,
};
unsigned int m_current_line_color = 0xFF2E483A;
std::string m_path_input;
std::string m_error;
uint32_t m_highlighted_line = 0;
bool m_scroll_to_highlight = false;
// the location bar shows the open path as a breadcrumb; a click swaps in
// the text field (and asks for its focus) until a file opens or it loses focus
bool m_editing_path = false;
bool m_focus_path = false;
float m_font_size = 16.0f;
float m_zoom_accumulator = 0.0f; // wheel travel not yet turned into a step
double m_zoom_badge_until = 0.0; // the "NN px" badge shows until this time
uint32_t m_frame_first_line = 0;
uint32_t m_frame_last_line = 0;
const std::unordered_set<std::string>* m_changed_locals = nullptr;
};
}
|