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