1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich,
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
14 #pragma implementation
21 #include "minibuffer.h"
22 #include "support/textutils.h"
25 // Returns the current selection. If nothing is selected or if the selection
26 // spans 2 paragraphs, an empty string is returned.
28 string GetCurrentSelectionAsString(LyXText * lt)
32 LyXParagraph * par = lt->cursor.par;
33 if (lt->selection && lt->sel_cursor.par == par) {
34 // (selected) and (begin/end in same paragraph)
35 LyXParagraph::size_type pos =
36 lt->sel_start_cursor.pos;
37 LyXParagraph::size_type endpos =
38 lt->sel_end_cursor.pos;
39 bool fPrevIsSpace = false;
41 while (pos < par->Last() && pos < endpos) {
42 ch = par->GetChar(pos);
44 //HB??: Maybe (ch <= ' ')
45 if ((ch == ' ') || (ch <= LyXParagraph::META_INSET)) {
46 // consecutive spaces --> 1 space char
48 ++pos; // Next text pos
49 continue; // same search pos
64 // If nothing selected, select the word at the cursor.
65 // Returns the current selection
67 string GetSelectionOrWordAtCursor(LyXText * lt)
69 lt->SelectWordWhenUnderCursor();
70 return GetCurrentSelectionAsString(lt);
74 // This is a copy of SetSelectionOverString from text.C
75 // It does the same, but uses only the length as a parameter
77 void SetSelectionOverLenChars(LyXText * lt, int len)
79 lt->sel_cursor = lt->cursor;
80 for (int i = 0; i < len; ++i)
86 //------------------------------
89 LyXFindReplace::LyXFindReplace()
94 LyXFindReplace::~LyXFindReplace()
98 void LyXFindReplace::StartSearch(BufferView * b)
101 SF.StartSearch(this);
102 SF.replaceEnabled(!bv->buffer()->isReadonly());
103 searchForward = true;
104 if (SF.SearchString().empty())
105 SF.SetSearchString(GetSelectionOrWordAtCursor(bv->text));
109 // TODO?: the user can insert multiple spaces with this
110 // routine (1999-01-11, dnaber)
111 void LyXFindReplace::SearchReplaceCB()
113 if (!bv->available()) return;
114 if (bv->buffer()->isReadonly()) return;
116 // CutSelection cannot cut a single space, so we have to stop
117 // in order to avoid endless loop :-(
118 if (SF.SearchString().length() == 0
119 || (SF.SearchString().length() == 1
120 && SF.SearchString()[0] == ' ') ) {
121 WriteAlert(_("Sorry!"), _("You cannot replace a single space, "
122 "nor an empty character."));
126 string const replacestring = SF.ReplaceString();
131 LyXText * ltCur = bv->text;
132 if (ltCur->selection) {
133 // clear the selection (if there is any)
134 bv->toggleSelection(false);
136 ReplaceSelectionWithString(replacestring.c_str());
138 SetSelectionOverString(replacestring.c_str());
142 // jump to next match:
143 SearchCB(searchForward);
147 // replaces all occurences of a string (1999-01-15, dnaber@mini.gt.owl.de)
148 void LyXFindReplace::SearchReplaceAllCB()
150 if (!bv->available()) return;
151 if (bv->buffer()->isReadonly()) return;
153 // CutSelection cannot cut a single space, so we have to stop
154 // in order to avoid endless loop :-(
155 if (SF.SearchString().length() == 0
156 || (SF.SearchString().length() == 1
157 && SF.SearchString()[0] == ' ') ) {
158 WriteAlert(_("Sorry!"), _("You cannot replace a single space, "
159 "nor an empty character."));
163 string const replacestring = SF.ReplaceString();
168 bv->text->ClearSelection();
169 bv->text->CursorTop();
171 int replace_count = 0;
175 if (ltCur->selection) {
177 bv->toggleSelection(false);
179 ReplaceSelectionWithString(replacestring.c_str());
181 SetSelectionOverString(replacestring.c_str());
185 } while (SearchCB(true));
186 if( replace_count == 0 ) {
188 bv->owner()->getMiniBuffer()->Set(
189 _("String not found!"));
191 if (replace_count == 1) {
192 bv->owner()->getMiniBuffer()->Set(
193 _("1 string has been replaced."));
195 string str = tostr(replace_count);
196 str += _(" strings have been replaced.");
197 bv->owner()->getMiniBuffer()->Set(str);
203 bool LyXFindReplace::SearchCB(bool fForward)
205 // store search direction
206 searchForward = fForward;
208 if (!bv->available())
213 LyXText * ltCur = bv->text;
214 if (ltCur->selection)
215 ltCur->cursor = fForward ? ltCur->sel_end_cursor :
216 ltCur->sel_start_cursor;
218 iLenSelected = SF.SearchString().length();
221 if (!SF.ValidSearchData() ||
222 (fForward ? SearchForward(ltCur) : SearchBackward(ltCur))) {
225 // clear the selection (if there is any)
226 bv->toggleSelection();
227 bv->text->ClearSelection();
229 // set the new selection
230 SetSelectionOverLenChars(bv->text, iLenSelected);
231 bv->toggleSelection(false);
232 bv->owner()->getMiniBuffer()->Set(_("Found."));
236 bv->owner()->getMiniBuffer()->Set(_("String not found!"));
247 // if the string can be found: return true and set the cursor to
249 // (was: LyXText::SearchForward(char const* string) in text2.C )
250 bool LyXFindReplace::SearchForward(LyXText * lt)
252 LyXParagraph * par = lt->cursor.par;
253 LyXParagraph::size_type pos = lt->cursor.pos;
255 while (par && !IsSearchStringInText(par, pos)) {
256 if (pos < par->Last() - 1)
264 lt->SetCursor(par, pos);
271 // if the string can be found: return true and set the cursor to
273 // (was: LyXText::SearchBackward(char const* string) in text2.C )
274 bool LyXFindReplace::SearchBackward(LyXText * lt)
276 LyXParagraph * par = lt->cursor.par;
277 int pos = lt->cursor.pos;
283 // We skip empty paragraphs (Asger)
285 par = par->Previous();
287 pos = par->Last() - 1;
288 } while (par && pos < 0);
290 } while (par && !IsSearchStringInText(par, pos));
293 lt->SetCursor(par, pos);
300 /* Compares 2 char values.
302 > 0 if chSearch > ch2
303 = 0 if chSearch == ch2
304 < 0 if chSearch < ch2
306 int LyXFindReplace::CompareChars(char chSearch, char chText) const
308 if (SF.CaseSensitive())
309 return (chSearch - chText);
310 return (toupper(chSearch) - toupper(chText));
314 // returns true if the search string is at the specified position
315 // (Copied from the original "LyXText::IsStringInText" in text2.C )
316 bool LyXFindReplace::IsSearchStringInText(LyXParagraph * par,
317 LyXParagraph::size_type pos) const
319 if (!par) return false;
323 bool fPrevIsSpace = false;
325 string::size_type iSrch = 0;
326 while (pos + iText < par->Last() &&
327 iSrch < SF.SearchString().length()) {
328 chSrch = SF.SearchString()[iSrch];
329 chText = par->GetChar(pos+iText);
332 ++iText; // next Text pos
333 continue; // same search pos
337 fPrevIsSpace = false;
338 if (CompareChars(chSrch, chText) != 0)
345 if (iSrch < SF.SearchString().length())
349 || ((pos <= 0 || !IsLetterCharOrDigit(par->GetChar(pos - 1)))
350 && (pos + iText >= par->Last()
351 || !IsLetterCharOrDigit(par->GetChar(pos + iText))))) {
352 iLenSelected = iText;