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