X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxfind.C;h=fa6acb468fb2962dacf05f498e971a09e53ed288;hb=c7db12d1acf83fb5191fab908e0153fa752f4530;hp=21d834eab1a40ecc87c3d0f7274166a7ef55eafc;hpb=4c6091b63f6ac4dae69ddcee26bf22e4f35a3cdf;p=lyx.git diff --git a/src/lyxfind.C b/src/lyxfind.C index 21d834eab1..fa6acb468f 100644 --- a/src/lyxfind.C +++ b/src/lyxfind.C @@ -7,133 +7,211 @@ #include "lyxtext.h" #include "lyxfind.h" #include "LyXView.h" -#include "lyx_gui_misc.h" +#include "frontends/Alert.h" #include "support/textutils.h" #include "support/lstrings.h" #include "BufferView.h" #include "buffer.h" +#include "debug.h" #include "gettext.h" +using lyx::pos_type; + + +/// +// locally used enum +/// +enum SearchResult { + // + SR_NOT_FOUND = 0, + // + SR_FOUND, + // + SR_FOUND_NOUPDATE +}; + + +/// returns true if the specified string is at the specified position +bool IsStringInText(Paragraph * par, pos_type pos, + string const & str, bool const & = true, + bool const & = false); + +/// if the string is found: return true and set the cursor to the new position +SearchResult SearchForward(BufferView *, LyXText * text, string const & str, + bool const & = true, bool const & = false); +/// +SearchResult SearchBackward(BufferView *, LyXText * text, string const & str, + bool const & = true, bool const & = false); + + int LyXReplace(BufferView * bv, - string const & searchstr, - string const & replacestr, - bool const & casesens, - bool const & matchwrd, - bool const & forward, - bool const & replaceall) + string const & searchstr, string const & replacestr, + bool forward, bool casesens, bool matchwrd, bool replaceall, + bool once) { - int replace_count = 0; - - if (!bv->available() || bv->buffer()->isReadonly()) - return replace_count; - - // CutSelection cannot cut a single space, so we have to stop - // in order to avoid endless loop :-( - if (searchstr.length() == 0 - || (searchstr.length() == 1 && searchstr[0] == ' ')) { - WriteAlert(_("Sorry!"), _("You cannot replace a single space, " - "nor an empty character.")); - return replace_count; - } - // now we can start searching for the first - // start at top if replaceall - bool fw = forward; - if (replaceall) { - bv->text->ClearSelection(bv); - bv->text->CursorTop(bv); - // override search direction because we search top to bottom - fw = true; - } - - // if nothing selected or selection does not equal search string - // search and select next occurance and return if no replaceall - if (searchstr!=bv->text->selectionAsString(bv->buffer())) { - LyXFind(bv, searchstr, casesens, matchwrd, fw); - if (!replaceall) + if (!bv->available() || bv->buffer()->isReadonly()) + return 0; + + // CutSelection cannot cut a single space, so we have to stop + // in order to avoid endless loop :-( + if (searchstr.length() == 0 + || (searchstr.length() == 1 && searchstr[0] == ' ')) + { + Alert::alert(_("Sorry!"), _("You cannot replace a single space, " + "nor an empty character.")); + return 0; + } + + LyXText * text = bv->getLyXText(); + + // now we can start searching for the first + // start at top if replaceall + bool fw = forward; + if (replaceall) { + text->clearSelection(); + if (text->inset_owner) { + bv->unlockInset(bv->theLockingInset()); + text = bv->text; + } + text->cursorTop(bv); + // override search direction because we search top to bottom + fw = true; + } + + // if nothing selected or selection does not equal search string + // search and select next occurance and return if no replaceall + string str1; + string str2; + if (casesens) { + str1 = searchstr; + str2 = text->selectionAsString(bv->buffer(), false); + } else { + str1 = lowercase(searchstr); + str2 = lowercase(text->selectionAsString(bv->buffer(), false)); + } + if (str1 != str2) { + if (!LyXFind(bv, searchstr, fw, false, casesens, matchwrd) || + !replaceall) + { + return 0; + } + } + + bool found = false; + int replace_count = 0; + do { + bv->hideCursor(); + bv->update(bv->getLyXText(), BufferView::SELECT|BufferView::FITCUR); + bv->toggleSelection(false); + bv->getLyXText()->replaceSelectionWithString(bv, replacestr); + bv->getLyXText()->setSelectionOverString(bv, replacestr); + bv->update(bv->getLyXText(), BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); + ++replace_count; + if (!once) + found = LyXFind(bv, searchstr, fw, false, casesens, matchwrd); + } while (!once && replaceall && found); + + if (bv->focus()) + bv->showCursor(); + return replace_count; - } - - bool found; - do { - bv->hideCursor(); - bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR); - bv->toggleSelection(false); - bv->text->ReplaceSelectionWithString(bv, replacestr); - bv->text->SetSelectionOverString(bv, replacestr); - bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); - ++replace_count; - found = LyXFind(bv, searchstr, casesens, matchwrd, fw); - } while (replaceall && found); - - if (bv->focus()) - bv->showCursor(); - - return replace_count; } bool LyXFind(BufferView * bv, - string const & searchstr, - bool const & casesens, - bool const & matchwrd, - bool const & forward) + string const & searchstr, bool forward, + bool frominset, bool casesens, bool matchwrd) { - bool found = false; - - if (!bv->available() || searchstr.empty()) - return found; - - bv->hideCursor(); - bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR); - - LyXText * ltCur = bv->text; - if (ltCur->selection) - ltCur->cursor = forward ? ltCur->sel_end_cursor - : ltCur->sel_start_cursor; - - if (forward - ? SearchForward(bv, searchstr, casesens, matchwrd) - : SearchBackward(bv, searchstr, casesens, matchwrd)) { - bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR); - bv->toggleSelection(); - bv->text->ClearSelection(bv); - bv->text->SetSelectionOverString(bv, searchstr); - bv->toggleSelection(false); - found = true; - }; - - if (bv->focus()) - bv->showCursor(); - - return found; + if (!bv->available() || searchstr.empty()) + return false; + + LyXText * text = bv->getLyXText(); + + bv->hideCursor(); + bv->update(text, BufferView::SELECT|BufferView::FITCUR); + + if (text->selection.set()) + text->cursor = forward ? + text->selection.end : text->selection.start; + + SearchResult result = SR_NOT_FOUND; + + if (!frominset && bv->theLockingInset()) { + bool found = forward ? + bv->theLockingInset()->searchForward(bv, searchstr, casesens, matchwrd) : + bv->theLockingInset()->searchBackward(bv, searchstr, casesens, matchwrd); + if (found) + result = SR_FOUND_NOUPDATE; + else { + text = bv->getLyXText(); + Paragraph * par = text->cursor.par(); + pos_type pos = text->cursor.pos(); + if (forward) { + if (pos < par->size() - 1) + ++pos; + else { + pos = 0; + par = par->next(); + } + if (par) + text->setCursor(bv, par, pos); + } + if (par) { + result = forward ? + SearchForward(bv, text, searchstr, casesens, matchwrd) : + SearchBackward(bv, text, searchstr, casesens, matchwrd); + } + } + } else { + result = forward ? + SearchForward(bv, text, searchstr, casesens, matchwrd) : + SearchBackward(bv, text, searchstr, casesens, matchwrd); + } + + bool found = true; + if (result == SR_FOUND) { + // the actual text pointer could have changed! + bv->update(bv->getLyXText(), BufferView::SELECT|BufferView::FITCUR); + bv->toggleSelection(); + bv->getLyXText()->clearSelection(); + bv->getLyXText()->setSelectionOverString(bv, searchstr); + bv->toggleSelection(false); + bv->update(bv->getLyXText(), BufferView::SELECT|BufferView::FITCUR); + } else if (result == SR_NOT_FOUND) + found = false; + + if (bv->focus()) + bv->showCursor(); + + return found; } // returns true if the specified string is at the specified position -bool IsStringInText(LyXParagraph * par, LyXParagraph::size_type pos, +bool IsStringInText(Paragraph * par, pos_type pos, string const & str, bool const & cs, bool const & mw) { if (!par) return false; - + string::size_type size = str.length(); - LyXParagraph::size_type i = 0; + pos_type i = 0; while (((pos + i) < par->size()) && (string::size_type(i) < size) - && (cs ? (str[i] == par->GetChar(pos + i)) - : (toupper(str[i]) == toupper(par->GetChar(pos + i))))) + && (cs ? (str[i] == par->getChar(pos + i)) + : (uppercase(str[i]) == uppercase(par->getChar(pos + i))))) { ++i; } if (size == string::size_type(i)) { - // if necessary, check whether string matches word - if (!mw || - (mw && ((pos <= 0 || !IsLetterCharOrDigit(par->GetChar(pos - 1))) - && (pos + size >= par->size() - || !IsLetterCharOrDigit(par->GetChar(pos + size)))) - ) - ) - return true; + // if necessary, check whether string matches word + if (!mw) + return true; + if ((pos <= 0 || !IsLetterCharOrDigit(par->getChar(pos - 1))) + && (pos + pos_type(size) >= par->size() + || !IsLetterCharOrDigit(par->getChar(pos + size)))) { + return true; + } } return false; } @@ -141,42 +219,64 @@ bool IsStringInText(LyXParagraph * par, LyXParagraph::size_type pos, // forward search: // if the string can be found: return true and set the cursor to // the new position, cs = casesensitive, mw = matchword -bool SearchForward(BufferView * bv, string const & str, - bool const & cs, bool const & mw) +SearchResult SearchForward(BufferView * bv, LyXText * text, string const & str, + bool const & cs, bool const & mw) { - LyXParagraph * par = bv->text->cursor.par(); - LyXParagraph::size_type pos = bv->text->cursor.pos(); - + Paragraph * par = text->cursor.par(); + pos_type pos = text->cursor.pos(); + Paragraph * prev_par = par; + UpdatableInset * inset; + while (par && !IsStringInText(par, pos, str, cs, mw)) { - if (pos < par->size() - 1) - ++pos; - else { - pos = 0; + if (par->isInset(pos) && + (inset = (UpdatableInset *)par->getInset(pos)) && + (inset->isTextInset())) + { + // lock the inset! + text->setCursor(bv, par, pos); + inset->edit(bv); + if (inset->searchForward(bv, str, cs, mw)) + return SR_FOUND_NOUPDATE; + text = bv->getLyXText(); + } + + ++pos; + + if (pos >= par->size()) { + prev_par = par; par = par->next(); + pos = 0; } } + if (par) { - bv->text->SetCursor(bv, par, pos); - return true; + text->setCursor(bv, par, pos); + return SR_FOUND; + } else { + // make sure we end up at the end of the text, + // not the start point of the last search + text->setCursor(bv, prev_par, prev_par->size()); + return SR_NOT_FOUND; } - else - return false; } // backward search: // if the string can be found: return true and set the cursor to // the new position, cs = casesensitive, mw = matchword -bool SearchBackward(BufferView * bv, string const & str, - bool const & cs, bool const & mw) +SearchResult SearchBackward(BufferView * bv, LyXText * text, + string const & str, + bool const & cs, bool const & mw) { - LyXParagraph * par = bv->text->cursor.par(); - LyXParagraph::size_type pos = bv->text->cursor.pos(); + Paragraph * par = text->cursor.par(); + pos_type pos = text->cursor.pos(); + Paragraph * prev_par = par; do { if (pos > 0) --pos; else { + prev_par = par; // We skip empty paragraphs (Asger) do { par = par->previous(); @@ -184,12 +284,26 @@ bool SearchBackward(BufferView * bv, string const & str, pos = par->size() - 1; } while (par && pos < 0); } + UpdatableInset * inset; + if (par && par->isInset(pos) && + (inset = (UpdatableInset *)par->getInset(pos)) && + (inset->isTextInset())) + { + // lock the inset! + text->setCursor(bv, par, pos); + inset->edit(bv, false); + if (inset->searchBackward(bv, str, cs, mw)) + return SR_FOUND_NOUPDATE; + text = bv->getLyXText(); + } } while (par && !IsStringInText(par, pos, str, cs, mw)); - + if (par) { - bv->text->SetCursor(bv, par, pos); - return true; - } else - return false; + text->setCursor(bv, par, pos); + return SR_FOUND; + } else { + // go to the last part of the unsuccessful search + text->setCursor(bv, prev_par, 0); + return SR_NOT_FOUND; + } } -