@@ -56,27 +56,30 @@ class Text : public Node {
5656 }
5757
5858 void Select (Selection& selection) override {
59- if (Box::Intersection (selection.GetBox (), box_).IsEmpty ()) {
59+ const Box selection_box = Box::Intersection (selection.GetBox (), box_);
60+ if (selection_box.IsEmpty ()) {
6061 return ;
6162 }
6263
63- selection_rows_.assign (lines_offsets_.size () - 1 , {-1 , -1 });
64+ // Only store the selected line range. Sizing per line would allocate one
65+ // entry per line of the whole text on every frame.
66+ const size_t lines_count = lines_offsets_.size () - 1 ;
67+ const size_t first = selection_box.y_min - box_.y_min ;
68+ const size_t last =
69+ std::min<size_t >(selection_box.y_max - box_.y_min + 1 , lines_count);
70+ if (first >= last) {
71+ return ;
72+ }
73+ selection_first_line_ = first;
74+ selection_rows_.assign (last - first, {-1 , -1 });
6475
65- for (size_t i = 0 ; i < lines_offsets_. size () - 1 ; ++i) {
76+ for (size_t i = first ; i < last ; ++i) {
6677 const int y = box_.y_min + (int )i;
67- if (y > box_.y_max ) {
68- break ;
69- }
70-
7178 const Box row_box{box_.x_min , box_.x_max , y, y};
72- if (Box::Intersection (selection.GetBox (), row_box).IsEmpty ()) {
73- continue ;
74- }
75-
7679 const Selection row_sel = selection.SaturateHorizontal (row_box);
7780 const int sel_start = row_sel.GetBox ().x_min ;
7881 const int sel_end = row_sel.GetBox ().x_max ;
79- selection_rows_[i] = {sel_start, sel_end};
82+ selection_rows_[i - first ] = {sel_start, sel_end};
8083
8184 std::string part;
8285 int x = box_.x_min ;
@@ -116,8 +119,9 @@ class Text : public Node {
116119 auto & cell = screen.CellAt (x, y);
117120 cell.character = *glyph;
118121
119- if (line < selection_rows_.size ()) {
120- const auto & [sel_start, sel_end] = selection_rows_[line];
122+ const size_t sel_index = line - selection_first_line_;
123+ if (sel_index < selection_rows_.size ()) {
124+ const auto & [sel_start, sel_end] = selection_rows_[sel_index];
121125 if (sel_start != -1 && x >= sel_start && x <= sel_end) {
122126 screen.GetSelectionStyle ()(cell);
123127 }
@@ -129,6 +133,9 @@ class Text : public Node {
129133 private:
130134 std::vector<std::string> glyphs_;
131135 std::vector<int > lines_offsets_;
136+ // Selection state for the line range [selection_first_line_,
137+ // selection_first_line_ + selection_rows_.size()).
138+ size_t selection_first_line_ = 0 ;
132139 std::vector<std::pair<int , int >> selection_rows_;
133140};
134141
0 commit comments