Removed a few dependencies on kernel32 functions.
[wine] / dlls / commdlg / finddlg.c
1 /*
2  * COMMDLG - 16 bits 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 "wine/winuser16.h"
14 #include "commdlg.h"
15 #include "ldt.h"
16 #include "module.h"
17 #include "debugtools.h"
18 #include "winproc.h"
19 #include "cderr.h"
20
21 DEFAULT_DEBUG_CHANNEL(commdlg)
22
23 #include "cdlg.h"
24
25 struct FRPRIVATE 
26 {
27     HANDLE16 hDlgTmpl16; /* handle for resource 16 */
28     HANDLE16 hResource16; /* handle for allocated resource 16 */
29     HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
30     LPCVOID template; /* template for 32 bits resource */
31     BOOL find; /* TRUE if find dialog, FALSE if replace dialog */
32     FINDREPLACE16 *fr16;
33 };
34
35 #define LFRPRIVATE struct FRPRIVATE *
36
37 LRESULT WINAPI FindTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
38                                  LPARAM lParam);
39 LRESULT WINAPI ReplaceTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
40                                     LPARAM lParam);
41
42 /***********************************************************************
43  *           FINDDLG_Get16BitsTemplate                                [internal]
44  *
45  * Get a template (FALSE if failure) when 16 bits dialogs are used
46  * by a 16 bits application
47  * FIXME : no test was done for the user-provided template cases
48  */
49 BOOL FINDDLG_Get16BitsTemplate(LFRPRIVATE lfr)
50 {
51     LPFINDREPLACE16 fr16 = lfr->fr16;
52
53     if (fr16->Flags & FR_ENABLETEMPLATEHANDLE)
54     {
55         lfr->template = GlobalLock16(fr16->hInstance);
56         if (!lfr->template)
57         {
58             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
59             return FALSE;
60         }
61     }
62     else if (fr16->Flags & FR_ENABLETEMPLATE)
63     {
64         HANDLE16 hResInfo;
65         if (!(hResInfo = FindResource16(fr16->hInstance,
66                                         fr16->lpTemplateName,
67                                         RT_DIALOG16)))
68         {
69             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
70             return FALSE;
71         }
72         if (!(lfr->hDlgTmpl16 = LoadResource16( fr16->hInstance, hResInfo )))
73         {
74             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
75             return FALSE;
76         }
77         lfr->hResource16 = lfr->hDlgTmpl16;
78         lfr->template = LockResource16(lfr->hResource16);
79         if (!lfr->template)
80         {
81             FreeResource16(lfr->hResource16);
82             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
83             return FALSE;
84         }
85     }
86     else
87     { /* get resource from (32 bits) own Wine resource; convert it to 16 */
88         HANDLE hResInfo, hDlgTmpl32;
89         LPCVOID template32;
90         DWORD size;
91         HGLOBAL16 hGlobal16;
92
93         if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, 
94                lfr->find ?
95                MAKEINTRESOURCEA(FINDDLGORD):MAKEINTRESOURCEA(REPLACEDLGORD),
96                RT_DIALOGA)))
97         {
98             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
99             return FALSE;
100         }
101         if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
102             !(template32 = LockResource( hDlgTmpl32 )))
103         {
104             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
105             return FALSE;
106         }
107         size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
108         hGlobal16 = GlobalAlloc16(0, size);
109         if (!hGlobal16)
110         {
111             COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
112             ERR("alloc failure for %ld bytes\n", size);
113             return FALSE;
114         }
115         lfr->template = GlobalLock16(hGlobal16);
116         if (!lfr->template)
117         {
118             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
119             ERR("global lock failure for %x handle\n", hGlobal16);
120             GlobalFree16(hGlobal16);
121             return FALSE;
122         }
123         ConvertDialog32To16((LPVOID)template32, size, (LPVOID)lfr->template);
124         lfr->hDlgTmpl16 = hGlobal16;
125         lfr->hGlobal16 = hGlobal16;
126     }
127     return TRUE;
128 }
129
130
131 /***********************************************************************
132  *           FINDDLG_FreeResources                                [internal]
133  *
134  * Free resources allocated 
135  */
136 void FINDDLG_FreeResources(LFRPRIVATE lfr)
137 {
138     /* free resources */
139     if (lfr->fr16->Flags & FR_ENABLETEMPLATEHANDLE)
140         GlobalUnlock16(lfr->fr16->hInstance);
141     if (lfr->hResource16)
142     {
143         GlobalUnlock16(lfr->hResource16);
144         FreeResource16(lfr->hResource16);
145     }
146     if (lfr->hGlobal16)
147     {
148         GlobalUnlock16(lfr->hGlobal16);
149         GlobalFree16(lfr->hGlobal16);
150     }
151 }
152
153 /***********************************************************************
154  *           FindText16   (COMMDLG.11)
155  */
156 HWND16 WINAPI FindText16( SEGPTR find )
157 {
158     HANDLE16 hInst;
159     HWND16 ret = 0;
160     FARPROC16 ptr;
161     LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
162
163     if (!lfr) return 0;
164     lfr->fr16 = (LPFINDREPLACE16)PTR_SEG_TO_LIN(find);
165     lfr->find = TRUE;
166     if (FINDDLG_Get16BitsTemplate(lfr))
167     {
168         hInst = GetWindowLongA( lfr->fr16->hwndOwner , GWL_HINSTANCE);
169         ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (SEGPTR) 13);
170         ret = CreateDialogIndirectParam16( hInst, lfr->template,
171                     lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
172         FINDDLG_FreeResources(lfr);
173     }
174     HeapFree(GetProcessHeap(), 0, lfr);
175     return ret;
176 }
177
178
179 /***********************************************************************
180  *           ReplaceText16   (COMMDLG.12)
181  */
182 HWND16 WINAPI ReplaceText16( SEGPTR find )
183 {
184     HANDLE16 hInst;
185     HWND16 ret = 0;
186     FARPROC16 ptr;
187     LFRPRIVATE lfr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FRPRIVATE));
188
189     if (!lfr) return 0;
190     /*
191      * FIXME : We should do error checking on the lpFind structure here
192      * and make CommDlgExtendedError() return the error condition.
193      */
194     lfr->fr16 = (LPFINDREPLACE16)PTR_SEG_TO_LIN(find);
195     lfr->find = FALSE;
196     if (FINDDLG_Get16BitsTemplate(lfr))
197     {
198         hInst = GetWindowLongA( lfr->fr16->hwndOwner , GWL_HINSTANCE);
199         ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (SEGPTR) 14);
200         ret = CreateDialogIndirectParam16( hInst, lfr->template,
201                     lfr->fr16->hwndOwner, (DLGPROC16) ptr, find);
202
203         FINDDLG_FreeResources(lfr);
204     }
205     HeapFree(GetProcessHeap(), 0, lfr);
206     return ret;
207 }
208
209
210 /***********************************************************************
211  *                              FINDDLG_WMInitDialog            [internal]
212  */
213 static LRESULT FINDDLG_WMInitDialog(HWND hWnd, LPARAM lParam, LPDWORD lpFlags,
214                                     LPSTR lpstrFindWhat, BOOL fUnicode)
215 {
216     SetWindowLongA(hWnd, DWL_USER, lParam);
217     *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
218     /*
219      * FIXME : If the initial FindWhat string is empty, we should disable the
220      * FindNext (IDOK) button.  Only after typing some text, the button should be
221      * enabled.
222      */
223     if (fUnicode) SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
224         else SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
225     CheckRadioButton(hWnd, rad1, rad2, (*lpFlags & FR_DOWN) ? rad2 : rad1);
226     if (*lpFlags & (FR_HIDEUPDOWN | FR_NOUPDOWN)) {
227         EnableWindow(GetDlgItem(hWnd, rad1), FALSE);
228         EnableWindow(GetDlgItem(hWnd, rad2), FALSE);
229     }
230     if (*lpFlags & FR_HIDEUPDOWN) {
231         ShowWindow(GetDlgItem(hWnd, rad1), SW_HIDE);
232         ShowWindow(GetDlgItem(hWnd, rad2), SW_HIDE);
233         ShowWindow(GetDlgItem(hWnd, grp1), SW_HIDE);
234     }
235     CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
236     if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
237         EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
238     if (*lpFlags & FR_HIDEWHOLEWORD)
239         ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
240     CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
241     if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
242         EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
243     if (*lpFlags & FR_HIDEMATCHCASE)
244         ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
245     if (!(*lpFlags & FR_SHOWHELP)) {
246         EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
247         ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
248     }
249     ShowWindow(hWnd, SW_SHOWNORMAL);
250     return TRUE;
251 }    
252
253
254 /***********************************************************************
255  *                              FINDDLG_WMCommand               [internal]
256  */
257 static LRESULT FINDDLG_WMCommand(HWND hWnd, WPARAM wParam, 
258                         HWND hwndOwner, LPDWORD lpFlags,
259                         LPSTR lpstrFindWhat, WORD wFindWhatLen, 
260                         BOOL fUnicode)
261 {
262     int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRING );
263     int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRING );
264
265     switch (wParam) {
266         case IDOK:
267             if (fUnicode) 
268               GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
269               else GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
270             if (IsDlgButtonChecked(hWnd, rad2))
271                 *lpFlags |= FR_DOWN;
272                 else *lpFlags &= ~FR_DOWN;
273             if (IsDlgButtonChecked(hWnd, chx1))
274                 *lpFlags |= FR_WHOLEWORD; 
275                 else *lpFlags &= ~FR_WHOLEWORD;
276             if (IsDlgButtonChecked(hWnd, chx2))
277                 *lpFlags |= FR_MATCHCASE; 
278                 else *lpFlags &= ~FR_MATCHCASE;
279             *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
280             *lpFlags |= FR_FINDNEXT;
281             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
282                           GetWindowLongA(hWnd, DWL_USER) );
283             return TRUE;
284         case IDCANCEL:
285             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
286             *lpFlags |= FR_DIALOGTERM;
287             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
288                           GetWindowLongA(hWnd, DWL_USER) );
289             DestroyWindow(hWnd);
290             return TRUE;
291         case pshHelp:
292             /* FIXME : should lpfr structure be passed as an argument ??? */
293             SendMessageA(hwndOwner, uHelpMessage, 0, 0);
294             return TRUE;
295     }
296     return FALSE;
297 }    
298
299
300 /***********************************************************************
301  *           FindTextDlgProc16   (COMMDLG.13)
302  */
303 LRESULT WINAPI FindTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
304                                  LPARAM lParam)
305 {
306     LPFINDREPLACE16 lpfr;
307     switch (wMsg) {
308         case WM_INITDIALOG:
309             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(lParam);
310             return FINDDLG_WMInitDialog(hWnd, lParam, &(lpfr->Flags),
311                 PTR_SEG_TO_LIN(lpfr->lpstrFindWhat), FALSE);
312         case WM_COMMAND:
313             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(GetWindowLongA(hWnd, DWL_USER));
314             return FINDDLG_WMCommand(hWnd, wParam, lpfr->hwndOwner,
315                 &lpfr->Flags, PTR_SEG_TO_LIN(lpfr->lpstrFindWhat),
316                 lpfr->wFindWhatLen, FALSE);
317     }
318     return FALSE;
319 }
320
321
322 /***********************************************************************
323  *                              REPLACEDLG_WMInitDialog         [internal]
324  */
325 static LRESULT REPLACEDLG_WMInitDialog(HWND hWnd, LPARAM lParam,
326                     LPDWORD lpFlags, LPSTR lpstrFindWhat, 
327                     LPSTR lpstrReplaceWith, BOOL fUnicode)
328 {
329     SetWindowLongA(hWnd, DWL_USER, lParam);
330     *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
331     /*
332      * FIXME : If the initial FindWhat string is empty, we should disable the FinNext /
333      * Replace / ReplaceAll buttons.  Only after typing some text, the buttons should be
334      * enabled.
335      */
336     if (fUnicode)     
337     {
338         SetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat);
339         SetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith);
340     } else
341     {
342         SetDlgItemTextA(hWnd, edt1, lpstrFindWhat);
343         SetDlgItemTextA(hWnd, edt2, lpstrReplaceWith);
344     }
345     CheckDlgButton(hWnd, chx1, (*lpFlags & FR_WHOLEWORD) ? 1 : 0);
346     if (*lpFlags & (FR_HIDEWHOLEWORD | FR_NOWHOLEWORD))
347         EnableWindow(GetDlgItem(hWnd, chx1), FALSE);
348     if (*lpFlags & FR_HIDEWHOLEWORD)
349         ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
350     CheckDlgButton(hWnd, chx2, (*lpFlags & FR_MATCHCASE) ? 1 : 0);
351     if (*lpFlags & (FR_HIDEMATCHCASE | FR_NOMATCHCASE))
352         EnableWindow(GetDlgItem(hWnd, chx2), FALSE);
353     if (*lpFlags & FR_HIDEMATCHCASE)
354         ShowWindow(GetDlgItem(hWnd, chx2), SW_HIDE);
355     if (!(*lpFlags & FR_SHOWHELP)) {
356         EnableWindow(GetDlgItem(hWnd, pshHelp), FALSE);
357         ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
358     }
359     ShowWindow(hWnd, SW_SHOWNORMAL);
360     return TRUE;
361 }    
362
363
364 /***********************************************************************
365  *                              REPLACEDLG_WMCommand            [internal]
366  */
367 static LRESULT REPLACEDLG_WMCommand(HWND hWnd, WPARAM16 wParam,
368                     HWND hwndOwner, LPDWORD lpFlags,
369                     LPSTR lpstrFindWhat, WORD wFindWhatLen,
370                     LPSTR lpstrReplaceWith, WORD wReplaceWithLen,
371                     BOOL fUnicode)
372 {
373     int uFindReplaceMessage = RegisterWindowMessageA( FINDMSGSTRING );
374     int uHelpMessage = RegisterWindowMessageA( HELPMSGSTRING );
375
376     switch (wParam) {
377         case IDOK:
378             if (fUnicode)
379             {
380                 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
381                 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
382             }  else
383             {
384                 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
385                 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
386             }
387             if (IsDlgButtonChecked(hWnd, chx1))
388                 *lpFlags |= FR_WHOLEWORD; 
389                 else *lpFlags &= ~FR_WHOLEWORD;
390             if (IsDlgButtonChecked(hWnd, chx2))
391                 *lpFlags |= FR_MATCHCASE; 
392                 else *lpFlags &= ~FR_MATCHCASE;
393             *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM);
394             *lpFlags |= FR_FINDNEXT;
395             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
396                           GetWindowLongA(hWnd, DWL_USER) );
397             return TRUE;
398         case IDCANCEL:
399             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL);
400             *lpFlags |= FR_DIALOGTERM;
401             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
402                           GetWindowLongA(hWnd, DWL_USER) );
403             DestroyWindow(hWnd);
404             return TRUE;
405         case psh1:
406             if (fUnicode)
407             {
408                 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
409                 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
410             }  else
411             {   
412                 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
413                 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
414             }
415             if (IsDlgButtonChecked(hWnd, chx1))
416                 *lpFlags |= FR_WHOLEWORD; 
417                 else *lpFlags &= ~FR_WHOLEWORD;
418             if (IsDlgButtonChecked(hWnd, chx2))
419                 *lpFlags |= FR_MATCHCASE; 
420                 else *lpFlags &= ~FR_MATCHCASE;
421             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACEALL | FR_DIALOGTERM);
422             *lpFlags |= FR_REPLACE;
423             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
424                           GetWindowLongA(hWnd, DWL_USER) );
425             return TRUE;
426         case psh2:
427             if (fUnicode)
428             {
429                 GetDlgItemTextW(hWnd, edt1, (LPWSTR)lpstrFindWhat, wFindWhatLen/2);
430                 GetDlgItemTextW(hWnd, edt2, (LPWSTR)lpstrReplaceWith, wReplaceWithLen/2);
431             }  else
432             {
433                 GetDlgItemTextA(hWnd, edt1, lpstrFindWhat, wFindWhatLen);
434                 GetDlgItemTextA(hWnd, edt2, lpstrReplaceWith, wReplaceWithLen);
435             }
436             if (IsDlgButtonChecked(hWnd, chx1))
437                 *lpFlags |= FR_WHOLEWORD; 
438                 else *lpFlags &= ~FR_WHOLEWORD;
439             if (IsDlgButtonChecked(hWnd, chx2))
440                 *lpFlags |= FR_MATCHCASE; 
441                 else *lpFlags &= ~FR_MATCHCASE;
442             *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_DIALOGTERM);
443             *lpFlags |= FR_REPLACEALL;
444             SendMessageA(hwndOwner, uFindReplaceMessage, 0,
445                           GetWindowLongA(hWnd, DWL_USER) );
446             return TRUE;
447         case pshHelp:
448             /* FIXME : should lpfr structure be passed as an argument ??? */
449             SendMessageA(hwndOwner, uHelpMessage, 0, 0);
450             return TRUE;
451     }
452     return FALSE;
453 }    
454
455
456 /***********************************************************************
457  *           ReplaceTextDlgProc16   (COMMDLG.14)
458  */
459 LRESULT WINAPI ReplaceTextDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
460                                     LPARAM lParam)
461 {
462     LPFINDREPLACE16 lpfr;
463     switch (wMsg) {
464         case WM_INITDIALOG:
465             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(lParam);
466             return REPLACEDLG_WMInitDialog(hWnd, lParam, &lpfr->Flags,
467                     PTR_SEG_TO_LIN(lpfr->lpstrFindWhat),
468                     PTR_SEG_TO_LIN(lpfr->lpstrReplaceWith), FALSE);
469         case WM_COMMAND:
470             lpfr=(LPFINDREPLACE16)PTR_SEG_TO_LIN(GetWindowLongA(hWnd, DWL_USER));
471             return REPLACEDLG_WMCommand(hWnd, wParam, lpfr->hwndOwner, 
472                     &lpfr->Flags, PTR_SEG_TO_LIN(lpfr->lpstrFindWhat),
473                     lpfr->wFindWhatLen, PTR_SEG_TO_LIN(lpfr->lpstrReplaceWith),
474                     lpfr->wReplaceWithLen, FALSE);
475     }
476     return FALSE;
477 }
478