Release 960506
[wine] / windows / defdlg.c
1 /*
2  * Default dialog procedure
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  */
7
8 #include "windows.h"
9 #include "dialog.h"
10 #include "win.h"
11 #include "stddebug.h"
12 /* #define DEBUG_DIALOG */
13 #include "debug.h"
14
15 /***********************************************************************
16  *           DEFDLG_SetFocus
17  *
18  * Set the focus to a control of the dialog, selecting the text if
19  * the control is an edit dialog.
20  */
21 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
22 {
23     HWND hwndPrev = GetFocus();
24
25     if (IsChild( hwndDlg, hwndPrev ))
26     {
27         if (SendMessage( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
28             SendMessage( hwndPrev, EM_SETSEL, TRUE, MAKELONG( -1, 0 ) );
29     }
30     if (SendMessage( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
31         SendMessage( hwndCtrl, EM_SETSEL, FALSE, MAKELONG( 0, -1 ) );
32     SetFocus( hwndCtrl );
33 }
34
35
36 /***********************************************************************
37  *           DEFDLG_SaveFocus
38  */
39 static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
40 {
41     HWND hwndFocus = GetFocus();
42
43     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
44     if (!infoPtr->hwndFocus) return FALSE;  /* Already saved */
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     DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
59     infoPtr->hwndFocus = 0;
60     return TRUE;
61 }
62
63
64 #ifdef SUPERFLUOUS_FUNCTIONS
65 /***********************************************************************
66  *           DEFDLG_FindDefButton
67  *
68  * Find the current default push-button.
69  */
70 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
71 {
72     HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
73     while (hwndChild)
74     {
75         if (SendMessage( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
76             break;
77         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
78     }
79     return hwndChild;
80 }
81 #endif
82
83
84 /***********************************************************************
85  *           DEFDLG_SetDefButton
86  *
87  * Set the new default button to be hwndNew.
88  */
89 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
90                                  HWND hwndNew )
91 {
92     if (hwndNew &&
93         !(SendMessage( hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
94         return FALSE;  /* Destination is not a push button */
95     
96     if (dlgInfo->msgResult)  /* There's already a default pushbutton */
97     {
98         HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->msgResult );
99         if (SendMessage( hwndOld, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
100             SendMessage( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
101     }
102     if (hwndNew)
103     {
104         SendMessage( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
105         dlgInfo->msgResult = GetDlgCtrlID( hwndNew );
106     }
107     else dlgInfo->msgResult = 0;
108     return TRUE;
109 }
110
111
112 /***********************************************************************
113  *           DefDlgProc   (USER.308)
114  */
115 LRESULT DefDlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
116 {
117     DIALOGINFO * dlgInfo;
118     BOOL result = FALSE;
119     WND * wndPtr = WIN_FindWndPtr( hwnd );
120     
121     if (!wndPtr) return 0;
122     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
123
124     dlgInfo->msgResult = 0;
125     if (dlgInfo->dlgProc)
126     {
127           /* Call dialog procedure */
128         result = (BOOL)CallWindowProc( dlgInfo->dlgProc, hwnd, 
129                                        msg, wParam, lParam );
130
131           /* Check if window destroyed by dialog procedure */
132         wndPtr = WIN_FindWndPtr( hwnd );
133         if (!wndPtr) return result;
134     }
135     
136     if (!result) switch(msg)
137     {
138         case WM_INITDIALOG:
139             break;
140
141         case WM_ERASEBKGND:
142             FillWindow( hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG );
143             return TRUE;
144
145         case WM_NCDESTROY:
146
147               /* Free dialog heap (if created) */
148             if (dlgInfo->hDialogHeap)
149             {
150                 GlobalUnlock16(dlgInfo->hDialogHeap);
151                 GlobalFree16(dlgInfo->hDialogHeap);
152                 dlgInfo->hDialogHeap = 0;
153             }
154
155               /* Delete font */
156             if (dlgInfo->hUserFont)
157             {
158                 DeleteObject( dlgInfo->hUserFont );
159                 dlgInfo->hUserFont = 0;
160             }
161
162               /* Delete menu */
163             if (dlgInfo->hMenu)
164             {           
165                 DestroyMenu( dlgInfo->hMenu );
166                 dlgInfo->hMenu = 0;
167             }
168
169               /* Window clean-up */
170             DefWindowProc( hwnd, msg, wParam, lParam );
171             break;
172
173         case WM_SHOWWINDOW:
174             if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
175             return DefWindowProc( hwnd, msg, wParam, lParam );
176
177         case WM_ACTIVATE:
178             if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
179             else DEFDLG_SaveFocus( hwnd, dlgInfo );
180             break;
181
182         case WM_SETFOCUS:
183             DEFDLG_RestoreFocus( hwnd, dlgInfo );
184             break;
185
186         case DM_SETDEFID:
187             if (dlgInfo->fEnd) return TRUE;
188             DEFDLG_SetDefButton( hwnd, dlgInfo,
189                                  wParam ? GetDlgItem( hwnd, wParam ) : 0 );
190             return TRUE;
191
192         case DM_GETDEFID:
193             if (dlgInfo->fEnd || !dlgInfo->msgResult) return 0;
194             return MAKELONG( dlgInfo->msgResult, DC_HASDEFID );
195
196         case WM_NEXTDLGCTL:
197             {
198                 HWND hwndDest = (HWND)wParam;
199                 if (!lParam)
200                 {
201                     HWND hwndPrev = GetFocus();
202                     if (!hwndPrev)  /* Set focus to the first item */
203                         hwndDest = DIALOG_GetFirstTabItem( hwnd );
204                     else
205                         hwndDest = GetNextDlgTabItem( hwnd, hwndPrev, wParam );
206                 }
207                 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
208                 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
209             }
210             break;
211
212         case WM_CLOSE:
213             EndDialog( hwnd, TRUE );
214             DestroyWindow( hwnd );
215             return 0;
216
217         default:
218             return DefWindowProc( hwnd, msg, wParam, lParam );
219     }
220         
221     return result;
222 }