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