Validate the parent with the child window client rectangle when the
[wine] / windows / msgbox.c
1 /*
2  * Message boxes
3  *
4  * Copyright 1995 Bernd Schmidt
5  */
6
7 #include <string.h>
8
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
11 #include "dlgs.h"
12 #include "heap.h"
13 #include "ldt.h"
14 #include "debugtools.h"
15 #include "debugstr.h"
16 #include "tweak.h"
17
18 DEFAULT_DEBUG_CHANNEL(dialog)
19
20 /**************************************************************************
21  *           MSGBOX_DlgProc
22  *
23  * Dialog procedure for message boxes.
24  */
25 static LRESULT CALLBACK MSGBOX_DlgProc( HWND hwnd, UINT message,
26                                         WPARAM wParam, LPARAM lParam )
27 {
28   static HFONT hFont = 0;
29   LPMSGBOXPARAMSA lpmb;
30
31   RECT rect, textrect;
32   HWND hItem;
33   HDC hdc;
34   LRESULT lRet;
35   int i, buttons, bwidth, bheight, theight, wwidth, bpos;
36   int borheight, iheight, tiheight;
37   
38   switch(message) {
39    case WM_INITDIALOG:
40     lpmb = (LPMSGBOXPARAMSA)lParam;
41     if (TWEAK_WineLook >= WIN95_LOOK) {
42         NONCLIENTMETRICSA nclm;
43         INT i;
44         nclm.cbSize = sizeof(NONCLIENTMETRICSA);
45         SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
46         hFont = CreateFontIndirectA (&nclm.lfMessageFont);
47         /* set button font */
48         for (i=1; i < 8; i++)
49             SendDlgItemMessageA (hwnd, i, WM_SETFONT, (WPARAM)hFont, 0);
50         /* set text font */
51         SendDlgItemMessageA (hwnd, 100, WM_SETFONT, (WPARAM)hFont, 0);
52     }
53     if (lpmb->lpszCaption) SetWindowTextA(hwnd, lpmb->lpszCaption);
54     SetWindowTextA(GetDlgItem(hwnd, 100), lpmb->lpszText);
55     /* Hide not selected buttons */
56     switch(lpmb->dwStyle & MB_TYPEMASK) {
57      case MB_OK:
58       ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
59       /* fall through */
60      case MB_OKCANCEL:
61       ShowWindow(GetDlgItem(hwnd, 3), SW_HIDE);
62       ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE);
63       ShowWindow(GetDlgItem(hwnd, 5), SW_HIDE);
64       ShowWindow(GetDlgItem(hwnd, 6), SW_HIDE);
65       ShowWindow(GetDlgItem(hwnd, 7), SW_HIDE);
66       break;
67      case MB_ABORTRETRYIGNORE:
68       ShowWindow(GetDlgItem(hwnd, 1), SW_HIDE);
69       ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
70       ShowWindow(GetDlgItem(hwnd, 6), SW_HIDE);
71       ShowWindow(GetDlgItem(hwnd, 7), SW_HIDE);
72       break;
73      case MB_YESNO:
74       ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
75       /* fall through */
76      case MB_YESNOCANCEL:
77       ShowWindow(GetDlgItem(hwnd, 1), SW_HIDE);
78       ShowWindow(GetDlgItem(hwnd, 3), SW_HIDE);
79       ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE);
80       ShowWindow(GetDlgItem(hwnd, 5), SW_HIDE);
81       break;
82     }
83     /* Set the icon */
84     switch(lpmb->dwStyle & MB_ICONMASK) {
85      case MB_ICONEXCLAMATION:
86       SendDlgItemMessage16(hwnd, stc1, STM_SETICON16,
87                            (WPARAM16)LoadIcon16(0, IDI_EXCLAMATION16), 0);
88       break;
89      case MB_ICONQUESTION:
90       SendDlgItemMessage16(hwnd, stc1, STM_SETICON16,
91                            (WPARAM16)LoadIcon16(0, IDI_QUESTION16), 0);
92       break;
93      case MB_ICONASTERISK:
94       SendDlgItemMessage16(hwnd, stc1, STM_SETICON16,
95                            (WPARAM16)LoadIcon16(0, IDI_ASTERISK16), 0);
96       break;
97      case MB_ICONHAND:
98      default:
99       SendDlgItemMessage16(hwnd, stc1, STM_SETICON16,
100                            (WPARAM16)LoadIcon16(0, IDI_HAND16), 0);
101       break;
102     }
103     
104     /* Position everything */
105     GetWindowRect(hwnd, &rect);
106     borheight = rect.bottom - rect.top;
107     wwidth = rect.right - rect.left;
108     GetClientRect(hwnd, &rect);
109     borheight -= rect.bottom - rect.top;
110
111     /* Get the icon height */
112     GetWindowRect(GetDlgItem(hwnd, 1088), &rect);
113     iheight = rect.bottom - rect.top;
114     
115     /* Get the number of visible buttons and their width */
116     GetWindowRect(GetDlgItem(hwnd, 2), &rect);
117     bheight = rect.bottom - rect.top;
118     bwidth = rect.left;
119     GetWindowRect(GetDlgItem(hwnd, 1), &rect);
120     bwidth -= rect.left;
121     for (buttons = 0, i = 1; i < 8; i++)
122     {
123       hItem = GetDlgItem(hwnd, i);
124       if (GetWindowLongA(hItem, GWL_STYLE) & WS_VISIBLE) buttons++;
125     }
126     
127     /* Get the text size */
128     hItem = GetDlgItem(hwnd, 100);
129     GetWindowRect(hItem, &textrect);
130     MapWindowPoints(0, hwnd, (LPPOINT)&textrect, 2);
131     
132     GetClientRect(hItem, &rect);
133     hdc = GetDC(hItem);
134     lRet = DrawTextA( hdc, lpmb->lpszText, -1, &rect,
135                         DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
136     theight = rect.bottom  - rect.top;
137     tiheight = 16 + MAX(iheight, theight);
138     ReleaseDC(hItem, hdc);
139     
140     /* Position the text */
141     SetWindowPos(hItem, 0, textrect.left, (tiheight - theight) / 2, 
142                    rect.right - rect.left, theight,
143                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
144     
145     /* Position the icon */
146     hItem = GetDlgItem(hwnd, 1088);
147     GetWindowRect(hItem, &rect);
148     MapWindowPoints(0, hwnd, (LPPOINT)&rect, 2);
149     SetWindowPos(hItem, 0, rect.left, (tiheight - iheight) / 2, 0, 0,
150                    SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
151     
152     /* Resize the window */
153     SetWindowPos(hwnd, 0, 0, 0, wwidth, 8 + tiheight + bheight + borheight,
154                    SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
155     
156     /* Position the buttons */
157     bpos = (wwidth - bwidth * buttons) / 2;
158     GetWindowRect(GetDlgItem(hwnd, 1), &rect);
159     for (buttons = i = 0; i < 7; i++) {
160       /* some arithmetic to get the right order for YesNoCancel windows */
161       hItem = GetDlgItem(hwnd, (i + 5) % 7 + 1);
162       if (GetWindowLongA(hItem, GWL_STYLE) & WS_VISIBLE) {
163         if (buttons++ == ((lpmb->dwStyle & MB_DEFMASK) >> 8)) {
164           SetFocus(hItem);
165           SendMessageA( hItem, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
166         }
167         SetWindowPos(hItem, 0, bpos, tiheight, 0, 0,
168                        SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
169         bpos += bwidth;
170       }
171     }
172     return 0;
173     break;
174     
175    case WM_COMMAND:
176     switch (wParam)
177     {
178      case IDOK:
179      case IDCANCEL:
180      case IDABORT:
181      case IDRETRY:
182      case IDIGNORE:
183      case IDYES:
184      case IDNO:
185       if ((TWEAK_WineLook > WIN31_LOOK) && hFont)
186         DeleteObject (hFont);
187       EndDialog(hwnd, wParam);
188       break;
189     }
190
191    default:
192      /* Ok. Ignore all the other messages */
193      TRACE("Message number %i is being ignored.\n", message);
194     break;
195   }
196   return 0;
197 }
198
199
200 /**************************************************************************
201  *           MessageBox16   (USER.1)
202  */
203 INT16 WINAPI MessageBox16( HWND16 hwnd, LPCSTR text, LPCSTR title, UINT16 type)
204 {
205     WARN("Messagebox\n");
206     return MessageBoxA( hwnd, text, title, type );
207 }
208
209
210 /**************************************************************************
211  *           MessageBox32A   (USER32.391)
212  *
213  * NOTES
214  *   The WARN is here to help debug erroneous MessageBoxes
215  *   Use: -debugmsg warn+dialog,+relay
216  */
217 INT WINAPI MessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type)
218 {
219     LPVOID template;
220     HRSRC hRes;
221     MSGBOXPARAMSA mbox;
222
223     WARN("Messagebox\n");
224
225     if(!(hRes = FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA)))
226         return 0;
227     if(!(template = (LPVOID)LoadResource(GetModuleHandleA("USER32"), hRes)))
228         return 0;
229
230     if (!text) text="<WINE-NULL>";
231     if (!title)
232       title="Error";
233     mbox.lpszCaption = title;
234     mbox.lpszText  = text;
235     mbox.dwStyle  = type;
236     return DialogBoxIndirectParamA( GetWindowLongA(hWnd,GWL_HINSTANCE), template,
237                                       hWnd, (DLGPROC)MSGBOX_DlgProc, (LPARAM)&mbox );
238 }
239
240
241 /**************************************************************************
242  *           MessageBox32W   (USER32.396)
243  */
244 INT WINAPI MessageBoxW( HWND hwnd, LPCWSTR text, LPCWSTR title,
245                             UINT type )
246 {
247     LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
248     LPSTR textA  = HEAP_strdupWtoA( GetProcessHeap(), 0, text );
249     INT ret;
250     
251     WARN("Messagebox\n");
252
253     ret = MessageBoxA( hwnd, textA, titleA, type );
254     HeapFree( GetProcessHeap(), 0, titleA );
255     HeapFree( GetProcessHeap(), 0, textA );
256     return ret;
257 }
258
259
260 /**************************************************************************
261  *           MessageBoxEx32A   (USER32.392)
262  */
263 INT WINAPI MessageBoxExA( HWND hWnd, LPCSTR text, LPCSTR title,
264                               UINT type, WORD langid )
265 {
266     WARN("Messagebox\n");
267     /* ignore language id for now */
268     return MessageBoxA(hWnd,text,title,type);
269 }
270
271 /**************************************************************************
272  *           MessageBoxEx32W   (USER32.393)
273  */
274 INT WINAPI MessageBoxExW( HWND hWnd, LPCWSTR text, LPCWSTR title,
275                               UINT type, WORD langid )
276 {
277     WARN("Messagebox\n");
278     /* ignore language id for now */
279     return MessageBoxW(hWnd,text,title,type);
280 }
281
282 /**************************************************************************
283  *           MessageBoxIndirect16   (USER.827)
284  */
285 INT16 WINAPI MessageBoxIndirect16( LPMSGBOXPARAMS16 msgbox )
286 {
287     LPVOID template;
288     HRSRC hRes;
289     MSGBOXPARAMSA msgbox32;
290
291     WARN("Messagebox\n");    
292     
293     if(!(hRes = FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA)))
294         return 0;
295     if(!(template = (LPVOID)LoadResource(GetModuleHandleA("USER32"), hRes)))
296         return 0;
297
298     msgbox32.cbSize             = msgbox->cbSize;
299     msgbox32.hwndOwner          = msgbox->hwndOwner;
300     msgbox32.hInstance          = msgbox->hInstance;
301     msgbox32.lpszText           = PTR_SEG_TO_LIN(msgbox->lpszText);
302     msgbox32.lpszCaption        = PTR_SEG_TO_LIN(msgbox->lpszCaption);
303     msgbox32.dwStyle            = msgbox->dwStyle;
304     msgbox32.lpszIcon           = PTR_SEG_TO_LIN(msgbox->lpszIcon);
305     msgbox32.dwContextHelpId    = msgbox->dwContextHelpId;
306     msgbox32.lpfnMsgBoxCallback = msgbox->lpfnMsgBoxCallback;
307     msgbox32.dwLanguageId       = msgbox->dwLanguageId;
308
309     return DialogBoxIndirectParamA( msgbox32.hInstance, template,
310                                       msgbox32.hwndOwner, (DLGPROC)MSGBOX_DlgProc,
311                                       (LPARAM)&msgbox32 );
312 }
313
314 /**************************************************************************
315  *           MessageBoxIndirect32A   (USER32.394)
316  */
317 INT WINAPI MessageBoxIndirectA( LPMSGBOXPARAMSA msgbox )
318 {
319     LPVOID template;
320     HRSRC hRes;
321
322     WARN("Messagebox\n");
323
324     if(!(hRes = FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA)))
325         return 0;
326     if(!(template = (LPVOID)LoadResource(GetModuleHandleA("USER32"), hRes)))
327         return 0;
328
329     return DialogBoxIndirectParamA( msgbox->hInstance, template,
330                                       msgbox->hwndOwner, (DLGPROC)MSGBOX_DlgProc,
331                                       (LPARAM)msgbox );
332 }
333
334 /**************************************************************************
335  *           MessageBoxIndirect32W   (USER32.395)
336  */
337 INT WINAPI MessageBoxIndirectW( LPMSGBOXPARAMSW msgbox )
338 {
339     MSGBOXPARAMSA       msgboxa;
340     WARN("Messagebox\n");
341
342     memcpy(&msgboxa,msgbox,sizeof(msgboxa));
343     if (msgbox->lpszCaption)    
344       lstrcpyWtoA((LPSTR)msgboxa.lpszCaption,msgbox->lpszCaption);
345     if (msgbox->lpszText)       
346       lstrcpyWtoA((LPSTR)msgboxa.lpszText,msgbox->lpszText);
347
348     return MessageBoxIndirectA(&msgboxa);
349 }
350
351
352 /**************************************************************************
353  *           FatalAppExit16   (KERNEL.137)
354  */
355 void WINAPI FatalAppExit16( UINT16 action, LPCSTR str )
356 {
357     WARN("AppExit\n");
358     FatalAppExitA( action, str );
359 }
360
361
362 /**************************************************************************
363  *           FatalAppExit32A   (KERNEL32.108)
364  */
365 void WINAPI FatalAppExitA( UINT action, LPCSTR str )
366 {
367     WARN("AppExit\n");
368     MessageBoxA( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
369     ExitProcess(0);
370 }
371
372
373 /**************************************************************************
374  *           FatalAppExit32W   (KERNEL32.109)
375  */
376 void WINAPI FatalAppExitW( UINT action, LPCWSTR str )
377 {
378     WARN("AppExit\n");
379     MessageBoxW( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
380     ExitProcess(0);
381 }
382
383