Forráskód Böngészése

fix(renderer): resolve GTK crash and TUI cursor glitch

Fixed GTK renderer crash by adding bounds check before completion substring extraction. Fixed TUI minibuffer cursor position by explicitly setting it after rendering content.
Bernardo Magri 1 hónapja
szülő
commit
2c6e725dda
2 módosított fájl, 36 hozzáadás és 29 törlés
  1. 32 29
      src/gtk_renderer.cpp
  2. 4 0
      src/tui_editor.cpp

+ 32 - 29
src/gtk_renderer.cpp

@@ -522,36 +522,39 @@ void GtkRenderer::render_minibuffer(const Cairo::RefPtr<Cairo::Context>& cr, int
         // Render completion overlay if applicable
         auto current_completion = core_.minibuffer_manager().get_current_completion();
         if (current_completion && input_part != *current_completion) {
-            std::string completion_suffix = current_completion->substr(input_part.length());
-            if (!completion_suffix.empty()) {
-                // Calculate width of existing text to position suffix
-                Pango::Rectangle ink_rect, logical_rect;
-                layout->get_pixel_extents(ink_rect, logical_rect);
-                double text_width = logical_rect.get_width();
-
-                auto completion_layout = Pango::Layout::create(main_drawing_area_.get_pango_context());
-                completion_layout->set_font_description(font_desc_);
-                completion_layout->set_text(completion_suffix); // Only draw suffix
-                
-                Pango::AttrList completion_attr_list;
-                if (auto face = theme->get_face("minibuffer-completion")) {
-                    apply_face_attributes(completion_attr_list, *face, 0, static_cast<int>(completion_suffix.length()));
-                } else {
-                    // Fallback: dimmed foreground
-                    Color dim_fg = fg;
-                    dim_fg.r = static_cast<unsigned char>(dim_fg.r * 0.7);
-                    dim_fg.g = static_cast<unsigned char>(dim_fg.g * 0.7);
-                    dim_fg.b = static_cast<unsigned char>(dim_fg.b * 0.7);
-                    auto attr = Pango::Attribute::create_attr_foreground(dim_fg.r * 257, dim_fg.g * 257, dim_fg.b * 257);
-                    attr.set_start_index(0);
-                    attr.set_end_index(static_cast<int>(completion_suffix.length()));
-                    completion_attr_list.insert(attr);
-                }
-                completion_layout->set_attributes(completion_attr_list);
+            // Safety check: ensure input_part length is valid for substring extraction
+            if (input_part.length() <= current_completion->length()) {
+                std::string completion_suffix = current_completion->substr(input_part.length());
+                if (!completion_suffix.empty()) {
+                    // Calculate width of existing text to position suffix
+                    Pango::Rectangle ink_rect, logical_rect;
+                    layout->get_pixel_extents(ink_rect, logical_rect);
+                    double text_width = logical_rect.get_width();
+
+                    auto completion_layout = Pango::Layout::create(main_drawing_area_.get_pango_context());
+                    completion_layout->set_font_description(font_desc_);
+                    completion_layout->set_text(completion_suffix); // Only draw suffix
+                    
+                    Pango::AttrList completion_attr_list;
+                    if (auto face = theme->get_face("minibuffer-completion")) {
+                        apply_face_attributes(completion_attr_list, *face, 0, static_cast<int>(completion_suffix.length()));
+                    } else {
+                        // Fallback: dimmed foreground
+                        Color dim_fg = fg;
+                        dim_fg.r = static_cast<unsigned char>(dim_fg.r * 0.7);
+                        dim_fg.g = static_cast<unsigned char>(dim_fg.g * 0.7);
+                        dim_fg.b = static_cast<unsigned char>(dim_fg.b * 0.7);
+                        auto attr = Pango::Attribute::create_attr_foreground(dim_fg.r * 257, dim_fg.g * 257, dim_fg.b * 257);
+                        attr.set_start_index(0);
+                        attr.set_end_index(static_cast<int>(completion_suffix.length()));
+                        completion_attr_list.insert(attr);
+                    }
+                    completion_layout->set_attributes(completion_attr_list);
 
-                cr->set_source_rgb(fg.r / 255.0, fg.g / 255.0, fg.b / 255.0);
-                cr->move_to(minibuffer_x + text_width, minibuffer_y); // Position after text
-                completion_layout->show_in_cairo_context(cr);
+                    cr->set_source_rgb(fg.r / 255.0, fg.g / 255.0, fg.b / 255.0);
+                    cr->move_to(minibuffer_x + text_width, minibuffer_y); // Position after text
+                    completion_layout->show_in_cairo_context(cr);
+                }
             }
         }
     }

+ 4 - 0
src/tui_editor.cpp

@@ -707,6 +707,10 @@ void TuiEditor::render_message_line() {
             mvprintw(msg_y - 1, 0, "%s", completion_display.c_str());
         }
 
+        // Explicitly place cursor at the correct position in minibuffer
+        // prompt_part is handled by get_prompt(), cursor_position is relative to input_buffer
+        move(msg_y, prompt_part.length() + core_->minibuffer_manager().get_cursor_position());
+
     } else if (!message_line_.empty()) {
         // Display transient message
         mvprintw(msg_y, 0, "%s", message_line_.c_str());