Release 960324
[wine] / windows / dialog.c
1 /*
2  * Dialog functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  *
6  */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include "windows.h"
12 #include "dialog.h"
13 #include "win.h"
14 #include "ldt.h"
15 #include "stackframe.h"
16 #include "user.h"
17 #include "message.h"
18 #include "stddebug.h"
19 /* #define DEBUG_DIALOG */
20 #include "debug.h"
21
22   /* Dialog base units */
23 WORD xBaseUnit = 0, yBaseUnit = 0;
24
25
26 /***********************************************************************
27  *           DIALOG_Init
28  *
29  * Initialisation of the dialog manager.
30  */
31 BOOL DIALOG_Init()
32 {
33     TEXTMETRIC tm;
34     HDC hdc;
35     
36       /* Calculate the dialog base units */
37
38     if (!(hdc = GetDC( 0 ))) return FALSE;
39     GetTextMetrics( hdc, &tm );
40     ReleaseDC( 0, hdc );
41     xBaseUnit = tm.tmAveCharWidth;
42     yBaseUnit = tm.tmHeight;
43
44       /* Dialog units are based on a proportional system font */
45       /* so we adjust them a bit for a fixed font. */
46     if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) xBaseUnit = xBaseUnit * 5 / 4;
47
48     dprintf_dialog( stddeb, "DIALOG_Init: base units = %d,%d\n",
49                     xBaseUnit, yBaseUnit );
50     return TRUE;
51 }
52
53
54 /***********************************************************************
55  *           DIALOG_GetFirstTabItem
56  *
57  * Return the first item of the dialog that has the WS_TABSTOP style.
58  */
59 HWND DIALOG_GetFirstTabItem( HWND hwndDlg )
60 {
61     WND *pWnd = WIN_FindWndPtr( hwndDlg );
62     for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
63         if (pWnd->dwStyle & WS_TABSTOP) return pWnd->hwndSelf;
64     return 0;
65 }
66
67
68 /***********************************************************************
69  *           DIALOG_GetControl
70  *
71  * Return the class and text of the control pointed to by ptr,
72  * and return a pointer to the next control.
73  */
74 static SEGPTR DIALOG_GetControl( SEGPTR ptr, SEGPTR *class, SEGPTR *text )
75 {
76     unsigned char *base = (unsigned char *)PTR_SEG_TO_LIN( ptr );
77     unsigned char *p = base;
78
79     p += 14;  /* size of control header */
80
81     if (*p & 0x80)
82     {
83         *class = MAKEINTRESOURCE( *p );
84         p++;
85     }
86     else 
87     {
88         *class = ptr + (WORD)(p - base);
89         p += strlen(p) + 1;
90     }
91
92     if (*p == 0xff)
93     {
94           /* Integer id, not documented (?). Only works for SS_ICON controls */
95         *text = MAKEINTRESOURCE( p[1] + 256 * p[2] );
96         p += 4;
97     }
98     else
99     {
100         *text = ptr + (WORD)(p - base);
101         p += strlen(p) + 2;
102     }
103     return ptr + (WORD)(p - base);
104 }
105
106
107 /***********************************************************************
108  *           DIALOG_ParseTemplate
109  *
110  * Fill a DLGTEMPLATE structure from the dialog template, and return
111  * a pointer to the first control.
112  */
113 static SEGPTR DIALOG_ParseTemplate( SEGPTR template, DLGTEMPLATE * result )
114 {
115     unsigned char *base = (unsigned char *)PTR_SEG_TO_LIN(template);
116     unsigned char * p = base;
117  
118     result->header = *(DLGTEMPLATEHEADER *)p;
119     p += 13;
120
121     /* Get the menu name */
122
123     if (*p == 0xff)
124     {
125         result->menuName = MAKEINTRESOURCE( p[1] + 256 * p[2] );
126         p += 3;
127     }
128     else if (*p)
129     {
130         result->menuName = template + (WORD)(p - base);
131         p += strlen(p) + 1;
132     }
133     else
134     {
135         result->menuName = 0;
136         p++;
137     }
138
139     /* Get the class name */
140
141     if (*p) result->className = template + (WORD)(p - base);
142     else result->className = DIALOG_CLASS_ATOM;
143     p += strlen(p) + 1;
144
145     /* Get the window caption */
146
147     result->caption = template + (WORD)(p - base);
148     p += strlen(p) + 1;
149
150     /* Get the font name */
151
152     if (result->header.style & DS_SETFONT)
153     {
154         result->pointSize = *(WORD *)p;
155         p += sizeof(WORD);
156         result->faceName = template + (WORD)(p - base);
157         p += strlen(p) + 1;
158     }
159
160     return template + (WORD)(p - base);
161 }
162
163
164 /***********************************************************************
165  *           DIALOG_DisplayTemplate
166  */
167 static void DIALOG_DisplayTemplate( DLGTEMPLATE * result )
168 {
169     dprintf_dialog(stddeb, "DIALOG %d, %d, %d, %d\n", result->header.x, result->header.y,
170             result->header.cx, result->header.cy );
171     dprintf_dialog(stddeb, " STYLE %08lx\n", result->header.style );
172     dprintf_dialog( stddeb, " CAPTION '%s'\n",
173                     (char *)PTR_SEG_TO_LIN(result->caption) );
174
175     if (HIWORD(result->className))
176         dprintf_dialog( stddeb, " CLASS '%s'\n",
177                         (char *)PTR_SEG_TO_LIN(result->className) );
178     else
179         dprintf_dialog( stddeb, " CLASS #%d\n", LOWORD(result->className) );
180
181     if (HIWORD(result->menuName))
182         dprintf_dialog( stddeb, " MENU '%s'\n",
183                         (char *)PTR_SEG_TO_LIN(result->menuName) );
184     else if (LOWORD(result->menuName))
185         dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
186
187     if (result->header.style & DS_SETFONT)
188         dprintf_dialog( stddeb, " FONT %d,'%s'\n", result->pointSize,
189                         (char *)PTR_SEG_TO_LIN(result->faceName) );
190 }
191
192
193 /***********************************************************************
194  *           CreateDialog   (USER.89)
195  */
196 HWND CreateDialog( HINSTANCE hInst, SEGPTR dlgTemplate,
197                    HWND owner, DLGPROC dlgProc )
198 {
199     return CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, 0 );
200 }
201
202
203 /***********************************************************************
204  *           CreateDialogParam   (USER.241)
205  */
206 HWND CreateDialogParam( HINSTANCE hInst, SEGPTR dlgTemplate,
207                         HWND owner, DLGPROC dlgProc, LPARAM param )
208 {
209     HWND hwnd = 0;
210     HRSRC hRsrc;
211     HGLOBAL hmem;
212     SEGPTR data;
213
214     dprintf_dialog(stddeb, "CreateDialogParam: %04x,%08lx,%04x,%08lx,%ld\n",
215                    hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
216      
217     if (!(hRsrc = FindResource( hInst, dlgTemplate, RT_DIALOG ))) return 0;
218     if (!(hmem = LoadResource( hInst, hRsrc ))) return 0;
219     if (!(data = WIN16_LockResource( hmem ))) hwnd = 0;
220     else hwnd = CreateDialogIndirectParam(hInst, data, owner, dlgProc, param);
221     FreeResource( hmem );
222     return hwnd;
223 }
224
225
226 /***********************************************************************
227  *           CreateDialogIndirect   (USER.219)
228  */
229 HWND CreateDialogIndirect( HINSTANCE hInst, SEGPTR dlgTemplate,
230                            HWND owner, DLGPROC dlgProc )
231 {
232     return CreateDialogIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
233 }
234
235
236 /***********************************************************************
237  *           CreateDialogIndirectParam   (USER.242)
238  */
239 HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate,
240                                 HWND owner, DLGPROC dlgProc, LPARAM param )
241 {
242     HMENU hMenu = 0;
243     HFONT hFont = 0;
244     HWND hwnd, hwndCtrl;
245     RECT rect;
246     WND * wndPtr;
247     int i;
248     DLGTEMPLATE template;
249     SEGPTR headerPtr;
250     DIALOGINFO * dlgInfo;
251     DWORD exStyle = 0;
252     WORD xUnit = xBaseUnit;
253     WORD yUnit = yBaseUnit;
254
255       /* Parse dialog template */
256
257     if (!dlgTemplate) return 0;
258     headerPtr = DIALOG_ParseTemplate( dlgTemplate, &template );
259     if (debugging_dialog) DIALOG_DisplayTemplate( &template );
260
261       /* Load menu */
262
263     if (template.menuName) hMenu = LoadMenu( hInst, template.menuName );
264
265       /* Create custom font if needed */
266
267     if (template.header.style & DS_SETFONT)
268     {
269           /* The font height must be negative as it is a point size */
270           /* (see CreateFont() documentation in the Windows SDK).   */
271         hFont = CreateFont( -template.pointSize, 0, 0, 0, FW_DONTCARE,
272                             FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
273                             DEFAULT_QUALITY, FF_DONTCARE,
274                             (LPSTR)PTR_SEG_TO_LIN(template.faceName) );
275         if (hFont)
276         {
277             TEXTMETRIC tm;
278             HFONT oldFont;
279             HDC hdc;
280
281             hdc = GetDC(0);
282             oldFont = SelectObject( hdc, hFont );
283             GetTextMetrics( hdc, &tm );
284             SelectObject( hdc, oldFont );
285             ReleaseDC( 0, hdc );
286             xUnit = tm.tmAveCharWidth;
287             yUnit = tm.tmHeight;
288             if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
289                 xBaseUnit = xBaseUnit * 5 / 4;  /* See DIALOG_Init() */
290         }
291     }
292     
293       /* Create dialog main window */
294
295     rect.left = rect.top = 0;
296     rect.right = template.header.cx * xUnit / 4;
297     rect.bottom = template.header.cy * yUnit / 8;
298     if (template.header.style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME;
299     AdjustWindowRectEx( &rect, template.header.style, 
300                         hMenu ? TRUE : FALSE , exStyle );
301     rect.right -= rect.left;
302     rect.bottom -= rect.top;
303
304     if ((INT)template.header.x == CW_USEDEFAULT)
305         rect.left = rect.top = CW_USEDEFAULT;
306     else
307     {
308         rect.left += template.header.x * xUnit / 4;
309         rect.top += template.header.y * yUnit / 8;
310         if (!(template.header.style & DS_ABSALIGN))
311             ClientToScreen( owner, (POINT *)&rect );
312     }
313
314     hwnd = CreateWindowEx( exStyle, template.className, template.caption, 
315                            template.header.style & ~WS_VISIBLE,
316                            rect.left, rect.top, rect.right, rect.bottom,
317                            owner, hMenu, hInst, (SEGPTR)0 );
318     if (!hwnd)
319     {
320         if (hFont) DeleteObject( hFont );
321         if (hMenu) DestroyMenu( hMenu );
322         return 0;
323     }
324     wndPtr = WIN_FindWndPtr( hwnd );
325
326       /* Purge junk from system menu */
327       /* FIXME: this doesn't belong here */
328
329     DeleteMenu(wndPtr->hSysMenu,SC_SIZE,MF_BYCOMMAND);
330     if (!(wndPtr->dwStyle & WS_MAXIMIZEBOX) )
331     {
332         DeleteMenu(wndPtr->hSysMenu,SC_MAXIMIZE,MF_BYCOMMAND);
333         if( !(wndPtr->dwStyle & WS_MINIMIZEBOX) )
334         {
335             DeleteMenu(wndPtr->hSysMenu,SC_MINIMIZE,MF_BYCOMMAND);
336             DeleteMenu(wndPtr->hSysMenu,SC_RESTORE,MF_BYCOMMAND);
337         }
338     }
339     else
340         if (!(wndPtr->dwStyle & WS_MINIMIZEBOX) )
341             DeleteMenu(wndPtr->hSysMenu,SC_MINIMIZE,MF_BYCOMMAND);
342
343       /* Create control windows */
344
345     dprintf_dialog(stddeb, " BEGIN\n" );
346
347     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
348     dlgInfo->msgResult = 0;  /* This is used to store the default button id */
349     dlgInfo->hDialogHeap = 0;
350
351     for (i = 0; i < template.header.nbItems; i++)
352     {
353         DLGCONTROLHEADER *header;
354         SEGPTR className, winName;
355         HWND hwndDefButton = 0;
356         char buffer[10];
357
358         header = (DLGCONTROLHEADER *)PTR_SEG_TO_LIN( headerPtr );
359         headerPtr = DIALOG_GetControl( headerPtr, &className, &winName );
360
361         if (!HIWORD(className))
362         {
363             switch(LOWORD(className))
364             {
365             case 0x80: strcpy( buffer, "BUTTON" ); break;
366             case 0x81: strcpy( buffer, "EDIT" ); break;
367             case 0x82: strcpy( buffer, "STATIC" ); break;
368             case 0x83: strcpy( buffer, "LISTBOX" ); break;
369             case 0x84: strcpy( buffer, "SCROLLBAR" ); break;
370             case 0x85: strcpy( buffer, "COMBOBOX" ); break;
371             default:   buffer[0] = '\0'; break;
372             }
373             className = MAKE_SEGPTR(buffer);
374         }
375
376         if (HIWORD(className))
377             dprintf_dialog(stddeb, "   %s ", (char*)PTR_SEG_TO_LIN(className));
378         else dprintf_dialog(stddeb, "   %04x ", LOWORD(className) );
379         if (HIWORD(winName))
380             dprintf_dialog(stddeb,"'%s'", (char *)PTR_SEG_TO_LIN(winName) );
381         else dprintf_dialog(stddeb,"%04x", LOWORD(winName) );
382
383         dprintf_dialog(stddeb," %d, %d, %d, %d, %d, %08lx\n", 
384                        header->id, header->x, header->y, 
385                        header->cx, header->cy, header->style );
386
387         if (HIWORD(className) &&
388             !strcmp( (char *)PTR_SEG_TO_LIN(className), "EDIT") &&
389             ((header->style & DS_LOCALEDIT) != DS_LOCALEDIT))
390         {
391             if (!dlgInfo->hDialogHeap)
392             {
393                 dlgInfo->hDialogHeap = GlobalAlloc(GMEM_FIXED, 0x10000);
394                 if (!dlgInfo->hDialogHeap)
395                 {
396                     fprintf(stderr,"CreateDialogIndirectParam: Insufficient memory to create heap for edit control\n");
397                     continue;
398                 }
399                 LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
400             }
401             hwndCtrl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, className, winName,
402                                       header->style | WS_CHILD,
403                                       header->x * xUnit / 4,
404                                       header->y * yUnit / 8,
405                                       header->cx * xUnit / 4,
406                                       header->cy * yUnit / 8,
407                                       hwnd, (HMENU)header->id,
408                                       dlgInfo->hDialogHeap, (SEGPTR)0 );
409         }
410         else
411         {
412             hwndCtrl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, className, winName,
413                                       header->style | WS_CHILD,
414                                       header->x * xUnit / 4,
415                                       header->y * yUnit / 8,
416                                       header->cx * xUnit / 4,
417                                       header->cy * yUnit / 8,
418                                       hwnd, (HMENU)header->id,
419                                       hInst, (SEGPTR)0 );
420         }
421
422         /* Make the control last one in Z-order, so that controls remain
423            in the order in which they were created */
424         SetWindowPos( hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0,
425                       SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
426
427             /* Send initialisation messages to the control */
428         if (hFont) SendMessage( hwndCtrl, WM_SETFONT, (WPARAM)hFont, 0 );
429         if (SendMessage( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
430         {
431               /* If there's already a default push-button, set it back */
432               /* to normal and use this one instead. */
433             if (hwndDefButton)
434                 SendMessage( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE);
435             hwndDefButton = hwndCtrl;
436             dlgInfo->msgResult = GetWindowWord( hwndCtrl, GWW_ID );
437         }
438     }    
439
440     dprintf_dialog(stddeb, " END\n" );
441     
442       /* Initialise dialog extra data */
443
444     dlgInfo->dlgProc   = dlgProc;
445     dlgInfo->hUserFont = hFont;
446     dlgInfo->hMenu     = hMenu;
447     dlgInfo->xBaseUnit = xUnit;
448     dlgInfo->yBaseUnit = yUnit;
449     dlgInfo->hwndFocus = DIALOG_GetFirstTabItem( hwnd );
450
451       /* Send initialisation messages and set focus */
452
453     if (dlgInfo->hUserFont)
454         SendMessage( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
455     if (SendMessage( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
456         SetFocus( dlgInfo->hwndFocus );
457     if (template.header.style & WS_VISIBLE) ShowWindow(hwnd, SW_SHOW);
458     return hwnd;
459 }
460
461
462 /***********************************************************************
463  *           DIALOG_DoDialogBox
464  */
465 int DIALOG_DoDialogBox( HWND hwnd, HWND owner )
466 {
467     WND * wndPtr;
468     DIALOGINFO * dlgInfo;
469     HANDLE msgHandle;
470     MSG* lpmsg;
471     int retval;
472
473       /* Owner must be a top-level window */
474     owner = WIN_GetTopParent( owner );
475     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
476     if (!(msgHandle = USER_HEAP_ALLOC( sizeof(MSG) ))) return -1;
477     lpmsg = (MSG *) USER_HEAP_LIN_ADDR( msgHandle );
478     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
479     EnableWindow( owner, FALSE );
480     ShowWindow( hwnd, SW_SHOW );
481
482     while (MSG_InternalGetMessage( (SEGPTR)USER_HEAP_SEG_ADDR(msgHandle), hwnd, owner,
483                                    MSGF_DIALOGBOX, PM_REMOVE,
484                                    !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
485     {
486         if (!IsDialogMessage( hwnd, lpmsg))
487         {
488             TranslateMessage( lpmsg );
489             DispatchMessage( lpmsg );
490         }
491         if (dlgInfo->fEnd) break;
492     }
493     retval = dlgInfo->msgResult;
494     DestroyWindow( hwnd );
495     USER_HEAP_FREE( msgHandle );
496     EnableWindow( owner, TRUE );
497     return retval;
498 }
499
500
501 /***********************************************************************
502  *           DialogBox   (USER.87)
503  */
504 INT DialogBox( HINSTANCE hInst, SEGPTR dlgTemplate,
505                HWND owner, DLGPROC dlgProc )
506 {
507     return DialogBoxParam( hInst, dlgTemplate, owner, dlgProc, 0 );
508 }
509
510
511 /***********************************************************************
512  *           DialogBoxParam   (USER.239)
513  */
514 INT DialogBoxParam( HINSTANCE hInst, SEGPTR dlgTemplate,
515                     HWND owner, DLGPROC dlgProc, LPARAM param )
516 {
517     HWND hwnd;
518     
519     dprintf_dialog(stddeb, "DialogBoxParam: %04x,%08lx,%04x,%08lx,%ld\n",
520                    hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
521     hwnd = CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, param );
522     if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
523     return -1;
524 }
525
526
527 /***********************************************************************
528  *           DialogBoxIndirect   (USER.218)
529  */
530 INT DialogBoxIndirect( HINSTANCE hInst, HANDLE dlgTemplate,
531                        HWND owner, DLGPROC dlgProc )
532 {
533     return DialogBoxIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
534 }
535
536
537 /***********************************************************************
538  *           DialogBoxIndirectParam   (USER.240)
539  */
540 INT DialogBoxIndirectParam( HINSTANCE hInst, HANDLE dlgTemplate,
541                             HWND owner, DLGPROC dlgProc, LPARAM param )
542 {
543     HWND hwnd;
544     SEGPTR ptr;
545
546     if (!(ptr = (SEGPTR)WIN16_GlobalLock( dlgTemplate ))) return -1;
547     hwnd = CreateDialogIndirectParam( hInst, ptr, owner, dlgProc, param );
548     GlobalUnlock( dlgTemplate );
549     if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
550     return -1;
551 }
552
553
554 /***********************************************************************
555  *           EndDialog   (USER.88)
556  */
557 BOOL EndDialog( HWND hwnd, INT retval )
558 {
559     WND * wndPtr = WIN_FindWndPtr( hwnd );
560     DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
561     dlgInfo->msgResult = retval;
562     dlgInfo->fEnd = TRUE;
563     dprintf_dialog(stddeb, "EndDialog: %04x %d\n", hwnd, retval );
564     return TRUE;
565 }
566
567
568 /***********************************************************************
569  *           IsDialogMessage   (USER.90)
570  */
571 BOOL IsDialogMessage( HWND hwndDlg, LPMSG msg )
572 {
573     WND * wndPtr;
574     int dlgCode;
575
576     if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return FALSE;
577     if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE;
578
579       /* Only the key messages get special processing */
580     if ((msg->message != WM_KEYDOWN) &&
581         (msg->message != WM_SYSCHAR) &&
582         (msg->message != WM_CHAR))
583         return FALSE;
584
585     dlgCode = SendMessage( msg->hwnd, WM_GETDLGCODE, 0, 0 );
586     if (dlgCode & DLGC_WANTMESSAGE)
587     {
588         DispatchMessage( msg );
589         return TRUE;
590     }
591
592     switch(msg->message)
593     {
594     case WM_KEYDOWN:
595         if (dlgCode & DLGC_WANTALLKEYS) break;
596         switch(msg->wParam)
597         {
598         case VK_TAB:
599             if (!(dlgCode & DLGC_WANTTAB))
600             {
601                 SendMessage( hwndDlg, WM_NEXTDLGCTL,
602                              (GetKeyState(VK_SHIFT) & 0x80), 0 );
603                 return TRUE;
604             }
605             break;
606             
607         case VK_RIGHT:
608         case VK_DOWN:
609             if (!(dlgCode & DLGC_WANTARROWS))
610             {
611                 SetFocus(GetNextDlgGroupItem(hwndDlg,GetFocus(),FALSE));
612                 return TRUE;
613             }
614             break;
615
616         case VK_LEFT:
617         case VK_UP:
618             if (!(dlgCode & DLGC_WANTARROWS))
619             {
620                 SetFocus(GetNextDlgGroupItem(hwndDlg,GetFocus(),TRUE));
621                 return TRUE;
622             }
623             break;
624
625         case VK_ESCAPE:
626 #ifdef WINELIB32
627             SendMessage( hwndDlg, WM_COMMAND, 
628                          MAKEWPARAM( IDCANCEL, 0 ),
629                          (LPARAM)GetDlgItem(hwndDlg,IDCANCEL) );
630 #else
631             SendMessage( hwndDlg, WM_COMMAND, IDCANCEL,
632                          MAKELPARAM( GetDlgItem(hwndDlg,IDCANCEL), 0 ));
633 #endif
634             break;
635
636         case VK_RETURN:
637             {
638                 DWORD dw = SendMessage( hwndDlg, DM_GETDEFID, 0, 0 );
639                 if (HIWORD(dw) == DC_HASDEFID)
640 #ifdef WINELIB32
641                     SendMessage( hwndDlg, WM_COMMAND, 
642                                  MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
643                                  (LPARAM)GetDlgItem( hwndDlg, LOWORD(dw) ) );
644                 else
645                     SendMessage( hwndDlg, WM_COMMAND, 
646                                  MAKEWPARAM( IDOK, 0 ),
647                                  (LPARAM)GetDlgItem(hwndDlg,IDOK) );
648 #else
649                     SendMessage( hwndDlg, WM_COMMAND, LOWORD(dw),
650                                  MAKELPARAM( GetDlgItem( hwndDlg, LOWORD(dw) ),
651                                              BN_CLICKED ));
652                 else
653                     SendMessage( hwndDlg, WM_COMMAND, IDOK,
654                                  MAKELPARAM( GetDlgItem(hwndDlg,IDOK), 0 ));
655 #endif
656             }
657             break;
658         }
659         break;  /* case WM_KEYDOWN */
660
661         
662     case WM_CHAR:
663         if (dlgCode & (DLGC_WANTALLKEYS | DLGC_WANTCHARS)) break;
664         break;
665
666     case WM_SYSCHAR:
667         if (dlgCode & DLGC_WANTALLKEYS) break;
668         break;
669     }
670
671       /* If we get here, the message has not been treated specially */
672       /* and can be sent to its destination window. */
673     DispatchMessage( msg );
674     return TRUE;
675 }
676
677
678 /****************************************************************
679  *         GetDlgCtrlID           (USER.277)
680  */
681 int GetDlgCtrlID( HWND hwnd )
682 {
683     WND *wndPtr = WIN_FindWndPtr(hwnd);
684     if (wndPtr) return wndPtr->wIDmenu;
685     else return 0;
686 }
687  
688
689 /***********************************************************************
690  *           GetDlgItem   (USER.91)
691  */
692 HWND GetDlgItem( HWND hwndDlg, WORD id )
693 {
694     WND *pWnd;
695
696     if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
697     for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
698         if (pWnd->wIDmenu == id) return pWnd->hwndSelf;
699     return 0;
700 }
701
702
703 /*******************************************************************
704  *           SendDlgItemMessage   (USER.101)
705  */
706 LRESULT SendDlgItemMessage(HWND hwnd, INT id, UINT msg, WPARAM wParam, LPARAM lParam)
707 {
708     HWND hwndCtrl = GetDlgItem( hwnd, id );
709     if (hwndCtrl) return SendMessage( hwndCtrl, msg, wParam, lParam );
710     else return 0;
711 }
712
713
714 /*******************************************************************
715  *           SetDlgItemText   (USER.92)
716  */
717 void SetDlgItemText( HWND hwnd, WORD id, SEGPTR lpString )
718 {
719     SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)lpString );
720 }
721
722
723 /***********************************************************************
724  *           GetDlgItemText   (USER.93)
725  */
726 int GetDlgItemText( HWND hwnd, WORD id, SEGPTR str, WORD max )
727 {
728     return (int)SendDlgItemMessage( hwnd, id, WM_GETTEXT, max, (DWORD)str );
729 }
730
731
732 /*******************************************************************
733  *           SetDlgItemInt   (USER.94)
734  */
735 void SetDlgItemInt( HWND hwnd, WORD id, WORD value, BOOL fSigned )
736 {
737     char str[20];
738
739     if (fSigned) sprintf( str, "%d", (int)value );
740     else sprintf( str, "%u", value );
741     SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(str) );
742 }
743
744
745 /***********************************************************************
746  *           GetDlgItemInt   (USER.95)
747  */
748 WORD GetDlgItemInt( HWND hwnd, WORD id, BOOL * translated, BOOL fSigned )
749 {
750     char str[30];
751     long result = 0;
752     
753     if (translated) *translated = FALSE;
754     if (SendDlgItemMessage( hwnd, id, WM_GETTEXT, 30, (LPARAM)MAKE_SEGPTR(str) ))
755     {
756         char * endptr;
757         result = strtol( str, &endptr, 10 );
758         if (endptr && (endptr != str))  /* Conversion was successful */
759         {
760             if (fSigned)
761             {
762                 if ((result < -32767) || (result > 32767)) result = 0;
763                 else if (translated) *translated = TRUE;
764             }
765             else
766             {
767                 if ((result < 0) || (result > 65535)) result = 0;
768                 else if (translated) *translated = TRUE;
769             }
770         }
771     }
772     return (WORD)result;
773 }
774
775
776 /***********************************************************************
777  *           CheckDlgButton   (USER.97)
778  */
779 BOOL CheckDlgButton( HWND hwnd, INT id, UINT check )
780 {
781     SendDlgItemMessage( hwnd, id, BM_SETCHECK, check, 0 );
782     return TRUE;
783 }
784
785
786 /***********************************************************************
787  *           IsDlgButtonChecked   (USER.98)
788  */
789 WORD IsDlgButtonChecked( HWND hwnd, WORD id )
790 {
791     return (WORD)SendDlgItemMessage( hwnd, id, BM_GETCHECK, 0, 0 );
792 }
793
794
795 /***********************************************************************
796  *           CheckRadioButton   (USER.96)
797  */
798 BOOL CheckRadioButton( HWND hwndDlg, UINT firstID, UINT lastID, UINT checkID )
799 {
800     WND *pWnd = WIN_FindWndPtr( hwndDlg );
801     if (!pWnd) return FALSE;
802
803     for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
804         if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID)) break;
805     if (!pWnd) return FALSE;
806
807     if (pWnd->wIDmenu == lastID)
808         lastID = firstID;  /* Buttons are in reverse order */
809     while (pWnd)
810     {
811         SendMessage(pWnd->hwndSelf, BM_SETCHECK, (pWnd->wIDmenu == checkID),0);
812         if (pWnd->wIDmenu == lastID) break;
813         pWnd = pWnd->next;
814     }
815     return TRUE;
816 }
817
818
819 /***********************************************************************
820  *           GetDialogBaseUnits   (USER.243)
821  */
822 DWORD GetDialogBaseUnits()
823 {
824     return MAKELONG( xBaseUnit, yBaseUnit );
825 }
826
827
828 /***********************************************************************
829  *           MapDialogRect   (USER.103)
830  */
831 void MapDialogRect( HWND hwnd, LPRECT rect )
832 {
833     DIALOGINFO * dlgInfo;
834     WND * wndPtr = WIN_FindWndPtr( hwnd );
835     if (!wndPtr) return;
836     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
837     rect->left   = (rect->left * dlgInfo->xBaseUnit) / 4;
838     rect->right  = (rect->right * dlgInfo->xBaseUnit) / 4;
839     rect->top    = (rect->top * dlgInfo->yBaseUnit) / 8;
840     rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
841 }
842
843
844 /***********************************************************************
845  *           GetNextDlgGroupItem   (USER.227)
846  */
847 HWND GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
848 {
849     WND *pWnd, *pWndStart, *pWndCtrl, *pWndDlg;
850
851     if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
852     if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
853     if (pWndCtrl->parent != pWndDlg) return 0;
854
855     if (!fPrevious && pWndCtrl->next)  /* Check if next control is in group */
856     {
857         if (!(pWndCtrl->next->dwStyle & WS_GROUP))
858             return pWndCtrl->next->hwndSelf;
859     }
860
861       /* Now we will have to find the start of the group */
862
863     for (pWnd = pWndStart = pWndDlg->child; pWnd; pWnd = pWnd->next)
864     {
865         if (pWnd->dwStyle & WS_GROUP) pWndStart = pWnd;  /* Start of a group */
866         if (pWnd == pWndCtrl) break;
867     }
868
869     if (!pWnd) fprintf(stderr, "GetNextDlgGroupItem: hwnd not in dialog!\n");
870
871       /* only case left for forward search: wraparound */
872     if (!fPrevious) return pWndStart->hwndSelf;
873
874     pWnd = pWndStart->next;
875     while (pWnd && (pWnd != pWndCtrl))
876     {
877         if (pWnd->dwStyle & WS_GROUP) break;
878         pWndStart = pWnd;
879         pWnd = pWnd->next;
880     }
881     return pWndStart->hwndSelf;
882 }
883
884
885 /***********************************************************************
886  *           GetNextDlgTabItem   (USER.228)
887  */
888 HWND GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
889 {
890     WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
891
892     if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
893     if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
894     if (pWndCtrl->parent != pWndDlg) return 0;
895
896     pWndLast = pWndCtrl;
897     pWnd = pWndCtrl->next;
898     while (1)
899     {
900         if (!pWnd) pWnd = pWndDlg->child;
901         if (pWnd == pWndCtrl) break;
902         if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE))
903         {
904             pWndLast = pWnd;
905             if (!fPrevious) break;
906         }
907         pWnd = pWnd->next;
908     }
909     return pWndLast->hwndSelf;
910 }