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