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