Răsfoiți Sursa

fix(tui): Correct ISearch highlighting logic

- Replace buggy single-line highlight logic with robust range intersection check.
- Correctly handle multi-line matches by checking if current line is within [start, end] range.
- Fix horizontal scrolling offset calculations for highlighted text.
Bernardo Magri 1 lună în urmă
părinte
comite
a584a0aecc
1 a modificat fișierele cu 34 adăugiri și 17 ștergeri
  1. 34 17
      src/tui_editor.cpp

+ 34 - 17
src/tui_editor.cpp

@@ -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);
                 }
             }
         }