Use min/max instead of MIN/MAX.
[wine] / dlls / commdlg / finddlg.c
1 /*
2  * COMMDLG - Find & Replace Text Dialogs
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  */
7
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "winbase.h"
12 #include "wine/winbase16.h"
13 #include "ldt.h"
14 #include "commdlg.h"
15 #include "dialog.h"
16 #include "dlgs.h"
17 #include "module.h"
18 #include "debugtools.h"
19 #include "winproc.h"
20 #include "cderr.h"
21
22 DEFAULT_DEBUG_CHANNEL(commdlg)
23
24 #include "cdlg.h"
25
26 /***********************************************************************
27  *           FindTextDlgProc [internal]
28  *
29  * FIXME: Convert to real 32-bit message processing
30  */
31 static LRESULT WINAPI FindTextDlgProc(HWND hDlg, UINT msg,
32                                       WPARAM wParam, LPARAM lParam)
33 {
34     UINT16 msg16;
35     MSGPARAM16 mp16;
36
37     mp16.lParam = lParam;
38     if (WINPROC_MapMsg32ATo16( hDlg, msg, wParam,
39                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
40         return 0;
41     mp16.lResult = FindTextDlgProc16( (HWND16)hDlg, msg16, 
42                                       mp16.wParam, mp16.lParam );
43     
44     WINPROC_UnmapMsg32ATo16( hDlg, msg, wParam, lParam, &mp16 );
45     return mp16.lResult;
46 }
47
48 /***********************************************************************
49  *           ReplaceTextDlgProc [internal]
50  *
51  * FIXME: Convert to real 32-bit message processing
52  */
53 static LRESULT WINAPI ReplaceTextDlgProc(HWND hDlg, UINT msg,
54                                       WPARAM wParam, LPARAM lParam)
55 {
56     UINT16 msg16;
57     MSGPARAM16 mp16;
58
59     mp16.lParam = lParam;
60     if (WINPROC_MapMsg32ATo16( hDlg, msg, wParam,
61                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
62         return 0;
63     mp16.lResult = ReplaceTextDlgProc16( (HWND16)hDlg, msg16, 
64                                          mp16.wParam, mp16.lParam );
65     
66     WINPROC_UnmapMsg32ATo16( hDlg, msg, wParam, lParam, &mp16 );
67     return mp16.lResult;
68 }
69
70 /***********************************************************************
71  *           FindText16   (COMMDLG.11)
72  */
73 HWND16 WINAPI FindText16( SEGPTR find )
74 {
75     HANDLE16 hInst;
76     LPCVOID ptr;
77     HANDLE hResInfo, hDlgTmpl;
78     LPFINDREPLACE16 lpFind = (LPFINDREPLACE16)PTR_SEG_TO_LIN(find);
79
80     /*
81      * FIXME : Should respond to FR_ENABLETEMPLATE and FR_ENABLEHOOK here
82      * For now, only the standard dialog works.
83      */
84     if (lpFind->Flags & (FR_ENABLETEMPLATE | FR_ENABLETEMPLATEHANDLE | 
85         FR_ENABLEHOOK)) FIXME(": unimplemented flag (ignored)\n");     
86     if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, MAKEINTRESOURCEA(FINDDLGORD), RT_DIALOGA)))
87     {
88         COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
89         return FALSE;
90     }
91     if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
92         !(ptr = LockResource( hDlgTmpl )))
93     {
94         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
95         return FALSE;
96     }
97     hInst = GetWindowLongA( lpFind->hwndOwner , GWL_HINSTANCE);
98     return DIALOG_CreateIndirect( hInst, ptr, TRUE, lpFind->hwndOwner,
99                                   (DLGPROC16)FindTextDlgProc,
100                                   find, WIN_PROC_32A );
101 }
102
103
104 /***********************************************************************
105  *           ReplaceText16   (COMMDLG.12)
106  */
107 HWND16 WINAPI ReplaceText16( SEGPTR find )
108 {
109     HANDLE16 hInst;
110     LPCVOID ptr;
111     HANDLE hResInfo, hDlgTmpl;
112     LPFINDREPLACE16 lpFind = (LPFINDREPLACE16)PTR_SEG_TO_LIN(find);
113
114     /*
115      * FIXME : We should do error checking on the lpFind structure here
116      * and make CommDlgExtendedError() return the error condition.
117      */
118     if (lpFind->Flags & (FR_ENABLETEMPLATE | FR_ENABLETEMPLATEHANDLE | 
119         FR_ENABLEHOOK)) FIXME(": unimplemented flag (ignored)\n");     
120     if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, MAKEINTRESOURCEA(REPLACEDLGORD), RT_DIALOGA)))
121     {
122         COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
123         return FALSE;
124     }
125     if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
126         !(ptr = LockResource( hDlgTmpl )))
127     {
128         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
129         return FALSE;
130     }
131     hInst = GetWindowLongA( lpFind->hwndOwner , GWL_HINSTANCE);
132     return DIALOG_CreateIndirect( hInst, ptr, TRUE, lpFind->hwndOwner,
133                                   (DLGPROC16)ReplaceTextDlgProc,
134                                   find, WIN_PROC_32A );
135 }
136
137
138 /***********************************************************************
139  *                              FINDDLG_WMInitDialog            [internal]
140  */
141 static LRESULT FINDDLG_WMInitDialog(HWND hWnd, LPARAM lParam, LPDWORD lpFlags,
142                                     LPSTR lpstrFindWhat, BOOL fUnicode)
143 {
144     SetWindowLongA(hWnd, DWL_USER, lParam);
145     *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
146     /*
147      * FIXME : If the initial FindWhat string is empty, we should disable the
148      * FindNext (IDOK) button.  Only after typing some text, the button should be
149      * enabled.
150      */
151     if (fUnicode) SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
152         else SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
153     CheckRadioButton(hWnd, rad1, rad2, (*lpFlags & FR_DOWN) ? rad2 : rad1);
154     if (*lpFlags & (FR_HIDEUPDOWN | FR_NOUPDOWN)) {
155         EnableWindow(GetDlgItem(hWnd, rad1), FALSE);
156         EnableWindow(GetDlgItem(hWnd, rad2), FALSE);
157     }
158     if (*lpFlags & FR_HIDEUPDOWN) {
159         ShowWindow(GetDlgItem(hWnd, rad1), SW_HIDE);
160         ShowWindow(GetDlgItem(hWnd, rad2), SW_HIDE);
161         ShowWindow(GetDlgItem(hWnd, grp1), SW_HIDE);
162     }
163     CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
164     if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
165         EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
166     if (*lpFlags & FR_HIDEWHOLEWORD)
167         ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
168     CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
169     if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
170         EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
171     if (*lpFlags & FR_HIDEMATCHCASE)
172         ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
173     if (!(*lpFlags & FR_SHOWHELP)) {
174         EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
175         ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
176     }
177     ShowWindow(hWnd, SW_SHOWNORMAL);
178     return TRUE;
179 }    
180
181
182 /***********************************************************************
183  *                              FINDDLG_WMCommand               [internal]
184  */
185 static LRESULT FINDDLG_WMCommand(HWND hWnd, WPARAM wParam, 
186                         HWND hwndOwner, LPDWORD lpFlags,
187                         LPSTR lpstrFindWhat, WORD wFindWhatLen, 
188                         BOOL fUnicode)
189 {
190     int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRING );
191     int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRING );
192
193     switch (wParam) {
194         case IDOK:
195             if (fUnicode) 
196               GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
197               else GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
198             if (IsDlgButtonChecked(hWnd, rad2))
199                 *lpFlags |= FR_DOWN;
200                 else *lpFlags &= ~FR_DOWN;
201             if (IsDlgButtonChecked(hWnd, chx1))
202                 *lpFlags |= FR_WHOLEWORD; 
203                 else *lpFlags &= ~FR_WHOLEWORD;
204             if (IsDlgButtonChecked(hWnd, chx2))
205                 *lpFlags |= FR_MATCHCASE; 
206                 else *lpFlags &= ~FR_MATCHCASE;
207             *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
208             *lpFlags |= FR_FINDNEXT;
209             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
210                           GetWindowLongA(hWnd, DWL_USER) );
211             return TRUE;
212         case IDCANCEL:
213             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
214             *lpFlags |= FR_DIALOGTERM;
215             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
216                           GetWindowLongA(hWnd, DWL_USER) );
217             DestroyWindow(hWnd);
218             return TRUE;
219         case pshHelp:
220             /* FIXME : should lpfr structure be passed as an argument ??? */
221             SendMessageA(hwndOwner, uHelpMessage, 0, 0);
222             return TRUE;
223     }
224     return FALSE;
225 }    
226
227
228 /***********************************************************************
229  *           FindTextDlgProc16   (COMMDLG.13)
230  */
231 LRESULT WINAPI FindTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
232                                  LPARAM lParam)
233 {
234     LPFINDREPLACE16 lpfr;
235     switch (wMsg) {
236         case WM_INITDIALOG:
237             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(lParam);
238             return FINDDLG_WMInitDialog(hWnd, lParam, &(lpfr->Flags),
239                 PTR_SEG_TO_LIN(lpfr->lpstrFindWhat), FALSE);
240         case WM_COMMAND:
241             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(GetWindowLongA(hWnd, DWL_USER));
242             return FINDDLG_WMCommand(hWnd, wParam, lpfr->hwndOwner,
243                 &lpfr->Flags, PTR_SEG_TO_LIN(lpfr->lpstrFindWhat),
244                 lpfr->wFindWhatLen, FALSE);
245     }
246     return FALSE;
247 }
248
249
250 /***********************************************************************
251  *                              REPLACEDLG_WMInitDialog         [internal]
252  */
253 static LRESULT REPLACEDLG_WMInitDialog(HWND hWnd, LPARAM lParam,
254                     LPDWORD lpFlags, LPSTR lpstrFindWhat, 
255                     LPSTR lpstrReplaceWith, BOOL fUnicode)
256 {
257     SetWindowLongA(hWnd, DWL_USER, lParam);
258     *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
259     /*
260      * FIXME : If the initial FindWhat string is empty, we should disable the FinNext /
261      * Replace / ReplaceAll buttons.  Only after typing some text, the buttons should be
262      * enabled.
263      */
264     if (fUnicode)     
265     {
266         SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
267         SetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith);
268     } else
269     {
270         SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
271         SetDlgItemTextA(hWnd, edt2, lpstrReplaceWith);
272     }
273     CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
274     if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
275         EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
276     if (*lpFlags & FR_HIDEWHOLEWORD)
277         ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
278     CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
279     if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
280         EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
281     if (*lpFlags & FR_HIDEMATCHCASE)
282         ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
283     if (!(*lpFlags & FR_SHOWHELP)) {
284         EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
285         ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
286     }
287     ShowWindow(hWnd, SW_SHOWNORMAL);
288     return TRUE;
289 }    
290
291
292 /***********************************************************************
293  *                              REPLACEDLG_WMCommand            [internal]
294  */
295 static LRESULT REPLACEDLG_WMCommand(HWND hWnd, WPARAM16 wParam,
296                     HWND hwndOwner, LPDWORD lpFlags,
297                     LPSTR lpstrFindWhat, WORD wFindWhatLen,
298                     LPSTR lpstrReplaceWith, WORD wReplaceWithLen,
299                     BOOL fUnicode)
300 {
301     int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRING );
302     int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRING );
303
304     switch (wParam) {
305         case IDOK:
306             if (fUnicode)
307             {
308                 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
309                 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
310             }  else
311             {
312                 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
313                 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
314             }
315             if (IsDlgButtonChecked(hWnd, chx1))
316                 *lpFlags |= FR_WHOLEWORD; 
317                 else *lpFlags &= ~FR_WHOLEWORD;
318             if (IsDlgButtonChecked(hWnd, chx2))
319                 *lpFlags |= FR_MATCHCASE; 
320                 else *lpFlags &= ~FR_MATCHCASE;
321             *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
322             *lpFlags |= FR_FINDNEXT;
323             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
324                           GetWindowLongA(hWnd, DWL_USER) );
325             return TRUE;
326         case IDCANCEL:
327             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
328             *lpFlags |= FR_DIALOGTERM;
329             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
330                           GetWindowLongA(hWnd, DWL_USER) );
331             DestroyWindow(hWnd);
332             return TRUE;
333         case psh1:
334             if (fUnicode)
335             {
336                 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
337                 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
338             }  else
339             {   
340                 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
341                 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
342             }
343             if (IsDlgButtonChecked(hWnd, chx1))
344                 *lpFlags |= FR_WHOLEWORD; 
345                 else *lpFlags &= ~FR_WHOLEWORD;
346             if (IsDlgButtonChecked(hWnd, chx2))
347                 *lpFlags |= FR_MATCHCASE; 
348                 else *lpFlags &= ~FR_MATCHCASE;
349             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACEALL | FR_DIALOGTERM);
350             *lpFlags |= FR_REPLACE;
351             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
352                           GetWindowLongA(hWnd, DWL_USER) );
353             return TRUE;
354         case psh2:
355             if (fUnicode)
356             {
357                 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
358                 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
359             }  else
360             {
361                 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
362                 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
363             }
364             if (IsDlgButtonChecked(hWnd, chx1))
365                 *lpFlags |= FR_WHOLEWORD; 
366                 else *lpFlags &= ~FR_WHOLEWORD;
367             if (IsDlgButtonChecked(hWnd, chx2))
368                 *lpFlags |= FR_MATCHCASE; 
369                 else *lpFlags &= ~FR_MATCHCASE;
370             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_DIALOGTERM);
371             *lpFlags |= FR_REPLACEALL;
372             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
373                           GetWindowLongA(hWnd, DWL_USER) );
374             return TRUE;
375         case pshHelp:
376             /* FIXME : should lpfr structure be passed as an argument ??? */
377             SendMessageA(hwndOwner, uHelpMessage, 0, 0);
378             return TRUE;
379     }
380     return FALSE;
381 }    
382
383
384 /***********************************************************************
385  *           ReplaceTextDlgProc16   (COMMDLG.14)
386  */
387 LRESULT WINAPI ReplaceTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
388                                     LPARAM lParam)
389 {
390     LPFINDREPLACE16 lpfr;
391     switch (wMsg) {
392         case WM_INITDIALOG:
393             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(lParam);
394             return REPLACEDLG_WMInitDialog(hWnd, lParam, &lpfr->Flags,
395                     PTR_SEG_TO_LIN(lpfr->lpstrFindWhat),
396                     PTR_SEG_TO_LIN(lpfr->lpstrReplaceWith), FALSE);
397         case WM_COMMAND:
398             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(GetWindowLongA(hWnd, DWL_USER));
399             return REPLACEDLG_WMCommand(hWnd, wParam, lpfr->hwndOwner, 
400                     &lpfr->Flags, PTR_SEG_TO_LIN(lpfr->lpstrFindWhat),
401                     lpfr->wFindWhatLen, PTR_SEG_TO_LIN(lpfr->lpstrReplaceWith),
402                     lpfr->wReplaceWithLen, FALSE);
403     }
404     return FALSE;
405 }
406