# HG changeset patch # User Torsten Lilge # Date 1559410256 -7200 # Node ID fbe46901ae626d9da26ebf4eba4e5862816cb92e # Parent 8ea53aa9ac3994b073e8e5733da9094093adf7d1 fix editors search and replace in selection (bug #56405) * file-editor-tab.cc (handle_double_click): update call to changed method octave_qscintilla::show_selection_markers * find-dialog.cc (find_dialog): parent is class octave_qscintilla, initialize the new class variables for searching in the selection; (handle_selection_changed): only disable selection checkbox if no text is selected, but leave check state as it is, remove the conditial compilation based on HAVE_QSCI_FINDSELECTION; (find): remove consitional compilation, initialize line and column for the search start also for selected text, remember start and end of a possible selection, remove workaround for wrong selection length update, only use finFirst also for the case with selection, check if search hit lies within the selection if necessary and stop search if required, update slection marker for showing the current selected area, remove this marker and restore real selection if no more occurrance of search text was found; (do_replace): update the length of the selection when replacing text; (replace): remove workaround for buggy selection length update * find-dialog.h: include octave_qscintilla, parent and _edit_area are of type octave_qscintilla, new class variable for storing and handling search in selection as well as selection begin and end * octave-qscintilla.cc (show_selection_markers): paraemters are now start line and column as wells as end line and column * octave-qscintilla.h: new parameters for show_selection_markers diff -r 8ea53aa9ac39 -r fbe46901ae62 libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc Sat Jun 01 08:56:51 2019 -0700 +++ b/libgui/src/m-editor/file-editor-tab.cc Sat Jun 01 19:30:56 2019 +0200 @@ -3166,7 +3166,7 @@ // get cursor position after having found an occurrence _edit_area->getCursorPosition (&oline, &ocol); // mark the selection - _edit_area->show_selection_markers (oline, ocol, wlen); + _edit_area->show_selection_markers (oline, ocol-wlen, oline, ocol); // find next occurrence find_result_available = _edit_area->findNext (); diff -r 8ea53aa9ac39 -r fbe46901ae62 libgui/src/m-editor/find-dialog.cc --- a/libgui/src/m-editor/find-dialog.cc Sat Jun 01 08:56:51 2019 -0700 +++ b/libgui/src/m-editor/find-dialog.cc Sat Jun 01 19:30:56 2019 +0200 @@ -80,9 +80,9 @@ namespace octave { - find_dialog::find_dialog (QsciScintilla *edit_area, + find_dialog::find_dialog (octave_qscintilla *edit_area, QList find_actions, QWidget *p) - : QDialog (p) + : QDialog (p), m_in_sel (false), m_sel_beg (-1), m_sel_end (-1) { setWindowTitle (tr ("Find and Replace")); setWindowIcon (QIcon (":/actions/icons/find.png")); @@ -120,14 +120,9 @@ _regex_check_box = new QCheckBox (tr ("Regular E&xpressions")); _backward_check_box = new QCheckBox (tr ("Search &backward")); _search_selection_check_box = new QCheckBox (tr ("Search se&lection")); -#if defined (HAVE_QSCI_FINDSELECTION) _search_selection_check_box->setCheckable (true); if (edit_area) _search_selection_check_box->setEnabled (edit_area->hasSelectedText ()); -#else - _search_selection_check_box->setCheckable (false); - _search_selection_check_box->setEnabled (false); -#endif _edit_area = edit_area; connect (_find_next_button, SIGNAL (clicked ()), @@ -147,12 +142,10 @@ connect (_search_line_edit, SIGNAL (textChanged (QString)), this, SLOT (handle_search_text_changed (QString))); -#if defined (HAVE_QSCI_FINDSELECTION) connect (_edit_area, SIGNAL (copyAvailable (bool)), this, SLOT (handle_selection_changed (bool))); connect (_search_selection_check_box, SIGNAL (stateChanged (int)), this, SLOT (handle_sel_search_changed (int))); -#endif QVBoxLayout *extension_layout = new QVBoxLayout (); extension_layout->setMargin (0); @@ -251,17 +244,12 @@ _find_result_available = false; } -#if defined (HAVE_QSCI_FINDSELECTION) void find_dialog::handle_sel_search_changed (int selected) { _from_start_check_box->setEnabled (! selected); _find_result_available = false; } -#else - void find_dialog::handle_sel_search_changed (int /* selected */) { } -#endif -#if defined (HAVE_QSCI_FINDSELECTION) void find_dialog::handle_selection_changed (bool has_selected) { if (_rep_active) @@ -269,12 +257,7 @@ _search_selection_check_box->setEnabled (has_selected); _find_result_available = false; - if (! has_selected) - _search_selection_check_box->setChecked (false); } -#else - void find_dialog::handle_selection_changed (bool /* has_selected */) { } -#endif // initialize search text with selected text if this is in one single line void find_dialog::init_search_text (void) @@ -311,46 +294,84 @@ if (! _edit_area) return; - int line, col; - line = col = -1; + // line adn col: -1 means search starts at current position + int line = -1, col = -1; + bool do_wrap = _wrap_check_box->isChecked (); bool do_forward = forward; + // Initialize the selection begin and end if it is the first search + if (! _find_result_available) + { + if (_search_selection_check_box->isChecked () + && _edit_area->hasSelectedText ()) + { + int l1, c1, l2, c2; + _edit_area->getSelection (&l1, &c1, &l2, &c2); + + // Store the position of the selection + m_sel_beg = _edit_area->positionFromLineIndex (l1, c1); + m_sel_end = _edit_area->positionFromLineIndex (l2, c2); + m_in_sel = true; + } + else + m_in_sel = false; + } + + // Get the correct line/col for beginning the search if (_rep_all) { + // Replace All if (_rep_all == 1) { - line = 0; - col = 0; - } - do_wrap = false; - // The following line is a workaround for the issue that when replacing - // a text with a new one with different size within the selection, - // the selection is not updated leading to missing or extra replacements. - // This does not happen, when the selection is search backwards - do_forward = ! _search_selection_check_box->isChecked (); - } - else - { - if (_from_start_check_box->isChecked ()) - { - if (do_forward) + // Start at the beginning of file/sel if it is the first try + if (m_in_sel) + _edit_area->lineIndexFromPosition (m_sel_beg, &line, &col); + else { line = 0; col = 0; } + } + do_wrap = false; // Never wrap when replacing all + } + else + { + // Normal search (not replace all): calculate start position of + // search (in file or selection) + if (_from_start_check_box->isChecked () + || (m_in_sel && (! _find_result_available))) + { + // From the beginning or the end of file/sel + if (do_forward) + { + // From the beginning + if (m_in_sel) + _edit_area->lineIndexFromPosition (m_sel_beg, &line, &col); + else + { + line = 0; + col = 0; + } + } else { - line = _edit_area->lines () - 1; - col = _edit_area->text (line).length () - 1; - if (col == -1) - col = 0; + // From the end + if (m_in_sel) + _edit_area->lineIndexFromPosition (m_sel_end, &line, &col); + else + { + line = _edit_area->lines () - 1; + col = _edit_area->text (line).length () - 1; + if (col == -1) + col = 0; + } } } else if (! do_forward) { - // search from position before search characters text length - // if search backward on existing results, + // Start from where the cursor is. Fix QScintilla's cursor + // positioning _edit_area->getCursorPosition (&line,&col); if (_find_result_available && _edit_area->hasSelectedText ()) { @@ -358,54 +379,65 @@ currpos -= (_search_line_edit->text ().length ()); if (currpos < 0) currpos = 0; - _edit_area->lineIndexFromPosition (currpos, &line,&col); + _edit_area->lineIndexFromPosition (currpos, &line, &col); } } } - if (_edit_area->hasSelectedText () - && _search_selection_check_box->isChecked ()) - { -#if defined (HAVE_QSCI_FINDSELECTION) - if (_find_result_available) - _find_result_available = _edit_area->findNext (); - else - _find_result_available - = _edit_area->findFirstInSelection ( - _search_line_edit->text (), - _regex_check_box->isChecked (), - _case_check_box->isChecked (), - _whole_words_check_box->isChecked (), - do_forward, - true + // Do the search + _find_result_available = _edit_area->findFirst ( + _search_line_edit->text (), + _regex_check_box->isChecked (), + _case_check_box->isChecked (), + _whole_words_check_box->isChecked (), + do_wrap, + do_forward, + line,col, + true #if defined (HAVE_QSCI_VERSION_2_6_0) - , true + , true #endif - ); -#endif - } - else + ); + + if (_find_result_available) { - _find_result_available - = _edit_area->findFirst (_search_line_edit->text (), - _regex_check_box->isChecked (), - _case_check_box->isChecked (), - _whole_words_check_box->isChecked (), - do_wrap, - do_forward, - line,col, - true -#if defined (HAVE_QSCI_VERSION_2_6_0) - , true -#endif - ); + // Search successful: reset search-from-start box and check for + // the current selection + _from_start_check_box->setChecked (0); + + if (m_in_sel) + { + _edit_area->getCursorPosition (&line,&col); + int pos = _edit_area->positionFromLineIndex (line, col); + + int l1, c1, l2, c2; + _edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1); + _edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2); + _edit_area->show_selection_markers (l1, c1, l2, c2); + + // Check if new start position is still wihtin the selection + _find_result_available = pos >= m_sel_beg && pos <= m_sel_end; + } } + // No more search hits + if (! _find_result_available) + { + if (m_in_sel) + { + // Restore real selection and remove marker for selection + int l1, c1, l2, c2; + _edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1); + _edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2); + _edit_area->setSelection (l1, c1, l2, c2); + _edit_area->clear_selection_markers (); + } - if (_find_result_available) - _from_start_check_box->setChecked (0); - else if (! _rep_all) - no_matches_message (); + // Display message if not replace all + if (! _rep_all) + no_matches_message (); + } + } void find_dialog::do_replace (void) @@ -413,7 +445,16 @@ if (_edit_area) { _rep_active = true; // changes in selection not made by the user + _edit_area->replace (_replace_line_edit->text ()); + if (m_in_sel) + { + // Update the length of the selection + m_sel_end = m_sel_end + - _search_line_edit->text ().toUtf8 ().size () + + _replace_line_edit->text ().toUtf8 ().size (); + } + _rep_active = false; } } @@ -422,14 +463,7 @@ { if (_edit_area) { - // The following line is a workaround for the issue that when replacing - // a text with a new one with different size within the selection, - // the selection is not updated leading to missing or extra replacements. - // This does not happen, when the selection is search backwards - if (_search_selection_check_box->isChecked ()) - _backward_check_box->setChecked (true); - - // do the replace if we have selected text + // Do the replace if we have selected text if (_find_result_available && _edit_area->hasSelectedText ()) do_replace (); diff -r 8ea53aa9ac39 -r fbe46901ae62 libgui/src/m-editor/find-dialog.h --- a/libgui/src/m-editor/find-dialog.h Sat Jun 01 08:56:51 2019 -0700 +++ b/libgui/src/m-editor/find-dialog.h Sat Jun 01 19:30:56 2019 +0200 @@ -63,7 +63,8 @@ #define octave_find_dialog_h 1 #include -#include + +#include "octave-qscintilla.h" class QCheckBox; class QDialogButtonBox; @@ -102,7 +103,7 @@ FIND_DLG_SEL = 128 }; - find_dialog (QsciScintilla *edit_area, QList find_actions, + find_dialog (octave_qscintilla *edit_area, QList find_actions, QWidget *parent = nullptr); void init_search_text (void); void save_data (find_dialog_data *fdlg_data); @@ -144,10 +145,14 @@ QPushButton *_replace_all_button; QPushButton *_more_button; QWidget *_extension; - QsciScintilla *_edit_area; + octave_qscintilla *_edit_area; bool _find_result_available; int _rep_all; bool _rep_active; + + bool m_in_sel; + int m_sel_beg; + int m_sel_end; }; } diff -r 8ea53aa9ac39 -r fbe46901ae62 libgui/src/m-editor/octave-qscintilla.cc --- a/libgui/src/m-editor/octave-qscintilla.cc Sat Jun 01 08:56:51 2019 -0700 +++ b/libgui/src/m-editor/octave-qscintilla.cc Sat Jun 01 19:30:56 2019 +0200 @@ -726,11 +726,12 @@ } } - void octave_qscintilla::show_selection_markers (int line, int col, int len) + void octave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2) { - fillIndicatorRange (line, col - len, line, col, m_indicator_id); + fillIndicatorRange (l1, c1, l2, c2, m_indicator_id); - markerAdd (line, marker::selection); + if (l1 == l2) + markerAdd (l1, marker::selection); } void octave_qscintilla::contextmenu_help (bool) diff -r 8ea53aa9ac39 -r fbe46901ae62 libgui/src/m-editor/octave-qscintilla.h --- a/libgui/src/m-editor/octave-qscintilla.h Sat Jun 01 08:56:51 2019 -0700 +++ b/libgui/src/m-editor/octave-qscintilla.h Sat Jun 01 19:30:56 2019 +0200 @@ -69,7 +69,7 @@ void set_word_selection (const QString& word = QString ()); - void show_selection_markers (int line, int col, int len); + void show_selection_markers (int l1, int c1, int l2, int c2); void set_selection_marker_color (const QColor& c);