Remove included color.h.
[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     HWND32 hwndNext;
1014     WND *wndPtr;
1015     BOOL32 RetVal = FALSE;
1016     INT32 dlgCode;
1017
1018     if (vKey == VK_SPACE)
1019     {
1020         dlgCode = SendMessage32A( hwndControl, WM_GETDLGCODE, 0, 0 );
1021         if (dlgCode & DLGC_BUTTON)
1022         {
1023             SendMessage32A( hwndControl, WM_LBUTTONDOWN, 0, 0);
1024             SendMessage32A( hwndControl, WM_LBUTTONUP, 0, 0);
1025             RetVal = TRUE;
1026         }
1027     }
1028     else
1029     {
1030         do
1031         {
1032             wndPtr = WIN_FindWndPtr( hwndControl );
1033             if (wndPtr != NULL && wndPtr->text != NULL && 
1034                     (wndPtr->dwStyle & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
1035             {
1036                 dlgCode = SendMessage32A( hwndControl, WM_GETDLGCODE, 0, 0 );
1037                 if (dlgCode & (DLGC_BUTTON | DLGC_STATIC))
1038                 {
1039                     /* find the accelerator key */
1040                     LPSTR p = wndPtr->text - 2;
1041                     do
1042                     {
1043                         p = strchr( p + 2, '&' );
1044                     }
1045                     while (p != NULL && p[1] == '&');
1046
1047                     /* and check if it's the one we're looking for */
1048                     if (p != NULL && toupper( p[1] ) == toupper( vKey ) )
1049                     {
1050                         if ((dlgCode & DLGC_STATIC) || 
1051                             (wndPtr->dwStyle & 0x0f) == BS_GROUPBOX )
1052                         {
1053                             /* set focus to the control */
1054                             SendMessage32A( hwndDlg, WM_NEXTDLGCTL,
1055                                     hwndControl, 1);
1056                             /* and bump it on to next */
1057                             SendMessage32A( hwndDlg, WM_NEXTDLGCTL, 0, 0);
1058                         }
1059                         else if (dlgCode & 
1060                             (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON))
1061                         {
1062                             /* send command message as from the control */
1063                             SendMessage32A( hwndDlg, WM_COMMAND, 
1064                                 MAKEWPARAM( LOWORD(wndPtr->wIDmenu), 
1065                                     BN_CLICKED ),
1066                                 (LPARAM)hwndControl );
1067                         }
1068                         else
1069                         {
1070                             /* click the control */
1071                             SendMessage32A( hwndControl, WM_LBUTTONDOWN, 0, 0);
1072                             SendMessage32A( hwndControl, WM_LBUTTONUP, 0, 0);
1073                         }
1074                         RetVal = TRUE;
1075                         break;
1076                     }
1077                 }
1078             }
1079             hwndNext = GetWindow32( hwndControl, GW_CHILD );
1080             if (!hwndNext)
1081             {
1082                 hwndNext = GetWindow32( hwndControl, GW_HWNDNEXT );
1083             }
1084             while (!hwndNext)
1085             {
1086                 hwndControl = GetParent32( hwndControl );
1087                 if (hwndControl == hwndDlg)
1088                 {
1089                     hwndNext = GetWindow32( hwndDlg, GW_CHILD );
1090                 }
1091                 else
1092                 {
1093                     hwndNext = GetWindow32( hwndControl, GW_HWNDNEXT );
1094                 }
1095             }
1096             hwndControl = hwndNext;
1097         }
1098         while (hwndControl != hwnd);
1099     }
1100     return RetVal;
1101 }
1102  
1103
1104 /***********************************************************************
1105  *           DIALOG_IsDialogMessage
1106  */
1107 static BOOL32 DIALOG_IsDialogMessage( HWND32 hwnd, HWND32 hwndDlg,
1108                                       UINT32 message, WPARAM32 wParam,
1109                                       LPARAM lParam, BOOL32 *translate,
1110                                       BOOL32 *dispatch, INT32 dlgCode )
1111 {
1112     *translate = *dispatch = FALSE;
1113
1114     if (message == WM_PAINT)
1115     {
1116         /* Apparently, we have to handle this one as well */
1117         *dispatch = TRUE;
1118         return TRUE;
1119     }
1120
1121       /* Only the key messages get special processing */
1122     if ((message != WM_KEYDOWN) &&
1123         (message != WM_SYSCHAR) &&
1124         (message != WM_CHAR))
1125         return FALSE;
1126
1127     if (dlgCode & DLGC_WANTMESSAGE)
1128     {
1129         *translate = *dispatch = TRUE;
1130         return TRUE;
1131     }
1132
1133     switch(message)
1134     {
1135     case WM_KEYDOWN:
1136         switch(wParam)
1137         {
1138         case VK_TAB:
1139             if (!(dlgCode & DLGC_WANTTAB))
1140             {
1141                 SendMessage32A( hwndDlg, WM_NEXTDLGCTL,
1142                                 (GetKeyState32(VK_SHIFT) & 0x8000), 0 );
1143                 return TRUE;
1144             }
1145             break;
1146             
1147         case VK_RIGHT:
1148         case VK_DOWN:
1149         case VK_LEFT:
1150         case VK_UP:
1151             if (!(dlgCode & DLGC_WANTARROWS))
1152             {
1153                 BOOL32 fPrevious = (wParam == VK_LEFT || wParam == VK_UP);
1154                 HWND32 hwndNext = 
1155                     GetNextDlgGroupItem32 (hwndDlg, GetFocus32(), fPrevious );
1156                 SendMessage32A( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
1157                 return TRUE;
1158             }
1159             break;
1160
1161         case VK_ESCAPE:
1162             SendMessage32A( hwndDlg, WM_COMMAND, IDCANCEL,
1163                             (LPARAM)GetDlgItem32( hwndDlg, IDCANCEL ) );
1164             return TRUE;
1165
1166         case VK_RETURN:
1167             {
1168                 DWORD dw = SendMessage16( hwndDlg, DM_GETDEFID, 0, 0 );
1169                 if (HIWORD(dw) == DC_HASDEFID)
1170                 {
1171                     SendMessage32A( hwndDlg, WM_COMMAND, 
1172                                     MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
1173                                     (LPARAM)GetDlgItem32(hwndDlg, LOWORD(dw)));
1174                 }
1175                 else
1176                 {
1177                     SendMessage32A( hwndDlg, WM_COMMAND, IDOK,
1178                                     (LPARAM)GetDlgItem32( hwndDlg, IDOK ) );
1179     
1180                 }
1181             }
1182             return TRUE;
1183         }
1184         *translate = TRUE;
1185         break; /* case WM_KEYDOWN */
1186
1187     case WM_CHAR:
1188         if (dlgCode & DLGC_WANTCHARS) break;
1189         /* drop through */
1190
1191     case WM_SYSCHAR:
1192         if (DIALOG_IsAccelerator( hwnd, hwndDlg, wParam ))
1193         {
1194             /* don't translate or dispatch */
1195             return TRUE;
1196         }
1197         break;
1198     }
1199
1200     /* If we get here, the message has not been treated specially */
1201     /* and can be sent to its destination window. */
1202     *dispatch = TRUE;
1203     return TRUE;
1204 }
1205
1206
1207 /***********************************************************************
1208  *           IsDialogMessage16   (USER.90)
1209  */
1210 BOOL16 WINAPI WIN16_IsDialogMessage16( HWND16 hwndDlg, SEGPTR msg16 )
1211 {
1212     LPMSG16 msg = PTR_SEG_TO_LIN(msg16);
1213     BOOL32 ret, translate, dispatch;
1214     INT32 dlgCode;
1215
1216     if ((hwndDlg != msg->hwnd) && !IsChild16( hwndDlg, msg->hwnd ))
1217         return FALSE;
1218
1219     dlgCode = SendMessage16( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg16);
1220     ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1221                                   msg->wParam, msg->lParam,
1222                                   &translate, &dispatch, dlgCode );
1223     if (translate) TranslateMessage16( msg );
1224     if (dispatch) DispatchMessage16( msg );
1225     return ret;
1226 }
1227
1228
1229 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, LPMSG16 msg )
1230 {
1231     LPMSG16 msg16 = SEGPTR_NEW(MSG16);
1232     BOOL32 ret;
1233
1234     *msg16 = *msg;
1235     ret = WIN16_IsDialogMessage16( hwndDlg, SEGPTR_GET(msg16) );
1236     SEGPTR_FREE(msg16);
1237     return ret;
1238 }
1239
1240 /***********************************************************************
1241  *           IsDialogMessage32A   (USER32.342)
1242  */
1243 BOOL32 WINAPI IsDialogMessage32A( HWND32 hwndDlg, LPMSG32 msg )
1244 {
1245     BOOL32 ret, translate, dispatch;
1246     INT32 dlgCode;
1247
1248     if ((hwndDlg != msg->hwnd) && !IsChild32( hwndDlg, msg->hwnd ))
1249         return FALSE;
1250
1251     dlgCode = SendMessage32A( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
1252     ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1253                                   msg->wParam, msg->lParam,
1254                                   &translate, &dispatch, dlgCode );
1255     if (translate) TranslateMessage32( msg );
1256     if (dispatch) DispatchMessage32A( msg );
1257     return ret;
1258 }
1259
1260
1261 /***********************************************************************
1262  *           IsDialogMessage32W   (USER32.343)
1263  */
1264 BOOL32 WINAPI IsDialogMessage32W( HWND32 hwndDlg, LPMSG32 msg )
1265 {
1266     BOOL32 ret, translate, dispatch;
1267     INT32 dlgCode;
1268
1269     if ((hwndDlg != msg->hwnd) && !IsChild32( hwndDlg, msg->hwnd ))
1270         return FALSE;
1271
1272     dlgCode = SendMessage32W( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
1273     ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1274                                   msg->wParam, msg->lParam,
1275                                   &translate, &dispatch, dlgCode );
1276     if (translate) TranslateMessage32( msg );
1277     if (dispatch) DispatchMessage32W( msg );
1278     return ret;
1279 }
1280
1281
1282 /****************************************************************
1283  *         GetDlgCtrlID16   (USER.277)
1284  */
1285 INT16 WINAPI GetDlgCtrlID16( HWND16 hwnd )
1286 {
1287     WND *wndPtr = WIN_FindWndPtr(hwnd);
1288     if (wndPtr) return wndPtr->wIDmenu;
1289     else return 0;
1290 }
1291  
1292
1293 /****************************************************************
1294  *         GetDlgCtrlID32   (USER32.234)
1295  */
1296 INT32 WINAPI GetDlgCtrlID32( HWND32 hwnd )
1297 {
1298     WND *wndPtr = WIN_FindWndPtr(hwnd);
1299     if (wndPtr) return wndPtr->wIDmenu;
1300     else return 0;
1301 }
1302  
1303
1304 /***********************************************************************
1305  *           GetDlgItem16   (USER.91)
1306  */
1307 HWND16 WINAPI GetDlgItem16( HWND16 hwndDlg, INT16 id )
1308 {
1309     WND *pWnd;
1310
1311     if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
1312     for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1313         if (pWnd->wIDmenu == (UINT16)id) return pWnd->hwndSelf;
1314     return 0;
1315 }
1316
1317
1318 /***********************************************************************
1319  *           GetDlgItem32   (USER32.235)
1320  */
1321 HWND32 WINAPI GetDlgItem32( HWND32 hwndDlg, INT32 id )
1322 {
1323     WND *pWnd;
1324
1325     if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
1326     for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1327         if (pWnd->wIDmenu == (UINT16)id) return pWnd->hwndSelf;
1328     return 0;
1329 }
1330
1331
1332 /*******************************************************************
1333  *           SendDlgItemMessage16   (USER.101)
1334  */
1335 LRESULT WINAPI SendDlgItemMessage16( HWND16 hwnd, INT16 id, UINT16 msg,
1336                                      WPARAM16 wParam, LPARAM lParam )
1337 {
1338     HWND16 hwndCtrl = GetDlgItem16( hwnd, id );
1339     if (hwndCtrl) return SendMessage16( hwndCtrl, msg, wParam, lParam );
1340     else return 0;
1341 }
1342
1343
1344 /*******************************************************************
1345  *           SendDlgItemMessage32A   (USER32.452)
1346  */
1347 LRESULT WINAPI SendDlgItemMessage32A( HWND32 hwnd, INT32 id, UINT32 msg,
1348                                       WPARAM32 wParam, LPARAM lParam )
1349 {
1350     HWND32 hwndCtrl = GetDlgItem32( hwnd, id );
1351     if (hwndCtrl) return SendMessage32A( hwndCtrl, msg, wParam, lParam );
1352     else return 0;
1353 }
1354
1355
1356 /*******************************************************************
1357  *           SendDlgItemMessage32W   (USER32.453)
1358  */
1359 LRESULT WINAPI SendDlgItemMessage32W( HWND32 hwnd, INT32 id, UINT32 msg,
1360                                       WPARAM32 wParam, LPARAM lParam )
1361 {
1362     HWND32 hwndCtrl = GetDlgItem32( hwnd, id );
1363     if (hwndCtrl) return SendMessage32W( hwndCtrl, msg, wParam, lParam );
1364     else return 0;
1365 }
1366
1367
1368 /*******************************************************************
1369  *           SetDlgItemText16   (USER.92)
1370  */
1371 void WINAPI SetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR lpString )
1372 {
1373     SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1374 }
1375
1376
1377 /*******************************************************************
1378  *           SetDlgItemText32A   (USER32.478)
1379  */
1380 BOOL32 WINAPI SetDlgItemText32A( HWND32 hwnd, INT32 id, LPCSTR lpString )
1381 {
1382     return SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1383 }
1384
1385
1386 /*******************************************************************
1387  *           SetDlgItemText32W   (USER32.479)
1388  */
1389 BOOL32 WINAPI SetDlgItemText32W( HWND32 hwnd, INT32 id, LPCWSTR lpString )
1390 {
1391     return SendDlgItemMessage32W( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1392 }
1393
1394
1395 /***********************************************************************
1396  *           GetDlgItemText16   (USER.93)
1397  */
1398 INT16 WINAPI GetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR str, UINT16 len )
1399 {
1400     return (INT16)SendDlgItemMessage16( hwnd, id, WM_GETTEXT,
1401                                         len, (LPARAM)str );
1402 }
1403
1404
1405 /***********************************************************************
1406  *           GetDlgItemText32A   (USER32.237)
1407  */
1408 INT32 WINAPI GetDlgItemText32A( HWND32 hwnd, INT32 id, LPSTR str, UINT32 len )
1409 {
1410     return (INT32)SendDlgItemMessage32A( hwnd, id, WM_GETTEXT,
1411                                          len, (LPARAM)str );
1412 }
1413
1414
1415 /***********************************************************************
1416  *           GetDlgItemText32W   (USER32.238)
1417  */
1418 INT32 WINAPI GetDlgItemText32W( HWND32 hwnd, INT32 id, LPWSTR str, UINT32 len )
1419 {
1420     return (INT32)SendDlgItemMessage32W( hwnd, id, WM_GETTEXT,
1421                                          len, (LPARAM)str );
1422 }
1423
1424
1425 /*******************************************************************
1426  *           SetDlgItemInt16   (USER.94)
1427  */
1428 void WINAPI SetDlgItemInt16( HWND16 hwnd, INT16 id, UINT16 value, BOOL16 fSigned )
1429 {
1430     return SetDlgItemInt32( hwnd, (UINT32)(UINT16)id, value, fSigned );
1431 }
1432
1433
1434 /*******************************************************************
1435  *           SetDlgItemInt32   (USER32.477)
1436  */
1437 void WINAPI SetDlgItemInt32( HWND32 hwnd, INT32 id, UINT32 value,
1438                              BOOL32 fSigned )
1439 {
1440     char str[20];
1441
1442     if (fSigned) sprintf( str, "%d", (INT32)value );
1443     else sprintf( str, "%u", value );
1444     SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
1445 }
1446
1447
1448 /***********************************************************************
1449  *           GetDlgItemInt16   (USER.95)
1450  */
1451 UINT16 WINAPI GetDlgItemInt16( HWND16 hwnd, INT16 id, BOOL16 *translated,
1452                                BOOL16 fSigned )
1453 {
1454     UINT32 result;
1455     BOOL32 ok;
1456
1457     if (translated) *translated = FALSE;
1458     result = GetDlgItemInt32( hwnd, (UINT32)(UINT16)id, &ok, fSigned );
1459     if (!ok) return 0;
1460     if (fSigned)
1461     {
1462         if (((INT32)result < -32767) || ((INT32)result > 32767)) return 0;
1463     }
1464     else
1465     {
1466         if (result > 65535) return 0;
1467     }
1468     if (translated) *translated = TRUE;
1469     return (UINT16)result;
1470 }
1471
1472
1473 /***********************************************************************
1474  *           GetDlgItemInt32   (USER32.236)
1475  */
1476 UINT32 WINAPI GetDlgItemInt32( HWND32 hwnd, INT32 id, BOOL32 *translated,
1477                                BOOL32 fSigned )
1478 {
1479     char str[30];
1480     char * endptr;
1481     long result = 0;
1482     
1483     if (translated) *translated = FALSE;
1484     if (!SendDlgItemMessage32A(hwnd, id, WM_GETTEXT, sizeof(str), (LPARAM)str))
1485         return 0;
1486     if (fSigned)
1487     {
1488         result = strtol( str, &endptr, 10 );
1489         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
1490             return 0;
1491         if (((result == LONG_MIN) || (result == LONG_MAX)) && (errno==ERANGE))
1492             return 0;
1493     }
1494     else
1495     {
1496         result = strtoul( str, &endptr, 10 );
1497         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
1498             return 0;
1499         if ((result == ULONG_MAX) && (errno == ERANGE)) return 0;
1500     }
1501     if (translated) *translated = TRUE;
1502     return (UINT32)result;
1503 }
1504
1505
1506 /***********************************************************************
1507  *           CheckDlgButton16   (USER.97)
1508  */
1509 BOOL16 WINAPI CheckDlgButton16( HWND16 hwnd, INT16 id, UINT16 check )
1510 {
1511     SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
1512     return TRUE;
1513 }
1514
1515
1516 /***********************************************************************
1517  *           CheckDlgButton32   (USER32.45)
1518  */
1519 BOOL32 WINAPI CheckDlgButton32( HWND32 hwnd, INT32 id, UINT32 check )
1520 {
1521     SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
1522     return TRUE;
1523 }
1524
1525
1526 /***********************************************************************
1527  *           IsDlgButtonChecked16   (USER.98)
1528  */
1529 UINT16 WINAPI IsDlgButtonChecked16( HWND16 hwnd, UINT16 id )
1530 {
1531     return (UINT16)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
1532 }
1533
1534
1535 /***********************************************************************
1536  *           IsDlgButtonChecked32   (USER32.344)
1537  */
1538 UINT32 WINAPI IsDlgButtonChecked32( HWND32 hwnd, UINT32 id )
1539 {
1540     return (UINT32)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
1541 }
1542
1543
1544 /***********************************************************************
1545  *           CheckRadioButton16   (USER.96)
1546  */
1547 BOOL16 WINAPI CheckRadioButton16( HWND16 hwndDlg, UINT16 firstID,
1548                                   UINT16 lastID, UINT16 checkID )
1549 {
1550     return CheckRadioButton32( hwndDlg, firstID, lastID, checkID );
1551 }
1552
1553
1554 /***********************************************************************
1555  *           CheckRadioButton32   (USER32.48)
1556  */
1557 BOOL32 WINAPI CheckRadioButton32( HWND32 hwndDlg, UINT32 firstID,
1558                                   UINT32 lastID, UINT32 checkID )
1559 {
1560     WND *pWnd = WIN_FindWndPtr( hwndDlg );
1561     if (!pWnd) return FALSE;
1562
1563     for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1564         if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID)) break;
1565     if (!pWnd) return FALSE;
1566
1567     if (pWnd->wIDmenu == lastID)
1568         lastID = firstID;  /* Buttons are in reverse order */
1569     while (pWnd)
1570     {
1571         SendMessage32A( pWnd->hwndSelf, BM_SETCHECK32,
1572                         (pWnd->wIDmenu == checkID), 0 );
1573         if (pWnd->wIDmenu == lastID) break;
1574         pWnd = pWnd->next;
1575     }
1576     return TRUE;
1577 }
1578
1579
1580 /***********************************************************************
1581  *           GetDialogBaseUnits   (USER.243) (USER32.233)
1582  */
1583 DWORD WINAPI GetDialogBaseUnits(void)
1584 {
1585     return MAKELONG( xBaseUnit, yBaseUnit );
1586 }
1587
1588
1589 /***********************************************************************
1590  *           MapDialogRect16   (USER.103)
1591  */
1592 void WINAPI MapDialogRect16( HWND16 hwnd, LPRECT16 rect )
1593 {
1594     DIALOGINFO * dlgInfo;
1595     WND * wndPtr = WIN_FindWndPtr( hwnd );
1596     if (!wndPtr) return;
1597     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1598     rect->left   = (rect->left * dlgInfo->xBaseUnit) / 4;
1599     rect->right  = (rect->right * dlgInfo->xBaseUnit) / 4;
1600     rect->top    = (rect->top * dlgInfo->yBaseUnit) / 8;
1601     rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1602 }
1603
1604
1605 /***********************************************************************
1606  *           MapDialogRect32   (USER32.382)
1607  */
1608 void WINAPI MapDialogRect32( HWND32 hwnd, LPRECT32 rect )
1609 {
1610     DIALOGINFO * dlgInfo;
1611     WND * wndPtr = WIN_FindWndPtr( hwnd );
1612     if (!wndPtr) return;
1613     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1614     rect->left   = (rect->left * dlgInfo->xBaseUnit) / 4;
1615     rect->right  = (rect->right * dlgInfo->xBaseUnit) / 4;
1616     rect->top    = (rect->top * dlgInfo->yBaseUnit) / 8;
1617     rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1618 }
1619
1620
1621 /***********************************************************************
1622  *           GetNextDlgGroupItem16   (USER.227)
1623  */
1624 HWND16 WINAPI GetNextDlgGroupItem16( HWND16 hwndDlg, HWND16 hwndCtrl,
1625                                      BOOL16 fPrevious )
1626 {
1627     return (HWND16)GetNextDlgGroupItem32( hwndDlg, hwndCtrl, fPrevious );
1628 }
1629
1630
1631 /***********************************************************************
1632  *           GetNextDlgGroupItem32   (USER32.275)
1633  */
1634 HWND32 WINAPI GetNextDlgGroupItem32( HWND32 hwndDlg, HWND32 hwndCtrl,
1635                                      BOOL32 fPrevious )
1636 {
1637     WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
1638
1639     if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1640     if (hwndCtrl)
1641     {
1642         if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1643         /* Make sure hwndCtrl is a top-level child */
1644         while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1645             pWndCtrl = pWndCtrl->parent;
1646         if (pWndCtrl->parent != pWndDlg) return 0;
1647     }
1648     else
1649     {
1650         /* No ctrl specified -> start from the beginning */
1651         if (!(pWndCtrl = pWndDlg->child)) return 0;
1652         if (fPrevious) while (pWndCtrl->next) pWndCtrl = pWndCtrl->next;
1653     }
1654
1655     pWndLast = pWndCtrl;
1656     pWnd = pWndCtrl->next;
1657     while (1)
1658     {
1659         if (!pWnd || (pWnd->dwStyle & WS_GROUP))
1660         {
1661             /* Wrap-around to the beginning of the group */
1662             WND *pWndStart = pWndDlg->child;
1663             for (pWnd = pWndStart; pWnd; pWnd = pWnd->next)
1664             {
1665                 if (pWnd->dwStyle & WS_GROUP) pWndStart = pWnd;
1666                 if (pWnd == pWndCtrl) break;
1667             }
1668             pWnd = pWndStart;
1669         }
1670         if (pWnd == pWndCtrl) break;
1671         if ((pWnd->dwStyle & WS_VISIBLE) && !(pWnd->dwStyle & WS_DISABLED))
1672         {
1673             pWndLast = pWnd;
1674             if (!fPrevious) break;
1675         }
1676         pWnd = pWnd->next;
1677     }
1678     return pWndLast->hwndSelf;
1679 }
1680
1681
1682 /***********************************************************************
1683  *           GetNextDlgTabItem16   (USER.228)
1684  */
1685 HWND16 WINAPI GetNextDlgTabItem16( HWND16 hwndDlg, HWND16 hwndCtrl,
1686                                    BOOL16 fPrevious )
1687 {
1688     return (HWND16)GetNextDlgTabItem32( hwndDlg, hwndCtrl, fPrevious );
1689 }
1690
1691
1692 /***********************************************************************
1693  *           GetNextDlgTabItem32   (USER32.276)
1694  */
1695 HWND32 WINAPI GetNextDlgTabItem32( HWND32 hwndDlg, HWND32 hwndCtrl,
1696                                    BOOL32 fPrevious )
1697 {
1698     WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
1699
1700     if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1701     if (hwndCtrl)
1702     {
1703         if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1704         /* Make sure hwndCtrl is a top-level child */
1705         while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1706             pWndCtrl = pWndCtrl->parent;
1707         if (pWndCtrl->parent != pWndDlg) return 0;
1708     }
1709     else
1710     {
1711         /* No ctrl specified -> start from the beginning */
1712         if (!(pWndCtrl = pWndDlg->child)) return 0;
1713         if (!fPrevious) while (pWndCtrl->next) pWndCtrl = pWndCtrl->next;
1714     }
1715
1716     pWndLast = pWndCtrl;
1717     pWnd = pWndCtrl->next;
1718     while (1)
1719     {
1720         if (!pWnd) pWnd = pWndDlg->child;
1721         if (pWnd == pWndCtrl) break;
1722         if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE) &&
1723             !(pWnd->dwStyle & WS_DISABLED))
1724         {
1725             pWndLast = pWnd;
1726             if (!fPrevious) break;
1727         }
1728         pWnd = pWnd->next;
1729     }
1730     return pWndLast->hwndSelf;
1731 }
1732
1733
1734 /**********************************************************************
1735  *           DIALOG_DlgDirSelect
1736  *
1737  * Helper function for DlgDirSelect*
1738  */
1739 static BOOL32 DIALOG_DlgDirSelect( HWND32 hwnd, LPSTR str, INT32 len,
1740                                    INT32 id, BOOL32 win32, BOOL32 unicode,
1741                                    BOOL32 combo )
1742 {
1743     char *buffer, *ptr;
1744     INT32 item, size;
1745     BOOL32 ret;
1746     HWND32 listbox = GetDlgItem32( hwnd, id );
1747
1748     TRACE(dialog, "%04x '%s' %d\n", hwnd, str, id );
1749     if (!listbox) return FALSE;
1750     if (win32)
1751     {
1752         item = SendMessage32A(listbox, combo ? CB_GETCURSEL32
1753                                              : LB_GETCURSEL32, 0, 0 );
1754         if (item == LB_ERR) return FALSE;
1755         size = SendMessage32A(listbox, combo ? CB_GETLBTEXTLEN32
1756                                              : LB_GETTEXTLEN32, 0, 0 );
1757         if (size == LB_ERR) return FALSE;
1758     }
1759     else
1760     {
1761         item = SendMessage32A(listbox, combo ? CB_GETCURSEL16
1762                                              : LB_GETCURSEL16, 0, 0 );
1763         if (item == LB_ERR) return FALSE;
1764         size = SendMessage32A(listbox, combo ? CB_GETLBTEXTLEN16
1765                                              : LB_GETTEXTLEN16, 0, 0 );
1766         if (size == LB_ERR) return FALSE;
1767     }
1768
1769     if (!(buffer = SEGPTR_ALLOC( size+1 ))) return FALSE;
1770
1771     if (win32)
1772         SendMessage32A( listbox, combo ? CB_GETLBTEXT32 : LB_GETTEXT32,
1773                         item, (LPARAM)buffer );
1774     else
1775         SendMessage16( listbox, combo ? CB_GETLBTEXT16 : LB_GETTEXT16,
1776                        item, (LPARAM)SEGPTR_GET(buffer) );
1777
1778     if ((ret = (buffer[0] == '[')))  /* drive or directory */
1779     {
1780         if (buffer[1] == '-')  /* drive */
1781         {
1782             buffer[3] = ':';
1783             buffer[4] = 0;
1784             ptr = buffer + 2;
1785         }
1786         else
1787         {
1788             buffer[strlen(buffer)-1] = '\\';
1789             ptr = buffer + 1;
1790         }
1791     }
1792     else ptr = buffer;
1793
1794     if (unicode) lstrcpynAtoW( (LPWSTR)str, ptr, len );
1795     else lstrcpyn32A( str, ptr, len );
1796     SEGPTR_FREE( buffer );
1797     TRACE(dialog, "Returning %d '%s'\n", ret, str );
1798     return ret;
1799 }
1800
1801
1802 /**********************************************************************
1803  *          DIALOG_DlgDirList
1804  *
1805  * Helper function for DlgDirList*
1806  */
1807 static INT32 DIALOG_DlgDirList( HWND32 hDlg, LPSTR spec, INT32 idLBox,
1808                                 INT32 idStatic, UINT32 attrib, BOOL32 combo )
1809 {
1810     int drive;
1811     HWND32 hwnd;
1812     LPSTR orig_spec = spec;
1813
1814 #define SENDMSG(msg,wparam,lparam) \
1815     ((attrib & DDL_POSTMSGS) ? PostMessage32A( hwnd, msg, wparam, lparam ) \
1816                              : SendMessage32A( hwnd, msg, wparam, lparam ))
1817
1818     TRACE(dialog, "%04x '%s' %d %d %04x\n",
1819                     hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
1820
1821     if (spec && spec[0] && (spec[1] == ':'))
1822     {
1823         drive = toupper( spec[0] ) - 'A';
1824         spec += 2;
1825         if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
1826     }
1827     else drive = DRIVE_GetCurrentDrive();
1828
1829     /* If the path exists and is a directory, chdir to it */
1830     if (!spec || !spec[0] || DRIVE_Chdir( drive, spec )) spec = "*.*";
1831     else
1832     {
1833         char *p, *p2;
1834         p = spec;
1835         if ((p2 = strrchr( p, '\\' ))) p = p2;
1836         if ((p2 = strrchr( p, '/' ))) p = p2;
1837         if (p != spec)
1838         {
1839             char sep = *p;
1840             *p = 0;
1841             if (!DRIVE_Chdir( drive, spec ))
1842             {
1843                 *p = sep;  /* Restore the original spec */
1844                 return FALSE;
1845             }
1846             spec = p + 1;
1847         }
1848     }
1849
1850     TRACE(dialog, "path=%c:\\%s mask=%s\n",
1851                     'A' + drive, DRIVE_GetDosCwd(drive), spec );
1852
1853     if (idLBox && ((hwnd = GetDlgItem32( hDlg, idLBox )) != 0))
1854     {
1855         SENDMSG( combo ? CB_RESETCONTENT32 : LB_RESETCONTENT32, 0, 0 );
1856         if (attrib & DDL_DIRECTORY)
1857         {
1858             if (!(attrib & DDL_EXCLUSIVE))
1859             {
1860                 if (SENDMSG( combo ? CB_DIR32 : LB_DIR32,
1861                              attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1862                              (LPARAM)spec ) == LB_ERR)
1863                     return FALSE;
1864             }
1865             if (SENDMSG( combo ? CB_DIR32 : LB_DIR32,
1866                        (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1867                          (LPARAM)"*.*" ) == LB_ERR)
1868                 return FALSE;
1869         }
1870         else
1871         {
1872             if (SENDMSG( combo ? CB_DIR32 : LB_DIR32, attrib,
1873                          (LPARAM)spec ) == LB_ERR)
1874                 return FALSE;
1875         }
1876     }
1877
1878     if (idStatic && ((hwnd = GetDlgItem32( hDlg, idStatic )) != 0))
1879     {
1880         char temp[512];
1881         int drive = DRIVE_GetCurrentDrive();
1882         strcpy( temp, "A:\\" );
1883         temp[0] += drive;
1884         lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
1885         CharLower32A( temp );
1886         /* Can't use PostMessage() here, because the string is on the stack */
1887         SetDlgItemText32A( hDlg, idStatic, temp );
1888     }
1889
1890     if (orig_spec && (spec != orig_spec))
1891     {
1892         /* Update the original file spec */
1893         char *p = spec;
1894         while ((*orig_spec++ = *p++));
1895     }
1896
1897     return TRUE;
1898 #undef SENDMSG
1899 }
1900
1901
1902 /**********************************************************************
1903  *          DIALOG_DlgDirListW
1904  *
1905  * Helper function for DlgDirList*32W
1906  */
1907 static INT32 DIALOG_DlgDirListW( HWND32 hDlg, LPWSTR spec, INT32 idLBox,
1908                                  INT32 idStatic, UINT32 attrib, BOOL32 combo )
1909 {
1910     if (spec)
1911     {
1912         LPSTR specA = HEAP_strdupWtoA( GetProcessHeap(), 0, spec );
1913         INT32 ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic,
1914                                        attrib, combo );
1915         lstrcpyAtoW( spec, specA );
1916         HeapFree( GetProcessHeap(), 0, specA );
1917         return ret;
1918     }
1919     return DIALOG_DlgDirList( hDlg, NULL, idLBox, idStatic, attrib, combo );
1920 }
1921
1922
1923 /**********************************************************************
1924  *          DlgDirSelect    (USER.99)
1925  */
1926 BOOL16 WINAPI DlgDirSelect( HWND16 hwnd, LPSTR str, INT16 id )
1927 {
1928     return DlgDirSelectEx16( hwnd, str, 128, id );
1929 }
1930
1931
1932 /**********************************************************************
1933  *          DlgDirSelectComboBox    (USER.194)
1934  */
1935 BOOL16 WINAPI DlgDirSelectComboBox( HWND16 hwnd, LPSTR str, INT16 id )
1936 {
1937     return DlgDirSelectComboBoxEx16( hwnd, str, 128, id );
1938 }
1939
1940
1941 /**********************************************************************
1942  *           DlgDirSelectEx16    (USER.422)
1943  */
1944 BOOL16 WINAPI DlgDirSelectEx16( HWND16 hwnd, LPSTR str, INT16 len, INT16 id )
1945 {
1946     return DIALOG_DlgDirSelect( hwnd, str, len, id, FALSE, FALSE, FALSE );
1947 }
1948
1949
1950 /**********************************************************************
1951  *           DlgDirSelectEx32A    (USER32.149)
1952  */
1953 BOOL32 WINAPI DlgDirSelectEx32A( HWND32 hwnd, LPSTR str, INT32 len, INT32 id )
1954 {
1955     return DIALOG_DlgDirSelect( hwnd, str, len, id, TRUE, FALSE, FALSE );
1956 }
1957
1958
1959 /**********************************************************************
1960  *           DlgDirSelectEx32W    (USER32.150)
1961  */
1962 BOOL32 WINAPI DlgDirSelectEx32W( HWND32 hwnd, LPWSTR str, INT32 len, INT32 id )
1963 {
1964     return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE, FALSE );
1965 }
1966
1967
1968 /**********************************************************************
1969  *           DlgDirSelectComboBoxEx16    (USER.423)
1970  */
1971 BOOL16 WINAPI DlgDirSelectComboBoxEx16( HWND16 hwnd, LPSTR str, INT16 len,
1972                                         INT16 id )
1973 {
1974     return DIALOG_DlgDirSelect( hwnd, str, len, id, FALSE, FALSE, TRUE );
1975 }
1976
1977
1978 /**********************************************************************
1979  *           DlgDirSelectComboBoxEx32A    (USER32.147)
1980  */
1981 BOOL32 WINAPI DlgDirSelectComboBoxEx32A( HWND32 hwnd, LPSTR str, INT32 len,
1982                                          INT32 id )
1983 {
1984     return DIALOG_DlgDirSelect( hwnd, str, len, id, TRUE, FALSE, TRUE );
1985 }
1986
1987
1988 /**********************************************************************
1989  *           DlgDirSelectComboBoxEx32W    (USER32.148)
1990  */
1991 BOOL32 WINAPI DlgDirSelectComboBoxEx32W( HWND32 hwnd, LPWSTR str, INT32 len,
1992                                          INT32 id)
1993 {
1994     return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE, TRUE );
1995 }
1996
1997
1998 /**********************************************************************
1999  *          DlgDirList16    (USER.100)
2000  */
2001 INT16 WINAPI DlgDirList16( HWND16 hDlg, LPSTR spec, INT16 idLBox,
2002                            INT16 idStatic, UINT16 attrib )
2003 {
2004     return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
2005 }
2006
2007
2008 /**********************************************************************
2009  *          DlgDirList32A    (USER32.143)
2010  */
2011 INT32 WINAPI DlgDirList32A( HWND32 hDlg, LPSTR spec, INT32 idLBox,
2012                             INT32 idStatic, UINT32 attrib )
2013 {
2014     return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
2015 }
2016
2017
2018 /**********************************************************************
2019  *          DlgDirList32W    (USER32.146)
2020  */
2021 INT32 WINAPI DlgDirList32W( HWND32 hDlg, LPWSTR spec, INT32 idLBox,
2022                             INT32 idStatic, UINT32 attrib )
2023 {
2024     return DIALOG_DlgDirListW( hDlg, spec, idLBox, idStatic, attrib, FALSE );
2025 }
2026
2027
2028 /**********************************************************************
2029  *          DlgDirListComboBox16    (USER.195)
2030  */
2031 INT16 WINAPI DlgDirListComboBox16( HWND16 hDlg, LPSTR spec, INT16 idCBox,
2032                                    INT16 idStatic, UINT16 attrib )
2033 {
2034     return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
2035 }
2036
2037
2038 /**********************************************************************
2039  *          DlgDirListComboBox32A    (USER32.144)
2040  */
2041 INT32 WINAPI DlgDirListComboBox32A( HWND32 hDlg, LPSTR spec, INT32 idCBox,
2042                                     INT32 idStatic, UINT32 attrib )
2043 {
2044     return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
2045 }
2046
2047
2048 /**********************************************************************
2049  *          DlgDirListComboBox32W    (USER32.145)
2050  */
2051 INT32 WINAPI DlgDirListComboBox32W( HWND32 hDlg, LPWSTR spec, INT32 idCBox,
2052                                     INT32 idStatic, UINT32 attrib )
2053 {
2054     return DIALOG_DlgDirListW( hDlg, spec, idCBox, idStatic, attrib, TRUE );
2055 }