|
|
@@ -466,24 +466,41 @@ void TuiEditor::render_window(std::shared_ptr<Window> window, int x, int y, int
|
|
|
|
|
|
// Highlight ISearch match
|
|
|
if (core_->minibuffer_manager().is_isearch_active() && core_->minibuffer_manager().get_isearch_match_range().has_value()) {
|
|
|
- auto isearch_match = core_->minibuffer_manager().get_isearch_match_range().value();
|
|
|
- if (isearch_match.start.line == buffer_line_idx) {
|
|
|
- size_t match_start = isearch_match.start.column;
|
|
|
- size_t match_len = isearch_match.end.column - match_start;
|
|
|
- if (match_start < line_text.size()) {
|
|
|
- size_t display_len = std::min(match_len, line_text.size() - match_start);
|
|
|
- std::string matched_text = line_text.substr(match_start, display_len);
|
|
|
+ auto match = core_->minibuffer_manager().get_isearch_match_range().value();
|
|
|
+
|
|
|
+ // Check if current line is part of the match
|
|
|
+ if (buffer_line_idx >= match.start.line && buffer_line_idx <= match.end.line) {
|
|
|
+ int horizontal_offset = window->viewport().horizontal_offset;
|
|
|
+
|
|
|
+ size_t hl_start = (buffer_line_idx == match.start.line) ? match.start.column : 0;
|
|
|
+ size_t hl_end = (buffer_line_idx == match.end.line) ? match.end.column : line_text.length();
|
|
|
+
|
|
|
+ // Handle case where match extends past end of line (e.g. capturing newline)
|
|
|
+ // Ensure we don't go past line text length for string extraction
|
|
|
+ size_t text_len = line_text.length();
|
|
|
+ size_t safe_hl_end = std::min(hl_end, text_len);
|
|
|
+
|
|
|
+ // Adjust for horizontal scroll
|
|
|
+ int draw_start = static_cast<int>(hl_start) - horizontal_offset;
|
|
|
+ int draw_end = static_cast<int>(safe_hl_end) - horizontal_offset;
|
|
|
+
|
|
|
+ // Clip to viewable area
|
|
|
+ draw_start = std::max(0, draw_start);
|
|
|
+ // Clip draw_end to window width
|
|
|
+ if (draw_end > content_width) draw_end = content_width;
|
|
|
+
|
|
|
+ if (draw_start < draw_end) {
|
|
|
+ // Extract text to highlight
|
|
|
+ std::string text_to_hl = line_text.substr(draw_start + horizontal_offset, draw_end - draw_start);
|
|
|
|
|
|
- int match_x = x + line_number_width + match_start;
|
|
|
- // Simple clipping check
|
|
|
- if (match_x < x + width) {
|
|
|
- int attrs = get_attributes_for_face(core_->minibuffer_manager().is_isearch_failed() ? "SearchFail" : "SearchMatch");
|
|
|
- if (attrs == 0) attrs = A_REVERSE; // Fallback
|
|
|
-
|
|
|
- attron(attrs);
|
|
|
- mvprintw(y + screen_y, match_x, "%s", matched_text.c_str());
|
|
|
- attroff(attrs);
|
|
|
- }
|
|
|
+ int screen_x = x + line_number_width + draw_start;
|
|
|
+
|
|
|
+ int attrs = get_attributes_for_face(core_->minibuffer_manager().is_isearch_failed() ? "SearchFail" : "SearchMatch");
|
|
|
+ if (attrs == 0) attrs = A_REVERSE;
|
|
|
+
|
|
|
+ attron(attrs);
|
|
|
+ mvprintw(y + screen_y, screen_x, "%s", text_to_hl.c_str());
|
|
|
+ attroff(attrs);
|
|
|
}
|
|
|
}
|
|
|
}
|