update for HEAD-2003091401
[reactos.git] / lib / user32 / windows / dialog.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * PROJECT:         ReactOS user32.dll
22  * FILE:            lib/user32/windows/dialog.c
23  * PURPOSE:         Input
24  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
25  *                  Thomas Weidenmueller (w3seek@users.sourceforge.net)
26  * UPDATE HISTORY:
27  *      07-26-2003  Code ported from wine
28  *      09-05-2001  CSH  Created
29  */
30
31 /* INCLUDES ******************************************************************/
32 #define __NTAPP__
33 #include <windows.h>
34 #include <string.h>
35 #include <user32.h>
36 #include <ntos/rtl.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <debug.h>
40
41 #include "user32/regcontrol.h"
42 #include "../controls/controls.h"
43
44
45 /* MACROS/DEFINITIONS ********************************************************/
46
47 #define DF_END  0x0001
48 #define DF_OWNERENABLED 0x0002
49 #define CW_USEDEFAULT16 ((short)0x8000)
50 #define DWL_INIT (12)
51 #define GETDLGINFO(hwnd) (DIALOGINFO*)GetWindowLongW((hwnd), DWL_INIT)
52 #define SETDLGINFO(hwnd, info) SetWindowLongW((hwnd), DWL_INIT, (LONG)(info))
53 #define GET_WORD(ptr)  (*(WORD *)(ptr))
54 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
55 #define MAKEINTATOMA(atom)  ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
56 #define MAKEINTATOMW(atom)  ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
57 #define DIALOG_CLASS_ATOMA   MAKEINTATOMA(32770)  /* Dialog */
58 #define DIALOG_CLASS_ATOMW   MAKEINTATOMW(32770)  /* Dialog */
59
60 /* INTERNAL STRUCTS **********************************************************/
61
62 /* Dialog info structure */
63 typedef struct
64 {
65     HWND      hwndFocus;   /* Current control with focus */
66     HFONT     hUserFont;   /* Dialog font */
67     HMENU     hMenu;       /* Dialog menu */
68     UINT      xBaseUnit;   /* Dialog units (depends on the font) */
69     UINT      yBaseUnit;
70     INT       idResult;    /* EndDialog() result / default pushbutton ID */
71     UINT      flags;       /* EndDialog() called for this dialog */
72 } DIALOGINFO;
73
74 /* Dialog control information */
75 typedef struct
76 {
77     DWORD      style;
78     DWORD      exStyle;
79     DWORD      helpId;
80     short      x;
81     short      y;
82     short      cx;
83     short      cy;
84     UINT       id;
85     LPCWSTR    className;
86     LPCWSTR    windowName;
87     LPCVOID    data;
88 } DLG_CONTROL_INFO;
89
90 /* Dialog template */
91 typedef struct
92 {
93     DWORD      style;
94     DWORD      exStyle;
95     DWORD      helpId;
96     WORD       nbItems;
97     short      x;
98     short      y;
99     short      cx;
100     short      cy;
101     LPCWSTR    menuName;
102     LPCWSTR    className;
103     LPCWSTR    caption;
104     WORD       pointSize;
105     WORD       weight;
106     BOOL       italic;
107     LPCWSTR    faceName;
108     BOOL       dialogEx;
109 } DLG_TEMPLATE;
110
111 /* GetDlgItem structure */
112 typedef struct
113 {
114     INT        nIDDlgItem;
115     HWND       control;
116 } GETDLGITEMINFO;
117
118
119 /*********************************************************************
120  * dialog class descriptor
121  */
122 const struct builtin_class_descr DIALOG_builtin_class =
123 {
124     DIALOG_CLASS_ATOMW, /* name */
125     CS_GLOBALCLASS | CS_SAVEBITS | CS_DBLCLKS, /* style  */
126     (WNDPROC) DefDlgProcW,        /* procW */
127     DWL_INIT + sizeof(LONG),  /* extra */
128     (LPCWSTR) IDC_ARROW,           /* cursor */
129     0                     /* brush */
130 };
131
132
133 /* INTERNAL FUNCTIONS ********************************************************/
134
135 /***********************************************************************
136  *           DIALOG_GetCharSize
137  *
138  * Despite most of MSDN insisting that the horizontal base unit is
139  * tmAveCharWidth it isn't.  Knowledge base article Q145994
140  * "HOWTO: Calculate Dialog Units When Not Using the System Font",
141  * says that we should take the average of the 52 English upper and lower
142  * case characters.
143  */
144 BOOL DIALOG_GetCharSize( HDC hDC, HFONT hFont, SIZE * pSize )
145 {
146     HFONT hFontPrev = 0;
147     char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
148     SIZE sz;
149     TEXTMETRICA tm;
150
151     if(!hDC) return FALSE;
152
153     if(hFont) hFontPrev = SelectObject(hDC, hFont);
154     if(!GetTextMetricsA(hDC, &tm)) return FALSE;
155     if(!GetTextExtentPointA(hDC, alphabet, 52, &sz)) return FALSE;
156
157     pSize->cy = tm.tmHeight;
158     pSize->cx = (sz.cx / 26 + 1) / 2;
159
160     if (hFontPrev) SelectObject(hDC, hFontPrev);
161
162     return TRUE;
163 }
164
165  /***********************************************************************
166  *           DIALOG_EnableOwner
167  *
168  * Helper function for modal dialogs to enable again the
169  * owner of the dialog box.
170  */
171 void DIALOG_EnableOwner( HWND hOwner )
172 {
173     /* Owner must be a top-level window */
174     if (hOwner)
175         hOwner = GetAncestor( hOwner, GA_ROOT );
176     if (!hOwner) return;
177         EnableWindow( hOwner, TRUE );
178 }
179
180  /***********************************************************************
181  *           DIALOG_DisableOwner
182  *
183  * Helper function for modal dialogs to disable the
184  * owner of the dialog box. Returns TRUE if owner was enabled.
185  */
186 BOOL DIALOG_DisableOwner( HWND hOwner )
187 {
188     /* Owner must be a top-level window */
189     if (hOwner)
190         hOwner = GetAncestor( hOwner, GA_ROOT );
191     if (!hOwner) return FALSE;
192     if (IsWindowEnabled( hOwner ))
193     {
194         EnableWindow( hOwner, FALSE );
195         return TRUE;
196     }
197     else
198         return FALSE;
199 }
200
201  /***********************************************************************
202  *           DIALOG_GetControl32
203  *
204  * Return the class and text of the control pointed to by ptr,
205  * fill the header structure and return a pointer to the next control.
206  */
207 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
208                                         BOOL dialogEx )
209 {
210     if (dialogEx)
211     {
212         info->helpId  = GET_DWORD(p); p += 2;
213         info->exStyle = GET_DWORD(p); p += 2;
214         info->style   = GET_DWORD(p); p += 2;
215     }
216     else
217     {
218         info->helpId  = 0;
219         info->style   = GET_DWORD(p); p += 2;
220         info->exStyle = GET_DWORD(p); p += 2;
221     }
222     info->x       = GET_WORD(p); p++;
223     info->y       = GET_WORD(p); p++;
224     info->cx      = GET_WORD(p); p++;
225     info->cy      = GET_WORD(p); p++;
226     
227     if (dialogEx)
228     {
229         /* id is a DWORD for DIALOGEX */
230         info->id = GET_DWORD(p);
231         p += 2;
232     }
233     else
234     {
235         info->id = GET_WORD(p);
236         p++;
237     }
238     
239     if (GET_WORD(p) == 0xffff)
240     {
241         static const WCHAR class_names[6][10] =
242         {
243             { 'B','u','t','t','o','n', },             /* 0x80 */
244             { 'E','d','i','t', },                     /* 0x81 */
245             { 'S','t','a','t','i','c', },             /* 0x82 */
246             { 'L','i','s','t','B','o','x', },         /* 0x83 */
247             { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
248             { 'C','o','m','b','o','B','o','x', }      /* 0x85 */
249         };
250         WORD id = GET_WORD(p+1);
251         /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */
252         if ((id >= 0x80) && (id <= 0x85)) id -= 0x80;
253         if (id <= 5)
254             info->className = class_names[id];
255         else
256         {
257             info->className = NULL;
258             /* FIXME: load other classes here? */
259         }
260         p += 2;
261     }
262     else
263     {
264         info->className = (LPCWSTR)p;
265         p += wcslen( info->className ) + 1;
266     }
267     
268     if (GET_WORD(p) == 0xffff)  /* Is it an integer id? */
269     {
270         info->windowName = (LPCWSTR)(UINT)GET_WORD(p + 1);
271         p += 2;
272     }
273     else
274     {
275         info->windowName = (LPCWSTR)p;
276         p += wcslen( info->windowName ) + 1;
277     }
278     
279     if (GET_WORD(p))
280     {
281         info->data = p + 1;
282         p += GET_WORD(p) / sizeof(WORD);
283     }
284     else info->data = NULL;
285     p++;
286     
287     /* Next control is on dword boundary */
288     return (const WORD *)((((int)p) + 3) & ~3);    
289 }
290
291  /***********************************************************************
292  *           DIALOG_CreateControls32
293  *
294  * Create the control windows for a dialog.
295  */
296 static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate,
297                                      HINSTANCE hInst, BOOL unicode )
298 {
299     DIALOGINFO * dlgInfo;
300     DLG_CONTROL_INFO info;
301     HWND hwndCtrl, hwndDefButton = 0;
302     INT items = dlgTemplate->nbItems;
303
304     if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
305
306     while (items--)
307     {
308         template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info,
309                                                 dlgTemplate->dialogEx );
310         /* Is this it? */
311         if (info.style & WS_BORDER)
312         {
313             info.style &= ~WS_BORDER;
314             info.exStyle |= WS_EX_CLIENTEDGE;
315         }
316         if (unicode)
317         {
318             hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
319                                         info.className, info.windowName,
320                                         info.style | WS_CHILD,
321                                         MulDiv(info.x, dlgInfo->xBaseUnit, 4),
322                                         MulDiv(info.y, dlgInfo->yBaseUnit, 8),
323                                         MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
324                                         MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
325                                         hwnd, (HMENU)info.id,
326                                         hInst, (LPVOID)info.data );
327         }
328         else
329         {
330             LPSTR class = (LPSTR)info.className;
331             LPSTR caption = (LPSTR)info.windowName;
332
333             if (HIWORD(class))
334             {
335                 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.className, -1, NULL, 0, NULL, NULL );
336                 class = HeapAlloc( GetProcessHeap(), 0, len );
337                 WideCharToMultiByte( CP_ACP, 0, info.className, -1, class, len, NULL, NULL );
338             }
339             if (HIWORD(caption))
340             {
341                 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, NULL, 0, NULL, NULL );
342                 caption = HeapAlloc( GetProcessHeap(), 0, len );
343                 WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, caption, len, NULL, NULL );
344             }
345             hwndCtrl = CreateWindowExA( info.exStyle | WS_EX_NOPARENTNOTIFY,
346                                         class, caption, info.style | WS_CHILD,
347                                         MulDiv(info.x, dlgInfo->xBaseUnit, 4),
348                                         MulDiv(info.y, dlgInfo->yBaseUnit, 8),
349                                         MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
350                                         MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
351                                         hwnd, (HMENU)info.id,
352                                         hInst, (LPVOID)info.data );
353             if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
354             if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
355         }
356         if (!hwndCtrl)
357         {
358             if (dlgTemplate->style & DS_NOFAILCREATE) continue;
359             return FALSE;
360         }
361
362         /* Send initialisation messages to the control */
363         if (dlgInfo->hUserFont) SendMessageA( hwndCtrl, WM_SETFONT,
364                                              (WPARAM)dlgInfo->hUserFont, 0 );
365         if (SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
366         {
367             /* If there's already a default push-button, set it back */
368             /* to normal and use this one instead. */
369             if (hwndDefButton)
370                 SendMessageA( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE );
371             hwndDefButton = hwndCtrl;
372             dlgInfo->idResult = GetWindowLongA( hwndCtrl, GWL_ID );
373         }
374     }
375     return TRUE;
376 }
377
378  /***********************************************************************
379   *           DIALOG_FindMsgDestination
380   *
381   * The messages that IsDialogMessage sends may not go to the dialog
382   * calling IsDialogMessage if that dialog is a child, and it has the
383   * DS_CONTROL style set.
384   * We propagate up until we hit one that does not have DS_CONTROL, or
385   * whose parent is not a dialog.
386   *
387   * This is undocumented behaviour.
388   */
389 static HWND DIALOG_FindMsgDestination( HWND hwndDlg )
390 {
391     while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL)
392     {
393         HWND hParent = GetParent(hwndDlg);
394         if (!hParent) break;
395         
396         if (!IsWindow(hParent)) break;
397
398         if (!GETDLGINFO(hParent)) /* TODO: Correct? */
399         {
400             break;
401         }
402
403         hwndDlg = hParent;
404     }
405
406     return hwndDlg;
407 }
408
409  /***********************************************************************
410   *           DIALOG_IsAccelerator
411   */
412 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM wParam )
413 {
414     HWND hwndControl = hwnd;
415     HWND hwndNext;
416     INT dlgCode;
417     WCHAR buffer[128];
418
419     do
420     {
421         DWORD style = GetWindowLongW( hwndControl, GWL_STYLE );
422         if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
423         {
424             dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
425             if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
426                  GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
427             {
428                 /* find the accelerator key */
429                 LPWSTR p = buffer - 2;
430
431                 do
432                 {
433                     p = wcschr( p + 2, '&' );
434                 }
435                 while (p != NULL && p[1] == '&');
436
437                 /* and check if it's the one we're looking for */
438                                 /* FIXME: usage of towupper correct? */
439                 if (p != NULL && towupper( p[1] ) == towupper( wParam ) )
440                 {
441                     if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
442                     {
443                         /* set focus to the control */
444                         SendMessageA( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1);
445                         /* and bump it on to next */
446                         SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
447                     }
448                     else if (dlgCode & DLGC_BUTTON)
449                     {
450                         /* send BM_CLICK message to the control */
451                         SendMessageA( hwndControl, BM_CLICK, 0, 0 );
452                     }
453                     return TRUE;
454                 }
455             }
456             hwndNext = GetWindow( hwndControl, GW_CHILD );
457         }
458         else hwndNext = 0;
459
460         if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
461
462         while (!hwndNext && hwndControl)
463         {
464             hwndControl = GetParent( hwndControl );
465             if (hwndControl == hwndDlg)
466             {
467                 if(hwnd==hwndDlg)   /* prevent endless loop */
468                 {
469                     hwndNext=hwnd;
470                     break;
471                 }
472                 hwndNext = GetWindow( hwndDlg, GW_CHILD );
473             }
474             else
475                 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
476         }
477         hwndControl = hwndNext;
478     }
479     while (hwndControl && (hwndControl != hwnd));
480
481     return FALSE;
482 }
483
484  /***********************************************************************
485  *           DIALOG_DoDialogBox
486  */
487 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
488 {
489     DIALOGINFO * dlgInfo;
490     MSG msg;
491     INT retval;
492     HWND ownerMsg = GetAncestor( owner, GA_ROOT );
493     if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
494
495     if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */
496     {
497         ShowWindow( hwnd, SW_SHOW );
498         for (;;)
499         {
500             if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
501             {
502                 if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
503                 {
504                     /* No message present -> send ENTERIDLE and wait */
505                     SendMessageW( ownerMsg, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd );
506                     if (!GetMessageW( &msg, 0, 0, 0 )) break;
507                 }
508             }
509             else if (!GetMessageW( &msg, 0, 0, 0 )) break;
510
511             if (!IsWindow( hwnd )) return -1;
512             if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg))
513             {
514                 TranslateMessage( &msg );
515                 DispatchMessageW( &msg );
516             }
517             if (dlgInfo->flags & DF_END) break;
518         }
519     }
520     if (dlgInfo->flags & DF_OWNERENABLED) DIALOG_EnableOwner( owner );
521     retval = dlgInfo->idResult;
522     DestroyWindow( hwnd );
523     return retval;
524 }
525
526  /***********************************************************************
527  *           DIALOG_ParseTemplate32
528  *
529  * Fill a DLG_TEMPLATE structure from the dialog template, and return
530  * a pointer to the first control.
531  */
532 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
533 {
534     const WORD *p = (const WORD *)template;
535
536     result->style = GET_DWORD(p); p += 2;
537     if (result->style == 0xffff0001)  /* DIALOGEX resource */
538     {
539         result->dialogEx = TRUE;
540         result->helpId   = GET_DWORD(p); p += 2;
541         result->exStyle  = GET_DWORD(p); p += 2;
542         result->style    = GET_DWORD(p); p += 2;
543     }
544     else
545     {
546         result->dialogEx = FALSE;
547         result->helpId   = 0;
548         result->exStyle  = GET_DWORD(p); p += 2;
549     }
550     result->nbItems = GET_WORD(p); p++;
551     result->x       = GET_WORD(p); p++;
552     result->y       = GET_WORD(p); p++;
553     result->cx      = GET_WORD(p); p++;
554     result->cy      = GET_WORD(p); p++;
555
556     /* Get the menu name */
557
558     switch(GET_WORD(p))
559     {
560         case 0x0000:
561             result->menuName = NULL;
562             p++;
563             break;
564         case 0xffff:
565             result->menuName = (LPCWSTR)(UINT)GET_WORD( p + 1 );
566             p += 2;
567             break;
568         default:
569             result->menuName = (LPCWSTR)p;
570             p += wcslen( result->menuName ) + 1;
571             break;
572     }
573         
574     /* Get the class name */
575         
576     switch(GET_WORD(p))
577     {
578         case 0x0000:
579             result->className = DIALOG_CLASS_ATOMW;
580             p++;
581             break;
582         case 0xffff:
583             result->className = (LPCWSTR)(UINT)GET_WORD( p + 1 );
584             p += 2;
585             break;
586         default:
587             result->className = (LPCWSTR)p;
588             p += wcslen( result->className ) + 1;
589             break;
590     }
591     
592     /* Get the window caption */
593
594     result->caption = (LPCWSTR)p;
595     p += wcslen( result->caption ) + 1;
596
597     /* Get the font name */
598
599     if (result->style & DS_SETFONT)
600     {
601         result->pointSize = GET_WORD(p);
602         p++;
603         if (result->dialogEx)
604         {
605             result->weight = GET_WORD(p); p++;
606             result->italic = LOBYTE(GET_WORD(p)); p++;
607         }
608         else
609         {
610             result->weight = FW_DONTCARE;
611             result->italic = FALSE;
612         }
613         result->faceName = (LPCWSTR)p;
614         p += wcslen( result->faceName ) + 1;
615     }
616
617     /* First control is on dword boundary */
618     return (LPCSTR)((((int)p) + 3) & ~3);
619 }
620
621  /***********************************************************************
622  *           DIALOG_CreateIndirect
623  *       Creates a dialog box window
624  *
625  *       modal = TRUE if we are called from a modal dialog box.
626  *       (it's more compatible to do it here, as under Windows the owner
627  *       is never disabled if the dialog fails because of an invalid template)
628  */
629 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
630                                    HWND owner, DLGPROC dlgProc, LPARAM param,
631                                    BOOL unicode, BOOL modal )
632 {
633     HWND hwnd;
634     RECT rect;
635     DLG_TEMPLATE template;
636     DIALOGINFO * dlgInfo;
637     DWORD units = GetDialogBaseUnits();
638     BOOL ownerEnabled = TRUE;
639
640     /* Parse dialog template */
641
642     if (!dlgTemplate) return 0;
643     dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
644
645     /* Initialise dialog extra data */
646     
647     if (!(dlgInfo = HeapAlloc( GetProcessHeap(), 0, sizeof(*dlgInfo) ))) return 0;
648     dlgInfo->hwndFocus   = 0;
649     dlgInfo->hUserFont   = 0;
650     dlgInfo->hMenu       = 0;
651     dlgInfo->xBaseUnit   = LOWORD(units);
652     dlgInfo->yBaseUnit   = HIWORD(units);
653     dlgInfo->idResult    = 0;
654     dlgInfo->flags       = 0;
655     //dlgInfo->hDialogHeap = 0;
656     
657     /* Load menu */
658
659     if (template.menuName) dlgInfo->hMenu = LoadMenuW( hInst, template.menuName );
660     
661     /* Create custom font if needed */
662
663     if (template.style & DS_SETFONT)
664     {
665         /* We convert the size to pixels and then make it -ve.  This works
666         * for both +ve and -ve template.pointSize */
667         HDC dc;
668         int pixels;
669         dc = GetDC(0);
670         pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72);
671         dlgInfo->hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight,
672                                             template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
673                                             PROOF_QUALITY, FF_DONTCARE,
674                                             template.faceName );
675         if (dlgInfo->hUserFont)
676         {
677             SIZE charSize;
678             if (DIALOG_GetCharSize( dc, dlgInfo->hUserFont, &charSize ))
679             {
680                 dlgInfo->xBaseUnit = charSize.cx;
681                 dlgInfo->yBaseUnit = charSize.cy;
682             }
683         }
684         ReleaseDC(0, dc);
685     }
686
687     /* Create dialog main window */
688
689     rect.left = rect.top = 0;
690     rect.right = MulDiv(template.cx, dlgInfo->xBaseUnit, 4);
691     rect.bottom =  MulDiv(template.cy, dlgInfo->yBaseUnit, 8);
692     if (template.style & DS_MODALFRAME)
693         template.exStyle |= WS_EX_DLGMODALFRAME;
694     AdjustWindowRectEx( &rect, template.style, (dlgInfo->hMenu != 0), template.exStyle );
695     rect.right -= rect.left;
696     rect.bottom -= rect.top;
697
698     if (template.x == CW_USEDEFAULT16)
699     {
700         rect.left = rect.top = CW_USEDEFAULT;
701     }
702     else
703     {
704         if (template.style & DS_CENTER)
705         {
706             rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
707             rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
708         }
709         else
710         {
711             rect.left += MulDiv(template.x, dlgInfo->xBaseUnit, 4);
712             rect.top += MulDiv(template.y, dlgInfo->yBaseUnit, 8);
713         }
714         if ( !(template.style & WS_CHILD) )
715         {
716             INT dX, dY;
717
718             if( !(template.style & DS_ABSALIGN) )
719                 ClientToScreen( owner, (POINT *)&rect );
720
721             /* try to fit it into the desktop */
722
723             if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
724                    - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
725             if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
726                    - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
727             if( rect.left < 0 ) rect.left = 0;
728             if( rect.top < 0 ) rect.top = 0;
729         }
730     }
731     
732     if (modal)
733     {
734         ownerEnabled = DIALOG_DisableOwner( owner );
735         if (ownerEnabled) dlgInfo->flags |= DF_OWNERENABLED;
736     }
737
738     if (unicode)
739     {
740         hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
741                                template.style & ~WS_VISIBLE,
742                                rect.left, rect.top, rect.right, rect.bottom,
743                                owner, dlgInfo->hMenu, hInst, NULL );
744     }
745     else
746     {
747         LPSTR class = (LPSTR)template.className;
748         LPSTR caption = (LPSTR)template.caption;
749
750         if (HIWORD(class))
751         {
752             DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL );
753             class = HeapAlloc( GetProcessHeap(), 0, len );
754             WideCharToMultiByte( CP_ACP, 0, template.className, -1, class, len, NULL, NULL );
755         }
756         if (HIWORD(caption))
757         {
758             DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL );
759             caption = HeapAlloc( GetProcessHeap(), 0, len );
760             WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption, len, NULL, NULL );
761         }
762         hwnd = CreateWindowExA(template.exStyle, class, caption,
763                                template.style & ~WS_VISIBLE,
764                                rect.left, rect.top, rect.right, rect.bottom,
765                                owner, dlgInfo->hMenu, hInst, NULL );
766         if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
767         if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
768     }    
769
770     if (!hwnd)
771     {
772         if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
773         if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
774         if (modal && (dlgInfo->flags & DF_OWNERENABLED)) DIALOG_EnableOwner(owner);
775         HeapFree( GetProcessHeap(), 0, dlgInfo );
776         return 0;
777     }
778
779     if (template.helpId)
780         SetWindowContextHelpId( hwnd, template.helpId );
781
782     if (unicode)
783     {
784         SETDLGINFO(hwnd, dlgInfo); /* maybe SetPropW? */
785         SetWindowLongW( hwnd, DWL_DLGPROC, (LONG)dlgProc );
786     }
787     else
788     {
789         SETDLGINFO(hwnd, dlgInfo);
790         SetWindowLongA( hwnd, DWL_DLGPROC, (LONG)dlgProc );
791     }
792     
793     if (dlgInfo->hUserFont)
794         SendMessageA( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
795     
796     /* Create controls */
797     
798     if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode ))
799     {
800         HWND hwndPreInitFocus;
801
802         /* Send initialisation messages and set focus */
803
804        dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
805
806         hwndPreInitFocus = GetFocus();
807         if (SendMessageA( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
808         {
809             /* check where the focus is again,
810              * some controls status might have changed in WM_INITDIALOG */
811             dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
812             if( dlgInfo->hwndFocus )
813                 SetFocus( dlgInfo->hwndFocus );
814         }
815         else
816         {
817             /* If the dlgproc has returned FALSE (indicating handling of keyboard focus)
818                but the focus has not changed, set the focus where we expect it. */
819             if ((GetFocus() == hwndPreInitFocus) &&
820                 (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
821             {
822                 dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
823                 if( dlgInfo->hwndFocus )
824                     SetFocus( dlgInfo->hwndFocus );
825             }
826         }
827
828         if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
829         {
830            ShowWindow( hwnd, SW_SHOWNORMAL );   /* SW_SHOW doesn't always work */
831         }
832         return hwnd;
833     }
834     
835     if( IsWindow(hwnd) ) DestroyWindow( hwnd );
836     if (modal && ownerEnabled) DIALOG_EnableOwner(owner);
837     return 0;
838 }
839
840 /***********************************************************************
841  *           DEFDLG_SetFocus
842  *
843  * Set the focus to a control of the dialog, selecting the text if
844  * the control is an edit dialog.
845  */
846 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
847 {
848     HWND hwndPrev = GetFocus();
849
850     if (IsChild( hwndDlg, hwndPrev ))
851     {
852         if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
853             SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
854     }
855     if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
856         SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
857     SetFocus( hwndCtrl );
858 }
859
860 /***********************************************************************
861  *           DEFDLG_SaveFocus
862  */
863 static void DEFDLG_SaveFocus( HWND hwnd )
864 {
865     DIALOGINFO *infoPtr;        
866     HWND hwndFocus = GetFocus();
867
868     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
869         if (!(infoPtr = GETDLGINFO(hwnd))) return;
870     infoPtr->hwndFocus = hwndFocus;
871     /* Remove default button */
872 }
873
874 /***********************************************************************
875  *           DEFDLG_RestoreFocus
876  */
877 static void DEFDLG_RestoreFocus( HWND hwnd )
878 {
879     DIALOGINFO *infoPtr;
880
881     if (IsIconic( hwnd )) return;
882     if (!(infoPtr = GETDLGINFO(hwnd))) return;
883     if (!IsWindow( infoPtr->hwndFocus )) return;
884     /* Don't set the focus back to controls if EndDialog is already called.*/
885     if (!(infoPtr->flags & DF_END))
886     {
887         DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
888         return;
889     }
890     /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
891        sometimes losing focus when receiving WM_SETFOCUS messages. */
892 }
893
894 /***********************************************************************
895  *           DEFDLG_FindDefButton
896  *
897  * Find the current default push-button.
898  */
899 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
900 {
901     HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
902     while (hwndChild)
903     {
904         if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
905             break;
906         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
907     }
908     return hwndChild;
909 }
910
911 /***********************************************************************
912  *           DEFDLG_SetDefButton
913  *
914  * Set the new default button to be hwndNew.
915  */
916 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
917                                  HWND hwndNew )
918 {
919     DWORD dlgcode=0; /* initialize just to avoid a warning */
920     if (hwndNew &&
921         !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
922             & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
923         return FALSE;  /* Destination is not a push button */
924
925     if (dlgInfo->idResult)  /* There's already a default pushbutton */
926     {
927         HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
928         if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
929             SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
930     }
931     if (hwndNew)
932     {
933         if(dlgcode==DLGC_UNDEFPUSHBUTTON)
934             SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
935         dlgInfo->idResult = GetDlgCtrlID( hwndNew );
936     }
937     else dlgInfo->idResult = 0;
938     return TRUE;
939 }
940
941 /***********************************************************************
942  *           DEFDLG_Proc
943  *
944  * Implementation of DefDlgProc(). Only handle messages that need special
945  * handling for dialogs.
946  */
947 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
948                             LPARAM lParam, DIALOGINFO *dlgInfo )
949 {
950     switch(msg)
951     {
952         case WM_ERASEBKGND:
953         {
954             HBRUSH brush = (HBRUSH)SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
955             if (!brush) brush = (HBRUSH)DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
956             if (brush)
957             {
958                 RECT rect;
959                 HDC hdc = (HDC)wParam;
960                 GetClientRect( hwnd, &rect );
961                 DPtoLP( hdc, (LPPOINT)&rect, 2 );
962                 FillRect( hdc, &rect, brush );
963             }
964             return 1;
965         }
966         case WM_NCDESTROY:
967             if ((dlgInfo = GETDLGINFO(hwnd)))
968             {
969                 /* Free dialog heap (if created) */
970                 /*if (dlgInfo->hDialogHeap)
971                 {
972                     GlobalUnlock16(dlgInfo->hDialogHeap);
973                     GlobalFree16(dlgInfo->hDialogHeap);
974                 }*/
975                 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
976                 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );                
977                 HeapFree( GetProcessHeap(), 0, dlgInfo );
978             }
979              /* Window clean-up */
980             return DefWindowProcA( hwnd, msg, wParam, lParam );
981
982                         case WM_SHOWWINDOW:
983             if (!wParam) DEFDLG_SaveFocus( hwnd );
984             return DefWindowProcA( hwnd, msg, wParam, lParam );
985
986         case WM_ACTIVATE:
987             if (wParam) DEFDLG_RestoreFocus( hwnd );
988             else DEFDLG_SaveFocus( hwnd );
989             return 0;
990
991         case WM_SETFOCUS:
992             DEFDLG_RestoreFocus( hwnd );
993             return 0;
994
995         case DM_SETDEFID:
996             if (dlgInfo && !(dlgInfo->flags & DF_END))
997                 DEFDLG_SetDefButton( hwnd, dlgInfo, wParam ? GetDlgItem( hwnd, wParam ) : 0 );
998             return 1;
999
1000         case DM_GETDEFID:
1001             if (dlgInfo && !(dlgInfo->flags & DF_END))
1002             {
1003                 HWND hwndDefId;
1004                 if (dlgInfo->idResult)
1005                     return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
1006                 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
1007                     return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
1008             }
1009             return 0;
1010
1011         case WM_NEXTDLGCTL:
1012             if (dlgInfo)
1013             {
1014                 HWND hwndDest = (HWND)wParam;
1015                 if (!lParam)
1016                     hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
1017                 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
1018                 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
1019             }
1020             return 0;
1021
1022         case WM_ENTERMENULOOP:
1023         case WM_LBUTTONDOWN:
1024         case WM_NCLBUTTONDOWN:
1025             {
1026                 HWND hwndFocus = GetFocus();
1027                 if (hwndFocus)
1028                 {
1029                     /* always make combo box hide its listbox control */
1030                     if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
1031                         SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
1032                 }
1033             }
1034             return DefWindowProcA( hwnd, msg, wParam, lParam );
1035
1036         case WM_GETFONT:
1037             return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0;
1038
1039         case WM_CLOSE:
1040             PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
1041                             (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
1042             return 0;
1043
1044         case WM_NOTIFYFORMAT:
1045              return DefWindowProcA( hwnd, msg, wParam, lParam );
1046     }
1047     return 0;
1048 }
1049
1050 /***********************************************************************
1051  *           DEFDLG_Epilog
1052  */
1053 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
1054 {
1055         // TODO: where's wine's WM_CTLCOLOR from?
1056     if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
1057          /*msg == WM_CTLCOLOR || */ msg == WM_COMPAREITEM ||
1058          msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
1059          msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
1060         return fResult;
1061
1062     return GetWindowLongA( hwnd, DWL_MSGRESULT );
1063 }
1064
1065 /***********************************************************************
1066  *           DIALOG_GetNextTabItem
1067  *
1068  * Helper for GetNextDlgTabItem
1069  */
1070 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1071 {
1072     LONG dsStyle;
1073     LONG exStyle;
1074     UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT;
1075     HWND retWnd = 0;
1076     HWND hChildFirst = 0;
1077
1078     if(!hwndCtrl)
1079     {
1080         hChildFirst = GetWindow(hwndDlg,GW_CHILD);
1081         if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST);
1082     }
1083     else if (IsChild( hwndMain, hwndCtrl ))
1084     {
1085         hChildFirst = GetWindow(hwndCtrl,wndSearch);
1086         if(!hChildFirst)
1087         {
1088             if(GetParent(hwndCtrl) != hwndMain)
1089                 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
1090             else
1091             {
1092                 if(fPrevious)
1093                     hChildFirst = GetWindow(hwndCtrl,GW_HWNDLAST);
1094                 else
1095                     hChildFirst = GetWindow(hwndCtrl,GW_HWNDFIRST);
1096             }
1097         }
1098     }
1099
1100     while(hChildFirst)
1101     {
1102         BOOL bCtrl = FALSE;
1103         while(hChildFirst)
1104         {
1105             dsStyle = GetWindowLongA(hChildFirst,GWL_STYLE);
1106             exStyle = GetWindowLongA(hChildFirst,GWL_EXSTYLE);
1107             if( (dsStyle & DS_CONTROL || exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1108             {
1109                 bCtrl=TRUE;
1110                 break;
1111             }
1112             else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1113                 break;
1114             hChildFirst = GetWindow(hChildFirst,wndSearch);
1115         }
1116         if(hChildFirst)
1117         {
1118             if(bCtrl)
1119                 retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
1120             else
1121                 retWnd = hChildFirst;
1122         }
1123         if(retWnd) break;
1124         hChildFirst = GetWindow(hChildFirst,wndSearch);
1125     }
1126     if(!retWnd && hwndCtrl)
1127     {
1128         HWND hParent = GetParent(hwndCtrl);
1129         while(hParent)
1130         {
1131             if(hParent == hwndMain) break;
1132             retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious );
1133             if(retWnd) break;
1134             hParent = GetParent(hParent);
1135         }
1136         if(!retWnd)
1137             retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
1138     }
1139     return retWnd;
1140 }
1141
1142 /***********************************************************************
1143  *           GetDlgItemEnumProc
1144  *
1145  * Callback for GetDlgItem
1146  */
1147 BOOL CALLBACK GetDlgItemEnumProc (HWND hwnd, LPARAM lParam )
1148 {
1149     GETDLGITEMINFO * info = (GETDLGITEMINFO *)lParam;
1150     if(info->nIDDlgItem == GetWindowLongW( hwnd, GWL_ID ))
1151     {        
1152         info->control = hwnd;        
1153         return FALSE;
1154     }
1155     return TRUE;
1156 }
1157
1158
1159 /* FUNCTIONS *****************************************************************/
1160
1161 /*
1162  * @implemented
1163  */
1164 HWND
1165 STDCALL
1166 CreateDialogIndirectParamA(
1167   HINSTANCE hInstance,
1168   LPCDLGTEMPLATE lpTemplate,
1169   HWND hWndParent,
1170   DLGPROC lpDialogFunc,
1171   LPARAM lParamInit)
1172 {
1173         return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, FALSE, FALSE );
1174 }
1175
1176
1177 /*
1178  * @unimplemented
1179  */
1180 HWND
1181 STDCALL
1182 CreateDialogIndirectParamAorW(
1183   HINSTANCE hInstance,
1184   LPCDLGTEMPLATE lpTemplate,
1185   HWND hWndParent,
1186   DLGPROC lpDialogFunc,
1187   LPARAM lParamInit)
1188 {
1189           /* FIXME:
1190          This function might be obsolete since I don't think it is exported by NT
1191      Also wine has one more parameter identifying weather it should call
1192          the function with unicode or not */
1193         UNIMPLEMENTED;
1194         return (HWND)0;
1195 }
1196
1197
1198 /*
1199  * @implemented
1200  */
1201 HWND
1202 STDCALL
1203 CreateDialogIndirectParamW(
1204   HINSTANCE hInstance,
1205   LPCDLGTEMPLATE lpTemplate,
1206   HWND hWndParent,
1207   DLGPROC lpDialogFunc,
1208   LPARAM lParamInit)
1209 {
1210         return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, TRUE, FALSE );
1211 }
1212
1213
1214 /*
1215  * @implemented
1216  */
1217 HWND
1218 STDCALL
1219 CreateDialogParamA(
1220   HINSTANCE hInstance,
1221   LPCSTR lpTemplateName,
1222   HWND hWndParent,
1223   DLGPROC lpDialogFunc,
1224   LPARAM dwInitParam)
1225 {
1226         HRSRC hrsrc;
1227         LPCDLGTEMPLATE ptr;
1228
1229     if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1230     if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1231         return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1232 }
1233
1234
1235 /*
1236  * @implemented
1237  */
1238 HWND
1239 STDCALL
1240 CreateDialogParamW(
1241   HINSTANCE hInstance,
1242   LPCWSTR lpTemplateName,
1243   HWND hWndParent,
1244   DLGPROC lpDialogFunc,
1245   LPARAM dwInitParam)
1246 {
1247         HRSRC hrsrc;
1248         LPCDLGTEMPLATE ptr;
1249
1250         if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1251         if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1252         return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1253 }
1254
1255
1256 /*
1257  * @implemented
1258  */
1259 LRESULT
1260 STDCALL
1261 DefDlgProcA(
1262   HWND hDlg,
1263   UINT Msg,
1264   WPARAM wParam,
1265   LPARAM lParam)
1266 {
1267     WNDPROC dlgproc;
1268     BOOL result = FALSE;
1269     DIALOGINFO * dlgInfo;
1270
1271         /* if there's no dialog info property then call default windows proc?? */
1272     if (!(dlgInfo = GETDLGINFO(hDlg))) 
1273             return DefWindowProcA( hDlg, Msg, wParam, lParam );
1274
1275     SetWindowLongW( hDlg, DWL_MSGRESULT, 0 );
1276
1277     if ((dlgproc = (WNDPROC)GetWindowLongA( hDlg, DWL_DLGPROC )))
1278     {
1279         /* Call dialog procedure */
1280         result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam );
1281     }
1282
1283     if (!result && IsWindow(hDlg))
1284     {
1285         /* callback didn't process this message */
1286
1287         switch(Msg)
1288         {
1289             case WM_ERASEBKGND:
1290             case WM_SHOWWINDOW:
1291             case WM_ACTIVATE:
1292             case WM_SETFOCUS:
1293             case DM_SETDEFID:
1294             case DM_GETDEFID:
1295             case WM_NEXTDLGCTL:
1296             case WM_GETFONT:
1297             case WM_CLOSE:
1298             case WM_NCDESTROY:
1299             case WM_ENTERMENULOOP:
1300             case WM_LBUTTONDOWN:
1301             case WM_NCLBUTTONDOWN:
1302                  return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1303             case WM_INITDIALOG:
1304             case WM_VKEYTOITEM:
1305             case WM_COMPAREITEM:
1306             case WM_CHARTOITEM:
1307                  break;
1308
1309             default:
1310                  return DefWindowProcA( hDlg, Msg, wParam, lParam );
1311         }
1312     }
1313     return DEFDLG_Epilog(hDlg, Msg, result);
1314 }
1315
1316
1317 /*
1318  * @implemented
1319  */
1320 LRESULT
1321 STDCALL
1322 DefDlgProcW(
1323   HWND hDlg,
1324   UINT Msg,
1325   WPARAM wParam,
1326   LPARAM lParam)
1327 {
1328     WNDPROC dlgproc;
1329     BOOL result = FALSE;
1330     DIALOGINFO * dlgInfo;
1331
1332         /* if there's no dialog info property then call default windows proc?? */
1333     if (!(dlgInfo = GETDLGINFO(hDlg))) 
1334             return DefWindowProcW( hDlg, Msg, wParam, lParam );
1335
1336     SetWindowLongW( hDlg, DWL_MSGRESULT, 0 );
1337
1338     if ((dlgproc = (WNDPROC)GetWindowLongW( hDlg, DWL_DLGPROC )))
1339     {
1340         /* Call dialog procedure */
1341         result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam );
1342     }
1343
1344     if (!result && IsWindow(hDlg))
1345     {
1346         /* callback didn't process this message */
1347
1348         switch(Msg)
1349         {
1350             case WM_ERASEBKGND:
1351             case WM_SHOWWINDOW:
1352             case WM_ACTIVATE:
1353             case WM_SETFOCUS:
1354             case DM_SETDEFID:
1355             case DM_GETDEFID:
1356             case WM_NEXTDLGCTL:
1357             case WM_GETFONT:
1358             case WM_CLOSE:
1359             case WM_NCDESTROY:
1360             case WM_ENTERMENULOOP:
1361             case WM_LBUTTONDOWN:
1362             case WM_NCLBUTTONDOWN:
1363                  return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1364             case WM_INITDIALOG:
1365             case WM_VKEYTOITEM:
1366             case WM_COMPAREITEM:
1367             case WM_CHARTOITEM:
1368                  break;
1369
1370             default:
1371                  return DefWindowProcW( hDlg, Msg, wParam, lParam );
1372         }
1373     }
1374     return DEFDLG_Epilog(hDlg, Msg, result);
1375 }
1376
1377
1378 /*
1379  * @implemented
1380  */
1381 INT_PTR
1382 STDCALL
1383 DialogBoxIndirectParamA(
1384   HINSTANCE hInstance,
1385   LPCDLGTEMPLATE hDialogTemplate,
1386   HWND hWndParent,
1387   DLGPROC lpDialogFunc,
1388   LPARAM dwInitParam)
1389 {
1390     HWND hwnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, FALSE, TRUE );
1391     if (hwnd) return DIALOG_DoDialogBox( hwnd, hWndParent );
1392     return -1;
1393 }
1394
1395
1396 /*
1397  * @unimplemented
1398  */
1399 INT_PTR
1400 STDCALL
1401 DialogBoxIndirectParamAorW(
1402   HINSTANCE hInstance,
1403   LPCDLGTEMPLATE hDialogTemplate,
1404   HWND hWndParent,
1405   DLGPROC lpDialogFunc,
1406   LPARAM dwInitParam)
1407 {
1408   /* FIXME:
1409          This function might be obsolete since I don't think it is exported by NT
1410      Also wine has one more parameter identifying weather it should call
1411          the function with unicode or not */
1412   UNIMPLEMENTED;
1413   return (INT_PTR)NULL;
1414 }
1415
1416
1417 /*
1418  * @implemented
1419  */
1420 INT_PTR
1421 STDCALL
1422 DialogBoxIndirectParamW(
1423   HINSTANCE hInstance,
1424   LPCDLGTEMPLATE hDialogTemplate,
1425   HWND hWndParent,
1426   DLGPROC lpDialogFunc,
1427   LPARAM dwInitParam)
1428 {
1429     HWND hwnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, TRUE, TRUE );
1430     if (hwnd) return DIALOG_DoDialogBox( hwnd, hWndParent );
1431     return -1;
1432 }
1433
1434
1435 /*
1436  * @implemented
1437  */
1438 INT_PTR
1439 STDCALL
1440 DialogBoxParamA(
1441   HINSTANCE hInstance,
1442   LPCSTR lpTemplateName,
1443   HWND hWndParent,
1444   DLGPROC lpDialogFunc,
1445   LPARAM dwInitParam)
1446 {
1447     HWND hwnd;
1448     HRSRC hrsrc;
1449     LPCDLGTEMPLATE ptr;
1450     
1451         if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1452         if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1453     hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, TRUE);
1454     if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1455     return -1;
1456 }
1457
1458
1459 /*
1460  * @implemented
1461  */
1462 INT_PTR
1463 STDCALL
1464 DialogBoxParamW(
1465   HINSTANCE hInstance,
1466   LPCWSTR lpTemplateName,
1467   HWND hWndParent,
1468   DLGPROC lpDialogFunc,
1469   LPARAM dwInitParam)
1470 {
1471     HWND hwnd;
1472     HRSRC hrsrc;
1473     LPCDLGTEMPLATE ptr;
1474     
1475         if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1476         if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1477     hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, TRUE);
1478     if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1479     return -1;
1480 }
1481
1482
1483 /*
1484  * @unimplemented
1485  */
1486 int
1487 STDCALL
1488 DlgDirListA(
1489   HWND hDlg,
1490   LPSTR lpPathSpec,
1491   int nIDListBox,
1492   int nIDStaticPath,
1493   UINT uFileType)
1494 {
1495   UNIMPLEMENTED;
1496   return 0;
1497 }
1498
1499
1500 /*
1501  * @unimplemented
1502  */
1503 int
1504 STDCALL
1505 DlgDirListComboBoxA(
1506   HWND hDlg,
1507   LPSTR lpPathSpec,
1508   int nIDComboBox,
1509   int nIDStaticPath,
1510   UINT uFiletype)
1511 {
1512   UNIMPLEMENTED;
1513   return 0;
1514 }
1515
1516
1517 /*
1518  * @unimplemented
1519  */
1520 int
1521 STDCALL
1522 DlgDirListComboBoxW(
1523   HWND hDlg,
1524   LPWSTR lpPathSpec,
1525   int nIDComboBox,
1526   int nIDStaticPath,
1527   UINT uFiletype)
1528 {
1529   UNIMPLEMENTED;
1530   return 0;
1531 }
1532
1533
1534 /*
1535  * @unimplemented
1536  */
1537 int
1538 STDCALL
1539 DlgDirListW(
1540   HWND hDlg,
1541   LPWSTR lpPathSpec,
1542   int nIDListBox,
1543   int nIDStaticPath,
1544   UINT uFileType)
1545 {
1546   UNIMPLEMENTED;
1547   return 0;
1548 }
1549
1550
1551 /*
1552  * @unimplemented
1553  */
1554 WINBOOL
1555 STDCALL
1556 DlgDirSelectComboBoxExA(
1557   HWND hDlg,
1558   LPSTR lpString,
1559   int nCount,
1560   int nIDComboBox)
1561 {
1562   UNIMPLEMENTED;
1563   return FALSE;
1564 }
1565
1566
1567 /*
1568  * @unimplemented
1569  */
1570 WINBOOL
1571 STDCALL
1572 DlgDirSelectComboBoxExW(
1573   HWND hDlg,
1574   LPWSTR lpString,
1575   int nCount,
1576   int nIDComboBox)
1577 {
1578   UNIMPLEMENTED;
1579   return FALSE;
1580 }
1581
1582
1583 /*
1584  * @unimplemented
1585  */
1586 WINBOOL
1587 STDCALL
1588 DlgDirSelectExA(
1589   HWND hDlg,
1590   LPSTR lpString,
1591   int nCount,
1592   int nIDListBox)
1593 {
1594   UNIMPLEMENTED;
1595   return FALSE;
1596 }
1597
1598
1599 /*
1600  * @unimplemented
1601  */
1602 WINBOOL
1603 STDCALL
1604 DlgDirSelectExW(
1605   HWND hDlg,
1606   LPWSTR lpString,
1607   int nCount,
1608   int nIDListBox)
1609 {
1610   UNIMPLEMENTED;
1611   return FALSE;
1612 }
1613
1614
1615 /*
1616  * @implemented
1617  */
1618 WINBOOL
1619 STDCALL
1620 EndDialog(
1621   HWND hDlg,
1622   INT_PTR nResult)
1623 {
1624     BOOL wasEnabled = TRUE;
1625     DIALOGINFO * dlgInfo;
1626     HWND owner;
1627
1628     if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
1629     
1630     dlgInfo->idResult = nResult;
1631     dlgInfo->flags |= DF_END;
1632     wasEnabled = (dlgInfo->flags & DF_OWNERENABLED);
1633
1634     if (wasEnabled && (owner = GetWindow( hDlg, GW_OWNER )))
1635         DIALOG_EnableOwner( owner );
1636
1637     /* Windows sets the focus to the dialog itself in EndDialog */
1638
1639     if (IsChild(hDlg, GetFocus()))
1640        SetFocus( hDlg );
1641
1642     /* Don't have to send a ShowWindow(SW_HIDE), just do
1643        SetWindowPos with SWP_HIDEWINDOW as done in Windows */
1644
1645     SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
1646                  | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
1647
1648     /* unblock dialog loop */
1649     PostMessageA(hDlg, WM_NULL, 0, 0);
1650     return TRUE;
1651 }
1652
1653
1654 /*
1655  * @implemented
1656  */
1657 LONG
1658 STDCALL
1659 GetDialogBaseUnits(VOID)
1660 {
1661     static DWORD units;
1662
1663     if (!units)
1664     {
1665         HDC hdc;
1666         SIZE size;
1667
1668         if ((hdc = GetDC(0)))
1669         {
1670             if (DIALOG_GetCharSize( hdc, 0, &size )) units = MAKELONG( size.cx, size.cy );
1671             ReleaseDC( 0, hdc );
1672         }
1673     }
1674     return units;
1675 }
1676
1677
1678 /*
1679  * @implemented
1680  */
1681 int
1682 STDCALL
1683 GetDlgCtrlID(
1684   HWND hwndCtl)
1685 {
1686         return GetWindowLongW( hwndCtl, GWL_ID );
1687 }
1688
1689
1690 /*
1691  * @implemented
1692  */
1693 HWND
1694 STDCALL
1695 GetDlgItem(
1696   HWND hDlg,
1697   int nIDDlgItem)
1698 {
1699     GETDLGITEMINFO info;
1700     info.nIDDlgItem = nIDDlgItem;
1701     info.control = 0;
1702     if(hDlg && !EnumChildWindows(hDlg, (ENUMWINDOWSPROC)&GetDlgItemEnumProc, (LPARAM)&info))
1703         return info.control;
1704     else
1705         return 0;
1706 }
1707
1708
1709 /*
1710  * @implemented
1711  */
1712 UINT
1713 STDCALL
1714 GetDlgItemInt(
1715   HWND hDlg,
1716   int nIDDlgItem,
1717   WINBOOL *lpTranslated,
1718   WINBOOL bSigned)
1719 {
1720         char str[30];
1721     char * endptr;
1722     long result = 0;
1723
1724     if (lpTranslated) *lpTranslated = FALSE;
1725     if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str))
1726         return 0;
1727     if (bSigned)
1728     {
1729         result = strtol( str, &endptr, 10 );
1730         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
1731             return 0;
1732                 /* FIXME: errno? */
1733         if (((result == LONG_MIN) || (result == LONG_MAX))/* && (errno == ERANGE) */)
1734             return 0;
1735     }
1736     else
1737     {
1738         result = strtoul( str, &endptr, 10 );
1739         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
1740             return 0;
1741                 /* FIXME: errno? */
1742         if ((result == LONG_MAX)/* && (errno == ERANGE) */) return 0;
1743     }
1744     if (lpTranslated) *lpTranslated = TRUE;
1745     return (UINT)result;
1746 }
1747
1748
1749 /*
1750  * @implemented
1751  */
1752 UINT
1753 STDCALL
1754 GetDlgItemTextA(
1755   HWND hDlg,
1756   int nIDDlgItem,
1757   LPSTR lpString,
1758   int nMaxCount)
1759 {
1760   return (UINT)SendDlgItemMessageA( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
1761 }
1762
1763
1764 /*
1765  * @implemented
1766  */
1767 UINT
1768 STDCALL
1769 GetDlgItemTextW(
1770   HWND hDlg,
1771   int nIDDlgItem,
1772   LPWSTR lpString,
1773   int nMaxCount)
1774 {
1775   return (UINT)SendDlgItemMessageW( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
1776 }
1777
1778
1779 /*
1780  * @implemented
1781  */
1782 HWND
1783 STDCALL
1784 GetNextDlgGroupItem(
1785   HWND hDlg,
1786   HWND hCtl,
1787   WINBOOL bPrevious)
1788 {
1789         HWND hwnd, retvalue;
1790
1791     if(hCtl)
1792     {
1793         /* if the hwndCtrl is the child of the control in the hwndDlg,
1794          * then the hwndDlg has to be the parent of the hwndCtrl */
1795         if(GetParent(hCtl) != hDlg && GetParent(GetParent(hCtl)) == hDlg)
1796             hDlg = GetParent(hCtl);
1797     }
1798
1799     if (hCtl)
1800     {
1801         /* Make sure hwndCtrl is a top-level child */
1802         HWND parent = GetParent( hCtl );
1803         while (parent && parent != hDlg) parent = GetParent(parent);
1804         if (parent != hDlg) return 0;
1805     }
1806     else
1807     {
1808         /* No ctrl specified -> start from the beginning */
1809         if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
1810         if (bPrevious) hCtl = GetWindow( hCtl, GW_HWNDLAST );
1811     }
1812
1813     retvalue = hCtl;
1814     hwnd = GetWindow( hCtl, GW_HWNDNEXT );
1815     while (1)
1816     {
1817         if (!hwnd || (GetWindowLongW( hwnd, GWL_STYLE ) & WS_GROUP))
1818         {
1819             /* Wrap-around to the beginning of the group */
1820             HWND tmp;
1821
1822             hwnd = GetWindow( hDlg, GW_CHILD );
1823             for (tmp = hwnd; tmp; tmp = GetWindow( tmp, GW_HWNDNEXT ) )
1824             {
1825                 if (GetWindowLongW( tmp, GWL_STYLE ) & WS_GROUP) hwnd = tmp;
1826                 if (tmp == hCtl) break;
1827             }
1828         }
1829         if (hwnd == hCtl) break;
1830         if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
1831         {
1832             retvalue = hwnd;
1833             if (!bPrevious) break;
1834         }
1835         hwnd = GetWindow( hwnd, GW_HWNDNEXT );
1836     }
1837     return retvalue;
1838 }
1839
1840
1841 /*
1842  * @implemented
1843  */
1844 HWND
1845 STDCALL
1846 GetNextDlgTabItem(
1847   HWND hDlg,
1848   HWND hCtl,
1849   WINBOOL bPrevious)
1850 {
1851         return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious);
1852 }
1853
1854 #if 0
1855 WINBOOL
1856 STDCALL
1857 IsDialogMessage(
1858   HWND hDlg,
1859   LPMSG lpMsg)
1860 {
1861         return IsDialogMessageW(hDlg, lpMsg);
1862 }
1863 #endif
1864
1865
1866 /*
1867  * @implemented
1868  */
1869 WINBOOL
1870 STDCALL
1871 IsDialogMessageA(
1872   HWND hDlg,
1873   LPMSG lpMsg)
1874 {
1875      INT dlgCode = 0;
1876  
1877      // FIXME: hooks
1878      //if (CallMsgFilterA( lpMsg, MSGF_DIALOGBOX )) return TRUE;
1879  
1880      if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
1881  
1882      hDlg = DIALOG_FindMsgDestination(hDlg);
1883  
1884      switch(lpMsg->message)
1885      {
1886      case WM_KEYDOWN:
1887         dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
1888          if (dlgCode & DLGC_WANTMESSAGE) break;
1889  
1890          switch(lpMsg->wParam)
1891          {
1892          case VK_TAB:
1893              if (!(dlgCode & DLGC_WANTTAB))
1894              {
1895                  SendMessageA( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
1896                  return TRUE;
1897              }
1898              break;
1899  
1900          case VK_RIGHT:
1901          case VK_DOWN:
1902          case VK_LEFT:
1903          case VK_UP:
1904              if (!(dlgCode & DLGC_WANTARROWS))
1905              {
1906                  BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
1907                  HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
1908                  SendMessageA( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
1909                  return TRUE;
1910              }
1911              break;
1912  
1913          case VK_CANCEL:
1914          case VK_ESCAPE:
1915              SendMessageA( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
1916              return TRUE;
1917  
1918          case VK_EXECUTE:
1919          case VK_RETURN:
1920              {
1921                  DWORD dw = SendMessageA( hDlg, DM_GETDEFID, 0, 0 );
1922                  if (HIWORD(dw) == DC_HASDEFID)
1923                  {
1924                      SendMessageA( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
1925                                      (LPARAM)GetDlgItem(hDlg, LOWORD(dw)));
1926                  }
1927                  else
1928                  {
1929                      SendMessageA( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
1930  
1931                  }
1932              }
1933              return TRUE;
1934          }
1935          break;
1936  
1937      case WM_CHAR:
1938          dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
1939          if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
1940          if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
1941          /* drop through */
1942  
1943      case WM_SYSCHAR:
1944          if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
1945          {
1946              /* don't translate or dispatch */
1947              return TRUE;
1948          }
1949          break;
1950      }
1951  
1952      TranslateMessage( lpMsg );
1953      DispatchMessageA( lpMsg );
1954      return TRUE;
1955 }
1956
1957
1958 /*
1959  * @implemented
1960  */
1961 WINBOOL
1962 STDCALL
1963 IsDialogMessageW(
1964   HWND hDlg,
1965   LPMSG lpMsg)
1966 {
1967      INT dlgCode = 0;
1968  
1969      // FIXME: hooks
1970      //if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE;
1971  
1972      if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
1973  
1974      hDlg = DIALOG_FindMsgDestination(hDlg);
1975  
1976      switch(lpMsg->message)
1977      {
1978      case WM_KEYDOWN:
1979         dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
1980          if (dlgCode & DLGC_WANTMESSAGE) break;
1981  
1982          switch(lpMsg->wParam)
1983          {
1984          case VK_TAB:
1985              if (!(dlgCode & DLGC_WANTTAB))
1986              {
1987                  SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
1988                  return TRUE;
1989              }
1990              break;
1991  
1992          case VK_RIGHT:
1993          case VK_DOWN:
1994          case VK_LEFT:
1995          case VK_UP:
1996              if (!(dlgCode & DLGC_WANTARROWS))
1997              {
1998                  BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
1999                  HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
2000                  SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2001                  return TRUE;
2002              }
2003              break;
2004  
2005          case VK_CANCEL:
2006          case VK_ESCAPE:
2007              SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2008              return TRUE;
2009  
2010          case VK_EXECUTE:
2011          case VK_RETURN:
2012              {
2013                  DWORD dw = SendMessageW( hDlg, DM_GETDEFID, 0, 0 );
2014                  if (HIWORD(dw) == DC_HASDEFID)
2015                  {
2016                      SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
2017                                      (LPARAM)GetDlgItem(hDlg, LOWORD(dw)));
2018                  }
2019                  else
2020                  {
2021                      SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2022  
2023                  }
2024              }
2025              return TRUE;
2026          }
2027          break;
2028  
2029      case WM_CHAR:
2030          dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2031          if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2032          if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2033          /* drop through */
2034  
2035      case WM_SYSCHAR:
2036          if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2037          {
2038              /* don't translate or dispatch */
2039              return TRUE;
2040          }
2041          break;
2042      }
2043  
2044      TranslateMessage( lpMsg );
2045      DispatchMessageW( lpMsg );
2046      return TRUE;
2047 }
2048
2049
2050 /*
2051  * @implemented
2052  */
2053 UINT
2054 STDCALL
2055 IsDlgButtonChecked(
2056   HWND hDlg,
2057   int nIDButton)
2058 {
2059   return (UINT)SendDlgItemMessageA( hDlg, nIDButton, BM_GETCHECK, 0, 0 );
2060 }
2061
2062
2063 /*
2064  * @implemented
2065  */
2066 WINBOOL
2067 STDCALL
2068 MapDialogRect(
2069   HWND hDlg,
2070   LPRECT lpRect)
2071 {
2072         DIALOGINFO * dlgInfo;
2073         if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
2074         lpRect->left   = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4);
2075         lpRect->right  = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4);
2076         lpRect->top    = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8);
2077         lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8);
2078         return TRUE;
2079 }
2080
2081
2082 /*
2083  * @implemented
2084  */
2085 LRESULT
2086 STDCALL
2087 SendDlgItemMessageA(
2088   HWND hDlg,
2089   int nIDDlgItem,
2090   UINT Msg,
2091   WPARAM wParam,
2092   LPARAM lParam)
2093 {
2094         HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2095         if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam );
2096         else return 0;
2097 }
2098
2099
2100 /*
2101  * @implemented
2102  */
2103 LRESULT
2104 STDCALL
2105 SendDlgItemMessageW(
2106   HWND hDlg,
2107   int nIDDlgItem,
2108   UINT Msg,
2109   WPARAM wParam,
2110   LPARAM lParam)
2111 {
2112         HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2113         if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam );
2114         else return 0;
2115 }
2116
2117
2118 /*
2119  * @implemented
2120  */
2121 WINBOOL
2122 STDCALL
2123 SetDlgItemInt(
2124   HWND hDlg,
2125   int nIDDlgItem,
2126   UINT uValue,
2127   WINBOOL bSigned)
2128 {
2129         char str[20];
2130
2131         if (bSigned) sprintf( str, "%d", (INT)uValue );
2132         else sprintf( str, "%u", uValue );
2133         SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str );
2134         return TRUE;
2135 }
2136
2137
2138 /*
2139  * @implemented
2140  */
2141 WINBOOL
2142 STDCALL
2143 SetDlgItemTextA(
2144   HWND hDlg,
2145   int nIDDlgItem,
2146   LPCSTR lpString)
2147 {
2148   return SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)lpString );
2149 }
2150
2151
2152 /*
2153  * @implemented
2154  */
2155 WINBOOL
2156 STDCALL
2157 SetDlgItemTextW(
2158   HWND hDlg,
2159   int nIDDlgItem,
2160   LPCWSTR lpString)
2161 {
2162   return SendDlgItemMessageW( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)lpString );
2163 }
2164
2165
2166 /*
2167  * @implemented
2168  */
2169 WINBOOL
2170 STDCALL
2171 CheckDlgButton(
2172   HWND hDlg,
2173   int nIDButton,
2174   UINT uCheck)
2175 {
2176         SendDlgItemMessageA( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 );
2177         return TRUE;
2178 }