1 /* AbiWord
2 * Copyright (C) 1998 AbiSource, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "ap_Features.h"
25
26 #include "ut_assert.h"
27 #include "ut_string.h"
28 #include "ut_string_class.h"
29 #include "ut_debugmsg.h"
30
31 #include "ap_Dialog_Replace.h"
32 #include "ap_Dialog_Id.h"
33 #include "ap_Strings.h"
34
35 #include "xap_App.h"
36 #include "xap_Dialog_Id.h"
37 #include "xap_DialogFactory.h"
38 #include "xap_Dlg_MessageBox.h"
39
40 #include "fl_DocLayout.h"
41 #include "fv_View.h"
42
43
AP_Dialog_Replace(XAP_DialogFactory * pDlgFactory,XAP_Dialog_Id id)44 AP_Dialog_Replace::AP_Dialog_Replace(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id)
45 : XAP_Dialog_Modeless(pDlgFactory,id, "interface/dialogreplace"),
46 m_findString(NULL),
47 m_replaceString(NULL)
48 {
49 m_pView = NULL;
50 m_pFrame = NULL;
51
52
53 // is this used?
54 m_answer = a_VOID;
55
56 UT_DEBUGMSG(("FODDEX: creating find/replace dialog\n"));
57 }
58
~AP_Dialog_Replace(void)59 AP_Dialog_Replace::~AP_Dialog_Replace(void)
60 {
61
62 // clean up memory
63 UT_sint32 i;
64 for (i=0; i<m_findList.getItemCount(); i++)
65 {
66 UT_UCS4Char* string = static_cast<UT_UCS4Char*>(m_findList.getNthItem(i));
67 if (string)
68 FREEP(string);
69 }
70 for (i=0; i<m_replaceList.getItemCount(); i++)
71 {
72 UT_UCS4Char* string = static_cast<UT_UCS4Char*>(m_replaceList.getNthItem(i));
73 if (string)
74 FREEP(string);
75 }
76 FREEP(m_findString);
77 FREEP(m_replaceString);
78 }
79
useStart(void)80 void AP_Dialog_Replace::useStart(void)
81 {
82 UT_DEBUGMSG(("AP_Dialog_Replace::useStart(void) I've been called\n"));
83
84 // restore from view
85 m_findString = getFvView()->findGetFindString();
86 m_replaceString = getFvView()->findGetReplaceString();
87 }
88
useEnd(void)89 void AP_Dialog_Replace::useEnd(void)
90 {
91
92 UT_DEBUGMSG(("AP_Dialog_Replace::useEnd(void) I've been called\n"));
93
94 }
95
getAnswer(void) const96 AP_Dialog_Replace::tAnswer AP_Dialog_Replace::getAnswer(void) const
97 {
98 // let our caller know if user hit ok, cancel, etc.
99 return m_answer;
100 }
101
102 // --------------------------- Setup Functions -----------------------------
103
setView(AV_View * view)104 bool AP_Dialog_Replace::setView(AV_View * view)
105 {
106 // we can do a static cast from AV_View into FV_View,
107 // so we can get WP specific information from it.
108 // This could be bad once we introduce an
109 // outline view, etc.
110 UT_return_val_if_fail (view, false);
111
112 m_pFrame = (XAP_Frame *) getActiveFrame();
113 UT_return_val_if_fail (m_pFrame, false);
114
115 m_pView = static_cast<FV_View *>(getActiveFrame()->getCurrentView());
116
117 getFvView()->findSetStartAtInsPoint();
118
119 return true;
120 }
121
getView(void)122 AV_View * AP_Dialog_Replace::getView(void)
123 {
124 return getActiveFrame()->getCurrentView();
125 }
126
setActiveFrame(XAP_Frame *)127 void AP_Dialog_Replace::setActiveFrame(XAP_Frame * /*pFrame*/)
128 {
129 setView(getView());
130 notifyActiveFrame(getActiveFrame());
131 }
132
ConstructWindowName(void)133 void AP_Dialog_Replace::ConstructWindowName(void)
134 {
135 const XAP_StringSet * pSS = m_pApp->getStringSet();
136 gchar * tmp = NULL;
137 // conditionally set title
138 std::string s;
139
140 if (m_id == AP_DIALOG_ID_FIND)
141 {
142 pSS->getValueUTF8(AP_STRING_ID_DLG_FR_FindTitle,s);
143 UT_XML_cloneNoAmpersands(tmp, s.c_str());
144 }
145 else
146 {
147 pSS->getValueUTF8(AP_STRING_ID_DLG_FR_ReplaceTitle,s);
148 UT_XML_cloneNoAmpersands(tmp, s.c_str());
149 }
150 BuildWindowName((char *) m_WindowName,(char*)tmp,sizeof(m_WindowName));
151 FREEP(tmp);
152 }
153
getFvView(void)154 FV_View * AP_Dialog_Replace::getFvView(void)
155 {
156 return static_cast<FV_View *>(getView());
157 }
158
setFindString(const UT_UCSChar * string)159 void AP_Dialog_Replace::setFindString(const UT_UCSChar * string)
160 {
161 UT_UCSChar *findString = getFvView()->findGetFindString(); // caller must FREEP
162 if (string && findString && UT_UCS4_strcmp(string, findString) != 0)
163 {
164 // When search parameters change, clear any existing selection to
165 // avoid replacement of the previous search string.
166 getFvView()->cmdUnselectSelection();
167 }
168 FREEP(findString);
169
170 getFvView()->findSetFindString(string);
171 }
172
173 /*!
174 Caller must FREEP() return value
175 */
getFindString(void)176 UT_UCSChar * AP_Dialog_Replace::getFindString(void)
177 {
178 UT_UCSChar * string = NULL;
179 string = getFvView()->findGetFindString();
180 if (string)
181 {
182 return string;
183 }
184 else
185 {
186 if (UT_UCS4_cloneString_char(&string, "")) {
187 return string;
188 }
189 }
190 return NULL;
191 }
192
setReplaceString(const UT_UCSChar * string)193 void AP_Dialog_Replace::setReplaceString(const UT_UCSChar * string)
194 {
195 UT_DEBUGMSG(("AP_dlg_replace::setReplaceString()\n"));
196
197 getFvView()->findSetReplaceString(string);
198 }
199
getReplaceString(void)200 UT_UCSChar * AP_Dialog_Replace::getReplaceString(void)
201 {
202 UT_UCSChar * string = NULL;
203 UT_UCSChar * replaceString = getFvView()->findGetReplaceString();
204
205 if (replaceString)
206 {
207 return replaceString;
208 }
209 else
210 {
211 if (UT_UCS4_cloneString_char(&string, ""))
212 return string;
213 }
214
215 return NULL;
216 }
217
setMatchCase(bool match)218 void AP_Dialog_Replace::setMatchCase(bool match)
219 {
220 UT_DEBUGMSG(("AP_dlg_replace::setMatchCase(%d)\n", match));
221
222 if (match != getFvView()->findGetMatchCase())
223 {
224 // When search parameters change, clear any existing selection to
225 // avoid replacement of the previous search string.
226 if ( !getFvView()->isSelectionEmpty() )
227 getFvView()->cmdUnselectSelection();
228 }
229
230 getFvView()->findSetMatchCase(match);
231 }
232
getMatchCase(void)233 bool AP_Dialog_Replace::getMatchCase(void)
234 {
235 UT_DEBUGMSG(("AP_dlg_replace::getMatchCase()\n"));
236 return getFvView()->findGetMatchCase();
237 }
238
setReverseFind(bool newValue)239 void AP_Dialog_Replace::setReverseFind(bool newValue)
240 {
241 UT_DEBUGMSG(("AP_dlg_replace::setReverseFind(%d)\n", newValue));
242
243 getFvView()->findSetReverseFind(newValue);
244 }
245
getReverseFind(void)246 bool AP_Dialog_Replace::getReverseFind(void)
247 {
248 UT_DEBUGMSG(("AP_dlg_replace::getReverseFind()\n"));
249 return getFvView()->findGetReverseFind();
250 }
251
setWholeWord(bool newValue)252 void AP_Dialog_Replace::setWholeWord(bool newValue)
253 {
254 UT_DEBUGMSG(("AP_dlg_replace::setWholeWord(%d)\n", newValue));
255
256 getFvView()->findSetWholeWord(newValue);
257 }
258
getWholeWord(void)259 bool AP_Dialog_Replace::getWholeWord(void)
260 {
261 UT_DEBUGMSG(("AP_dlg_replace::getWholeWord()\n"));
262 return getFvView()->findGetWholeWord();
263 }
264
265 // --------------------------- Action Functions -----------------------------
266
findPrev()267 bool AP_Dialog_Replace::findPrev()
268 {
269 UT_DEBUGMSG(("AP_dlg_replace::findPrev()\n"));
270
271 bool bDoneEntireDocument = false;
272
273 // call view to do the work
274 bool result = getFvView()->findPrev(bDoneEntireDocument);
275
276 if (bDoneEntireDocument == true)
277 _messageFinishedFind();
278
279 return result;
280 }
281
findNext()282 bool AP_Dialog_Replace::findNext()
283 {
284
285 // manage the list of find strings
286 UT_UCSChar* findString = getFindString();
287 UT_UCSChar* replaceString = getReplaceString();
288
289 bool var1 = _manageList(&m_findList, findString);
290 bool var2 = _manageList(&m_replaceList, replaceString);
291 if (var1 || var2)
292 {
293 _updateLists();
294 }
295 FREEP(findString);
296 FREEP(replaceString);
297
298 bool bDoneEntireDocument = false;
299
300 // call view to do the work
301 bool result = getFvView()->findNext(bDoneEntireDocument);
302
303 if (bDoneEntireDocument == true)
304 _messageFinishedFind();
305
306 return result;
307 }
308
findReplaceReverse()309 bool AP_Dialog_Replace::findReplaceReverse()
310 {
311
312 bool bDoneEntireDocument = false;
313
314
315 // call view to do the work
316 bool result = getFvView()->findReplaceReverse(bDoneEntireDocument);
317
318
319 if (bDoneEntireDocument == true)
320 _messageFinishedFind();
321
322 return result;
323 }
324
findReplace()325 bool AP_Dialog_Replace::findReplace()
326 {
327
328 // manage the list of find strings
329 UT_UCSChar* findString = getFindString();
330 UT_UCSChar* replaceString = getReplaceString();
331
332 // manage the list of find & replace strings
333 bool var1 = _manageList(&m_findList, findString);
334 bool var2 = _manageList(&m_replaceList, replaceString);
335 if (var1 || var2)
336 {
337 _updateLists();
338 }
339
340 bool bDoneEntireDocument = false;
341
342 // call view to do the work
343 bool result = getFvView()->findReplace(bDoneEntireDocument);
344
345 if (bDoneEntireDocument == true)
346 _messageFinishedFind();
347
348 return result;
349 }
350
findReplaceAll()351 bool AP_Dialog_Replace::findReplaceAll()
352 {
353
354 // manage the list of find & replace strings
355 UT_UCSChar* findString = getFindString();
356 UT_UCSChar* replaceString = getReplaceString();
357
358 bool var1 = _manageList(&m_findList, findString);
359 bool var2 = _manageList(&m_replaceList, replaceString);
360 if (var1 || var2)
361 {
362 _updateLists();
363 }
364
365 FREEP(findString);
366 FREEP(replaceString);
367
368 // call view to do the work
369 UT_uint32 numReplaced = getFvView()->findReplaceAll();
370
371 _messageFinishedReplace(numReplaced);
372
373 return true;
374 }
375
_messageFinishedFind(void)376 void AP_Dialog_Replace::_messageFinishedFind(void)
377 {
378 getActiveFrame()->showMessageBox(AP_STRING_ID_DLG_FR_FinishedFind,
379 XAP_Dialog_MessageBox::b_O,
380 XAP_Dialog_MessageBox::a_OK);
381 }
382
_messageFinishedReplace(UT_uint32 numReplaced)383 void AP_Dialog_Replace::_messageFinishedReplace(UT_uint32 numReplaced)
384 {
385 XAP_Dialog_MessageBox * message =
386 getActiveFrame()->createMessageBox(AP_STRING_ID_DLG_FR_FinishedReplace,
387 XAP_Dialog_MessageBox::b_O,
388 XAP_Dialog_MessageBox::a_OK,
389 numReplaced);
390 getActiveFrame()->showMessageBox(message);
391 }
392
_manageList(UT_GenericVector<UT_UCS4Char * > * list,UT_UCSChar * string)393 bool AP_Dialog_Replace::_manageList(UT_GenericVector<UT_UCS4Char*>* list, UT_UCSChar* string)
394 {
395 UT_UCS4String us(string);
396 UT_sint32 i = 0;
397 bool found = false;
398
399 UT_DEBUGMSG(("FODDEX: AP_Dialog_Replace::_manageList: called\n"));
400
401 // check if the current string is already in the list
402 for (i=0; i<list->getItemCount(); i++)
403 {
404 if (!UT_UCS4_strcmp(string, list->getNthItem(i)))
405 {
406 found = true;
407 break;
408 }
409 }
410
411 UT_UCSChar * clone = NULL;
412 if (UT_UCS4_cloneString(&clone, string))
413 {
414 if (!found)
415 {
416 // if not present, just add it to the internal list
417 list->insertItemAt(clone, 0);
418 UT_DEBUGMSG(("FODDEX: adding '%s' to list\n", us.utf8_str()));
419 return true;
420 } else {
421 // g_free the old string
422 UT_UCSChar* temp = static_cast<UT_UCSChar*>(list->getNthItem(i));
423 if (temp) FREEP(temp);
424 // remove the reference from the list
425 list->deleteNthItem(i);
426 // add it again to the top of the list
427 list->insertItemAt(clone, 0);
428 }
429 } else {
430 UT_DEBUGMSG(("FODDEX: warning, failed to clone UCS4 string: '%s'\n", us.utf8_str()));
431 return false;
432 }
433
434 // cloning failed or the string already existed, so do nothing
435 UT_DEBUGMSG(("FODDEX: string '%s' already in list\n", us.utf8_str()));
436 return false;
437 }
438