Release 960805
[wine] / windows / defdlg.c
1 /*
2  * Default dialog procedure
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *
6  */
7
8 #include "windows.h"
9 #include "dialog.h"
10 #include "win.h"
11 #include "winproc.h"
12
13
14 /***********************************************************************
15  *           DEFDLG_SetFocus
16  *
17  * Set the focus to a control of the dialog, selecting the text if
18  * the control is an edit dialog.
19  */
20 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
21 {
22     HWND hwndPrev = GetFocus();
23
24     if (IsChild( hwndDlg, hwndPrev ))
25     {
26         if (SendMessage16( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
27             SendMessage16( hwndPrev, EM_SETSEL, TRUE, MAKELONG( -1, 0 ) );
28     }
29     if (SendMessage16( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
30         SendMessage16( hwndCtrl, EM_SETSEL, FALSE, MAKELONG( 0, -1 ) );
31     SetFocus( hwndCtrl );
32 }
33
34
35 /***********************************************************************
36  *           DEFDLG_SaveFocus
37  */
38 static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
39 {
40     HWND hwndFocus = GetFocus();
41
42     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
43     infoPtr->hwndFocus = hwndFocus;
44       /* Remove default button */
45     return TRUE;
46 }
47
48
49 /***********************************************************************
50  *           DEFDLG_RestoreFocus
51  */
52 static BOOL DEFDLG_RestoreFocus( HWND hwnd, DIALOGINFO *infoPtr )
53 {
54     if (!infoPtr->hwndFocus || IsIconic(hwnd)) return FALSE;
55     if (!IsWindow( infoPtr->hwndFocus )) return FALSE;
56     DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
57     infoPtr->hwndFocus = 0;
58     return TRUE;
59 }
60
61
62 /***********************************************************************
63  *           DEFDLG_FindDefButton
64  *
65  * Find the current default push-button.
66  */
67 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
68 {
69     HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
70     while (hwndChild)
71     {
72         if (SendMessage16( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
73             break;
74         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
75     }
76     return hwndChild;
77 }
78
79
80 /***********************************************************************
81  *           DEFDLG_SetDefButton
82  *
83  * Set the new default button to be hwndNew.
84  */
85 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
86                                  HWND hwndNew )
87 {
88     if (hwndNew &&
89         !(SendMessage16(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
90         return FALSE;  /* Destination is not a push button */
91     
92     if (dlgInfo->msgResult)  /* There's already a default pushbutton */
93     {
94         HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->msgResult );
95         if (SendMessage32A( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
96             SendMessage32A( hwndOld, BM_SETSTYLE32, BS_PUSHBUTTON, TRUE );
97     }
98     if (hwndNew)
99     {
100         SendMessage32A( hwndNew, BM_SETSTYLE32, BS_DEFPUSHBUTTON, TRUE );
101         dlgInfo->msgResult = GetDlgCtrlID( hwndNew );
102     }
103     else dlgInfo->msgResult = 0;
104     return TRUE;
105 }
106
107
108 /***********************************************************************
109  *           DEFDLG_Proc
110  *
111  * Implementation of DefDlgProc(). Only handle messages that need special
112  * handling for dialogs.
113  */
114 static LRESULT DEFDLG_Proc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
115                             LPARAM lParam, DIALOGINFO *dlgInfo )
116 {
117     HWND hwndDefId;
118
119     switch(msg)
120     {
121         case WM_INITDIALOG:
122             return 0;
123
124         case WM_ERASEBKGND:
125             FillWindow( hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG );
126             return 1;
127
128         case WM_NCDESTROY:
129
130               /* Free dialog heap (if created) */
131             if (dlgInfo->hDialogHeap)
132             {
133                 GlobalUnlock16(dlgInfo->hDialogHeap);
134                 GlobalFree16(dlgInfo->hDialogHeap);
135                 dlgInfo->hDialogHeap = 0;
136             }
137
138               /* Delete font */
139             if (dlgInfo->hUserFont)
140             {
141                 DeleteObject( dlgInfo->hUserFont );
142                 dlgInfo->hUserFont = 0;
143             }
144
145               /* Delete menu */
146             if (dlgInfo->hMenu)
147             {           
148                 DestroyMenu( dlgInfo->hMenu );
149                 dlgInfo->hMenu = 0;
150             }
151
152             /* Delete window procedure */
153             WINPROC_FreeProc( dlgInfo->dlgProc );
154             dlgInfo->dlgProc = (HWINDOWPROC)0;
155
156               /* Window clean-up */
157             return DefWindowProc32A( hwnd, msg, wParam, lParam );
158
159         case WM_SHOWWINDOW:
160             if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
161             return DefWindowProc32A( hwnd, msg, wParam, lParam );
162
163         case WM_ACTIVATE:
164             if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
165             else DEFDLG_SaveFocus( hwnd, dlgInfo );
166             return 0;
167
168         case WM_SETFOCUS:
169             DEFDLG_RestoreFocus( hwnd, dlgInfo );
170             return 0;
171
172         case DM_SETDEFID:
173             if (dlgInfo->fEnd) return 1;
174             DEFDLG_SetDefButton( hwnd, dlgInfo,
175                                  wParam ? GetDlgItem( hwnd, wParam ) : 0 );
176             return 1;
177
178         case DM_GETDEFID:
179             if (dlgInfo->fEnd) return 0;
180             if (dlgInfo->msgResult)
181               return MAKELONG( dlgInfo->msgResult, DC_HASDEFID );
182             hwndDefId = DEFDLG_FindDefButton( hwnd );
183             if (hwndDefId)
184               return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
185             return 0;
186
187         case WM_NEXTDLGCTL:
188             {
189                 HWND hwndDest = (HWND)wParam;
190                 if (!lParam)
191                 {
192                     HWND hwndPrev = GetFocus();
193                     if (!hwndPrev)  /* Set focus to the first item */
194                         hwndDest = DIALOG_GetFirstTabItem( hwnd );
195                     else
196                         hwndDest = GetNextDlgTabItem( hwnd, hwndPrev, wParam );
197                 }
198                 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
199                 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
200             }
201             return 0;
202
203         case WM_CLOSE:
204             EndDialog( hwnd, TRUE );
205             DestroyWindow( hwnd );
206             return 0;
207     }
208     return 0;
209 }
210
211
212 /***********************************************************************
213  *           DefDlgProc16   (USER.308)
214  */
215 LRESULT DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
216 {
217     DIALOGINFO * dlgInfo;
218     BOOL16 result = FALSE;
219     WND * wndPtr = WIN_FindWndPtr( hwnd );
220     
221     if (!wndPtr) return 0;
222     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
223
224     dlgInfo->msgResult = 0;
225     if (dlgInfo->dlgProc)
226     {
227           /* Call dialog procedure */
228         result = (BOOL16)CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
229                                            hwnd, msg, wParam, lParam );
230
231         /* Check if window was destroyed by dialog procedure */
232         if (result || !IsWindow( hwnd )) return result;
233     }
234     
235     switch(msg)
236     {
237         case WM_INITDIALOG:
238         case WM_ERASEBKGND:
239         case WM_NCDESTROY:
240         case WM_SHOWWINDOW:
241         case WM_ACTIVATE:
242         case WM_SETFOCUS:
243         case DM_SETDEFID:
244         case DM_GETDEFID:
245         case WM_NEXTDLGCTL:
246         case WM_CLOSE:
247             return DEFDLG_Proc( (HWND32)hwnd, msg, (WPARAM32)wParam,
248                                 lParam, dlgInfo );
249
250         default:
251             return DefWindowProc16( hwnd, msg, wParam, lParam );
252     }
253 }
254
255
256 /***********************************************************************
257  *           DefDlgProc32A   (USER32.119)
258  */
259 LRESULT DefDlgProc32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
260 {
261     DIALOGINFO * dlgInfo;
262     BOOL16 result = FALSE;
263     WND * wndPtr = WIN_FindWndPtr( hwnd );
264     
265     if (!wndPtr) return 0;
266     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
267
268     dlgInfo->msgResult = 0;
269     if (dlgInfo->dlgProc)
270     {
271           /* Call dialog procedure */
272         result = (BOOL16)CallWindowProc32A( (WNDPROC32)dlgInfo->dlgProc,
273                                             hwnd, msg, wParam, lParam );
274
275         /* Check if window was destroyed by dialog procedure */
276         if (result || !IsWindow( hwnd )) return result;
277     }
278     
279     switch(msg)
280     {
281         case WM_INITDIALOG:
282         case WM_ERASEBKGND:
283         case WM_NCDESTROY:
284         case WM_SHOWWINDOW:
285         case WM_ACTIVATE:
286         case WM_SETFOCUS:
287         case DM_SETDEFID:
288         case DM_GETDEFID:
289         case WM_NEXTDLGCTL:
290         case WM_CLOSE:
291             return DEFDLG_Proc( hwnd, msg, wParam, lParam, dlgInfo );
292
293         default:
294             return DefWindowProc32A( hwnd, msg, wParam, lParam );
295     }
296 }
297
298
299 /***********************************************************************
300  *           DefDlgProc32W   (USER32.120)
301  */
302 LRESULT DefDlgProc32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
303 {
304     DIALOGINFO * dlgInfo;
305     BOOL16 result = FALSE;
306     WND * wndPtr = WIN_FindWndPtr( hwnd );
307     
308     if (!wndPtr) return 0;
309     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
310
311     dlgInfo->msgResult = 0;
312     if (dlgInfo->dlgProc)
313     {
314           /* Call dialog procedure */
315         result = (BOOL16)CallWindowProc32W( (WNDPROC32)dlgInfo->dlgProc,
316                                             hwnd, msg, wParam, lParam );
317
318         /* Check if window was destroyed by dialog procedure */
319         if (result || !IsWindow( hwnd )) return result;
320     }
321     
322     switch(msg)
323     {
324         case WM_INITDIALOG:
325         case WM_ERASEBKGND:
326         case WM_NCDESTROY:
327         case WM_SHOWWINDOW:
328         case WM_ACTIVATE:
329         case WM_SETFOCUS:
330         case DM_SETDEFID:
331         case DM_GETDEFID:
332         case WM_NEXTDLGCTL:
333         case WM_CLOSE:
334             return DEFDLG_Proc( hwnd, msg, wParam, lParam, dlgInfo );
335
336         default:
337             return DefWindowProc32W( hwnd, msg, wParam, lParam );
338     }
339 }