mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-26 11:16:55 +00:00
Add support for search/replace within selection (#2548)
This commit is contained in:
parent
df4da34836
commit
5980afaee0
@ -460,8 +460,9 @@ void BufferView::setSearchRequestCache(docstring const & text)
|
|||||||
bool forward;
|
bool forward;
|
||||||
bool wrap;
|
bool wrap;
|
||||||
bool instant;
|
bool instant;
|
||||||
|
bool onlysel;
|
||||||
docstring const search = string2find(text, casesensitive, matchword,
|
docstring const search = string2find(text, casesensitive, matchword,
|
||||||
forward, wrap, instant);
|
forward, wrap, instant, onlysel);
|
||||||
theClipboard().setFindBuffer(search);
|
theClipboard().setFindBuffer(search);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1648,7 +1649,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
|
|||||||
|
|
||||||
docstring const data =
|
docstring const data =
|
||||||
find2string(searched_string, false, false,
|
find2string(searched_string, false, false,
|
||||||
act == LFUN_WORD_FIND_FORWARD, false, false);
|
act == LFUN_WORD_FIND_FORWARD, false, false, false);
|
||||||
bool found = lyxfind(this, FuncRequest(LFUN_WORD_FIND, data));
|
bool found = lyxfind(this, FuncRequest(LFUN_WORD_FIND, data));
|
||||||
if (found)
|
if (found)
|
||||||
dr.screenUpdate(Update::Force | Update::FitCursor);
|
dr.screenUpdate(Update::Force | Update::FitCursor);
|
||||||
|
@ -201,7 +201,7 @@ void GuiSearchWidget::findClicked(bool const backwards)
|
|||||||
{
|
{
|
||||||
docstring const needle = qstring_to_ucs4(findCO->currentText());
|
docstring const needle = qstring_to_ucs4(findCO->currentText());
|
||||||
find(needle, caseCB->isChecked(), wordsCB->isChecked(), !backwards,
|
find(needle, caseCB->isChecked(), wordsCB->isChecked(), !backwards,
|
||||||
instantSearchCB->isChecked(), wrapCB->isChecked());
|
instantSearchCB->isChecked(), wrapCB->isChecked(), selectionCB->isChecked());
|
||||||
uniqueInsert(findCO, findCO->currentText());
|
uniqueInsert(findCO, findCO->currentText());
|
||||||
if (!instantSearchCB->isChecked())
|
if (!instantSearchCB->isChecked())
|
||||||
findCO->lineEdit()->selectAll();
|
findCO->lineEdit()->selectAll();
|
||||||
@ -219,7 +219,7 @@ void GuiSearchWidget::replaceClicked(bool const backwards)
|
|||||||
docstring const needle = qstring_to_ucs4(findCO->currentText());
|
docstring const needle = qstring_to_ucs4(findCO->currentText());
|
||||||
docstring const repl = qstring_to_ucs4(replaceCO->currentText());
|
docstring const repl = qstring_to_ucs4(replaceCO->currentText());
|
||||||
replace(needle, repl, caseCB->isChecked(), wordsCB->isChecked(),
|
replace(needle, repl, caseCB->isChecked(), wordsCB->isChecked(),
|
||||||
!backwards, false, wrapCB->isChecked());
|
!backwards, false, wrapCB->isChecked(), selectionCB->isChecked());
|
||||||
uniqueInsert(findCO, findCO->currentText());
|
uniqueInsert(findCO, findCO->currentText());
|
||||||
uniqueInsert(replaceCO, replaceCO->currentText());
|
uniqueInsert(replaceCO, replaceCO->currentText());
|
||||||
}
|
}
|
||||||
@ -235,7 +235,8 @@ void GuiSearchWidget::replaceallClicked()
|
|||||||
{
|
{
|
||||||
replace(qstring_to_ucs4(findCO->currentText()),
|
replace(qstring_to_ucs4(findCO->currentText()),
|
||||||
qstring_to_ucs4(replaceCO->currentText()),
|
qstring_to_ucs4(replaceCO->currentText()),
|
||||||
caseCB->isChecked(), wordsCB->isChecked(), true, true, true);
|
caseCB->isChecked(), wordsCB->isChecked(),
|
||||||
|
true, true, true, selectionCB->isChecked());
|
||||||
uniqueInsert(findCO, findCO->currentText());
|
uniqueInsert(findCO, findCO->currentText());
|
||||||
uniqueInsert(replaceCO, replaceCO->currentText());
|
uniqueInsert(replaceCO, replaceCO->currentText());
|
||||||
}
|
}
|
||||||
@ -243,11 +244,11 @@ void GuiSearchWidget::replaceallClicked()
|
|||||||
|
|
||||||
void GuiSearchWidget::find(docstring const & search, bool casesensitive,
|
void GuiSearchWidget::find(docstring const & search, bool casesensitive,
|
||||||
bool matchword, bool forward, bool instant,
|
bool matchword, bool forward, bool instant,
|
||||||
bool wrap)
|
bool wrap, bool onlysel)
|
||||||
{
|
{
|
||||||
docstring const sdata =
|
docstring const sdata =
|
||||||
find2string(search, casesensitive, matchword,
|
find2string(search, casesensitive, matchword,
|
||||||
forward, wrap, instant);
|
forward, wrap, instant, onlysel);
|
||||||
|
|
||||||
dispatch(FuncRequest(LFUN_WORD_FIND, sdata));
|
dispatch(FuncRequest(LFUN_WORD_FIND, sdata));
|
||||||
}
|
}
|
||||||
@ -255,11 +256,11 @@ void GuiSearchWidget::find(docstring const & search, bool casesensitive,
|
|||||||
|
|
||||||
void GuiSearchWidget::replace(docstring const & search, docstring const & replace,
|
void GuiSearchWidget::replace(docstring const & search, docstring const & replace,
|
||||||
bool casesensitive, bool matchword,
|
bool casesensitive, bool matchword,
|
||||||
bool forward, bool all, bool wrap)
|
bool forward, bool all, bool wrap, bool onlysel)
|
||||||
{
|
{
|
||||||
docstring const sdata =
|
docstring const sdata =
|
||||||
replace2string(replace, search, casesensitive,
|
replace2string(replace, search, casesensitive,
|
||||||
matchword, all, forward, wrap);
|
matchword, all, forward, true, wrap, onlysel);
|
||||||
dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
|
dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,6 +270,7 @@ void GuiSearchWidget::saveSession(QSettings & settings, QString const & session_
|
|||||||
settings.setValue(session_key + "/words", wordsCB->isChecked());
|
settings.setValue(session_key + "/words", wordsCB->isChecked());
|
||||||
settings.setValue(session_key + "/instant", instantSearchCB->isChecked());
|
settings.setValue(session_key + "/instant", instantSearchCB->isChecked());
|
||||||
settings.setValue(session_key + "/wrap", wrapCB->isChecked());
|
settings.setValue(session_key + "/wrap", wrapCB->isChecked());
|
||||||
|
settings.setValue(session_key + "/selection", selectionCB->isChecked());
|
||||||
settings.setValue(session_key + "/minimized", minimized_);
|
settings.setValue(session_key + "/minimized", minimized_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,6 +282,7 @@ void GuiSearchWidget::restoreSession(QString const & session_key)
|
|||||||
wordsCB->setChecked(settings.value(session_key + "/words", false).toBool());
|
wordsCB->setChecked(settings.value(session_key + "/words", false).toBool());
|
||||||
instantSearchCB->setChecked(settings.value(session_key + "/instant", false).toBool());
|
instantSearchCB->setChecked(settings.value(session_key + "/instant", false).toBool());
|
||||||
wrapCB->setChecked(settings.value(session_key + "/wrap", false).toBool());
|
wrapCB->setChecked(settings.value(session_key + "/wrap", false).toBool());
|
||||||
|
selectionCB->setChecked(settings.value(session_key + "/selection", false).toBool());
|
||||||
minimized_ = settings.value(session_key + "/minimized", false).toBool();
|
minimized_ = settings.value(session_key + "/minimized", false).toBool();
|
||||||
// initialize hidings
|
// initialize hidings
|
||||||
minimizeClicked(false);
|
minimizeClicked(false);
|
||||||
|
@ -63,11 +63,11 @@ private:
|
|||||||
/// Searches occurrence of string
|
/// Searches occurrence of string
|
||||||
void find(docstring const & search,
|
void find(docstring const & search,
|
||||||
bool casesensitive, bool matchword,
|
bool casesensitive, bool matchword,
|
||||||
bool forward, bool instant, bool wrap);
|
bool forward, bool instant, bool wrap, bool onlysel);
|
||||||
/// Replaces occurrence of string
|
/// Replaces occurrence of string
|
||||||
void replace(docstring const & search, docstring const & replace,
|
void replace(docstring const & search, docstring const & replace,
|
||||||
bool casesensitive, bool matchword,
|
bool casesensitive, bool matchword,
|
||||||
bool forward, bool all, bool wrap);
|
bool forward, bool all, bool wrap, bool onlysel);
|
||||||
///
|
///
|
||||||
BufferView const * bv_ = nullptr;
|
BufferView const * bv_ = nullptr;
|
||||||
///
|
///
|
||||||
|
@ -467,7 +467,7 @@ void SpellcheckerWidget::on_findNextPB_clicked()
|
|||||||
return;
|
return;
|
||||||
docstring const textfield = qstring_to_ucs4(d->ui.wordED->text());
|
docstring const textfield = qstring_to_ucs4(d->ui.wordED->text());
|
||||||
docstring const datastring = find2string(textfield,
|
docstring const datastring = find2string(textfield,
|
||||||
true, true, true, false, false);
|
true, true, true, false, false, false);
|
||||||
LYXERR(Debug::GUI, "Spellchecker: find next (" << textfield << ")");
|
LYXERR(Debug::GUI, "Spellchecker: find next (" << textfield << ")");
|
||||||
dispatch(FuncRequest(LFUN_WORD_FIND, datastring));
|
dispatch(FuncRequest(LFUN_WORD_FIND, datastring));
|
||||||
d->canCheck();
|
d->canCheck();
|
||||||
@ -487,7 +487,8 @@ void SpellcheckerWidget::on_replacePB_clicked()
|
|||||||
false, // all words
|
false, // all words
|
||||||
true, // forward
|
true, // forward
|
||||||
false, // find next
|
false, // find next
|
||||||
false); // auto-wrap
|
false, // auto-wrap
|
||||||
|
false); // only selection
|
||||||
|
|
||||||
LYXERR(Debug::GUI, "Replace (" << replacement << ")");
|
LYXERR(Debug::GUI, "Replace (" << replacement << ")");
|
||||||
dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring));
|
dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring));
|
||||||
@ -510,7 +511,8 @@ void SpellcheckerWidget::on_replaceAllPB_clicked()
|
|||||||
true, // all words
|
true, // all words
|
||||||
true, // forward
|
true, // forward
|
||||||
false, // find next
|
false, // find next
|
||||||
false); // auto-wrap
|
false, // auto-wrap
|
||||||
|
false); // only selection
|
||||||
|
|
||||||
LYXERR(Debug::GUI, "Replace all (" << replacement << ")");
|
LYXERR(Debug::GUI, "Replace all (" << replacement << ")");
|
||||||
dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring));
|
dispatch(FuncRequest(LFUN_WORD_REPLACE, datastring));
|
||||||
|
@ -267,7 +267,8 @@ void GuiThesaurus::replace(docstring const & newstr)
|
|||||||
true, // match word
|
true, // match word
|
||||||
false, // all words
|
false, // all words
|
||||||
true, // forward
|
true, // forward
|
||||||
false);// auto-wrap
|
false, // auto-wrap
|
||||||
|
false); // only selection
|
||||||
dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
|
dispatch(FuncRequest(LFUN_WORD_REPLACE, sdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,7 +848,8 @@ void MenuDefinition::expandSpellingSuggestions(BufferView const * bv)
|
|||||||
false, // all words
|
false, // all words
|
||||||
true, // forward
|
true, // forward
|
||||||
false, // find next
|
false, // find next
|
||||||
false))); // auto-wrap
|
false, // auto-wrap
|
||||||
|
false))); // only selection
|
||||||
if (i < m)
|
if (i < m)
|
||||||
add(w);
|
add(w);
|
||||||
else
|
else
|
||||||
|
@ -212,13 +212,23 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="selectionCB">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Onlysearch in selection</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Selection onl&y</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="instantSearchCB">
|
<widget class="QCheckBox" name="instantSearchCB">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>If this is checked, LyX will search forward immediately</string>
|
<string>If this is checked, LyX will search forward immediately</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Search as you t&ype</string>
|
<string>Search as yo&u type</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
158
src/lyxfind.cpp
158
src/lyxfind.cpp
@ -225,24 +225,33 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int findForward(DocIterator & cur, MatchString const & match,
|
int findForward(DocIterator & cur, DocIterator const endcur,
|
||||||
bool find_del = true)
|
MatchString const & match,
|
||||||
|
bool find_del = true, bool onlysel = false)
|
||||||
{
|
{
|
||||||
for (; cur; cur.forwardChar())
|
for (; cur; cur.forwardChar()) {
|
||||||
|
if (onlysel && endcur.pit() == cur.pit()
|
||||||
|
&& endcur.idx() == cur.idx() && endcur.pos() < cur.pos())
|
||||||
|
break;
|
||||||
if (cur.inTexted()) {
|
if (cur.inTexted()) {
|
||||||
int len = match(cur.paragraph(), cur.pos(), find_del);
|
int len = match(cur.paragraph(), cur.pos(), find_del);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int findBackwards(DocIterator & cur, MatchString const & match,
|
int findBackwards(DocIterator & cur, DocIterator const endcur,
|
||||||
bool find_del = true)
|
MatchString const & match,
|
||||||
|
bool find_del = true, bool onlysel = false)
|
||||||
{
|
{
|
||||||
while (cur) {
|
while (cur) {
|
||||||
cur.backwardChar();
|
cur.backwardChar();
|
||||||
|
if (onlysel && endcur.pit() == cur.pit()
|
||||||
|
&& endcur.idx() == cur.idx() && endcur.pos() > cur.pos())
|
||||||
|
break;
|
||||||
if (cur.inTexted()) {
|
if (cur.inTexted()) {
|
||||||
int len = match(cur.paragraph(), cur.pos(), find_del);
|
int len = match(cur.paragraph(), cur.pos(), find_del);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
@ -268,23 +277,56 @@ bool searchAllowed(docstring const & str)
|
|||||||
bool findOne(BufferView * bv, docstring const & searchstr,
|
bool findOne(BufferView * bv, docstring const & searchstr,
|
||||||
bool case_sens, bool whole, bool forward,
|
bool case_sens, bool whole, bool forward,
|
||||||
bool find_del, bool check_wrap, bool auto_wrap,
|
bool find_del, bool check_wrap, bool auto_wrap,
|
||||||
bool instant)
|
bool instant, bool onlysel)
|
||||||
{
|
{
|
||||||
if (!searchAllowed(searchstr))
|
if (!searchAllowed(searchstr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
DocIterator const endcur = forward ? bv->cursor().selectionEnd() : bv->cursor().selectionBegin();
|
||||||
|
|
||||||
|
if (onlysel && bv->cursor().selection()) {
|
||||||
|
docstring const matchstring = bv->cursor().selectionAsString(false);
|
||||||
|
docstring const lcmatchsting = support::lowercase(matchstring);
|
||||||
|
if (matchstring == searchstr || (!case_sens && lcmatchsting == lowercase(searchstr))) {
|
||||||
|
docstring q = _("The search string matches the selection, and search is limited to selection.\n"
|
||||||
|
"Continue search outside?");
|
||||||
|
int search_answer = frontend::Alert::prompt(_("Search outside selection?"),
|
||||||
|
q, 0, 1, _("&Yes"), _("&No"));
|
||||||
|
if (search_answer == 0) {
|
||||||
|
bv->clearSelection();
|
||||||
|
if (findOne(bv, searchstr, case_sens, whole, forward,
|
||||||
|
find_del, check_wrap, auto_wrap, false, false))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DocIterator cur = forward
|
DocIterator cur = forward
|
||||||
? (instant ? bv->cursor().selectionBegin() : bv->cursor().selectionEnd())
|
? ((instant || onlysel) ? bv->cursor().selectionBegin() : bv->cursor().selectionEnd())
|
||||||
: (instant ? bv->cursor().selectionEnd() : bv->cursor().selectionBegin());
|
: ((instant || onlysel) ? bv->cursor().selectionEnd() : bv->cursor().selectionBegin());
|
||||||
|
|
||||||
MatchString const match(searchstr, case_sens, whole);
|
MatchString const match(searchstr, case_sens, whole);
|
||||||
|
|
||||||
int match_len = forward
|
int match_len = forward
|
||||||
? findForward(cur, match, find_del)
|
? findForward(cur, endcur, match, find_del, onlysel)
|
||||||
: findBackwards(cur, match, find_del);
|
: findBackwards(cur, endcur, match, find_del, onlysel);
|
||||||
|
|
||||||
if (match_len > 0)
|
if (match_len > 0)
|
||||||
bv->putSelectionAt(cur, match_len, !forward);
|
bv->putSelectionAt(cur, match_len, !forward);
|
||||||
|
else if (onlysel) {
|
||||||
|
docstring q = _("The search string was not found within the selection.\n"
|
||||||
|
"Continue search outside?");
|
||||||
|
int search_answer = frontend::Alert::prompt(_("Search outside selection?"),
|
||||||
|
q, 0, 1, _("&Yes"), _("&No"));
|
||||||
|
if (search_answer == 0) {
|
||||||
|
bv->clearSelection();
|
||||||
|
if (findOne(bv, searchstr, case_sens, whole, forward,
|
||||||
|
find_del, check_wrap, auto_wrap, false, false))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else if (check_wrap) {
|
else if (check_wrap) {
|
||||||
DocIterator cur_orig(bv->cursor());
|
DocIterator cur_orig(bv->cursor());
|
||||||
if (!auto_wrap) {
|
if (!auto_wrap) {
|
||||||
@ -309,7 +351,7 @@ bool findOne(BufferView * bv, docstring const & searchstr,
|
|||||||
}
|
}
|
||||||
bv->clearSelection();
|
bv->clearSelection();
|
||||||
if (findOne(bv, searchstr, case_sens, whole, forward,
|
if (findOne(bv, searchstr, case_sens, whole, forward,
|
||||||
find_del, false, false, false))
|
find_del, false, false, false, false))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bv->cursor().setCursor(cur_orig);
|
bv->cursor().setCursor(cur_orig);
|
||||||
@ -324,14 +366,16 @@ namespace {
|
|||||||
|
|
||||||
int replaceAll(BufferView * bv,
|
int replaceAll(BufferView * bv,
|
||||||
docstring const & searchstr, docstring const & replacestr,
|
docstring const & searchstr, docstring const & replacestr,
|
||||||
bool case_sens, bool whole)
|
bool case_sens, bool whole, bool onlysel)
|
||||||
{
|
{
|
||||||
Buffer & buf = bv->buffer();
|
Buffer & buf = bv->buffer();
|
||||||
|
|
||||||
if (!searchAllowed(searchstr) || buf.isReadonly())
|
if (!searchAllowed(searchstr) || buf.isReadonly())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DocIterator cur_orig(bv->cursor());
|
DocIterator startcur = bv->cursor().selectionBegin();
|
||||||
|
DocIterator endcur = bv->cursor().selectionEnd();
|
||||||
|
bool const had_selection = bv->cursor().selection();
|
||||||
|
|
||||||
MatchString const match(searchstr, case_sens, whole);
|
MatchString const match(searchstr, case_sens, whole);
|
||||||
int num = 0;
|
int num = 0;
|
||||||
@ -341,29 +385,48 @@ int replaceAll(BufferView * bv,
|
|||||||
|
|
||||||
Cursor cur(*bv);
|
Cursor cur(*bv);
|
||||||
cur.setCursor(doc_iterator_begin(&buf));
|
cur.setCursor(doc_iterator_begin(&buf));
|
||||||
int match_len = findForward(cur, match, false);
|
int match_len = findForward(cur, endcur, match, false, onlysel);
|
||||||
while (match_len > 0) {
|
while (match_len > 0) {
|
||||||
// Backup current cursor position and font.
|
// Backup current cursor position and font.
|
||||||
pos_type const pos = cur.pos();
|
pos_type const pos = cur.pos();
|
||||||
Font const font = cur.paragraph().getFontSettings(buf.params(), pos);
|
Font const font = cur.paragraph().getFontSettings(buf.params(), pos);
|
||||||
cur.recordUndo();
|
cur.recordUndo();
|
||||||
int striked = ssize -
|
int struck = ssize -
|
||||||
cur.paragraph().eraseChars(pos, pos + match_len,
|
cur.paragraph().eraseChars(pos, pos + match_len,
|
||||||
buf.params().track_changes);
|
buf.params().track_changes);
|
||||||
cur.paragraph().insert(pos, replacestr, font,
|
cur.paragraph().insert(pos, replacestr, font,
|
||||||
Change(buf.params().track_changes
|
Change(buf.params().track_changes
|
||||||
? Change::INSERTED
|
? Change::INSERTED
|
||||||
: Change::UNCHANGED));
|
: Change::UNCHANGED));
|
||||||
for (int i = 0; i < rsize + striked; ++i)
|
for (int i = 0; i < rsize + struck; ++i)
|
||||||
cur.forwardChar();
|
cur.forwardChar();
|
||||||
|
if (onlysel && cur.pit() == endcur.pit() && cur.idx() == endcur.idx()) {
|
||||||
|
// Adjust end of selection for replace-all in selection
|
||||||
|
if (rsize > ssize) {
|
||||||
|
int const offset = rsize - ssize;
|
||||||
|
for (int i = 0; i < offset + struck; ++i)
|
||||||
|
endcur.forwardPos();
|
||||||
|
} else {
|
||||||
|
int const offset = ssize - rsize;
|
||||||
|
for (int i = 0; i < offset + struck; ++i)
|
||||||
|
endcur.backwardPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
++num;
|
++num;
|
||||||
match_len = findForward(cur, match, false);
|
match_len = findForward(cur, endcur, match, false, onlysel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bv->putSelectionAt(doc_iterator_begin(&buf), 0, false);
|
bv->putSelectionAt(doc_iterator_begin(&buf), 0, false);
|
||||||
|
|
||||||
cur_orig.fixIfBroken();
|
startcur.fixIfBroken();
|
||||||
bv->setCursor(cur_orig);
|
bv->setCursor(startcur);
|
||||||
|
|
||||||
|
// Reset selection, accounting for changes in selection
|
||||||
|
if (had_selection) {
|
||||||
|
endcur.fixIfBroken();
|
||||||
|
bv->cursor().resetAnchor();
|
||||||
|
bv->setCursorSelectionTo(endcur);
|
||||||
|
}
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
@ -386,14 +449,15 @@ int replaceAll(BufferView * bv,
|
|||||||
// whether anything at all was done.
|
// whether anything at all was done.
|
||||||
pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
|
pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
|
||||||
docstring const & replacestr, bool case_sens,
|
docstring const & replacestr, bool case_sens,
|
||||||
bool whole, bool forward, bool findnext, bool wrap)
|
bool whole, bool forward, bool findnext, bool wrap,
|
||||||
|
bool onlysel)
|
||||||
{
|
{
|
||||||
Cursor & cur = bv->cursor();
|
Cursor & cur = bv->cursor();
|
||||||
if (!cur.selection()) {
|
if (!cur.selection() || onlysel) {
|
||||||
// no selection, non-empty search string: find it
|
// no selection, non-empty search string: find it
|
||||||
if (!searchstr.empty()) {
|
if (!searchstr.empty()) {
|
||||||
bool const found = findOne(bv, searchstr, case_sens, whole,
|
bool const found = findOne(bv, searchstr, case_sens, whole,
|
||||||
forward, true, findnext, wrap, false);
|
forward, true, findnext, wrap, false, onlysel);
|
||||||
return make_pair(found, 0);
|
return make_pair(found, 0);
|
||||||
}
|
}
|
||||||
// empty search string
|
// empty search string
|
||||||
@ -423,7 +487,7 @@ pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
|
|||||||
// just find the search word
|
// just find the search word
|
||||||
if (!have_selection || !match) {
|
if (!have_selection || !match) {
|
||||||
bool const found = findOne(bv, searchstr, case_sens, whole, forward,
|
bool const found = findOne(bv, searchstr, case_sens, whole, forward,
|
||||||
true, findnext, wrap, false);
|
true, findnext, wrap, false, onlysel);
|
||||||
return make_pair(found, 0);
|
return make_pair(found, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +504,7 @@ pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
|
|||||||
}
|
}
|
||||||
if (findnext)
|
if (findnext)
|
||||||
findOne(bv, searchstr, case_sens, whole,
|
findOne(bv, searchstr, case_sens, whole,
|
||||||
forward, false, findnext, wrap, false);
|
forward, false, findnext, wrap, false, onlysel);
|
||||||
|
|
||||||
return make_pair(true, 1);
|
return make_pair(true, 1);
|
||||||
}
|
}
|
||||||
@ -450,7 +514,8 @@ pair<bool, int> replaceOne(BufferView * bv, docstring searchstr,
|
|||||||
|
|
||||||
docstring const find2string(docstring const & search,
|
docstring const find2string(docstring const & search,
|
||||||
bool casesensitive, bool matchword,
|
bool casesensitive, bool matchword,
|
||||||
bool forward, bool wrap, bool instant)
|
bool forward, bool wrap, bool instant,
|
||||||
|
bool onlysel)
|
||||||
{
|
{
|
||||||
odocstringstream ss;
|
odocstringstream ss;
|
||||||
ss << search << '\n'
|
ss << search << '\n'
|
||||||
@ -458,7 +523,8 @@ docstring const find2string(docstring const & search,
|
|||||||
<< int(matchword) << ' '
|
<< int(matchword) << ' '
|
||||||
<< int(forward) << ' '
|
<< int(forward) << ' '
|
||||||
<< int(wrap) << ' '
|
<< int(wrap) << ' '
|
||||||
<< int(instant);
|
<< int(instant) << ' '
|
||||||
|
<< int(onlysel);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +532,8 @@ docstring const find2string(docstring const & search,
|
|||||||
docstring const replace2string(docstring const & replace,
|
docstring const replace2string(docstring const & replace,
|
||||||
docstring const & search,
|
docstring const & search,
|
||||||
bool casesensitive, bool matchword,
|
bool casesensitive, bool matchword,
|
||||||
bool all, bool forward, bool findnext, bool wrap)
|
bool all, bool forward, bool findnext,
|
||||||
|
bool wrap, bool onlysel)
|
||||||
{
|
{
|
||||||
odocstringstream ss;
|
odocstringstream ss;
|
||||||
ss << replace << '\n'
|
ss << replace << '\n'
|
||||||
@ -476,7 +543,8 @@ docstring const replace2string(docstring const & replace,
|
|||||||
<< int(all) << ' '
|
<< int(all) << ' '
|
||||||
<< int(forward) << ' '
|
<< int(forward) << ' '
|
||||||
<< int(findnext) << ' '
|
<< int(findnext) << ' '
|
||||||
<< int(wrap);
|
<< int(wrap) << ' '
|
||||||
|
<< int(onlysel);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,11 +554,12 @@ docstring const string2find(docstring const & argument,
|
|||||||
bool &matchword,
|
bool &matchword,
|
||||||
bool &forward,
|
bool &forward,
|
||||||
bool &wrap,
|
bool &wrap,
|
||||||
bool &instant)
|
bool &instant,
|
||||||
|
bool &onlysel)
|
||||||
{
|
{
|
||||||
// data is of the form
|
// data is of the form
|
||||||
// "<search>
|
// "<search>
|
||||||
// <casesensitive> <matchword> <forward> <wrap>"
|
// <casesensitive> <matchword> <forward> <wrap> <onlysel>"
|
||||||
docstring search;
|
docstring search;
|
||||||
docstring howto = split(argument, search, '\n');
|
docstring howto = split(argument, search, '\n');
|
||||||
|
|
||||||
@ -499,6 +568,7 @@ docstring const string2find(docstring const & argument,
|
|||||||
forward = parse_bool(howto, true);
|
forward = parse_bool(howto, true);
|
||||||
wrap = parse_bool(howto);
|
wrap = parse_bool(howto);
|
||||||
instant = parse_bool(howto);
|
instant = parse_bool(howto);
|
||||||
|
onlysel = parse_bool(howto);
|
||||||
|
|
||||||
return search;
|
return search;
|
||||||
}
|
}
|
||||||
@ -515,12 +585,13 @@ bool lyxfind(BufferView * bv, FuncRequest const & ev)
|
|||||||
bool forward;
|
bool forward;
|
||||||
bool wrap;
|
bool wrap;
|
||||||
bool instant;
|
bool instant;
|
||||||
|
bool onlysel;
|
||||||
|
|
||||||
docstring search = string2find(ev.argument(), casesensitive,
|
docstring search = string2find(ev.argument(), casesensitive,
|
||||||
matchword, forward, wrap, instant);
|
matchword, forward, wrap, instant, onlysel);
|
||||||
|
|
||||||
return findOne(bv, search, casesensitive, matchword, forward,
|
return findOne(bv, search, casesensitive, matchword, forward,
|
||||||
false, true, wrap, instant);
|
false, true, wrap, instant, onlysel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -532,7 +603,7 @@ bool lyxreplace(BufferView * bv, FuncRequest const & ev)
|
|||||||
// data is of the form
|
// data is of the form
|
||||||
// "<search>
|
// "<search>
|
||||||
// <replace>
|
// <replace>
|
||||||
// <casesensitive> <matchword> <all> <forward> <findnext> <wrap>"
|
// <casesensitive> <matchword> <all> <forward> <findnext> <wrap> <onlysel>"
|
||||||
docstring search;
|
docstring search;
|
||||||
docstring rplc;
|
docstring rplc;
|
||||||
docstring howto = split(ev.argument(), rplc, '\n');
|
docstring howto = split(ev.argument(), rplc, '\n');
|
||||||
@ -544,16 +615,23 @@ bool lyxreplace(BufferView * bv, FuncRequest const & ev)
|
|||||||
bool forward = parse_bool(howto, true);
|
bool forward = parse_bool(howto, true);
|
||||||
bool findnext = parse_bool(howto, true);
|
bool findnext = parse_bool(howto, true);
|
||||||
bool wrap = parse_bool(howto);
|
bool wrap = parse_bool(howto);
|
||||||
|
bool onlysel = parse_bool(howto);
|
||||||
|
|
||||||
|
if (!bv->cursor().selection())
|
||||||
|
// only selection only makes sense with selection
|
||||||
|
onlysel = false;
|
||||||
|
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
|
||||||
int replace_count = 0;
|
int replace_count = 0;
|
||||||
if (all) {
|
if (all) {
|
||||||
replace_count = replaceAll(bv, search, rplc, casesensitive, matchword);
|
replace_count = replaceAll(bv, search, rplc, casesensitive,
|
||||||
|
matchword, onlysel);
|
||||||
update = replace_count > 0;
|
update = replace_count > 0;
|
||||||
} else {
|
} else {
|
||||||
pair<bool, int> rv =
|
pair<bool, int> rv =
|
||||||
replaceOne(bv, search, rplc, casesensitive, matchword, forward, findnext, wrap);
|
replaceOne(bv, search, rplc, casesensitive, matchword,
|
||||||
|
forward, findnext, wrap, onlysel);
|
||||||
update = rv.first;
|
update = rv.first;
|
||||||
replace_count = rv.second;
|
replace_count = rv.second;
|
||||||
}
|
}
|
||||||
@ -561,15 +639,19 @@ bool lyxreplace(BufferView * bv, FuncRequest const & ev)
|
|||||||
Buffer const & buf = bv->buffer();
|
Buffer const & buf = bv->buffer();
|
||||||
if (!update) {
|
if (!update) {
|
||||||
// emit message signal.
|
// emit message signal.
|
||||||
buf.message(_("String not found."));
|
if (onlysel)
|
||||||
|
buf.message(_("String not found in selection."));
|
||||||
|
else
|
||||||
|
buf.message(_("String not found."));
|
||||||
} else {
|
} else {
|
||||||
if (replace_count == 0) {
|
if (replace_count == 0) {
|
||||||
buf.message(_("String found."));
|
buf.message(_("String found."));
|
||||||
} else if (replace_count == 1) {
|
} else if (replace_count == 1) {
|
||||||
buf.message(_("String has been replaced."));
|
buf.message(_("String has been replaced."));
|
||||||
} else {
|
} else {
|
||||||
docstring const str =
|
docstring const str = onlysel
|
||||||
bformat(_("%1$d strings have been replaced."), replace_count);
|
? bformat(_("%1$d strings have been replaced in the selection."), replace_count)
|
||||||
|
: bformat(_("%1$d strings have been replaced."), replace_count);
|
||||||
buf.message(str);
|
buf.message(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ docstring const string2find(docstring const & argument,
|
|||||||
bool &matchword,
|
bool &matchword,
|
||||||
bool &forward,
|
bool &forward,
|
||||||
bool &wrap,
|
bool &wrap,
|
||||||
bool &instant);
|
bool &instant,
|
||||||
|
bool &onlysel);
|
||||||
|
|
||||||
/** Encode the parameters needed to find \c search as a string
|
/** Encode the parameters needed to find \c search as a string
|
||||||
* that can be dispatched to the LyX core in a FuncRequest wrapper.
|
* that can be dispatched to the LyX core in a FuncRequest wrapper.
|
||||||
@ -46,7 +47,8 @@ docstring const find2string(docstring const & search,
|
|||||||
bool matchword,
|
bool matchword,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool wrap,
|
bool wrap,
|
||||||
bool instant);
|
bool instant,
|
||||||
|
bool onlysel);
|
||||||
|
|
||||||
/** Encode the parameters needed to replace \c search with \c replace
|
/** Encode the parameters needed to replace \c search with \c replace
|
||||||
* as a string that can be dispatched to the LyX core in a FuncRequest
|
* as a string that can be dispatched to the LyX core in a FuncRequest
|
||||||
@ -59,7 +61,8 @@ docstring const replace2string(docstring const & replace,
|
|||||||
bool all,
|
bool all,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool findnext = true,
|
bool findnext = true,
|
||||||
bool wrap = true);
|
bool wrap = true,
|
||||||
|
bool onlysel = false);
|
||||||
|
|
||||||
/** Parse the string encoding of the find request that is found in
|
/** Parse the string encoding of the find request that is found in
|
||||||
* \c ev.argument and act on it.
|
* \c ev.argument and act on it.
|
||||||
@ -71,7 +74,8 @@ bool lyxfind(BufferView * bv, FuncRequest const & ev);
|
|||||||
bool findOne(BufferView * bv, docstring const & searchstr,
|
bool findOne(BufferView * bv, docstring const & searchstr,
|
||||||
bool case_sens, bool whole, bool forward,
|
bool case_sens, bool whole, bool forward,
|
||||||
bool find_del = true, bool check_wrap = false,
|
bool find_del = true, bool check_wrap = false,
|
||||||
bool auto_wrap = false, bool instant = false);
|
bool auto_wrap = false, bool instant = false,
|
||||||
|
bool onlysel = false);
|
||||||
|
|
||||||
/** Parse the string encoding of the replace request that is found in
|
/** Parse the string encoding of the replace request that is found in
|
||||||
* \c ev.argument and act on it.
|
* \c ev.argument and act on it.
|
||||||
|
Loading…
Reference in New Issue
Block a user