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