Fixed window refcount handling in GetNextDlgGroupItem.
[wine] / windows / dialog.c
1 /*
2  * Dialog functions
3  *
4  * Copyright 1993, 1994, 1996 Alexandre Julliard
5  */
6
7 #include <ctype.h>
8 #include <errno.h>
9 #include <limits.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "winuser.h"
13 #include "wine/winuser16.h"
14 #include "wine/winbase16.h"
15 #include "dialog.h"
16 #include "drive.h"
17 #include "heap.h"
18 #include "win.h"
19 #include "ldt.h"
20 #include "user.h"
21 #include "winproc.h"
22 #include "message.h"
23 #include "sysmetrics.h"
24 #include "debug.h"
25
26 DEFAULT_DEBUG_CHANNEL(dialog)
27
28
29   /* Dialog control information */
30 typedef struct
31 {
32     DWORD      style;
33     DWORD      exStyle;
34     DWORD      helpId;
35     INT16      x;
36     INT16      y;
37     INT16      cx;
38     INT16      cy;
39     UINT     id;
40     LPCSTR     className;
41     LPCSTR     windowName;
42     LPVOID     data;
43 } DLG_CONTROL_INFO;
44
45   /* Dialog template */
46 typedef struct
47 {
48     DWORD      style;
49     DWORD      exStyle;
50     DWORD      helpId;
51     UINT16     nbItems;
52     INT16      x;
53     INT16      y;
54     INT16      cx;
55     INT16      cy;
56     LPCSTR     menuName;
57     LPCSTR     className;
58     LPCSTR     caption;
59     WORD       pointSize;
60     WORD       weight;
61     BOOL     italic;
62     LPCSTR     faceName;
63     BOOL     dialogEx;
64 } DLG_TEMPLATE;
65
66   /* Dialog base units */
67 static WORD xBaseUnit = 0, yBaseUnit = 0;
68
69
70 /***********************************************************************
71  *           DIALOG_Init
72  *
73  * Initialisation of the dialog manager.
74  */
75 BOOL DIALOG_Init(void)
76 {
77     TEXTMETRIC16 tm;
78     HDC16 hdc;
79     
80       /* Calculate the dialog base units */
81
82     if (!(hdc = CreateDC16( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
83     GetTextMetrics16( hdc, &tm );
84     DeleteDC( hdc );
85     xBaseUnit = tm.tmAveCharWidth;
86     yBaseUnit = tm.tmHeight;
87
88       /* Dialog units are based on a proportional system font */
89       /* so we adjust them a bit for a fixed font. */
90     if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH))
91         xBaseUnit = xBaseUnit * 5 / 4;
92
93     TRACE(dialog, "base units = %d,%d\n",
94                     xBaseUnit, yBaseUnit );
95     return TRUE;
96 }
97
98
99 /***********************************************************************
100  *           DIALOG_GetControl16
101  *
102  * Return the class and text of the control pointed to by ptr,
103  * fill the header structure and return a pointer to the next control.
104  */
105 static LPCSTR DIALOG_GetControl16( LPCSTR p, DLG_CONTROL_INFO *info )
106 {
107     static char buffer[10];
108     int int_id;
109
110     info->x       = GET_WORD(p);  p += sizeof(WORD);
111     info->y       = GET_WORD(p);  p += sizeof(WORD);
112     info->cx      = GET_WORD(p);  p += sizeof(WORD);
113     info->cy      = GET_WORD(p);  p += sizeof(WORD);
114     info->id      = GET_WORD(p);  p += sizeof(WORD);
115     info->style   = GET_DWORD(p); p += sizeof(DWORD);
116     info->exStyle = 0;
117
118     if (*p & 0x80)
119     {
120         switch((BYTE)*p)
121         {
122             case 0x80: strcpy( buffer, "BUTTON" ); break;
123             case 0x81: strcpy( buffer, "EDIT" ); break;
124             case 0x82: strcpy( buffer, "STATIC" ); break;
125             case 0x83: strcpy( buffer, "LISTBOX" ); break;
126             case 0x84: strcpy( buffer, "SCROLLBAR" ); break;
127             case 0x85: strcpy( buffer, "COMBOBOX" ); break;
128             default:   buffer[0] = '\0'; break;
129         }
130         info->className = buffer;
131         p++;
132     }
133     else 
134     {
135         info->className = p;
136         p += strlen(p) + 1;
137     }
138
139     int_id = ((BYTE)*p == 0xff);
140     if (int_id)
141     {
142           /* Integer id, not documented (?). Only works for SS_ICON controls */
143         info->windowName = (LPCSTR)(UINT)GET_WORD(p+1);
144         p += 3;
145     }
146     else
147     {
148         info->windowName = p;
149         p += strlen(p) + 1;
150     }
151
152     info->data = (LPVOID)(*p ? p + 1 : NULL);  /* FIXME: should be a segptr */
153     p += *p + 1;
154
155     if(int_id)
156       TRACE(dialog,"   %s %04x %d, %d, %d, %d, %d, %08lx, %08lx\n", 
157                       info->className,  LOWORD(info->windowName),
158                       info->id, info->x, info->y, info->cx, info->cy,
159                       info->style, (DWORD)info->data);
160     else
161       TRACE(dialog,"   %s '%s' %d, %d, %d, %d, %d, %08lx, %08lx\n", 
162                       info->className,  info->windowName,
163                       info->id, info->x, info->y, info->cx, info->cy,
164                       info->style, (DWORD)info->data);
165
166     return p;
167 }
168
169
170 /***********************************************************************
171  *           DIALOG_GetControl32
172  *
173  * Return the class and text of the control pointed to by ptr,
174  * fill the header structure and return a pointer to the next control.
175  */
176 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
177                                         BOOL dialogEx )
178 {
179     if (dialogEx)
180     {
181         info->helpId  = GET_DWORD(p); p += 2;
182         info->exStyle = GET_DWORD(p); p += 2;
183         info->style   = GET_DWORD(p); p += 2;
184     }
185     else
186     {
187         info->helpId  = 0;
188         info->style   = GET_DWORD(p); p += 2;
189         info->exStyle = GET_DWORD(p); p += 2;
190     }
191     info->x       = GET_WORD(p); p++;
192     info->y       = GET_WORD(p); p++;
193     info->cx      = GET_WORD(p); p++;
194     info->cy      = GET_WORD(p); p++;
195
196     if (dialogEx)
197     {
198         /* id is a DWORD for DIALOGEX */
199         info->id = GET_DWORD(p);
200         p += 2;
201     }
202     else
203     {
204         info->id = GET_WORD(p);
205         p++;
206     }
207
208     if (GET_WORD(p) == 0xffff)
209     {
210         static const WCHAR class_names[6][10] =
211         {
212             { 'B','u','t','t','o','n', },             /* 0x80 */
213             { 'E','d','i','t', },                     /* 0x81 */
214             { 'S','t','a','t','i','c', },             /* 0x82 */
215             { 'L','i','s','t','B','o','x', },         /* 0x83 */
216             { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
217             { 'C','o','m','b','o','B','o','x', }      /* 0x85 */
218         };
219         WORD id = GET_WORD(p+1);
220         if ((id >= 0x80) && (id <= 0x85))
221             info->className = (LPCSTR)class_names[id - 0x80];
222         else
223         {
224             info->className = NULL;
225             ERR( dialog, "Unknown built-in class id %04x\n", id );
226         }
227         p += 2;
228     }
229     else
230     {
231         info->className = (LPCSTR)p;
232         p += lstrlenW( (LPCWSTR)p ) + 1;
233     }
234
235     if (GET_WORD(p) == 0xffff)  /* Is it an integer id? */
236     {
237         info->windowName = (LPCSTR)(UINT)GET_WORD(p + 1);
238         p += 2;
239     }
240     else
241     {
242         info->windowName = (LPCSTR)p;
243         p += lstrlenW( (LPCWSTR)p ) + 1;
244     }
245
246     TRACE(dialog,"    %s %s %d, %d, %d, %d, %d, %08lx, %08lx, %08lx\n", 
247           debugstr_w( (LPCWSTR)info->className ),
248           debugres_w( (LPCWSTR)info->windowName ),
249           info->id, info->x, info->y, info->cx, info->cy,
250           info->style, info->exStyle, info->helpId );
251
252     if (GET_WORD(p))
253     {
254         if (TRACE_ON(dialog))
255         {
256             WORD i, count = GET_WORD(p) / sizeof(WORD);
257             TRACE(dialog, "  BEGIN\n");
258             TRACE(dialog, "    ");
259             for (i = 0; i < count; i++) DUMP( "%04x,", GET_WORD(p+i+1) );
260             DUMP("\n");
261             TRACE(dialog, "  END\n" );
262         }
263         info->data = (LPVOID)(p + 1);
264         p += GET_WORD(p) / sizeof(WORD);
265     }
266     else info->data = NULL;
267     p++;
268
269     /* Next control is on dword boundary */
270     return (const WORD *)((((int)p) + 3) & ~3);
271 }
272
273
274 /***********************************************************************
275  *           DIALOG_CreateControls
276  *
277  * Create the control windows for a dialog.
278  */
279 static BOOL DIALOG_CreateControls( WND *pWnd, LPCSTR template,
280                                      const DLG_TEMPLATE *dlgTemplate,
281                                      HINSTANCE hInst, BOOL win32 )
282 {
283     DIALOGINFO *dlgInfo = (DIALOGINFO *)pWnd->wExtra;
284     DLG_CONTROL_INFO info;
285     HWND hwndCtrl, hwndDefButton = 0;
286     INT items = dlgTemplate->nbItems;
287
288     TRACE(dialog, " BEGIN\n" );
289     while (items--)
290     {
291         if (!win32)
292         {
293             HINSTANCE16 instance;
294             template = DIALOG_GetControl16( template, &info );
295             if (HIWORD(info.className) && !strcmp( info.className, "EDIT") &&
296                 ((pWnd->dwStyle & DS_LOCALEDIT) != DS_LOCALEDIT))
297             {
298                 if (!dlgInfo->hDialogHeap)
299                 {
300                     dlgInfo->hDialogHeap = GlobalAlloc16(GMEM_FIXED, 0x10000);
301                     if (!dlgInfo->hDialogHeap)
302                     {
303                         ERR(dialog, "Insufficient memory to create heap for edit control\n" );
304                         continue;
305                     }
306                     LocalInit16(dlgInfo->hDialogHeap, 0, 0xffff);
307                 }
308                 instance = dlgInfo->hDialogHeap;
309             }
310             else instance = (HINSTANCE16)hInst;
311
312             hwndCtrl = CreateWindowEx16( info.exStyle | WS_EX_NOPARENTNOTIFY,
313                                          info.className, info.windowName,
314                                          info.style | WS_CHILD,
315                                          info.x * dlgInfo->xBaseUnit / 4,
316                                          info.y * dlgInfo->yBaseUnit / 8,
317                                          info.cx * dlgInfo->xBaseUnit / 4,
318                                          info.cy * dlgInfo->yBaseUnit / 8,
319                                          pWnd->hwndSelf, (HMENU16)info.id,
320                                          instance, info.data );
321         }
322         else
323         {
324             template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info,
325                                                     dlgTemplate->dialogEx );
326             hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
327                                           (LPCWSTR)info.className,
328                                           (LPCWSTR)info.windowName,
329                                           info.style | WS_CHILD,
330                                           info.x * dlgInfo->xBaseUnit / 4,
331                                           info.y * dlgInfo->yBaseUnit / 8,
332                                           info.cx * dlgInfo->xBaseUnit / 4,
333                                           info.cy * dlgInfo->yBaseUnit / 8,
334                                           pWnd->hwndSelf, (HMENU)info.id,
335                                           hInst, info.data );
336         }
337         if (!hwndCtrl) return FALSE;
338
339             /* Send initialisation messages to the control */
340         if (dlgInfo->hUserFont) SendMessageA( hwndCtrl, WM_SETFONT,
341                                              (WPARAM)dlgInfo->hUserFont, 0 );
342         if (SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
343         {
344               /* If there's already a default push-button, set it back */
345               /* to normal and use this one instead. */
346             if (hwndDefButton)
347                 SendMessageA( hwndDefButton, BM_SETSTYLE,
348                                 BS_PUSHBUTTON,FALSE );
349             hwndDefButton = hwndCtrl;
350             dlgInfo->idResult = GetWindowWord( hwndCtrl, GWW_ID );
351         }
352     }    
353     TRACE(dialog, " END\n" );
354     return TRUE;
355 }
356
357
358 /***********************************************************************
359  *           DIALOG_ParseTemplate16
360  *
361  * Fill a DLG_TEMPLATE structure from the dialog template, and return
362  * a pointer to the first control.
363  */
364 static LPCSTR DIALOG_ParseTemplate16( LPCSTR p, DLG_TEMPLATE * result )
365 {
366     result->style   = GET_DWORD(p); p += sizeof(DWORD);
367     result->exStyle = 0;
368     result->nbItems = *p++;
369     result->x       = GET_WORD(p);  p += sizeof(WORD);
370     result->y       = GET_WORD(p);  p += sizeof(WORD);
371     result->cx      = GET_WORD(p);  p += sizeof(WORD);
372     result->cy      = GET_WORD(p);  p += sizeof(WORD);
373     TRACE(dialog, "DIALOG %d, %d, %d, %d\n",
374                     result->x, result->y, result->cx, result->cy );
375     TRACE(dialog, " STYLE %08lx\n", result->style );
376
377     /* Get the menu name */
378
379     switch( (BYTE)*p )
380     {
381     case 0:
382         result->menuName = 0;
383         p++;
384         break;
385     case 0xff:
386         result->menuName = (LPCSTR)(UINT)GET_WORD( p + 1 );
387         p += 3;
388         TRACE(dialog, " MENU %04x\n", LOWORD(result->menuName) );
389         break;
390     default:
391         result->menuName = p;
392         TRACE(dialog, " MENU '%s'\n", p );
393         p += strlen(p) + 1;
394         break;
395     }
396
397     /* Get the class name */
398
399     if (*p)
400     {
401         result->className = p;
402         TRACE(dialog, " CLASS '%s'\n", result->className );
403     }
404     else result->className = DIALOG_CLASS_ATOM;
405     p += strlen(p) + 1;
406
407     /* Get the window caption */
408
409     result->caption = p;
410     p += strlen(p) + 1;
411     TRACE(dialog, " CAPTION '%s'\n", result->caption );
412
413     /* Get the font name */
414
415     if (result->style & DS_SETFONT)
416     {
417         result->pointSize = GET_WORD(p);
418         p += sizeof(WORD);
419         result->faceName = p;
420         p += strlen(p) + 1;
421         TRACE(dialog, " FONT %d,'%s'\n",
422                         result->pointSize, result->faceName );
423     }
424     return p;
425 }
426
427
428 /***********************************************************************
429  *           DIALOG_ParseTemplate32
430  *
431  * Fill a DLG_TEMPLATE structure from the dialog template, and return
432  * a pointer to the first control.
433  */
434 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
435 {
436     const WORD *p = (const WORD *)template;
437
438     result->style = GET_DWORD(p); p += 2;
439     if (result->style == 0xffff0001)  /* DIALOGEX resource */
440     {
441         result->dialogEx = TRUE;
442         result->helpId   = GET_DWORD(p); p += 2;
443         result->exStyle  = GET_DWORD(p); p += 2;
444         result->style    = GET_DWORD(p); p += 2;
445     }
446     else
447     {
448         result->dialogEx = FALSE;
449         result->helpId   = 0;
450         result->exStyle  = GET_DWORD(p); p += 2;
451     }
452     result->nbItems = GET_WORD(p); p++;
453     result->x       = GET_WORD(p); p++;
454     result->y       = GET_WORD(p); p++;
455     result->cx      = GET_WORD(p); p++;
456     result->cy      = GET_WORD(p); p++;
457     TRACE( dialog, "DIALOG%s %d, %d, %d, %d, %ld\n",
458            result->dialogEx ? "EX" : "", result->x, result->y,
459            result->cx, result->cy, result->helpId );
460     TRACE( dialog, " STYLE 0x%08lx\n", result->style );
461     TRACE( dialog, " EXSTYLE 0x%08lx\n", result->exStyle );
462
463     /* Get the menu name */
464
465     switch(GET_WORD(p))
466     {
467     case 0x0000:
468         result->menuName = NULL;
469         p++;
470         break;
471     case 0xffff:
472         result->menuName = (LPCSTR)(UINT)GET_WORD( p + 1 );
473         p += 2;
474         TRACE(dialog, " MENU %04x\n", LOWORD(result->menuName) );
475         break;
476     default:
477         result->menuName = (LPCSTR)p;
478         TRACE(dialog, " MENU %s\n", debugstr_w( (LPCWSTR)p ));
479         p += lstrlenW( (LPCWSTR)p ) + 1;
480         break;
481     }
482
483     /* Get the class name */
484
485     switch(GET_WORD(p))
486     {
487     case 0x0000:
488         result->className = DIALOG_CLASS_ATOM;
489         p++;
490         break;
491     case 0xffff:
492         result->className = (LPCSTR)(UINT)GET_WORD( p + 1 );
493         p += 2;
494         TRACE(dialog, " CLASS %04x\n", LOWORD(result->className) );
495         break;
496     default:
497         result->className = (LPCSTR)p;
498         TRACE(dialog, " CLASS %s\n", debugstr_w( (LPCWSTR)p ));
499         p += lstrlenW( (LPCWSTR)p ) + 1;
500         break;
501     }
502
503     /* Get the window caption */
504
505     result->caption = (LPCSTR)p;
506     p += lstrlenW( (LPCWSTR)p ) + 1;
507     TRACE(dialog, " CAPTION %s\n", debugstr_w( (LPCWSTR)result->caption ) );
508
509     /* Get the font name */
510
511     if (result->style & DS_SETFONT)
512     {
513         result->pointSize = GET_WORD(p);
514         p++;
515         if (result->dialogEx)
516         {
517             result->weight = GET_WORD(p); p++;
518             result->italic = LOBYTE(GET_WORD(p)); p++;
519         }
520         else
521         {
522             result->weight = FW_DONTCARE;
523             result->italic = FALSE;
524         }
525         result->faceName = (LPCSTR)p;
526         p += lstrlenW( (LPCWSTR)p ) + 1;
527         TRACE(dialog, " FONT %d, %s, %d, %s\n",
528               result->pointSize, debugstr_w( (LPCWSTR)result->faceName ),
529               result->weight, result->italic ? "TRUE" : "FALSE" );
530     }
531
532     /* First control is on dword boundary */
533     return (LPCSTR)((((int)p) + 3) & ~3);
534 }
535
536
537 /***********************************************************************
538  *           DIALOG_CreateIndirect
539  */
540 HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCSTR dlgTemplate,
541                               BOOL win32Template, HWND owner,
542                               DLGPROC16 dlgProc, LPARAM param,
543                               WINDOWPROCTYPE procType )
544 {
545     HMENU16 hMenu = 0;
546     HFONT16 hFont = 0;
547     HWND hwnd;
548     RECT rect;
549     WND * wndPtr;
550     DLG_TEMPLATE template;
551     DIALOGINFO * dlgInfo;
552     WORD xUnit = xBaseUnit;
553     WORD yUnit = yBaseUnit;
554
555       /* Parse dialog template */
556
557     if (!dlgTemplate) return 0;
558     if (win32Template)
559         dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
560     else
561         dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
562
563       /* Load menu */
564
565     if (template.menuName)
566     {
567         if (!win32Template)
568         {
569             LPSTR str = SEGPTR_STRDUP( template.menuName );
570             hMenu = LoadMenu16( hInst, SEGPTR_GET(str) );
571             SEGPTR_FREE( str );
572         }
573         else hMenu = LoadMenuW( hInst, (LPCWSTR)template.menuName );
574     }
575
576       /* Create custom font if needed */
577
578     if (template.style & DS_SETFONT)
579     {
580           /* The font height must be negative as it is a point size */
581           /* (see CreateFont() documentation in the Windows SDK).   */
582
583         if (win32Template)
584             hFont = CreateFontW( -template.pointSize, 0, 0, 0,
585                                    template.weight, template.italic, FALSE,
586                                    FALSE, DEFAULT_CHARSET, 0, 0, PROOF_QUALITY,
587                                    FF_DONTCARE, (LPCWSTR)template.faceName );
588         else
589             hFont = CreateFont16( -template.pointSize, 0, 0, 0, FW_DONTCARE,
590                                   FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
591                                   PROOF_QUALITY, FF_DONTCARE,
592                                   template.faceName );
593         if (hFont)
594         {
595             TEXTMETRIC16 tm;
596             HFONT16 oldFont;
597
598             HDC hdc = GetDC(0);
599             oldFont = SelectObject( hdc, hFont );
600             GetTextMetrics16( hdc, &tm );
601             SelectObject( hdc, oldFont );
602             ReleaseDC( 0, hdc );
603             xUnit = tm.tmAveCharWidth;
604             yUnit = tm.tmHeight;
605             if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH))
606                 xBaseUnit = xBaseUnit * 5 / 4;  /* See DIALOG_Init() */
607         }
608     }
609     
610     /* Create dialog main window */
611
612     rect.left = rect.top = 0;
613     rect.right = template.cx * xUnit / 4;
614     rect.bottom = template.cy * yUnit / 8;
615     if (template.style & DS_MODALFRAME)
616         template.exStyle |= WS_EX_DLGMODALFRAME;
617     AdjustWindowRectEx( &rect, template.style, 
618                           hMenu ? TRUE : FALSE , template.exStyle );
619     rect.right -= rect.left;
620     rect.bottom -= rect.top;
621
622     if ((INT16)template.x == CW_USEDEFAULT16)
623     {
624         rect.left = rect.top = (procType == WIN_PROC_16) ? CW_USEDEFAULT16
625                                                          : CW_USEDEFAULT;
626     }
627     else
628     {
629         if (template.style & DS_CENTER)
630         {
631             rect.left = (SYSMETRICS_CXSCREEN - rect.right) / 2;
632             rect.top = (SYSMETRICS_CYSCREEN - rect.bottom) / 2;
633         }
634         else
635         {
636             rect.left += template.x * xUnit / 4;
637             rect.top += template.y * yUnit / 8;
638         }
639         if ( !(template.style & WS_CHILD) )
640         {
641             INT16 dX, dY;
642
643             if( !(template.style & DS_ABSALIGN) )
644                 ClientToScreen( owner, (POINT *)&rect );
645             
646             /* try to fit it into the desktop */
647
648             if( (dX = rect.left + rect.right + SYSMETRICS_CXDLGFRAME 
649                  - SYSMETRICS_CXSCREEN) > 0 ) rect.left -= dX;
650             if( (dY = rect.top + rect.bottom + SYSMETRICS_CYDLGFRAME
651                  - SYSMETRICS_CYSCREEN) > 0 ) rect.top -= dY;
652             if( rect.left < 0 ) rect.left = 0;
653             if( rect.top < 0 ) rect.top = 0;
654         }
655     }
656
657     if (procType == WIN_PROC_16)
658         hwnd = CreateWindowEx16(template.exStyle, template.className,
659                                 template.caption, template.style & ~WS_VISIBLE,
660                                 rect.left, rect.top, rect.right, rect.bottom,
661                                 owner, hMenu, hInst, NULL );
662     else
663         hwnd = CreateWindowExW(template.exStyle, (LPCWSTR)template.className,
664                                  (LPCWSTR)template.caption,
665                                  template.style & ~WS_VISIBLE,
666                                  rect.left, rect.top, rect.right, rect.bottom,
667                                  owner, hMenu, hInst, NULL );
668         
669     if (!hwnd)
670     {
671         if (hFont) DeleteObject( hFont );
672         if (hMenu) DestroyMenu( hMenu );
673         return 0;
674     }
675     wndPtr = WIN_FindWndPtr( hwnd );
676     wndPtr->flags |= WIN_ISDIALOG;
677     wndPtr->helpContext = template.helpId;
678
679       /* Initialise dialog extra data */
680
681     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
682     WINPROC_SetProc( &dlgInfo->dlgProc, (WNDPROC16)dlgProc, procType, WIN_PROC_WINDOW );
683     dlgInfo->hUserFont = hFont;
684     dlgInfo->hMenu     = hMenu;
685     dlgInfo->xBaseUnit = xUnit;
686     dlgInfo->yBaseUnit = yUnit;
687     dlgInfo->msgResult = 0;
688     dlgInfo->idResult  = 0;
689     dlgInfo->flags     = 0;
690     dlgInfo->hDialogHeap = 0;
691
692     if (dlgInfo->hUserFont)
693         SendMessageA( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
694
695     /* Create controls */
696
697     if (DIALOG_CreateControls( wndPtr, dlgTemplate, &template,
698                                hInst, win32Template ))
699     {
700        /* Send initialisation messages and set focus */
701
702         dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
703
704         if (SendMessageA( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
705             SetFocus( dlgInfo->hwndFocus );
706
707         if (template.style & WS_VISIBLE && !(wndPtr->dwStyle & WS_VISIBLE)) 
708         {
709            ShowWindow( hwnd, SW_SHOWNORMAL );   /* SW_SHOW doesn't always work */
710            UpdateWindow( hwnd );
711         }
712         WIN_ReleaseWndPtr(wndPtr);
713         return hwnd;
714     }
715     WIN_ReleaseWndPtr(wndPtr);
716     if( IsWindow(hwnd) ) DestroyWindow( hwnd );
717     return 0;
718 }
719
720
721 /***********************************************************************
722  *           CreateDialog16   (USER.89)
723  */
724 HWND16 WINAPI CreateDialog16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
725                               HWND16 owner, DLGPROC16 dlgProc )
726 {
727     return CreateDialogParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
728 }
729
730
731 /***********************************************************************
732  *           CreateDialogParam16   (USER.241)
733  */
734 HWND16 WINAPI CreateDialogParam16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
735                                    HWND16 owner, DLGPROC16 dlgProc,
736                                    LPARAM param )
737 {
738     HWND16 hwnd = 0;
739     HRSRC16 hRsrc;
740     HGLOBAL16 hmem;
741     LPCVOID data;
742
743     TRACE(dialog, "%04x,%08lx,%04x,%08lx,%ld\n",
744                    hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
745
746     if (!(hRsrc = FindResource16( hInst, dlgTemplate, RT_DIALOG16 ))) return 0;
747     if (!(hmem = LoadResource16( hInst, hRsrc ))) return 0;
748     if (!(data = LockResource16( hmem ))) hwnd = 0;
749     else hwnd = CreateDialogIndirectParam16( hInst, data, owner,
750                                              dlgProc, param );
751     FreeResource16( hmem );
752     return hwnd;
753 }
754
755 /***********************************************************************
756  *           CreateDialogParam32A   (USER32.73)
757  */
758 HWND WINAPI CreateDialogParamA( HINSTANCE hInst, LPCSTR name,
759                                     HWND owner, DLGPROC dlgProc,
760                                     LPARAM param )
761 {
762     if (HIWORD(name))
763     {
764         LPWSTR str = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
765         HWND hwnd = CreateDialogParamW( hInst, str, owner, dlgProc, param);
766         HeapFree( GetProcessHeap(), 0, str );
767         return hwnd;
768     }
769     return CreateDialogParamW( hInst, (LPCWSTR)name, owner, dlgProc, param );
770 }
771
772
773 /***********************************************************************
774  *           CreateDialogParam32W   (USER32.74)
775  */
776 HWND WINAPI CreateDialogParamW( HINSTANCE hInst, LPCWSTR name,
777                                     HWND owner, DLGPROC dlgProc,
778                                     LPARAM param )
779 {
780     HANDLE hrsrc = FindResourceW( hInst, name, RT_DIALOGW );
781     if (!hrsrc) return 0;
782     return CreateDialogIndirectParamW( hInst,
783                                          (LPVOID)LoadResource(hInst, hrsrc),
784                                          owner, dlgProc, param );
785 }
786
787
788 /***********************************************************************
789  *           CreateDialogIndirect16   (USER.219)
790  */
791 HWND16 WINAPI CreateDialogIndirect16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
792                                       HWND16 owner, DLGPROC16 dlgProc )
793 {
794     return CreateDialogIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0);
795 }
796
797
798 /***********************************************************************
799  *           CreateDialogIndirectParam16   (USER.242)
800  */
801 HWND16 WINAPI CreateDialogIndirectParam16( HINSTANCE16 hInst,
802                                            LPCVOID dlgTemplate,
803                                            HWND16 owner, DLGPROC16 dlgProc,
804                                            LPARAM param )
805 {
806     return DIALOG_CreateIndirect( hInst, dlgTemplate, FALSE, owner,
807                                   dlgProc, param, WIN_PROC_16 );
808 }
809
810
811 /***********************************************************************
812  *           CreateDialogIndirectParam32A   (USER32.69)
813  */
814 HWND WINAPI CreateDialogIndirectParamA( HINSTANCE hInst,
815                                             LPCVOID dlgTemplate,
816                                             HWND owner, DLGPROC dlgProc,
817                                             LPARAM param )
818 {
819     return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
820                                   (DLGPROC16)dlgProc, param, WIN_PROC_32A );
821 }
822
823 /***********************************************************************
824  *           CreateDialogIndirectParam32AorW   (USER32.71)
825  */
826 HWND WINAPI CreateDialogIndirectParamAorW( HINSTANCE hInst,
827                                             LPCVOID dlgTemplate,
828                                             HWND owner, DLGPROC dlgProc,
829                                             LPARAM param )
830 {   FIXME(dialog,"assume WIN_PROC_32W\n");
831     return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
832                                   (DLGPROC16)dlgProc, param, WIN_PROC_32W );
833 }
834
835 /***********************************************************************
836  *           CreateDialogIndirectParam32W   (USER32.72)
837  */
838 HWND WINAPI CreateDialogIndirectParamW( HINSTANCE hInst,
839                                             LPCVOID dlgTemplate,
840                                             HWND owner, DLGPROC dlgProc,
841                                             LPARAM param )
842 {
843     return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
844                                   (DLGPROC16)dlgProc, param, WIN_PROC_32W );
845 }
846
847
848 /***********************************************************************
849  *           DIALOG_DoDialogBox
850  */
851 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
852 {
853     WND * wndPtr;
854     DIALOGINFO * dlgInfo;
855     MSG msg;
856     INT retval;
857
858       /* Owner must be a top-level window */
859     owner = WIN_GetTopParent( owner );
860     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
861     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
862
863     if (!dlgInfo->flags & DF_END) /* was EndDialog called in WM_INITDIALOG ? */
864     {
865         EnableWindow( owner, FALSE );
866         ShowWindow( hwnd, SW_SHOW );
867         while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX, 
868                                       PM_REMOVE, !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
869         {
870             if (!IsDialogMessageA( hwnd, &msg))
871             {
872                 TranslateMessage( &msg );
873                 DispatchMessageA( &msg );
874             }
875             if (dlgInfo->flags & DF_END) break;
876         }
877         EnableWindow( owner, TRUE );
878     }
879     retval = dlgInfo->idResult; 
880     WIN_ReleaseWndPtr(wndPtr);
881     DestroyWindow( hwnd );
882     return retval;
883 }
884
885
886 /***********************************************************************
887  *           DialogBox16   (USER.87)
888  */
889 INT16 WINAPI DialogBox16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
890                           HWND16 owner, DLGPROC16 dlgProc )
891 {
892     return DialogBoxParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
893 }
894
895
896 /***********************************************************************
897  *           DialogBoxParam16   (USER.239)
898  */
899 INT16 WINAPI DialogBoxParam16( HINSTANCE16 hInst, SEGPTR template,
900                                HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
901 {
902     HWND16 hwnd = CreateDialogParam16( hInst, template, owner, dlgProc, param);
903     if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
904     return -1;
905 }
906
907
908 /***********************************************************************
909  *           DialogBoxParam32A   (USER32.139)
910  */
911 INT WINAPI DialogBoxParamA( HINSTANCE hInst, LPCSTR name,
912                                 HWND owner, DLGPROC dlgProc, LPARAM param )
913 {
914     HWND hwnd = CreateDialogParamA( hInst, name, owner, dlgProc, param );
915     if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
916     return -1;
917 }
918
919
920 /***********************************************************************
921  *           DialogBoxParam32W   (USER32.140)
922  */
923 INT WINAPI DialogBoxParamW( HINSTANCE hInst, LPCWSTR name,
924                                 HWND owner, DLGPROC dlgProc, LPARAM param )
925 {
926     HWND hwnd = CreateDialogParamW( hInst, name, owner, dlgProc, param );
927     if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
928     return -1;
929 }
930
931
932 /***********************************************************************
933  *           DialogBoxIndirect16   (USER.218)
934  */
935 INT16 WINAPI DialogBoxIndirect16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
936                                   HWND16 owner, DLGPROC16 dlgProc )
937 {
938     return DialogBoxIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
939 }
940
941
942 /***********************************************************************
943  *           DialogBoxIndirectParam16   (USER.240)
944  */
945 INT16 WINAPI DialogBoxIndirectParam16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
946                                        HWND16 owner, DLGPROC16 dlgProc,
947                                        LPARAM param )
948 {
949     HWND16 hwnd;
950     LPCVOID ptr;
951
952     if (!(ptr = GlobalLock16( dlgTemplate ))) return -1;
953     hwnd = CreateDialogIndirectParam16( hInst, ptr, owner, dlgProc, param );
954     GlobalUnlock16( dlgTemplate );
955     if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
956     return -1;
957 }
958
959
960 /***********************************************************************
961  *           DialogBoxIndirectParam32A   (USER32.136)
962  */
963 INT WINAPI DialogBoxIndirectParamA(HINSTANCE hInstance, LPCVOID template,
964                                        HWND owner, DLGPROC dlgProc,
965                                        LPARAM param )
966 {
967     HWND hwnd = CreateDialogIndirectParamA( hInstance, template,
968                                                 owner, dlgProc, param );
969     if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
970     return -1;
971 }
972
973
974 /***********************************************************************
975  *           DialogBoxIndirectParam32W   (USER32.138)
976  */
977 INT WINAPI DialogBoxIndirectParamW(HINSTANCE hInstance, LPCVOID template,
978                                        HWND owner, DLGPROC dlgProc,
979                                        LPARAM param )
980 {
981     HWND hwnd = CreateDialogIndirectParamW( hInstance, template,
982                                                 owner, dlgProc, param );
983     if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
984     return -1;
985 }
986
987
988 /***********************************************************************
989  *           EndDialog16   (USER.88)
990  */
991 BOOL16 WINAPI EndDialog16( HWND16 hwnd, INT16 retval )
992 {
993     return EndDialog( hwnd, retval );
994 }
995
996
997 /***********************************************************************
998  *           EndDialog32   (USER32.173)
999  */
1000 BOOL WINAPI EndDialog( HWND hwnd, INT retval )
1001 {
1002     WND * wndPtr = WIN_FindWndPtr( hwnd );
1003     DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1004
1005     TRACE(dialog, "%04x %d\n", hwnd, retval );
1006
1007     if( dlgInfo )
1008     {
1009         dlgInfo->idResult = retval;
1010         dlgInfo->flags |= DF_END;
1011     }
1012
1013     /* Paint Shop Pro 4.14 calls EndDialog for a CreateDialog* dialog,
1014      * which isn't "normal". Only DialogBox* dialogs may be EndDialog()ed.
1015      * Just hide the window as windows does it...
1016      */
1017     ShowWindow(hwnd, SW_HIDE);
1018
1019     WIN_ReleaseWndPtr(wndPtr);
1020     return TRUE;
1021 }
1022
1023
1024 /***********************************************************************
1025  *           DIALOG_IsAccelerator
1026  */
1027 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM vKey )
1028 {
1029     HWND hwndControl = hwnd;
1030     HWND hwndNext;
1031     WND *wndPtr;
1032     BOOL RetVal = FALSE;
1033     INT dlgCode;
1034
1035     if (vKey == VK_SPACE)
1036     {
1037         dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
1038         if (dlgCode & DLGC_BUTTON)
1039         {
1040             SendMessageA( hwndControl, WM_LBUTTONDOWN, 0, 0);
1041             SendMessageA( hwndControl, WM_LBUTTONUP, 0, 0);
1042             RetVal = TRUE;
1043         }
1044     }
1045     else
1046     {
1047         do
1048         {
1049             wndPtr = WIN_FindWndPtr( hwndControl );
1050             if ( (wndPtr != NULL) && 
1051                  ((wndPtr->dwStyle & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) )
1052             {
1053                 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
1054                 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) && 
1055                      (wndPtr->text!=NULL))
1056                 {
1057                     /* find the accelerator key */
1058                     LPSTR p = wndPtr->text - 2;
1059                     do
1060                     {
1061                         p = strchr( p + 2, '&' );
1062                     }
1063                     while (p != NULL && p[1] == '&');
1064
1065                     /* and check if it's the one we're looking for */
1066                     if (p != NULL && toupper( p[1] ) == toupper( vKey ) )
1067                     {
1068                         if ((dlgCode & DLGC_STATIC) || 
1069                             (wndPtr->dwStyle & 0x0f) == BS_GROUPBOX )
1070                         {
1071                             /* set focus to the control */
1072                             SendMessageA( hwndDlg, WM_NEXTDLGCTL,
1073                                     hwndControl, 1);
1074                             /* and bump it on to next */
1075                             SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
1076                         }
1077                         else if (dlgCode & 
1078                             (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON))
1079                         {
1080                             /* send command message as from the control */
1081                             SendMessageA( hwndDlg, WM_COMMAND, 
1082                                 MAKEWPARAM( LOWORD(wndPtr->wIDmenu), 
1083                                     BN_CLICKED ),
1084                                 (LPARAM)hwndControl );
1085                         }
1086                         else
1087                         {
1088                             /* click the control */
1089                             SendMessageA( hwndControl, WM_LBUTTONDOWN, 0, 0);
1090                             SendMessageA( hwndControl, WM_LBUTTONUP, 0, 0);
1091                         }
1092                         RetVal = TRUE;
1093                         break;
1094                     }
1095                 }
1096                 hwndNext = GetWindow( hwndControl, GW_CHILD );
1097             }
1098             else
1099             {
1100                 hwndNext = 0;
1101             }
1102             WIN_ReleaseWndPtr(wndPtr);
1103             if (!hwndNext)
1104             {
1105                 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
1106             }
1107             while (!hwndNext)
1108             {
1109                 hwndControl = GetParent( hwndControl );
1110                 if (hwndControl == hwndDlg)
1111                 {
1112                     hwndNext = GetWindow( hwndDlg, GW_CHILD );
1113                 }
1114                 else
1115                 {
1116                     hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
1117                 }
1118             }
1119             hwndControl = hwndNext;
1120         }
1121         while (hwndControl != hwnd);
1122     }
1123     return RetVal;
1124 }
1125  
1126
1127 /***********************************************************************
1128  *           DIALOG_IsDialogMessage
1129  */
1130 static BOOL DIALOG_IsDialogMessage( HWND hwnd, HWND hwndDlg,
1131                                       UINT message, WPARAM wParam,
1132                                       LPARAM lParam, BOOL *translate,
1133                                       BOOL *dispatch, INT dlgCode )
1134 {
1135     *translate = *dispatch = FALSE;
1136
1137     if (message == WM_PAINT)
1138     {
1139         /* Apparently, we have to handle this one as well */
1140         *dispatch = TRUE;
1141         return TRUE;
1142     }
1143
1144       /* Only the key messages get special processing */
1145     if ((message != WM_KEYDOWN) &&
1146         (message != WM_SYSCHAR) &&
1147         (message != WM_CHAR))
1148         return FALSE;
1149
1150     if (dlgCode & DLGC_WANTMESSAGE)
1151     {
1152         *translate = *dispatch = TRUE;
1153         return TRUE;
1154     }
1155
1156     switch(message)
1157     {
1158     case WM_KEYDOWN:
1159         switch(wParam)
1160         {
1161         case VK_TAB:
1162             if (!(dlgCode & DLGC_WANTTAB))
1163             {
1164                 SendMessageA( hwndDlg, WM_NEXTDLGCTL,
1165                                 (GetKeyState(VK_SHIFT) & 0x8000), 0 );
1166                 return TRUE;
1167             }
1168             break;
1169             
1170         case VK_RIGHT:
1171         case VK_DOWN:
1172         case VK_LEFT:
1173         case VK_UP:
1174             if (!(dlgCode & DLGC_WANTARROWS))
1175             {
1176                 BOOL fPrevious = (wParam == VK_LEFT || wParam == VK_UP);
1177                 HWND hwndNext = 
1178                     GetNextDlgGroupItem (hwndDlg, GetFocus(), fPrevious );
1179                 SendMessageA( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
1180                 return TRUE;
1181             }
1182             break;
1183
1184         case VK_ESCAPE:
1185             SendMessageA( hwndDlg, WM_COMMAND, IDCANCEL,
1186                             (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
1187             return TRUE;
1188
1189         case VK_RETURN:
1190             {
1191                 DWORD dw = SendMessage16( hwndDlg, DM_GETDEFID, 0, 0 );
1192                 if (HIWORD(dw) == DC_HASDEFID)
1193                 {
1194                     SendMessageA( hwndDlg, WM_COMMAND, 
1195                                     MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
1196                                     (LPARAM)GetDlgItem(hwndDlg, LOWORD(dw)));
1197                 }
1198                 else
1199                 {
1200                     SendMessageA( hwndDlg, WM_COMMAND, IDOK,
1201                                     (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
1202     
1203                 }
1204             }
1205             return TRUE;
1206         }
1207         *translate = TRUE;
1208         break; /* case WM_KEYDOWN */
1209
1210     case WM_CHAR:
1211         if (dlgCode & DLGC_WANTCHARS) break;
1212         /* drop through */
1213
1214     case WM_SYSCHAR:
1215         if (DIALOG_IsAccelerator( hwnd, hwndDlg, wParam ))
1216         {
1217             /* don't translate or dispatch */
1218             return TRUE;
1219         }
1220         break;
1221     }
1222
1223     /* If we get here, the message has not been treated specially */
1224     /* and can be sent to its destination window. */
1225     *dispatch = TRUE;
1226     return TRUE;
1227 }
1228
1229
1230 /***********************************************************************
1231  *           IsDialogMessage16   (USER.90)
1232  */
1233 BOOL16 WINAPI WIN16_IsDialogMessage16( HWND16 hwndDlg, SEGPTR msg16 )
1234 {
1235     LPMSG16 msg = PTR_SEG_TO_LIN(msg16);
1236     BOOL ret, translate, dispatch;
1237     INT dlgCode;
1238
1239     if ((hwndDlg != msg->hwnd) && !IsChild16( hwndDlg, msg->hwnd ))
1240         return FALSE;
1241
1242     dlgCode = SendMessage16( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg16);
1243     ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1244                                   msg->wParam, msg->lParam,
1245                                   &translate, &dispatch, dlgCode );
1246     if (translate) TranslateMessage16( msg );
1247     if (dispatch) DispatchMessage16( msg );
1248     return ret;
1249 }
1250
1251
1252 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, LPMSG16 msg )
1253 {
1254     LPMSG16 msg16 = SEGPTR_NEW(MSG16);
1255     BOOL ret;
1256
1257     *msg16 = *msg;
1258     ret = WIN16_IsDialogMessage16( hwndDlg, SEGPTR_GET(msg16) );
1259     SEGPTR_FREE(msg16);
1260     return ret;
1261 }
1262
1263 /***********************************************************************
1264  *           IsDialogMessage32A   (USER32.342)
1265  */
1266 BOOL WINAPI IsDialogMessageA( HWND hwndDlg, LPMSG msg )
1267 {
1268     BOOL ret, translate, dispatch;
1269     INT dlgCode;
1270
1271     if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
1272         return FALSE;
1273
1274     dlgCode = SendMessageA( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
1275     ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1276                                   msg->wParam, msg->lParam,
1277                                   &translate, &dispatch, dlgCode );
1278     if (translate) TranslateMessage( msg );
1279     if (dispatch) DispatchMessageA( msg );
1280     return ret;
1281 }
1282
1283
1284 /***********************************************************************
1285  *           IsDialogMessage32W   (USER32.343)
1286  */
1287 BOOL WINAPI IsDialogMessageW( HWND hwndDlg, LPMSG msg )
1288 {
1289     BOOL ret, translate, dispatch;
1290     INT dlgCode;
1291
1292     if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
1293         return FALSE;
1294
1295     dlgCode = SendMessageW( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
1296     ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1297                                   msg->wParam, msg->lParam,
1298                                   &translate, &dispatch, dlgCode );
1299     if (translate) TranslateMessage( msg );
1300     if (dispatch) DispatchMessageW( msg );
1301     return ret;
1302 }
1303
1304
1305 /****************************************************************
1306  *         GetDlgCtrlID16   (USER.277)
1307  */
1308 INT16 WINAPI GetDlgCtrlID16( HWND16 hwnd )
1309 {
1310     WND *wndPtr = WIN_FindWndPtr(hwnd);
1311     INT16 retvalue;
1312     
1313     if (!wndPtr) return 0;
1314
1315     retvalue = wndPtr->wIDmenu;
1316     WIN_ReleaseWndPtr(wndPtr);
1317     return retvalue;
1318 }
1319  
1320
1321 /****************************************************************
1322  *         GetDlgCtrlID32   (USER32.234)
1323  */
1324 INT WINAPI GetDlgCtrlID( HWND hwnd )
1325 {
1326     INT retvalue;
1327     WND *wndPtr = WIN_FindWndPtr(hwnd);
1328     if (!wndPtr) return 0;
1329     retvalue = wndPtr->wIDmenu;
1330     WIN_ReleaseWndPtr(wndPtr);
1331     return retvalue;
1332 }
1333  
1334
1335 /***********************************************************************
1336  *           GetDlgItem16   (USER.91)
1337  */
1338 HWND16 WINAPI GetDlgItem16( HWND16 hwndDlg, INT16 id )
1339 {
1340     WND *pWnd;
1341
1342     if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
1343     for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1344         if (pWnd->wIDmenu == (UINT16)id)
1345         {
1346             HWND16 retvalue = pWnd->hwndSelf;
1347             WIN_ReleaseWndPtr(pWnd);
1348             return retvalue;
1349         }
1350     return 0;
1351 }
1352
1353
1354 /***********************************************************************
1355  *           GetDlgItem32   (USER32.235)
1356  */
1357 HWND WINAPI GetDlgItem( HWND hwndDlg, INT id )
1358 {
1359     WND *pWnd;
1360
1361     if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
1362     for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
1363         if (pWnd->wIDmenu == (UINT16)id)
1364         {
1365             HWND retvalue = pWnd->hwndSelf;
1366             WIN_ReleaseWndPtr(pWnd);
1367             return retvalue;
1368         }
1369     return 0;
1370 }
1371
1372
1373 /*******************************************************************
1374  *           SendDlgItemMessage16   (USER.101)
1375  */
1376 LRESULT WINAPI SendDlgItemMessage16( HWND16 hwnd, INT16 id, UINT16 msg,
1377                                      WPARAM16 wParam, LPARAM lParam )
1378 {
1379     HWND16 hwndCtrl = GetDlgItem16( hwnd, id );
1380     if (hwndCtrl) return SendMessage16( hwndCtrl, msg, wParam, lParam );
1381     else return 0;
1382 }
1383
1384
1385 /*******************************************************************
1386  *           SendDlgItemMessage32A   (USER32.452)
1387  */
1388 LRESULT WINAPI SendDlgItemMessageA( HWND hwnd, INT id, UINT msg,
1389                                       WPARAM wParam, LPARAM lParam )
1390 {
1391     HWND hwndCtrl = GetDlgItem( hwnd, id );
1392     if (hwndCtrl) return SendMessageA( hwndCtrl, msg, wParam, lParam );
1393     else return 0;
1394 }
1395
1396
1397 /*******************************************************************
1398  *           SendDlgItemMessage32W   (USER32.453)
1399  */
1400 LRESULT WINAPI SendDlgItemMessageW( HWND hwnd, INT id, UINT msg,
1401                                       WPARAM wParam, LPARAM lParam )
1402 {
1403     HWND hwndCtrl = GetDlgItem( hwnd, id );
1404     if (hwndCtrl) return SendMessageW( hwndCtrl, msg, wParam, lParam );
1405     else return 0;
1406 }
1407
1408
1409 /*******************************************************************
1410  *           SetDlgItemText16   (USER.92)
1411  */
1412 void WINAPI SetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR lpString )
1413 {
1414     SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1415 }
1416
1417
1418 /*******************************************************************
1419  *           SetDlgItemText32A   (USER32.478)
1420  */
1421 BOOL WINAPI SetDlgItemTextA( HWND hwnd, INT id, LPCSTR lpString )
1422 {
1423     return SendDlgItemMessageA( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1424 }
1425
1426
1427 /*******************************************************************
1428  *           SetDlgItemText32W   (USER32.479)
1429  */
1430 BOOL WINAPI SetDlgItemTextW( HWND hwnd, INT id, LPCWSTR lpString )
1431 {
1432     return SendDlgItemMessageW( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1433 }
1434
1435
1436 /***********************************************************************
1437  *           GetDlgItemText16   (USER.93)
1438  */
1439 INT16 WINAPI GetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR str, UINT16 len )
1440 {
1441     return (INT16)SendDlgItemMessage16( hwnd, id, WM_GETTEXT,
1442                                         len, (LPARAM)str );
1443 }
1444
1445
1446 /***********************************************************************
1447  *           GetDlgItemText32A   (USER32.237)
1448  */
1449 INT WINAPI GetDlgItemTextA( HWND hwnd, INT id, LPSTR str, UINT len )
1450 {
1451     return (INT)SendDlgItemMessageA( hwnd, id, WM_GETTEXT,
1452                                          len, (LPARAM)str );
1453 }
1454
1455
1456 /***********************************************************************
1457  *           GetDlgItemText32W   (USER32.238)
1458  */
1459 INT WINAPI GetDlgItemTextW( HWND hwnd, INT id, LPWSTR str, UINT len )
1460 {
1461     return (INT)SendDlgItemMessageW( hwnd, id, WM_GETTEXT,
1462                                          len, (LPARAM)str );
1463 }
1464
1465
1466 /*******************************************************************
1467  *           SetDlgItemInt16   (USER.94)
1468  */
1469 void WINAPI SetDlgItemInt16( HWND16 hwnd, INT16 id, UINT16 value, BOOL16 fSigned )
1470 {
1471     SetDlgItemInt( hwnd, (UINT)(UINT16)id, value, fSigned );
1472 }
1473
1474
1475 /*******************************************************************
1476  *           SetDlgItemInt32   (USER32.477)
1477  */
1478 BOOL WINAPI SetDlgItemInt( HWND hwnd, INT id, UINT value,
1479                              BOOL fSigned )
1480 {
1481     char str[20];
1482
1483     if (fSigned) sprintf( str, "%d", (INT)value );
1484     else sprintf( str, "%u", value );
1485     SendDlgItemMessageA( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
1486     return TRUE;
1487 }
1488
1489
1490 /***********************************************************************
1491  *           GetDlgItemInt16   (USER.95)
1492  */
1493 UINT16 WINAPI GetDlgItemInt16( HWND16 hwnd, INT16 id, BOOL16 *translated,
1494                                BOOL16 fSigned )
1495 {
1496     UINT result;
1497     BOOL ok;
1498
1499     if (translated) *translated = FALSE;
1500     result = GetDlgItemInt( hwnd, (UINT)(UINT16)id, &ok, fSigned );
1501     if (!ok) return 0;
1502     if (fSigned)
1503     {
1504         if (((INT)result < -32767) || ((INT)result > 32767)) return 0;
1505     }
1506     else
1507     {
1508         if (result > 65535) return 0;
1509     }
1510     if (translated) *translated = TRUE;
1511     return (UINT16)result;
1512 }
1513
1514
1515 /***********************************************************************
1516  *           GetDlgItemInt32   (USER32.236)
1517  */
1518 UINT WINAPI GetDlgItemInt( HWND hwnd, INT id, BOOL *translated,
1519                                BOOL fSigned )
1520 {
1521     char str[30];
1522     char * endptr;
1523     long result = 0;
1524     
1525     if (translated) *translated = FALSE;
1526     if (!SendDlgItemMessageA(hwnd, id, WM_GETTEXT, sizeof(str), (LPARAM)str))
1527         return 0;
1528     if (fSigned)
1529     {
1530         result = strtol( str, &endptr, 10 );
1531         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
1532             return 0;
1533         if (((result == LONG_MIN) || (result == LONG_MAX)) && (errno==ERANGE))
1534             return 0;
1535     }
1536     else
1537     {
1538         result = strtoul( str, &endptr, 10 );
1539         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
1540             return 0;
1541         if ((result == ULONG_MAX) && (errno == ERANGE)) return 0;
1542     }
1543     if (translated) *translated = TRUE;
1544     return (UINT)result;
1545 }
1546
1547
1548 /***********************************************************************
1549  *           CheckDlgButton16   (USER.97)
1550  */
1551 BOOL16 WINAPI CheckDlgButton16( HWND16 hwnd, INT16 id, UINT16 check )
1552 {
1553     SendDlgItemMessageA( hwnd, id, BM_SETCHECK, check, 0 );
1554     return TRUE;
1555 }
1556
1557
1558 /***********************************************************************
1559  *           CheckDlgButton32   (USER32.45)
1560  */
1561 BOOL WINAPI CheckDlgButton( HWND hwnd, INT id, UINT check )
1562 {
1563     SendDlgItemMessageA( hwnd, id, BM_SETCHECK, check, 0 );
1564     return TRUE;
1565 }
1566
1567
1568 /***********************************************************************
1569  *           IsDlgButtonChecked16   (USER.98)
1570  */
1571 UINT16 WINAPI IsDlgButtonChecked16( HWND16 hwnd, UINT16 id )
1572 {
1573     return (UINT16)SendDlgItemMessageA( hwnd, id, BM_GETCHECK, 0, 0 );
1574 }
1575
1576
1577 /***********************************************************************
1578  *           IsDlgButtonChecked32   (USER32.344)
1579  */
1580 UINT WINAPI IsDlgButtonChecked( HWND hwnd, UINT id )
1581 {
1582     return (UINT)SendDlgItemMessageA( hwnd, id, BM_GETCHECK, 0, 0 );
1583 }
1584
1585
1586 /***********************************************************************
1587  *           CheckRadioButton16   (USER.96)
1588  */
1589 BOOL16 WINAPI CheckRadioButton16( HWND16 hwndDlg, UINT16 firstID,
1590                                   UINT16 lastID, UINT16 checkID )
1591 {
1592     return CheckRadioButton( hwndDlg, firstID, lastID, checkID );
1593 }
1594
1595
1596 /***********************************************************************
1597  *           CheckRadioButton32   (USER32.48)
1598  */
1599 BOOL WINAPI CheckRadioButton( HWND hwndDlg, UINT firstID,
1600                                   UINT lastID, UINT checkID )
1601 {
1602     WND *pWnd = WIN_FindWndPtr( hwndDlg );
1603
1604     if (!pWnd) return FALSE;
1605
1606     for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
1607         if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID))
1608         {
1609             break;
1610         }
1611
1612     if (!pWnd) return FALSE;
1613
1614     if (pWnd->wIDmenu == lastID)
1615         lastID = firstID;  /* Buttons are in reverse order */
1616     while (pWnd)
1617     {
1618         SendMessageA( pWnd->hwndSelf, BM_SETCHECK,
1619                         (pWnd->wIDmenu == checkID), 0 );
1620         if (pWnd->wIDmenu == lastID)
1621         {
1622                 WIN_ReleaseWndPtr(pWnd);
1623                 break;
1624         }
1625         WIN_UpdateWndPtr(&pWnd,pWnd->next);
1626     }
1627     return TRUE;
1628 }
1629
1630
1631 /***********************************************************************
1632  *           GetDialogBaseUnits   (USER.243) (USER32.233)
1633  */
1634 DWORD WINAPI GetDialogBaseUnits(void)
1635 {
1636     return MAKELONG( xBaseUnit, yBaseUnit );
1637 }
1638
1639
1640 /***********************************************************************
1641  *           MapDialogRect16   (USER.103)
1642  */
1643 void WINAPI MapDialogRect16( HWND16 hwnd, LPRECT16 rect )
1644 {
1645     DIALOGINFO * dlgInfo;
1646     WND * wndPtr = WIN_FindWndPtr( hwnd );
1647     if (!wndPtr) return;
1648     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1649     rect->left   = (rect->left * dlgInfo->xBaseUnit) / 4;
1650     rect->right  = (rect->right * dlgInfo->xBaseUnit) / 4;
1651     rect->top    = (rect->top * dlgInfo->yBaseUnit) / 8;
1652     rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1653     WIN_ReleaseWndPtr(wndPtr);
1654 }
1655
1656
1657 /***********************************************************************
1658  *           MapDialogRect32   (USER32.382)
1659  */
1660 BOOL WINAPI MapDialogRect( HWND hwnd, LPRECT rect )
1661 {
1662     DIALOGINFO * dlgInfo;
1663     WND * wndPtr = WIN_FindWndPtr( hwnd );
1664     if (!wndPtr) return FALSE;
1665     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1666     rect->left   = (rect->left * dlgInfo->xBaseUnit) / 4;
1667     rect->right  = (rect->right * dlgInfo->xBaseUnit) / 4;
1668     rect->top    = (rect->top * dlgInfo->yBaseUnit) / 8;
1669     rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1670     WIN_ReleaseWndPtr(wndPtr);
1671     return TRUE;
1672 }
1673
1674
1675 /***********************************************************************
1676  *           GetNextDlgGroupItem16   (USER.227)
1677  */
1678 HWND16 WINAPI GetNextDlgGroupItem16( HWND16 hwndDlg, HWND16 hwndCtrl,
1679                                      BOOL16 fPrevious )
1680 {
1681     return (HWND16)GetNextDlgGroupItem( hwndDlg, hwndCtrl, fPrevious );
1682 }
1683
1684
1685 /***********************************************************************
1686  *           GetNextDlgGroupItem32   (USER32.275)
1687  */
1688 HWND WINAPI GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl,
1689                                      BOOL fPrevious )
1690 {
1691     WND *pWnd = NULL,
1692         *pWndLast = NULL,
1693         *pWndCtrl = NULL,
1694         *pWndDlg = NULL;
1695     HWND retvalue;
1696
1697     if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1698     if (hwndCtrl)
1699     {
1700         if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl )))
1701     {
1702             retvalue = 0;
1703             goto END;
1704         }
1705         /* Make sure hwndCtrl is a top-level child */
1706         while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1707             WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->parent);
1708         if (pWndCtrl->parent != pWndDlg)
1709         {
1710             retvalue = 0;
1711             goto END;
1712         }
1713     }
1714     else
1715     {
1716         /* No ctrl specified -> start from the beginning */
1717         if (!(pWndCtrl = WIN_LockWndPtr(pWndDlg->child)))
1718         {
1719             retvalue = 0;
1720             goto END;
1721         }
1722         if (fPrevious)
1723             while (pWndCtrl->next) WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->next);
1724     }
1725
1726     pWndLast = WIN_LockWndPtr(pWndCtrl);
1727     pWnd = WIN_LockWndPtr(pWndCtrl->next);
1728
1729     while (1)
1730     {
1731         if (!pWnd || (pWnd->dwStyle & WS_GROUP))
1732         {
1733             /* Wrap-around to the beginning of the group */
1734             WND *pWndTemp;
1735
1736             WIN_UpdateWndPtr( &pWnd, pWndDlg->child );
1737             for ( pWndTemp = WIN_LockWndPtr( pWnd ); 
1738                   pWndTemp;
1739                   WIN_UpdateWndPtr( &pWndTemp, pWndTemp->next) )
1740             {
1741                 if (pWndTemp->dwStyle & WS_GROUP) WIN_UpdateWndPtr( &pWnd, pWndTemp );
1742                 if (pWndTemp == pWndCtrl) break;
1743             }
1744             WIN_ReleaseWndPtr( pWndTemp );
1745         }
1746         if (pWnd == pWndCtrl) break;
1747         if ((pWnd->dwStyle & WS_VISIBLE) && !(pWnd->dwStyle & WS_DISABLED))
1748         {
1749             WIN_UpdateWndPtr(&pWndLast,pWnd);
1750             if (!fPrevious) break;
1751         }
1752         WIN_UpdateWndPtr(&pWnd,pWnd->next);
1753     }
1754     retvalue = pWndLast->hwndSelf;
1755
1756     WIN_ReleaseWndPtr(pWndLast);
1757     WIN_ReleaseWndPtr(pWnd);
1758 END:
1759     WIN_ReleaseWndPtr(pWndCtrl);
1760     WIN_ReleaseWndPtr(pWndDlg);
1761
1762     return retvalue;
1763 }
1764
1765
1766 /***********************************************************************
1767  *           GetNextDlgTabItem16   (USER.228)
1768  */
1769 HWND16 WINAPI GetNextDlgTabItem16( HWND16 hwndDlg, HWND16 hwndCtrl,
1770                                    BOOL16 fPrevious )
1771 {
1772     return (HWND16)GetNextDlgTabItem( hwndDlg, hwndCtrl, fPrevious );
1773 }
1774
1775
1776 /***********************************************************************
1777  *           GetNextDlgTabItem32   (USER32.276)
1778  */
1779 HWND WINAPI GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl,
1780                                    BOOL fPrevious )
1781 {
1782     WND *pWnd = NULL,
1783         *pWndLast = NULL,
1784         *pWndCtrl = NULL,
1785         *pWndDlg = NULL;
1786     HWND retvalue;
1787
1788     if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1789     if (hwndCtrl)
1790     {
1791         if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl )))
1792     {
1793             retvalue = 0;
1794             goto END;
1795         }
1796         /* Make sure hwndCtrl is a top-level child */
1797         while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1798             WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->parent);
1799         if (pWndCtrl->parent != pWndDlg)
1800         {
1801             retvalue = 0;
1802             goto END;
1803     }
1804     }
1805     else
1806     {
1807         /* No ctrl specified -> start from the beginning */
1808         if (!(pWndCtrl = WIN_LockWndPtr(pWndDlg->child)))
1809         {
1810             retvalue = 0;
1811             goto END;
1812         }
1813         
1814         if (!fPrevious)
1815             while (pWndCtrl->next) WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->next);
1816     }
1817
1818     pWndLast = WIN_LockWndPtr(pWndCtrl);
1819     pWnd = WIN_LockWndPtr(pWndCtrl->next);
1820     while (1)
1821     {
1822         if (!pWnd) pWnd = WIN_LockWndPtr(pWndDlg->child);
1823         if (pWnd == pWndCtrl) break;
1824         if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE) &&
1825             !(pWnd->dwStyle & WS_DISABLED))
1826         {
1827             WIN_UpdateWndPtr(&pWndLast,pWnd);
1828             if (!fPrevious) break;
1829         }
1830         WIN_UpdateWndPtr(&pWnd,pWnd->next);
1831     }
1832     retvalue = pWndLast->hwndSelf;
1833     
1834     WIN_ReleaseWndPtr(pWndLast);
1835     WIN_ReleaseWndPtr(pWnd);
1836 END:
1837     WIN_ReleaseWndPtr(pWndCtrl);
1838     WIN_ReleaseWndPtr(pWndDlg);
1839
1840     return retvalue;
1841
1842 }
1843
1844
1845 /**********************************************************************
1846  *           DIALOG_DlgDirSelect
1847  *
1848  * Helper function for DlgDirSelect*
1849  */
1850 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPSTR str, INT len,
1851                                    INT id, BOOL win32, BOOL unicode,
1852                                    BOOL combo )
1853 {
1854     char *buffer, *ptr;
1855     INT item, size;
1856     BOOL ret;
1857     HWND listbox = GetDlgItem( hwnd, id );
1858
1859     TRACE(dialog, "%04x '%s' %d\n", hwnd, str, id );
1860     if (!listbox) return FALSE;
1861     if (win32)
1862     {
1863         item = SendMessageA(listbox, combo ? CB_GETCURSEL
1864                                              : LB_GETCURSEL, 0, 0 );
1865         if (item == LB_ERR) return FALSE;
1866         size = SendMessageA(listbox, combo ? CB_GETLBTEXTLEN
1867                                              : LB_GETTEXTLEN, 0, 0 );
1868         if (size == LB_ERR) return FALSE;
1869     }
1870     else
1871     {
1872         item = SendMessageA(listbox, combo ? CB_GETCURSEL16
1873                                              : LB_GETCURSEL16, 0, 0 );
1874         if (item == LB_ERR) return FALSE;
1875         size = SendMessageA(listbox, combo ? CB_GETLBTEXTLEN16
1876                                              : LB_GETTEXTLEN16, 0, 0 );
1877         if (size == LB_ERR) return FALSE;
1878     }
1879
1880     if (!(buffer = SEGPTR_ALLOC( size+1 ))) return FALSE;
1881
1882     if (win32)
1883         SendMessageA( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT,
1884                         item, (LPARAM)buffer );
1885     else
1886         SendMessage16( listbox, combo ? CB_GETLBTEXT16 : LB_GETTEXT16,
1887                        item, (LPARAM)SEGPTR_GET(buffer) );
1888
1889     if ((ret = (buffer[0] == '[')))  /* drive or directory */
1890     {
1891         if (buffer[1] == '-')  /* drive */
1892         {
1893             buffer[3] = ':';
1894             buffer[4] = 0;
1895             ptr = buffer + 2;
1896         }
1897         else
1898         {
1899             buffer[strlen(buffer)-1] = '\\';
1900             ptr = buffer + 1;
1901         }
1902     }
1903     else ptr = buffer;
1904
1905     if (unicode) lstrcpynAtoW( (LPWSTR)str, ptr, len );
1906     else lstrcpynA( str, ptr, len );
1907     SEGPTR_FREE( buffer );
1908     TRACE(dialog, "Returning %d '%s'\n", ret, str );
1909     return ret;
1910 }
1911
1912
1913 /**********************************************************************
1914  *          DIALOG_DlgDirList
1915  *
1916  * Helper function for DlgDirList*
1917  */
1918 static INT DIALOG_DlgDirList( HWND hDlg, LPSTR spec, INT idLBox,
1919                                 INT idStatic, UINT attrib, BOOL combo )
1920 {
1921     int drive;
1922     HWND hwnd;
1923     LPSTR orig_spec = spec;
1924
1925 #define SENDMSG(msg,wparam,lparam) \
1926     ((attrib & DDL_POSTMSGS) ? PostMessageA( hwnd, msg, wparam, lparam ) \
1927                              : SendMessageA( hwnd, msg, wparam, lparam ))
1928
1929     TRACE(dialog, "%04x '%s' %d %d %04x\n",
1930                     hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
1931
1932     if (spec && spec[0] && (spec[1] == ':'))
1933     {
1934         drive = toupper( spec[0] ) - 'A';
1935         spec += 2;
1936         if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
1937     }
1938     else drive = DRIVE_GetCurrentDrive();
1939
1940     /* If the path exists and is a directory, chdir to it */
1941     if (!spec || !spec[0] || DRIVE_Chdir( drive, spec )) spec = "*.*";
1942     else
1943     {
1944         char *p, *p2;
1945         p = spec;
1946         if ((p2 = strrchr( p, '\\' ))) p = p2;
1947         if ((p2 = strrchr( p, '/' ))) p = p2;
1948         if (p != spec)
1949         {
1950             char sep = *p;
1951             *p = 0;
1952             if (!DRIVE_Chdir( drive, spec ))
1953             {
1954                 *p = sep;  /* Restore the original spec */
1955                 return FALSE;
1956             }
1957             spec = p + 1;
1958         }
1959     }
1960
1961     TRACE(dialog, "path=%c:\\%s mask=%s\n",
1962                     'A' + drive, DRIVE_GetDosCwd(drive), spec );
1963
1964     if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1965     {
1966         SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
1967         if (attrib & DDL_DIRECTORY)
1968         {
1969             if (!(attrib & DDL_EXCLUSIVE))
1970             {
1971                 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1972                              attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1973                              (LPARAM)spec ) == LB_ERR)
1974                     return FALSE;
1975             }
1976             if (SENDMSG( combo ? CB_DIR : LB_DIR,
1977                        (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1978                          (LPARAM)"*.*" ) == LB_ERR)
1979                 return FALSE;
1980         }
1981         else
1982         {
1983             if (SENDMSG( combo ? CB_DIR : LB_DIR, attrib,
1984                          (LPARAM)spec ) == LB_ERR)
1985                 return FALSE;
1986         }
1987     }
1988
1989     if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
1990     {
1991         char temp[512];
1992         int drive = DRIVE_GetCurrentDrive();
1993         strcpy( temp, "A:\\" );
1994         temp[0] += drive;
1995         lstrcpynA( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
1996         CharLowerA( temp );
1997         /* Can't use PostMessage() here, because the string is on the stack */
1998         SetDlgItemTextA( hDlg, idStatic, temp );
1999     }
2000
2001     if (orig_spec && (spec != orig_spec))
2002     {
2003         /* Update the original file spec */
2004         char *p = spec;
2005         while ((*orig_spec++ = *p++));
2006     }
2007
2008     return TRUE;
2009 #undef SENDMSG
2010 }
2011
2012
2013 /**********************************************************************
2014  *          DIALOG_DlgDirListW
2015  *
2016  * Helper function for DlgDirList*32W
2017  */
2018 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
2019                                  INT idStatic, UINT attrib, BOOL combo )
2020 {
2021     if (spec)
2022     {
2023         LPSTR specA = HEAP_strdupWtoA( GetProcessHeap(), 0, spec );
2024         INT ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic,
2025                                        attrib, combo );
2026         lstrcpyAtoW( spec, specA );
2027         HeapFree( GetProcessHeap(), 0, specA );
2028         return ret;
2029     }
2030     return DIALOG_DlgDirList( hDlg, NULL, idLBox, idStatic, attrib, combo );
2031 }
2032
2033
2034 /**********************************************************************
2035  *          DlgDirSelect    (USER.99)
2036  */
2037 BOOL16 WINAPI DlgDirSelect16( HWND16 hwnd, LPSTR str, INT16 id )
2038 {
2039     return DlgDirSelectEx16( hwnd, str, 128, id );
2040 }
2041
2042
2043 /**********************************************************************
2044  *          DlgDirSelectComboBox    (USER.194)
2045  */
2046 BOOL16 WINAPI DlgDirSelectComboBox16( HWND16 hwnd, LPSTR str, INT16 id )
2047 {
2048     return DlgDirSelectComboBoxEx16( hwnd, str, 128, id );
2049 }
2050
2051
2052 /**********************************************************************
2053  *           DlgDirSelectEx16    (USER.422)
2054  */
2055 BOOL16 WINAPI DlgDirSelectEx16( HWND16 hwnd, LPSTR str, INT16 len, INT16 id )
2056 {
2057     return DIALOG_DlgDirSelect( hwnd, str, len, id, FALSE, FALSE, FALSE );
2058 }
2059
2060
2061 /**********************************************************************
2062  *           DlgDirSelectEx32A    (USER32.149)
2063  */
2064 BOOL WINAPI DlgDirSelectExA( HWND hwnd, LPSTR str, INT len, INT id )
2065 {
2066     return DIALOG_DlgDirSelect( hwnd, str, len, id, TRUE, FALSE, FALSE );
2067 }
2068
2069
2070 /**********************************************************************
2071  *           DlgDirSelectEx32W    (USER32.150)
2072  */
2073 BOOL WINAPI DlgDirSelectExW( HWND hwnd, LPWSTR str, INT len, INT id )
2074 {
2075     return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE, FALSE );
2076 }
2077
2078
2079 /**********************************************************************
2080  *           DlgDirSelectComboBoxEx16    (USER.423)
2081  */
2082 BOOL16 WINAPI DlgDirSelectComboBoxEx16( HWND16 hwnd, LPSTR str, INT16 len,
2083                                         INT16 id )
2084 {
2085     return DIALOG_DlgDirSelect( hwnd, str, len, id, FALSE, FALSE, TRUE );
2086 }
2087
2088
2089 /**********************************************************************
2090  *           DlgDirSelectComboBoxEx32A    (USER32.147)
2091  */
2092 BOOL WINAPI DlgDirSelectComboBoxExA( HWND hwnd, LPSTR str, INT len,
2093                                          INT id )
2094 {
2095     return DIALOG_DlgDirSelect( hwnd, str, len, id, TRUE, FALSE, TRUE );
2096 }
2097
2098
2099 /**********************************************************************
2100  *           DlgDirSelectComboBoxEx32W    (USER32.148)
2101  */
2102 BOOL WINAPI DlgDirSelectComboBoxExW( HWND hwnd, LPWSTR str, INT len,
2103                                          INT id)
2104 {
2105     return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE, TRUE );
2106 }
2107
2108
2109 /**********************************************************************
2110  *          DlgDirList16    (USER.100)
2111  */
2112 INT16 WINAPI DlgDirList16( HWND16 hDlg, LPSTR spec, INT16 idLBox,
2113                            INT16 idStatic, UINT16 attrib )
2114 {
2115     return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
2116 }
2117
2118
2119 /**********************************************************************
2120  *          DlgDirList32A    (USER32.143)
2121  */
2122 INT WINAPI DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox,
2123                             INT idStatic, UINT attrib )
2124 {
2125     return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
2126 }
2127
2128
2129 /**********************************************************************
2130  *          DlgDirList32W    (USER32.146)
2131  */
2132 INT WINAPI DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
2133                             INT idStatic, UINT attrib )
2134 {
2135     return DIALOG_DlgDirListW( hDlg, spec, idLBox, idStatic, attrib, FALSE );
2136 }
2137
2138
2139 /**********************************************************************
2140  *          DlgDirListComboBox16    (USER.195)
2141  */
2142 INT16 WINAPI DlgDirListComboBox16( HWND16 hDlg, LPSTR spec, INT16 idCBox,
2143                                    INT16 idStatic, UINT16 attrib )
2144 {
2145     return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
2146 }
2147
2148
2149 /**********************************************************************
2150  *          DlgDirListComboBox32A    (USER32.144)
2151  */
2152 INT WINAPI DlgDirListComboBoxA( HWND hDlg, LPSTR spec, INT idCBox,
2153                                     INT idStatic, UINT attrib )
2154 {
2155     return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
2156 }
2157
2158
2159 /**********************************************************************
2160  *          DlgDirListComboBox32W    (USER32.145)
2161  */
2162 INT WINAPI DlgDirListComboBoxW( HWND hDlg, LPWSTR spec, INT idCBox,
2163                                     INT idStatic, UINT attrib )
2164 {
2165     return DIALOG_DlgDirListW( hDlg, spec, idCBox, idStatic, attrib, TRUE );
2166 }