No longer directly accessing debuggee memory.
[wine] / windows / defdlg.c
1 /*
2  * Default dialog procedure
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *
6  */
7
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "dialog.h"
12 #include "win.h"
13 #include "winproc.h"
14
15
16 /***********************************************************************
17  *           DEFDLG_SetFocus
18  *
19  * Set the focus to a control of the dialog, selecting the text if
20  * the control is an edit dialog.
21  */
22 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
23 {
24     HWND hwndPrev = GetFocus();
25
26     if (IsChild( hwndDlg, hwndPrev ))
27     {
28         if (SendMessage16( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
29             SendMessage16( hwndPrev, EM_SETSEL16, TRUE, MAKELONG( -1, 0 ) );
30     }
31     if (SendMessage16( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
32         SendMessage16( hwndCtrl, EM_SETSEL16, FALSE, MAKELONG( 0, -1 ) );
33     SetFocus( hwndCtrl );
34 }
35
36
37 /***********************************************************************
38  *           DEFDLG_SaveFocus
39  */
40 static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
41 {
42     HWND hwndFocus = GetFocus();
43
44     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
45     infoPtr->hwndFocus = hwndFocus;
46       /* Remove default button */
47     return TRUE;
48 }
49
50
51 /***********************************************************************
52  *           DEFDLG_RestoreFocus
53  */
54 static BOOL DEFDLG_RestoreFocus( HWND hwnd, DIALOGINFO *infoPtr )
55 {
56     if (!infoPtr->hwndFocus || IsIconic(hwnd)) return FALSE;
57     if (!IsWindow( infoPtr->hwndFocus )) return FALSE;
58
59     /* Don't set the focus back to controls if EndDialog is already called.*/
60     if (!(infoPtr->flags & DF_END))
61        DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
62
63     /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
64        sometimes losing focus when receiving WM_SETFOCUS messages. */
65     return TRUE;
66 }
67
68
69 /***********************************************************************
70  *           DEFDLG_FindDefButton
71  *
72  * Find the current default push-button.
73  */
74 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
75 {
76     HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
77     while (hwndChild)
78     {
79         if (SendMessage16( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
80             break;
81         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
82     }
83     return hwndChild;
84 }
85
86
87 /***********************************************************************
88  *           DEFDLG_SetDefButton
89  *
90  * Set the new default button to be hwndNew.
91  */
92 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
93                                    HWND hwndNew )
94 {
95     if (hwndNew &&
96         !(SendMessage16(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
97         return FALSE;  /* Destination is not a push button */
98     
99     if (dlgInfo->idResult)  /* There's already a default pushbutton */
100     {
101         HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
102         if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
103             SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
104     }
105     if (hwndNew)
106     {
107         SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
108         dlgInfo->idResult = GetDlgCtrlID( hwndNew );
109     }
110     else dlgInfo->idResult = 0;
111     return TRUE;
112 }
113
114
115 /***********************************************************************
116  *           DEFDLG_Proc
117  *
118  * Implementation of DefDlgProc(). Only handle messages that need special
119  * handling for dialogs.
120  */
121 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
122                             LPARAM lParam, DIALOGINFO *dlgInfo )
123 {
124     switch(msg)
125     {
126         case WM_ERASEBKGND:
127             FillWindow16( hwnd, hwnd, (HDC16)wParam, (HBRUSH16)CTLCOLOR_DLG );
128             return 1;
129
130         case WM_NCDESTROY:
131
132               /* Free dialog heap (if created) */
133             if (dlgInfo->hDialogHeap)
134             {
135                 GlobalUnlock16(dlgInfo->hDialogHeap);
136                 GlobalFree16(dlgInfo->hDialogHeap);
137                 dlgInfo->hDialogHeap = 0;
138             }
139
140               /* Delete font */
141             if (dlgInfo->hUserFont)
142             {
143                 DeleteObject( dlgInfo->hUserFont );
144                 dlgInfo->hUserFont = 0;
145             }
146
147               /* Delete menu */
148             if (dlgInfo->hMenu)
149             {           
150                 DestroyMenu( dlgInfo->hMenu );
151                 dlgInfo->hMenu = 0;
152             }
153
154             /* Delete window procedure */
155             WINPROC_FreeProc( dlgInfo->dlgProc, WIN_PROC_WINDOW );
156             dlgInfo->dlgProc = (HWINDOWPROC)0;
157             dlgInfo->flags |= DF_END;  /* just in case */
158
159               /* Window clean-up */
160             return DefWindowProcA( hwnd, msg, wParam, lParam );
161
162         case WM_SHOWWINDOW:
163             if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
164             return DefWindowProcA( hwnd, msg, wParam, lParam );
165
166         case WM_ACTIVATE:
167             if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
168             else DEFDLG_SaveFocus( hwnd, dlgInfo );
169             return 0;
170
171         case WM_SETFOCUS:
172             DEFDLG_RestoreFocus( hwnd, dlgInfo );
173             return 0;
174
175         case DM_SETDEFID:
176             if (dlgInfo->flags & DF_END) return 1;
177             DEFDLG_SetDefButton( hwnd, dlgInfo,
178                                  wParam ? GetDlgItem( hwnd, wParam ) : 0 );
179             return 1;
180
181         case DM_GETDEFID:
182             {
183                 HWND hwndDefId;
184                 if (dlgInfo->flags & DF_END) return 0;
185                 if (dlgInfo->idResult)
186                     return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
187                 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
188                     return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
189             }
190             return 0;
191
192         case WM_NEXTDLGCTL:
193             {
194                 HWND hwndDest = (HWND)wParam;
195                 if (!lParam)
196                     hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
197                 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
198                 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
199             }
200             return 0;
201
202         case WM_ENTERMENULOOP:
203         case WM_LBUTTONDOWN:
204         case WM_NCLBUTTONDOWN:
205             {
206                 HWND hwndFocus = GetFocus();
207                 if (hwndFocus)
208                 {
209                     WND *wnd = WIN_FindWndPtr( hwndFocus );
210
211                     if( wnd )
212                     {
213                         /* always make combo box hide its listbox control */
214
215                         if( WIDGETS_IsControl( wnd, BIC32_COMBO ) )
216                             SendMessageA( hwndFocus, CB_SHOWDROPDOWN,
217                                             FALSE, 0 );
218                         else if( WIDGETS_IsControl( wnd, BIC32_EDIT ) &&
219                                  WIDGETS_IsControl( wnd->parent,
220                                                       BIC32_COMBO ))
221                             SendMessageA( wnd->parent->hwndSelf, 
222                                             CB_SHOWDROPDOWN, FALSE, 0 );
223                     }
224                     WIN_ReleaseWndPtr(wnd);
225                 }
226             }
227             return DefWindowProcA( hwnd, msg, wParam, lParam );
228
229         case WM_GETFONT: 
230             return dlgInfo->hUserFont;
231
232         case WM_CLOSE:
233             PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
234                             (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
235             return 0;
236     
237         case WM_NOTIFYFORMAT:
238             return DefWindowProcA( hwnd, msg, wParam, lParam );
239     }
240     return 0;
241 }
242
243 /***********************************************************************
244  *           DEFDLG_Epilog
245  */
246 static LRESULT DEFDLG_Epilog(DIALOGINFO* dlgInfo, UINT msg, BOOL fResult)
247 {
248     /* see SDK 3.1 */
249
250     if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
251          msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
252          msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
253          msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
254         return fResult; 
255
256     return dlgInfo->msgResult;
257 }
258
259 /***********************************************************************
260  *           DefDlgProc16   (USER.308)
261  */
262 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
263                              LPARAM lParam )
264 {
265     DIALOGINFO * dlgInfo;
266     BOOL result = FALSE;
267     WND * wndPtr = WIN_FindWndPtr( hwnd );
268     
269     if (!wndPtr) return 0;
270     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
271     dlgInfo->msgResult = 0;
272
273     if (dlgInfo->dlgProc) {     /* Call dialog procedure */
274         result = CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
275                                            hwnd, msg, wParam, lParam );
276         /* 16 bit dlg procs only return BOOL16 */
277         if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
278             result = LOWORD(result);
279     }
280
281     if (!result && IsWindow(hwnd))
282     {
283         /* callback didn't process this message */
284
285         switch(msg)
286         {
287             case WM_ERASEBKGND:
288             case WM_SHOWWINDOW:
289             case WM_ACTIVATE:
290             case WM_SETFOCUS:
291             case DM_SETDEFID:
292             case DM_GETDEFID:
293             case WM_NEXTDLGCTL:
294             case WM_GETFONT:
295             case WM_CLOSE:
296             case WM_NCDESTROY:
297             case WM_ENTERMENULOOP:
298             case WM_LBUTTONDOWN:
299             case WM_NCLBUTTONDOWN:
300                 WIN_ReleaseWndPtr(wndPtr);
301                 return DEFDLG_Proc( (HWND)hwnd, msg, 
302                                     (WPARAM)wParam, lParam, dlgInfo );
303             case WM_INITDIALOG:
304             case WM_VKEYTOITEM:
305             case WM_COMPAREITEM:
306             case WM_CHARTOITEM:
307                 break;
308
309             default:
310                 WIN_ReleaseWndPtr(wndPtr);
311                 return DefWindowProc16( hwnd, msg, wParam, lParam );
312         }
313     }   
314     WIN_ReleaseWndPtr(wndPtr);
315     return DEFDLG_Epilog(dlgInfo, msg, result);
316 }
317
318
319 /***********************************************************************
320  *           DefDlgProc32A   (USER32.120)
321  */
322 LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg,
323                               WPARAM wParam, LPARAM lParam )
324 {
325     DIALOGINFO * dlgInfo;
326     BOOL result = FALSE;
327     WND * wndPtr = WIN_FindWndPtr( hwnd );
328     
329     if (!wndPtr) return 0;
330     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
331     dlgInfo->msgResult = 0;
332
333     if (dlgInfo->dlgProc) {      /* Call dialog procedure */
334         result = CallWindowProcA( (WNDPROC)dlgInfo->dlgProc,
335                                             hwnd, msg, wParam, lParam );
336         /* 16 bit dlg procs only return BOOL16 */
337         if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
338             result = LOWORD(result);
339     }
340
341     if (!result && IsWindow(hwnd))
342     {
343         /* callback didn't process this message */
344
345         switch(msg)
346         {
347             case WM_ERASEBKGND:
348             case WM_SHOWWINDOW:
349             case WM_ACTIVATE:
350             case WM_SETFOCUS:
351             case DM_SETDEFID:
352             case DM_GETDEFID:
353             case WM_NEXTDLGCTL:
354             case WM_GETFONT:
355             case WM_CLOSE:
356             case WM_NCDESTROY:
357             case WM_ENTERMENULOOP:
358             case WM_LBUTTONDOWN:
359             case WM_NCLBUTTONDOWN:
360                  WIN_ReleaseWndPtr(wndPtr);
361                  return DEFDLG_Proc( (HWND)hwnd, msg,
362                                      (WPARAM)wParam, lParam, dlgInfo );
363             case WM_INITDIALOG:
364             case WM_VKEYTOITEM:
365             case WM_COMPAREITEM:
366             case WM_CHARTOITEM:
367                  break;
368
369             default:
370                  WIN_ReleaseWndPtr(wndPtr);
371                  return DefWindowProcA( hwnd, msg, wParam, lParam );
372         }
373     }
374     WIN_ReleaseWndPtr(wndPtr);
375     return DEFDLG_Epilog(dlgInfo, msg, result);
376 }
377
378
379 /***********************************************************************
380  *           DefDlgProc32W   (USER32.121)
381  */
382 LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam,
383                               LPARAM lParam )
384 {
385     DIALOGINFO * dlgInfo;
386     BOOL result = FALSE;
387     WND * wndPtr = WIN_FindWndPtr( hwnd );
388     
389     if (!wndPtr) return 0;
390     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
391     dlgInfo->msgResult = 0;
392
393     if (dlgInfo->dlgProc) {      /* Call dialog procedure */
394         result = CallWindowProcW( (WNDPROC)dlgInfo->dlgProc,
395                                             hwnd, msg, wParam, lParam );
396         /* 16 bit dlg procs only return BOOL16 */
397         if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
398             result = LOWORD(result);
399     }
400
401     if (!result && IsWindow(hwnd))
402     {
403         /* callback didn't process this message */
404
405         switch(msg)
406         {
407             case WM_ERASEBKGND:
408             case WM_SHOWWINDOW:
409             case WM_ACTIVATE:
410             case WM_SETFOCUS:
411             case DM_SETDEFID:
412             case DM_GETDEFID:
413             case WM_NEXTDLGCTL:
414             case WM_GETFONT:
415             case WM_CLOSE:
416             case WM_NCDESTROY:
417             case WM_ENTERMENULOOP:
418             case WM_LBUTTONDOWN:
419             case WM_NCLBUTTONDOWN:
420                  WIN_ReleaseWndPtr(wndPtr);
421                  return DEFDLG_Proc( (HWND)hwnd, msg,
422                                      (WPARAM)wParam, lParam, dlgInfo );
423             case WM_INITDIALOG:
424             case WM_VKEYTOITEM:
425             case WM_COMPAREITEM:
426             case WM_CHARTOITEM:
427                  break;
428
429             default:
430                  WIN_ReleaseWndPtr(wndPtr);
431                  return DefWindowProcW( hwnd, msg, wParam, lParam );
432         }
433     }
434     WIN_ReleaseWndPtr(wndPtr);
435     return DEFDLG_Epilog(dlgInfo, msg, result);
436 }