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