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