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