mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-14 06:57:01 +00:00
8cb2e519b3
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@1730 a592a061-630c-0410-9148-cb99ea01b6c8
212 lines
5.2 KiB
C
212 lines
5.2 KiB
C
#include <config.h>
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "lyxtext.h"
|
|
#include "lyxfind.h"
|
|
#include "LyXView.h"
|
|
#include "minibuffer.h"
|
|
#include "lyx_gui_misc.h"
|
|
#include "support/textutils.h"
|
|
#include "support/lstrings.h"
|
|
#include "BufferView.h"
|
|
#include "buffer.h"
|
|
|
|
int LyXReplace(BufferView * bv,
|
|
string const & searchstr,
|
|
string const & replacestr,
|
|
bool const & casesens,
|
|
bool const & matchwrd,
|
|
bool const & forward,
|
|
bool const & replaceall)
|
|
{
|
|
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)
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
// returns true if the specified string is at the specified position
|
|
bool IsStringInText(LyXParagraph * par, LyXParagraph::size_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;
|
|
#ifndef NEW_INSETS
|
|
while (((pos + i) < par->Last())
|
|
#else
|
|
while (((pos + i) < par->size())
|
|
#endif
|
|
&& (string::size_type(i) < size)
|
|
&& (cs ? (str[i] == par->GetChar(pos + i))
|
|
: (toupper(str[i]) == toupper(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)))
|
|
#ifndef NEW_INSETS
|
|
&& (pos + size >= par->Last()
|
|
#else
|
|
&& (pos + size >= par->size()
|
|
#endif
|
|
|| !IsLetterCharOrDigit(par->GetChar(pos + size))))
|
|
)
|
|
)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
LyXParagraph * par = bv->text->cursor.par();
|
|
LyXParagraph::size_type pos = bv->text->cursor.pos();
|
|
|
|
while (par && !IsStringInText(par, pos, str, cs, mw)) {
|
|
#ifndef NEW_INSETS
|
|
if (pos < par->Last() - 1)
|
|
#else
|
|
if (pos < par->size() - 1)
|
|
#endif
|
|
++pos;
|
|
else {
|
|
pos = 0;
|
|
par = par->next();
|
|
}
|
|
}
|
|
if (par) {
|
|
bv->text->SetCursor(bv, par, pos);
|
|
return true;
|
|
}
|
|
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)
|
|
{
|
|
LyXParagraph * par = bv->text->cursor.par();
|
|
LyXParagraph::size_type pos = bv->text->cursor.pos();
|
|
|
|
do {
|
|
if (pos > 0)
|
|
--pos;
|
|
else {
|
|
// We skip empty paragraphs (Asger)
|
|
do {
|
|
par = par->previous();
|
|
if (par)
|
|
#ifndef NEW_INSETS
|
|
pos = par->Last() - 1;
|
|
#else
|
|
pos = par->size() - 1;
|
|
#endif
|
|
} while (par && pos < 0);
|
|
}
|
|
} while (par && !IsStringInText(par, pos, str, cs, mw));
|
|
|
|
if (par) {
|
|
bv->text->SetCursor(bv, par, pos);
|
|
return true;
|
|
} else
|
|
return false;
|
|
}
|
|
|