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