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 //////////////////////////////////////////////////////////////////
21 // THIS CODE RUNS BOTH THE "Find" AND THE "Find-Replace" DIALOGS.
22 //////////////////////////////////////////////////////////////////
23 
24 #include <windows.h>
25 
26 #include "ut_string.h"
27 #include "ut_assert.h"
28 #include "ut_debugmsg.h"
29 
30 #include "xap_Win32App.h"
31 #include "xap_Win32FrameImpl.h"
32 
33 #include "ap_Strings.h"
34 #include "ap_Dialog_Id.h"
35 #include "ap_Dialog_Replace.h"
36 #include "ap_Win32Dialog_Replace.h"
37 #include "xap_Win32DialogHelper.h"
38 #include "ap_Win32Resources.rc2"
39 #include "ap_Win32App.h"
40 
41 /*****************************************************************/
static_constructor(XAP_DialogFactory * pFactory,XAP_Dialog_Id id)42 XAP_Dialog * AP_Win32Dialog_Replace::static_constructor(XAP_DialogFactory * pFactory,
43 													   XAP_Dialog_Id id)
44 {
45 	AP_Win32Dialog_Replace * p = new AP_Win32Dialog_Replace(pFactory,id);
46 	return p;
47 }
48 
AP_Win32Dialog_Replace(XAP_DialogFactory * pDlgFactory,XAP_Dialog_Id id)49 AP_Win32Dialog_Replace::AP_Win32Dialog_Replace(XAP_DialogFactory * pDlgFactory,
50 											   XAP_Dialog_Id id)
51 	: AP_Dialog_Replace(pDlgFactory,id)
52 {
53 
54 }
55 
~AP_Win32Dialog_Replace(void)56 AP_Win32Dialog_Replace::~AP_Win32Dialog_Replace(void)
57 {
58 }
59 
activate(void)60 void AP_Win32Dialog_Replace::activate(void)
61 {
62 	int iResult;
63     UT_Win32LocaleString findstr;
64 
65 	// Update the caption
66 	ConstructWindowName();
67 	setDialogTitle(m_WindowName);
68 
69 	SetFocus( GetDlgItem( m_hDlg,AP_RID_DIALOG_REPLACE_COMBO_FIND) );
70 
71 	iResult = ShowWindow( m_hDlg, SW_SHOW );
72 
73 	iResult = BringWindowToTop( m_hDlg );
74 
75 	UT_return_if_fail ((iResult != 0));
76 
77 	{
78 	UT_UCSChar * bufferUnicode = getFindString();
79 	findstr.fromUCS4 (bufferUnicode);
80 	if (!findstr.empty())
81 	{
82 	    SetDlgItemTextW(m_hDlg, AP_RID_DIALOG_REPLACE_COMBO_FIND,findstr.c_str());
83 		SendMessageW(GetDlgItem(m_hDlg,AP_RID_DIALOG_REPLACE_COMBO_FIND), CB_SETEDITSEL, 0, MAKELONG (0, -1));
84 	}
85 	FREEP(bufferUnicode);
86 	}
87 
88 	if (m_id == AP_DIALOG_ID_REPLACE)
89 	{
90 
91 		UT_UCSChar * bufferUnicode = getReplaceString();
92 		findstr.fromUCS4 (bufferUnicode);
93 		if (!findstr.empty())
94 		{
95 			SetDlgItemTextW(m_hDlg,AP_RID_DIALOG_REPLACE_COMBO_REPLACE,findstr.c_str());
96 			SendMessageW(GetDlgItem(m_hDlg,AP_RID_DIALOG_REPLACE_COMBO_FIND), CB_SETEDITSEL, 0, MAKELONG (0, -1));
97 		}
98 		FREEP(bufferUnicode);
99 	}
100 }
101 
102 
destroy(void)103 void AP_Win32Dialog_Replace::destroy(void)
104 {
105 	UT_DebugOnly<int> iResult = DestroyWindow( m_hDlg );
106 
107 	UT_ASSERT_HARMLESS((iResult != 0));
108 
109 	modeless_cleanup();
110 }
111 
notifyActiveFrame(XAP_Frame * pFrame)112 void AP_Win32Dialog_Replace::notifyActiveFrame(XAP_Frame *pFrame)
113 {
114 	if((HWND)GetWindowLongPtrW(m_hDlg, GWLP_HWNDPARENT) != static_cast<XAP_Win32FrameImpl*>(pFrame->getFrameImpl())->getTopLevelWindow())
115 	{
116 		// Update the caption
117 		ConstructWindowName();
118 		setDialogTitle(m_WindowName);
119 
120 		SetWindowLongPtrW(m_hDlg, GWLP_HWNDPARENT, (LONG_PTR)static_cast<XAP_Win32FrameImpl*>(pFrame->getFrameImpl())->getTopLevelWindow());
121 		SetWindowPos(m_hDlg, NULL, 0, 0, 0, 0,
122 						SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
123 	}
124 }
125 
notifyCloseFrame(XAP_Frame * pFrame)126 void AP_Win32Dialog_Replace::notifyCloseFrame(XAP_Frame *pFrame)
127 {
128 	if((HWND)GetWindowLongPtrW(m_hDlg, GWLP_HWNDPARENT) == static_cast<XAP_Win32FrameImpl*>(pFrame->getFrameImpl())->getTopLevelWindow())
129 	{
130 		SetWindowLongPtrW(m_hDlg, GWLP_HWNDPARENT, 0);
131 		SetWindowPos(m_hDlg, NULL, 0, 0, 0, 0,
132 						SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
133 	}
134 }
135 
runModeless(XAP_Frame * pFrame)136 void AP_Win32Dialog_Replace::runModeless(XAP_Frame * pFrame)
137 {
138 	LPCWSTR lpTemplate = NULL;
139 	if (m_id == AP_DIALOG_ID_REPLACE)
140 		lpTemplate = MAKEINTRESOURCEW(AP_RID_DIALOG_REPLACE);
141 	else if (m_id == AP_DIALOG_ID_FIND)
142 		lpTemplate = MAKEINTRESOURCEW(AP_RID_DIALOG_FIND);
143 	else
144 	{
145 		UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
146 		return;
147 	}
148 
149 	setView(static_cast<FV_View *> (pFrame->getCurrentView()) );
150     createModeless(pFrame, lpTemplate);
151 
152     //  Save dialog the ID number and pointer to the widget
153 	m_pApp->rememberModelessId(/* (UT_sint32)*/	getDialogId(), (XAP_Dialog_Modeless *) m_pDialog);
154 
155 	// Update the caption
156 	ConstructWindowName();
157 	setDialogTitle(m_WindowName);
158 
159     ShowWindow( m_hDlg, SW_SHOW );
160 	m_pView->focusChange(AV_FOCUS_MODELESS);
161 }
162 
_initButtons(HWND hWnd)163 void AP_Win32Dialog_Replace::_initButtons(HWND hWnd)
164 {
165 	HWND hWndEditFind = GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_COMBO_FIND);
166 //	HWND hWndEditReplace = GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_COMBO_REPLACE);
167 	DWORD lenFind = GetWindowTextLengthW(hWndEditFind);
168 //	DWORD lenReplace = GetWindowTextLengthW(hWndEditReplace);
169 
170 	BOOL bEnableFind = (lenFind > 0);
171 	EnableWindow(GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_BTN_FINDNEXT),bEnableFind);
172 
173 
174 	if (m_id == AP_DIALOG_ID_REPLACE)
175 	{
176 
177 		BOOL bEnableReplace = bEnableFind;
178 		EnableWindow(GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_BTN_REPLACE),bEnableReplace);
179 		EnableWindow(GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_BTN_REPLACEALL),bEnableReplace);
180 	}
181 
182 	CheckDlgButton(hWnd,AP_RID_DIALOG_REPLACE_CHECK_MATCHCASE,
183 				   ((getMatchCase()) ? BST_CHECKED : BST_UNCHECKED));
184 
185 	CheckDlgButton(hWnd,AP_RID_DIALOG_REPLACE_CHECK_WHOLEWORD,
186 				   ((getWholeWord()) ? BST_CHECKED : BST_UNCHECKED));
187 
188 	CheckDlgButton(hWnd,AP_RID_DIALOG_REPLACE_CHECK_REVERSEFIND,
189 				   ((getReverseFind()) ? BST_CHECKED : BST_UNCHECKED));
190 
191 	return;
192 }
193 
194 #define _DS(c,s)	setDlgItemText(AP_RID_DIALOG_##c,pSS->getValue(AP_STRING_ID_##s))
195 #define _DSX(c,s)	setDlgItemText(AP_RID_DIALOG_##c,pSS->getValue(XAP_STRING_ID_##s))
196 
_onInitDialog(HWND hWnd,WPARAM,LPARAM)197 BOOL AP_Win32Dialog_Replace::_onInitDialog(HWND hWnd, WPARAM /*wParam*/, LPARAM /*lParam*/)
198 {
199 
200 	const XAP_StringSet * pSS = m_pApp->getStringSet();
201 
202 	if (m_id == AP_DIALOG_ID_FIND)
203 		setDialogTitle(pSS->getValue(AP_STRING_ID_DLG_FR_FindTitle));
204 	else
205 		setDialogTitle(pSS->getValue(AP_STRING_ID_DLG_FR_ReplaceTitle));
206 
207 	// localize controls shared across dialogs
208 	_DS(REPLACE_BTN_FINDNEXT,		DLG_FR_FindNextButton);
209 	_DS(REPLACE_TEXT_FIND,			DLG_FR_FindLabel);
210 	_DS(REPLACE_CHECK_MATCHCASE,	DLG_FR_MatchCase);
211 	_DS(REPLACE_CHECK_REVERSEFIND, DLG_FR_ReverseFind);
212 	_DS(REPLACE_CHECK_WHOLEWORD, DLG_FR_WholeWord);
213 
214 	_DSX(REPLACE_BTN_CLOSE, 		DLG_Cancel);
215 
216 
217 	if (m_id == AP_DIALOG_ID_REPLACE)
218 	{
219 
220 		// localize replace-specific controls
221 		_DS(REPLACE_BTN_REPLACE,	DLG_FR_ReplaceButton);
222 		_DS(REPLACE_BTN_REPLACEALL, DLG_FR_ReplaceAllButton);
223 		_DS(REPLACE_TEXT_REPLACE,	DLG_FR_ReplaceWithLabel);
224 	}
225 
226 	_initButtons(hWnd);
227 
228 	SetFocus( GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_COMBO_FIND) );
229 
230 	centerDialog();
231 
232 	return 0;							// 0 == we did call SetFocus()
233 }
234 
_onCommand(HWND hWnd,WPARAM wParam,LPARAM)235 BOOL AP_Win32Dialog_Replace::_onCommand(HWND hWnd, WPARAM wParam, LPARAM /*lParam*/)
236 {
237 	WORD wId = LOWORD(wParam);
238 
239 	// before doing anything else, make sure that the main window is not entirely
240 	// without focus
241 	m_pView->focusChange(AV_FOCUS_MODELESS);
242 	xxx_UT_DEBUGMSG(("s_dlgProc: wId 0x%x\n",wId));
243 
244 	switch (wId)
245 	{
246 	case AP_RID_DIALOG_REPLACE_COMBO_FIND:
247 	case AP_RID_DIALOG_REPLACE_COMBO_REPLACE:
248 		xxx_UT_DEBUGMSG(("_onCommand: edit control\n"));
249 		_initButtons(hWnd);
250 		return 0;
251 
252 	case AP_RID_DIALOG_REPLACE_CHECK_MATCHCASE:
253 		setMatchCase((IsDlgButtonChecked(hWnd,AP_RID_DIALOG_REPLACE_CHECK_MATCHCASE)==BST_CHECKED));
254 		return 1;
255 
256 	case AP_RID_DIALOG_REPLACE_CHECK_WHOLEWORD:
257 		setWholeWord((IsDlgButtonChecked(hWnd,AP_RID_DIALOG_REPLACE_CHECK_WHOLEWORD)==BST_CHECKED));
258 		return 1;
259 
260 	case AP_RID_DIALOG_REPLACE_CHECK_REVERSEFIND:
261 		{
262 		bool currentVal = (IsDlgButtonChecked(hWnd,AP_RID_DIALOG_REPLACE_CHECK_REVERSEFIND)==BST_CHECKED);
263 		setReverseFind(currentVal);
264 
265 		if (!m_pView->isSelectionEmpty())
266 		{
267 		// if there's a selection, clear it
268 			UT_UCS4Char * pSelection;
269 			m_pView->getSelectionText(pSelection);
270 
271 			if ( pSelection != NULL)
272 			{
273 				PT_DocPosition pt = m_pView->getSelectionAnchor();
274 				PT_DocPosition ln = UT_UCS4_strlen (pSelection);
275 				if (currentVal)
276 				{
277 					m_pView->moveInsPtTo(pt);
278 				}
279 				else
280 				{
281 					m_pView->moveInsPtTo(pt+ln);
282 				}
283 				m_pView->cmdUnselectSelection();
284 			}
285 
286 			FREEP(pSelection);
287 		}
288 
289 		m_pView->findSetStartAtInsPoint();
290 
291 		return 1;
292 		}
293 	case AP_RID_DIALOG_REPLACE_BTN_FINDNEXT:
294 		return _onBtn_Find(hWnd, find_FIND_NEXT);
295 
296 	case AP_RID_DIALOG_REPLACE_BTN_REPLACE:
297 		return _onBtn_Find(hWnd, find_REPLACE);
298 
299 	case AP_RID_DIALOG_REPLACE_BTN_REPLACEALL:
300 		return _onBtn_Find(hWnd, find_REPLACE_ALL);
301 
302 	case IDCANCEL:						// also AP_RID_DIALOG_REPLACE_BTN_CLOSE
303 		EndDialog(hWnd,0);
304 		return 1;
305 
306 	default:							// we did not handle this notification
307 		UT_DEBUGMSG(("WM_Command for id %ld\n",wId));
308 		return 0;						// return zero to let windows take care of it.
309 	}
310 }
311 
_onBtn_Find(HWND hWnd,tFindType tFindType)312 BOOL AP_Win32Dialog_Replace::_onBtn_Find(HWND hWnd, tFindType tFindType)
313 {
314 	wchar_t * pBufFromDialogFind = NULL;
315 	wchar_t * pBufFromDialogReplace = NULL;
316 	UT_UCSChar * pUCSReplace = NULL;
317     UT_Win32LocaleString findstr;
318     UT_Win32LocaleString replacestr;
319 
320 	// Check find string
321 	HWND hWndEditFind = GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_COMBO_FIND);
322 	DWORD lenFind = GetWindowTextLengthW(hWndEditFind);
323 	if (!lenFind)
324 		return 1;
325 
326 	pBufFromDialogFind = new wchar_t [lenFind + 1];
327 	if (!pBufFromDialogFind)
328 		goto FreeMemory;
329 	GetWindowTextW(hWndEditFind,pBufFromDialogFind,lenFind+1);
330 
331 	UT_DEBUGMSG(("Find entry contents: [%s]\n",pBufFromDialogFind));
332 
333     findstr.fromLocale (pBufFromDialogFind);
334 
335 	setFindString(findstr.ucs4_str().ucs4_str());
336 
337     if (m_id == AP_DIALOG_ID_REPLACE)
338 	{
339 		// Check Replace string
340 		HWND hWndEditReplace = GetDlgItem(hWnd,AP_RID_DIALOG_REPLACE_COMBO_REPLACE);
341 		DWORD lenReplace = GetWindowTextLengthW(hWndEditReplace);
342 
343 		pBufFromDialogReplace = new wchar_t [lenReplace + 1];
344 		if (!pBufFromDialogReplace)
345 			goto FreeMemory;
346 		GetWindowTextW(hWndEditReplace,pBufFromDialogReplace,lenReplace+1);
347 
348 		UT_DEBUGMSG(("Replace entry contents: [%s]\n",pBufFromDialogReplace));
349 
350 	    replacestr.fromLocale (pBufFromDialogReplace);
351 		setReplaceString(replacestr.ucs4_str().ucs4_str());
352 	}
353 
354 	if (tFindType == find_REPLACE_ALL)
355 	{
356 		UT_return_val_if_fail ((m_id == AP_DIALOG_ID_REPLACE),0); //should never happen in Find dialog
357 		findReplaceAll();
358 	}
359 	else if (tFindType == find_REPLACE)
360 	{
361 		UT_return_val_if_fail ((m_id == AP_DIALOG_ID_REPLACE),0); //should never happen in Find dialog
362 		if (!getReverseFind())
363 			findReplace();
364 		else
365 			findReplaceReverse();
366 	}
367 	else if (tFindType == find_FIND_NEXT)
368 	{
369 		if (!getReverseFind())
370 			findNext();
371 		else
372 			findPrev();
373 	}
374 
375     FreeMemory:
376 	DELETEP(pBufFromDialogFind);
377 	DELETEP(pBufFromDialogReplace);
378 	FREEP(pUCSReplace);
379 	return 1;
380 }
381 
_updateLists()382 void AP_Win32Dialog_Replace::_updateLists()
383 {
384 	_updateList(GetDlgItem(m_hDlg, AP_RID_DIALOG_REPLACE_COMBO_FIND), 		&m_findList);
385 	_updateList(GetDlgItem(m_hDlg, AP_RID_DIALOG_REPLACE_COMBO_REPLACE), 	&m_replaceList);
386 }
387 
_updateList(HWND hWnd,UT_GenericVector<UT_UCS4Char * > * list)388 void AP_Win32Dialog_Replace::_updateList(HWND hWnd, UT_GenericVector<UT_UCS4Char*> *list)
389 {
390 	UT_DEBUGMSG(("AP_Win32Dialog_Replace::_updateList\n"));
391 
392     UT_Win32LocaleString str;
393 
394 	SendMessageW(hWnd, CB_RESETCONTENT, 0,0);
395 
396 	for (UT_sint32 i = 0; i < list->getItemCount(); i++)
397 	{
398 		// leaving the size 0 causes the string class to determine the length itself
399         str.fromUCS4 ((UT_UCS4Char*)list->getNthItem(i));
400     	SendMessageW(hWnd, CB_ADDSTRING, 0, (LPARAM) str.c_str());
401 	}
402 
403 	SendMessageW(hWnd, CB_SETCURSEL, 0,0);
404 }
405 
406