]> git.lyx.org Git - lyx.git/blob - src/lyxfind.C
remove Last when NEW_INSETS is defined
[lyx.git] / src / lyxfind.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include "lyxtext.h"
8 #include "lyxfind.h"
9 #include "LyXView.h"
10 #include "minibuffer.h"
11 #include "lyx_gui_misc.h"
12 #include "support/textutils.h"
13 #include "support/lstrings.h"
14 #include "BufferView.h"
15 #include "buffer.h"
16
17 int LyXReplace(BufferView * bv,
18                 string const & searchstr,
19                 string const & replacestr,
20                 bool const & casesens,
21                 bool const & matchwrd,
22                 bool const & forward,
23                 bool const & replaceall)
24 {
25    int replace_count = 0;
26  
27    if (!bv->available() || bv->buffer()->isReadonly()) 
28      return replace_count;
29    
30    // CutSelection cannot cut a single space, so we have to stop
31    // in order to avoid endless loop :-(
32    if (searchstr.length() == 0
33        || (searchstr.length() == 1 && searchstr[0] == ' ')) {
34       WriteAlert(_("Sorry!"), _("You cannot replace a single space, "
35                                 "nor an empty character."));
36       return replace_count;
37    }
38    // now we can start searching for the first 
39    // start at top if replaceall
40    bool fw = forward;
41    if (replaceall) {
42       bv->text->ClearSelection(bv);
43       bv->text->CursorTop(bv);
44       // override search direction because we search top to bottom
45       fw = true;
46    }
47
48    // if nothing selected or selection does not equal search string
49    // search and select next occurance and return if no replaceall
50    if (searchstr!=bv->text->selectionAsString(bv->buffer())) {
51       LyXFind(bv, searchstr, casesens, matchwrd, fw);
52       if (!replaceall)
53         return replace_count;
54    }
55    
56    bool found;
57    do {
58       bv->hideCursor();
59       bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR);
60       bv->toggleSelection(false);
61       bv->text->ReplaceSelectionWithString(bv, replacestr);
62       bv->text->SetSelectionOverString(bv, replacestr);
63       bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
64       ++replace_count;
65       found = LyXFind(bv, searchstr, casesens, matchwrd, fw);
66    } while (replaceall && found);
67    
68    if (bv->focus())
69      bv->showCursor();
70
71    return replace_count;
72 }
73
74 bool LyXFind(BufferView * bv,
75              string const & searchstr,
76              bool const & casesens,
77              bool const & matchwrd,
78              bool const & forward)
79 {
80    bool found = false;
81    
82    if (!bv->available() || searchstr.empty())
83      return found;
84
85    bv->hideCursor();
86    bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR);
87    
88    LyXText * ltCur = bv->text;
89    if (ltCur->selection)
90      ltCur->cursor = forward ? ltCur->sel_end_cursor
91      : ltCur->sel_start_cursor;
92
93    if (forward 
94        ? SearchForward(bv, searchstr, casesens, matchwrd)
95        : SearchBackward(bv, searchstr, casesens, matchwrd)) {
96       bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR);
97       bv->toggleSelection();
98       bv->text->ClearSelection(bv);
99       bv->text->SetSelectionOverString(bv, searchstr);
100       bv->toggleSelection(false);
101       found = true;
102    };
103    
104    if (bv->focus())
105      bv->showCursor();
106    
107    return found;
108 }
109
110
111 // returns true if the specified string is at the specified position
112 bool IsStringInText(LyXParagraph * par, LyXParagraph::size_type pos,
113                     string const & str, bool const & cs,
114                     bool const & mw)
115 {
116         if (!par)
117                 return false;
118    
119         string::size_type size = str.length();
120         LyXParagraph::size_type i = 0;
121 #ifndef NEW_INSETS
122         while (((pos + i) < par->Last())
123 #else
124         while (((pos + i) < par->size())
125 #endif
126                && (string::size_type(i) < size)
127                && (cs ? (str[i] == par->GetChar(pos + i))
128                    : (toupper(str[i]) == toupper(par->GetChar(pos + i)))))
129         {
130                 ++i;
131         }
132         if (size == string::size_type(i)) {
133           // if necessary, check whether string matches word
134           if (!mw || 
135               (mw && ((pos <= 0 || !IsLetterCharOrDigit(par->GetChar(pos - 1)))
136 #ifndef NEW_INSETS
137                       && (pos + size >= par->Last()
138 #else
139                       && (pos + size >= par->size()
140 #endif
141                           || !IsLetterCharOrDigit(par->GetChar(pos + size))))
142                )
143               )
144             return true;
145         }
146         return false;
147 }
148
149 // forward search:
150 // if the string can be found: return true and set the cursor to
151 // the new position, cs = casesensitive, mw = matchword
152 bool SearchForward(BufferView * bv, string const & str,
153                    bool const & cs, bool const & mw)
154 {
155         LyXParagraph * par = bv->text->cursor.par();
156         LyXParagraph::size_type pos = bv->text->cursor.pos();
157    
158         while (par && !IsStringInText(par, pos, str, cs, mw)) {
159 #ifndef NEW_INSETS
160                 if (pos < par->Last() - 1)
161 #else
162                 if (pos < par->size() - 1)
163 #endif
164                         ++pos;
165                 else {
166                         pos = 0;
167                         par = par->next();
168                 }
169         }
170         if (par) {
171                 bv->text->SetCursor(bv, par, pos);
172                 return true;
173         }
174         else
175                 return false;
176 }
177
178
179 // backward search:
180 // if the string can be found: return true and set the cursor to
181 // the new position, cs = casesensitive, mw = matchword
182 bool SearchBackward(BufferView * bv, string const & str,
183                     bool const & cs, bool const & mw)
184 {
185         LyXParagraph * par = bv->text->cursor.par();
186         LyXParagraph::size_type pos = bv->text->cursor.pos();
187
188         do {
189                 if (pos > 0)
190                         --pos;
191                 else {
192                         // We skip empty paragraphs (Asger)
193                         do {
194                                 par = par->previous();
195                                 if (par)
196 #ifndef NEW_INSETS
197                                         pos = par->Last() - 1;
198 #else
199                                         pos = par->size() - 1;
200 #endif
201                         } while (par && pos < 0);
202                 }
203         } while (par && !IsStringInText(par, pos, str, cs, mw));
204   
205         if (par) {
206                 bv->text->SetCursor(bv, par, pos);
207                 return true;
208         } else
209                 return false;
210 }
211