- Fix debug header nonsense
[reactos.git] / reactos / lib / user32 / windows / dialog.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/dialog.c
23 * PURPOSE: Input
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
26 * Steven Edwards (Steven_Ed4153@yahoo.com)
27 * UPDATE HISTORY:
28 * 07-26-2003 Code ported from wine
29 * 09-05-2001 CSH Created
30 */
31
32 /* INCLUDES ******************************************************************/
33
34 #include <user32.h>
35 #define NDEBUG
36 #include <debug.h>
37
38 /* MACROS/DEFINITIONS ********************************************************/
39
40 #define DF_END 0x0001
41 #define DF_OWNERENABLED 0x0002
42 #define CW_USEDEFAULT16 ((short)0x8000)
43 #define DWL_INIT (12)
44 #define GETDLGINFO(hwnd) (DIALOGINFO*)GetWindowLongW((hwnd), DWL_INIT)
45 #define SETDLGINFO(hwnd, info) SetWindowLongW((hwnd), DWL_INIT, (LONG)(info))
46 #define GET_WORD(ptr) (*(WORD *)(ptr))
47 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
48 #define MAKEINTATOMA(atom) ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
49 #define MAKEINTATOMW(atom) ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
50 #define DIALOG_CLASS_ATOMA MAKEINTATOMA(32770) /* Dialog */
51 #define DIALOG_CLASS_ATOMW MAKEINTATOMW(32770) /* Dialog */
52
53 /* INTERNAL STRUCTS **********************************************************/
54
55 /* Dialog info structure */
56 typedef struct
57 {
58 HWND hwndFocus; /* Current control with focus */
59 HFONT hUserFont; /* Dialog font */
60 HMENU hMenu; /* Dialog menu */
61 UINT xBaseUnit; /* Dialog units (depends on the font) */
62 UINT yBaseUnit;
63 INT idResult; /* EndDialog() result / default pushbutton ID */
64 UINT flags; /* EndDialog() called for this dialog */
65 } DIALOGINFO;
66
67 /* Dialog control information */
68 typedef struct
69 {
70 DWORD style;
71 DWORD exStyle;
72 DWORD helpId;
73 short x;
74 short y;
75 short cx;
76 short cy;
77 UINT id;
78 LPCWSTR className;
79 LPCWSTR windowName;
80 BOOL windowNameFree;
81 LPCVOID data;
82 } DLG_CONTROL_INFO;
83
84 /* Dialog template */
85 typedef struct
86 {
87 DWORD style;
88 DWORD exStyle;
89 DWORD helpId;
90 WORD nbItems;
91 short x;
92 short y;
93 short cx;
94 short cy;
95 LPCWSTR menuName;
96 LPCWSTR className;
97 LPCWSTR caption;
98 WORD pointSize;
99 WORD weight;
100 BOOL italic;
101 LPCWSTR faceName;
102 BOOL dialogEx;
103 } DLG_TEMPLATE;
104
105 /* GetDlgItem structure */
106 typedef struct
107 {
108 INT nIDDlgItem;
109 HWND control;
110 } GETDLGITEMINFO;
111
112 /* CheckRadioButton structure */
113 typedef struct
114 {
115 UINT firstID;
116 UINT lastID;
117 UINT checkID;
118 } RADIOGROUP;
119
120
121 /*********************************************************************
122 * dialog class descriptor
123 */
124 const struct builtin_class_descr DIALOG_builtin_class =
125 {
126 DIALOG_CLASS_ATOMW, /* name */
127 CS_SAVEBITS | CS_DBLCLKS, /* style */
128 (WNDPROC) DefDlgProcW, /* procW */
129 (WNDPROC) DefDlgProcA, /* procA */
130 DWL_INIT + sizeof(LONG), /* extra */
131 (LPCWSTR) IDC_ARROW, /* cursor */
132 0 /* brush */
133 };
134
135
136 /* INTERNAL FUNCTIONS ********************************************************/
137
138 /***********************************************************************
139 * DIALOG_GetCharSize
140 *
141 * Despite most of MSDN insisting that the horizontal base unit is
142 * tmAveCharWidth it isn't. Knowledge base article Q145994
143 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
144 * says that we should take the average of the 52 English upper and lower
145 * case characters.
146 */
147 BOOL DIALOG_GetCharSize( HDC hDC, HFONT hFont, SIZE * pSize )
148 {
149 HFONT hFontPrev = 0;
150 char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
151 SIZE sz;
152 TEXTMETRICA tm;
153
154 if(!hDC) return FALSE;
155
156 if(hFont) hFontPrev = SelectObject(hDC, hFont);
157 if(!GetTextMetricsA(hDC, &tm)) return FALSE;
158 if(!GetTextExtentPointA(hDC, alphabet, 52, &sz)) return FALSE;
159
160 pSize->cy = tm.tmHeight;
161 pSize->cx = (sz.cx / 26 + 1) / 2;
162
163 if (hFontPrev) SelectObject(hDC, hFontPrev);
164
165 return TRUE;
166 }
167
168 /***********************************************************************
169 * DIALOG_EnableOwner
170 *
171 * Helper function for modal dialogs to enable again the
172 * owner of the dialog box.
173 */
174 void DIALOG_EnableOwner( HWND hOwner )
175 {
176 /* Owner must be a top-level window */
177 if (hOwner)
178 hOwner = GetAncestor( hOwner, GA_ROOT );
179 if (!hOwner) return;
180 EnableWindow( hOwner, TRUE );
181 }
182
183 /***********************************************************************
184 * DIALOG_DisableOwner
185 *
186 * Helper function for modal dialogs to disable the
187 * owner of the dialog box. Returns TRUE if owner was enabled.
188 */
189 BOOL DIALOG_DisableOwner( HWND hOwner )
190 {
191 /* Owner must be a top-level window */
192 if (hOwner)
193 hOwner = GetAncestor( hOwner, GA_ROOT );
194 if (!hOwner) return FALSE;
195 if (IsWindowEnabled( hOwner ))
196 {
197 EnableWindow( hOwner, FALSE );
198 return TRUE;
199 }
200 else
201 return FALSE;
202 }
203
204 /***********************************************************************
205 * DIALOG_GetControl32
206 *
207 * Return the class and text of the control pointed to by ptr,
208 * fill the header structure and return a pointer to the next control.
209 */
210 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
211 BOOL dialogEx )
212 {
213 if (dialogEx)
214 {
215 info->helpId = GET_DWORD(p); p += 2;
216 info->exStyle = GET_DWORD(p); p += 2;
217 info->style = GET_DWORD(p); p += 2;
218 }
219 else
220 {
221 info->helpId = 0;
222 info->style = GET_DWORD(p); p += 2;
223 info->exStyle = GET_DWORD(p); p += 2;
224 }
225 info->x = GET_WORD(p); p++;
226 info->y = GET_WORD(p); p++;
227 info->cx = GET_WORD(p); p++;
228 info->cy = GET_WORD(p); p++;
229
230 if (dialogEx)
231 {
232 /* id is a DWORD for DIALOGEX */
233 info->id = GET_DWORD(p);
234 p += 2;
235 }
236 else
237 {
238 info->id = GET_WORD(p);
239 p++;
240 }
241
242 if (GET_WORD(p) == 0xffff)
243 {
244 static const WCHAR class_names[6][10] =
245 {
246 { 'B','u','t','t','o','n', }, /* 0x80 */
247 { 'E','d','i','t', }, /* 0x81 */
248 { 'S','t','a','t','i','c', }, /* 0x82 */
249 { 'L','i','s','t','B','o','x', }, /* 0x83 */
250 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
251 { 'C','o','m','b','o','B','o','x', } /* 0x85 */
252 };
253 WORD id = GET_WORD(p+1);
254 /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */
255 if ((id >= 0x80) && (id <= 0x85)) id -= 0x80;
256 if (id <= 5)
257 info->className = class_names[id];
258 else
259 {
260 info->className = NULL;
261 /* FIXME: load other classes here? */
262 }
263 p += 2;
264 }
265 else
266 {
267 info->className = (LPCWSTR)p;
268 p += wcslen( info->className ) + 1;
269 }
270
271 if (GET_WORD(p) == 0xffff) /* Is it an integer id? */
272 {
273 info->windowName = HeapAlloc( GetProcessHeap(), 0, 10 );
274 swprintf((LPWSTR)info->windowName, L"#%d", GET_WORD(p + 1));
275 info->windowNameFree = TRUE;
276 p += 2;
277 }
278 else
279 {
280 info->windowName = (LPCWSTR)p;
281 info->windowNameFree = FALSE;
282 p += wcslen( info->windowName ) + 1;
283 }
284
285 if (GET_WORD(p))
286 {
287 info->data = p + 1;
288 p += GET_WORD(p) / sizeof(WORD);
289 }
290 else info->data = NULL;
291 p++;
292
293 /* Next control is on dword boundary */
294 return (const WORD *)((((int)p) + 3) & ~3);
295 }
296
297 /***********************************************************************
298 * DIALOG_CreateControls32
299 *
300 * Create the control windows for a dialog.
301 */
302 static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate,
303 HINSTANCE hInst, BOOL unicode )
304 {
305 DIALOGINFO * dlgInfo;
306 DLG_CONTROL_INFO info;
307 HWND hwndCtrl, hwndDefButton = 0;
308 INT items = dlgTemplate->nbItems;
309
310 if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
311
312 while (items--)
313 {
314 template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info,
315 dlgTemplate->dialogEx );
316 /* Is this it? */
317 if (info.style & WS_BORDER)
318 {
319 info.style &= ~WS_BORDER;
320 info.exStyle |= WS_EX_CLIENTEDGE;
321 }
322 if (unicode)
323 {
324 hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
325 info.className, info.windowName,
326 info.style | WS_CHILD,
327 MulDiv(info.x, dlgInfo->xBaseUnit, 4),
328 MulDiv(info.y, dlgInfo->yBaseUnit, 8),
329 MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
330 MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
331 hwnd, (HMENU)info.id,
332 hInst, (LPVOID)info.data );
333 }
334 else
335 {
336 LPSTR class = (LPSTR)info.className;
337 LPSTR caption = (LPSTR)info.windowName;
338
339 if (HIWORD(class))
340 {
341 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.className, -1, NULL, 0, NULL, NULL );
342 class = HeapAlloc( GetProcessHeap(), 0, len );
343 WideCharToMultiByte( CP_ACP, 0, info.className, -1, class, len, NULL, NULL );
344 }
345 if (HIWORD(caption))
346 {
347 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, NULL, 0, NULL, NULL );
348 caption = HeapAlloc( GetProcessHeap(), 0, len );
349 WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, caption, len, NULL, NULL );
350 }
351 hwndCtrl = CreateWindowExA( info.exStyle | WS_EX_NOPARENTNOTIFY,
352 class, caption, info.style | WS_CHILD,
353 MulDiv(info.x, dlgInfo->xBaseUnit, 4),
354 MulDiv(info.y, dlgInfo->yBaseUnit, 8),
355 MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
356 MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
357 hwnd, (HMENU)info.id,
358 hInst, (LPVOID)info.data );
359 if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
360 if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
361 }
362
363 if (info.windowNameFree)
364 {
365 HeapFree( GetProcessHeap(), 0, (LPVOID)info.windowName );
366 }
367
368 if (!hwndCtrl)
369 {
370 if (dlgTemplate->style & DS_NOFAILCREATE) continue;
371 return FALSE;
372 }
373
374 /* Send initialisation messages to the control */
375 if (dlgInfo->hUserFont) SendMessageA( hwndCtrl, WM_SETFONT,
376 (WPARAM)dlgInfo->hUserFont, 0 );
377 if (SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
378 {
379 /* If there's already a default push-button, set it back */
380 /* to normal and use this one instead. */
381 if (hwndDefButton)
382 SendMessageA( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE );
383 hwndDefButton = hwndCtrl;
384 dlgInfo->idResult = GetWindowLongA( hwndCtrl, GWL_ID );
385 }
386 }
387 return TRUE;
388 }
389
390 /***********************************************************************
391 * DIALOG_FindMsgDestination
392 *
393 * The messages that IsDialogMessage sends may not go to the dialog
394 * calling IsDialogMessage if that dialog is a child, and it has the
395 * DS_CONTROL style set.
396 * We propagate up until we hit one that does not have DS_CONTROL, or
397 * whose parent is not a dialog.
398 *
399 * This is undocumented behaviour.
400 */
401 static HWND DIALOG_FindMsgDestination( HWND hwndDlg )
402 {
403 while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL)
404 {
405 HWND hParent = GetParent(hwndDlg);
406 if (!hParent) break;
407
408 if (!IsWindow(hParent)) break;
409
410 if (!GETDLGINFO(hParent)) /* TODO: Correct? */
411 {
412 break;
413 }
414
415 hwndDlg = hParent;
416 }
417
418 return hwndDlg;
419 }
420
421 /***********************************************************************
422 * DIALOG_IsAccelerator
423 */
424 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM wParam )
425 {
426 HWND hwndControl = hwnd;
427 HWND hwndNext;
428 INT dlgCode;
429 WCHAR buffer[128];
430
431 do
432 {
433 DWORD style = GetWindowLongW( hwndControl, GWL_STYLE );
434 if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
435 {
436 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
437 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
438 GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
439 {
440 /* find the accelerator key */
441 LPWSTR p = buffer - 2;
442
443 do
444 {
445 p = wcschr( p + 2, '&' );
446 }
447 while (p != NULL && p[1] == '&');
448
449 /* and check if it's the one we're looking for */
450 /* FIXME: usage of towupper correct? */
451 if (p != NULL && towupper( p[1] ) == towupper( wParam ) )
452 {
453 if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
454 {
455 /* set focus to the control */
456 SendMessageA( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1);
457 /* and bump it on to next */
458 SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
459 }
460 else if (dlgCode & DLGC_BUTTON)
461 {
462 /* send BM_CLICK message to the control */
463 SendMessageA( hwndControl, BM_CLICK, 0, 0 );
464 }
465 return TRUE;
466 }
467 }
468 hwndNext = GetWindow( hwndControl, GW_CHILD );
469 }
470 else hwndNext = 0;
471
472 if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
473
474 while (!hwndNext && hwndControl)
475 {
476 hwndControl = GetParent( hwndControl );
477 if (hwndControl == hwndDlg)
478 {
479 if(hwnd==hwndDlg) /* prevent endless loop */
480 {
481 hwndNext=hwnd;
482 break;
483 }
484 hwndNext = GetWindow( hwndDlg, GW_CHILD );
485 }
486 else
487 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
488 }
489 hwndControl = hwndNext;
490 }
491 while (hwndControl && (hwndControl != hwnd));
492
493 return FALSE;
494 }
495
496 /***********************************************************************
497 * DIALOG_DoDialogBox
498 */
499 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
500 {
501 DIALOGINFO * dlgInfo;
502 MSG msg;
503 INT retval;
504 HWND ownerMsg = GetAncestor( owner, GA_ROOT );
505 if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
506
507 if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */
508 {
509 ShowWindow( hwnd, SW_SHOW );
510 for (;;)
511 {
512 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
513 {
514 if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
515 {
516 /* No message present -> send ENTERIDLE and wait */
517 SendMessageW( ownerMsg, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd );
518 if (!GetMessageW( &msg, 0, 0, 0 )) break;
519 }
520 }
521 else if (!GetMessageW( &msg, 0, 0, 0 )) break;
522
523 if (!IsWindow( hwnd )) return -1;
524 if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg))
525 {
526 TranslateMessage( &msg );
527 DispatchMessageW( &msg );
528 }
529 if (dlgInfo->flags & DF_END) break;
530 }
531 }
532 if (dlgInfo->flags & DF_OWNERENABLED) DIALOG_EnableOwner( owner );
533 retval = dlgInfo->idResult;
534 DestroyWindow( hwnd );
535 return retval;
536 }
537
538 /***********************************************************************
539 * DIALOG_ParseTemplate32
540 *
541 * Fill a DLG_TEMPLATE structure from the dialog template, and return
542 * a pointer to the first control.
543 */
544 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
545 {
546 const WORD *p = (const WORD *)template;
547
548 result->style = GET_DWORD(p); p += 2;
549 if (result->style == 0xffff0001) /* DIALOGEX resource */
550 {
551 result->dialogEx = TRUE;
552 result->helpId = GET_DWORD(p); p += 2;
553 result->exStyle = GET_DWORD(p); p += 2;
554 result->style = GET_DWORD(p); p += 2;
555 }
556 else
557 {
558 result->dialogEx = FALSE;
559 result->helpId = 0;
560 result->exStyle = GET_DWORD(p); p += 2;
561 }
562 result->nbItems = GET_WORD(p); p++;
563 result->x = GET_WORD(p); p++;
564 result->y = GET_WORD(p); p++;
565 result->cx = GET_WORD(p); p++;
566 result->cy = GET_WORD(p); p++;
567
568 /* Get the menu name */
569
570 switch(GET_WORD(p))
571 {
572 case 0x0000:
573 result->menuName = NULL;
574 p++;
575 break;
576 case 0xffff:
577 result->menuName = (LPCWSTR)(UINT)GET_WORD( p + 1 );
578 p += 2;
579 break;
580 default:
581 result->menuName = (LPCWSTR)p;
582 p += wcslen( result->menuName ) + 1;
583 break;
584 }
585
586 /* Get the class name */
587
588 switch(GET_WORD(p))
589 {
590 case 0x0000:
591 result->className = DIALOG_CLASS_ATOMW;
592 p++;
593 break;
594 case 0xffff:
595 result->className = (LPCWSTR)(UINT)GET_WORD( p + 1 );
596 p += 2;
597 break;
598 default:
599 result->className = (LPCWSTR)p;
600 p += wcslen( result->className ) + 1;
601 break;
602 }
603
604 /* Get the window caption */
605
606 result->caption = (LPCWSTR)p;
607 p += wcslen( result->caption ) + 1;
608
609 /* Get the font name */
610
611 if (result->style & DS_SETFONT)
612 {
613 result->pointSize = GET_WORD(p);
614 p++;
615 if (result->dialogEx)
616 {
617 result->weight = GET_WORD(p); p++;
618 result->italic = LOBYTE(GET_WORD(p)); p++;
619 }
620 else
621 {
622 result->weight = FW_DONTCARE;
623 result->italic = FALSE;
624 }
625 result->faceName = (LPCWSTR)p;
626 p += wcslen( result->faceName ) + 1;
627 }
628 else
629 {
630 result->pointSize = 0;
631 result->weight = FW_DONTCARE;
632 result->italic = FALSE;
633 result->faceName = NULL;
634 }
635
636 /* First control is on dword boundary */
637 return (LPCSTR)((((int)p) + 3) & ~3);
638 }
639
640 /***********************************************************************
641 * DIALOG_CreateIndirect
642 * Creates a dialog box window
643 *
644 * modal = TRUE if we are called from a modal dialog box.
645 * (it's more compatible to do it here, as under Windows the owner
646 * is never disabled if the dialog fails because of an invalid template)
647 */
648 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
649 HWND owner, DLGPROC dlgProc, LPARAM param,
650 BOOL unicode, BOOL modal )
651 {
652 HWND hwnd;
653 RECT rect;
654 DLG_TEMPLATE template;
655 DIALOGINFO * dlgInfo;
656 DWORD units = GetDialogBaseUnits();
657 BOOL ownerEnabled = TRUE;
658
659 /* Parse dialog template */
660
661 if (!dlgTemplate) return 0;
662 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
663
664 /* Initialise dialog extra data */
665
666 if (!(dlgInfo = HeapAlloc( GetProcessHeap(), 0, sizeof(*dlgInfo) ))) return 0;
667 dlgInfo->hwndFocus = 0;
668 dlgInfo->hUserFont = 0;
669 dlgInfo->hMenu = 0;
670 dlgInfo->xBaseUnit = LOWORD(units);
671 dlgInfo->yBaseUnit = HIWORD(units);
672 dlgInfo->idResult = 0;
673 dlgInfo->flags = 0;
674 //dlgInfo->hDialogHeap = 0;
675
676 /* Load menu */
677
678 if (template.menuName) dlgInfo->hMenu = LoadMenuW( hInst, template.menuName );
679
680 /* Create custom font if needed */
681
682 if (template.style & DS_SETFONT)
683 {
684 /* We convert the size to pixels and then make it -ve. This works
685 * for both +ve and -ve template.pointSize */
686 HDC dc;
687 int pixels;
688 dc = GetDC(0);
689 pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72);
690 dlgInfo->hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight,
691 template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
692 PROOF_QUALITY, FF_DONTCARE,
693 template.faceName );
694 if (dlgInfo->hUserFont)
695 {
696 SIZE charSize;
697 HFONT hOldFont = SelectObject( dc, dlgInfo->hUserFont );
698 charSize.cx = GdiGetCharDimensions( dc, NULL, &charSize.cy );
699 if (charSize.cx)
700 {
701 dlgInfo->xBaseUnit = charSize.cx;
702 dlgInfo->yBaseUnit = charSize.cy;
703 }
704 SelectObject( dc, hOldFont );
705 }
706 ReleaseDC(0, dc);
707 }
708
709 /* Create dialog main window */
710
711 rect.left = rect.top = 0;
712 rect.right = MulDiv(template.cx, dlgInfo->xBaseUnit, 4);
713 rect.bottom = MulDiv(template.cy, dlgInfo->yBaseUnit, 8);
714 if (template.style & WS_CHILD)
715 template.style &= ~(WS_CAPTION|WS_SYSMENU);
716 if (template.style & DS_MODALFRAME)
717 template.exStyle |= WS_EX_DLGMODALFRAME;
718 if (template.style & DS_CONTROL)
719 template.exStyle |= WS_EX_CONTROLPARENT;
720 AdjustWindowRectEx( &rect, template.style, (dlgInfo->hMenu != 0), template.exStyle );
721 rect.right -= rect.left;
722 rect.bottom -= rect.top;
723
724 if (template.x == CW_USEDEFAULT16)
725 {
726 rect.left = rect.top = CW_USEDEFAULT;
727 }
728 else
729 {
730 if (template.style & DS_CENTER)
731 {
732 rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
733 rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
734 }
735 else
736 {
737 rect.left += MulDiv(template.x, dlgInfo->xBaseUnit, 4);
738 rect.top += MulDiv(template.y, dlgInfo->yBaseUnit, 8);
739 }
740 if ( !(template.style & WS_CHILD) )
741 {
742 INT dX, dY;
743
744 if( !(template.style & DS_ABSALIGN) )
745 ClientToScreen( owner, (POINT *)&rect );
746
747 /* try to fit it into the desktop */
748
749 if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
750 - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
751 if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
752 - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
753 if( rect.left < 0 ) rect.left = 0;
754 if( rect.top < 0 ) rect.top = 0;
755 }
756 }
757
758 if (modal)
759 {
760 ownerEnabled = DIALOG_DisableOwner( owner );
761 if (ownerEnabled) dlgInfo->flags |= DF_OWNERENABLED;
762 }
763
764 if (unicode)
765 {
766 hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
767 template.style & ~WS_VISIBLE,
768 rect.left, rect.top, rect.right, rect.bottom,
769 owner, dlgInfo->hMenu, hInst, NULL );
770 }
771 else
772 {
773 LPSTR class = (LPSTR)template.className;
774 LPSTR caption = (LPSTR)template.caption;
775
776 if (HIWORD(class))
777 {
778 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL );
779 class = HeapAlloc( GetProcessHeap(), 0, len );
780 WideCharToMultiByte( CP_ACP, 0, template.className, -1, class, len, NULL, NULL );
781 }
782 if (HIWORD(caption))
783 {
784 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL );
785 caption = HeapAlloc( GetProcessHeap(), 0, len );
786 WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption, len, NULL, NULL );
787 }
788 hwnd = CreateWindowExA(template.exStyle, class, caption,
789 template.style & ~WS_VISIBLE,
790 rect.left, rect.top, rect.right, rect.bottom,
791 owner, dlgInfo->hMenu, hInst, NULL );
792 if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
793 if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
794 }
795
796 if (!hwnd)
797 {
798 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
799 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
800 if (modal && (dlgInfo->flags & DF_OWNERENABLED)) DIALOG_EnableOwner(owner);
801 HeapFree( GetProcessHeap(), 0, dlgInfo );
802 return 0;
803 }
804
805 if (template.helpId)
806 SetWindowContextHelpId( hwnd, template.helpId );
807
808 if (unicode)
809 {
810 SETDLGINFO(hwnd, dlgInfo); /* maybe SetPropW? */
811 SetWindowLongW( hwnd, DWL_DLGPROC, (LONG)dlgProc );
812 }
813 else
814 {
815 SETDLGINFO(hwnd, dlgInfo);
816 SetWindowLongA( hwnd, DWL_DLGPROC, (LONG)dlgProc );
817 }
818
819 if (dlgInfo->hUserFont)
820 SendMessageA( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
821
822 /* Create controls */
823
824 if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode ))
825 {
826 /* Send initialisation messages and set focus */
827
828 if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
829 {
830 /* By returning TRUE, app has requested a default focus assignment */
831 dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
832 if( dlgInfo->hwndFocus )
833 SetFocus( dlgInfo->hwndFocus );
834 }
835
836 if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
837 {
838 ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
839 }
840 return hwnd;
841 }
842
843 if( IsWindow(hwnd) ) DestroyWindow( hwnd );
844 if (modal && ownerEnabled) DIALOG_EnableOwner(owner);
845 return 0;
846 }
847
848 /***********************************************************************
849 * DEFDLG_SetFocus
850 *
851 * Set the focus to a control of the dialog, selecting the text if
852 * the control is an edit dialog.
853 */
854 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
855 {
856 HWND hwndPrev = GetFocus();
857
858 if (IsChild( hwndDlg, hwndPrev ))
859 {
860 if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
861 SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
862 }
863 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
864 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
865 SetFocus( hwndCtrl );
866 }
867
868 /***********************************************************************
869 * DEFDLG_SaveFocus
870 */
871 static void DEFDLG_SaveFocus( HWND hwnd )
872 {
873 DIALOGINFO *infoPtr;
874 HWND hwndFocus = GetFocus();
875
876 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
877 if (!(infoPtr = GETDLGINFO(hwnd))) return;
878 infoPtr->hwndFocus = hwndFocus;
879 /* Remove default button */
880 }
881
882 /***********************************************************************
883 * DEFDLG_RestoreFocus
884 */
885 static void DEFDLG_RestoreFocus( HWND hwnd )
886 {
887 DIALOGINFO *infoPtr;
888
889 if (IsIconic( hwnd )) return;
890 if (!(infoPtr = GETDLGINFO(hwnd))) return;
891 if (!IsWindow( infoPtr->hwndFocus )) return;
892 /* Don't set the focus back to controls if EndDialog is already called.*/
893 if (!(infoPtr->flags & DF_END))
894 {
895 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
896 return;
897 }
898 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
899 sometimes losing focus when receiving WM_SETFOCUS messages. */
900 }
901
902 /***********************************************************************
903 * DEFDLG_FindDefButton
904 *
905 * Find the current default push-button.
906 */
907 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
908 {
909 HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
910 while (hwndChild)
911 {
912 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
913 break;
914 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
915 }
916 return hwndChild;
917 }
918
919 /***********************************************************************
920 * DEFDLG_SetDefButton
921 *
922 * Set the new default button to be hwndNew.
923 */
924 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
925 HWND hwndNew )
926 {
927 DWORD dlgcode=0; /* initialize just to avoid a warning */
928 if (hwndNew &&
929 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
930 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
931 return FALSE; /* Destination is not a push button */
932
933 if (dlgInfo->idResult) /* There's already a default pushbutton */
934 {
935 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
936 if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
937 SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
938 }
939 if (hwndNew)
940 {
941 if(dlgcode==DLGC_UNDEFPUSHBUTTON)
942 SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
943 dlgInfo->idResult = GetDlgCtrlID( hwndNew );
944 }
945 else dlgInfo->idResult = 0;
946 return TRUE;
947 }
948
949 /***********************************************************************
950 * DEFDLG_Proc
951 *
952 * Implementation of DefDlgProc(). Only handle messages that need special
953 * handling for dialogs.
954 */
955 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
956 LPARAM lParam, DIALOGINFO *dlgInfo )
957 {
958 switch(msg)
959 {
960 case WM_ERASEBKGND:
961 {
962 HBRUSH brush = (HBRUSH)SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
963 if (!brush) brush = (HBRUSH)DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
964 if (brush)
965 {
966 RECT rect;
967 HDC hdc = (HDC)wParam;
968 GetClientRect( hwnd, &rect );
969 DPtoLP( hdc, (LPPOINT)&rect, 2 );
970 FillRect( hdc, &rect, brush );
971 }
972 return 1;
973 }
974 case WM_NCDESTROY:
975 if ((dlgInfo = GETDLGINFO(hwnd)))
976 {
977 /* Free dialog heap (if created) */
978 /*if (dlgInfo->hDialogHeap)
979 {
980 GlobalUnlock16(dlgInfo->hDialogHeap);
981 GlobalFree16(dlgInfo->hDialogHeap);
982 }*/
983 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
984 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
985 HeapFree( GetProcessHeap(), 0, dlgInfo );
986 }
987 /* Window clean-up */
988 return DefWindowProcA( hwnd, msg, wParam, lParam );
989
990 case WM_SHOWWINDOW:
991 if (!wParam) DEFDLG_SaveFocus( hwnd );
992 return DefWindowProcA( hwnd, msg, wParam, lParam );
993
994 case WM_ACTIVATE:
995 if (wParam) DEFDLG_RestoreFocus( hwnd );
996 else DEFDLG_SaveFocus( hwnd );
997 return 0;
998
999 case WM_SETFOCUS:
1000 DEFDLG_RestoreFocus( hwnd );
1001 return 0;
1002
1003 case DM_SETDEFID:
1004 if (dlgInfo && !(dlgInfo->flags & DF_END))
1005 DEFDLG_SetDefButton( hwnd, dlgInfo, wParam ? GetDlgItem( hwnd, wParam ) : 0 );
1006 return 1;
1007
1008 case DM_GETDEFID:
1009 if (dlgInfo && !(dlgInfo->flags & DF_END))
1010 {
1011 HWND hwndDefId;
1012 if (dlgInfo->idResult)
1013 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
1014 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
1015 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
1016 }
1017 return 0;
1018
1019 case WM_NEXTDLGCTL:
1020 if (dlgInfo)
1021 {
1022 HWND hwndDest = (HWND)wParam;
1023 if (!lParam)
1024 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
1025 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
1026 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
1027 }
1028 return 0;
1029
1030 case WM_ENTERMENULOOP:
1031 case WM_LBUTTONDOWN:
1032 case WM_NCLBUTTONDOWN:
1033 {
1034 HWND hwndFocus = GetFocus();
1035 if (hwndFocus)
1036 {
1037 /* always make combo box hide its listbox control */
1038 if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
1039 SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
1040 }
1041 }
1042 return DefWindowProcA( hwnd, msg, wParam, lParam );
1043
1044 case WM_GETFONT:
1045 return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0;
1046
1047 case WM_CLOSE:
1048 PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
1049 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
1050 return 0;
1051
1052 case WM_NOTIFYFORMAT:
1053 return DefWindowProcA( hwnd, msg, wParam, lParam );
1054 }
1055 return 0;
1056 }
1057
1058 /***********************************************************************
1059 * DEFDLG_Epilog
1060 */
1061 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
1062 {
1063 // TODO: where's wine's WM_CTLCOLOR from?
1064 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
1065 /*msg == WM_CTLCOLOR || */ msg == WM_COMPAREITEM ||
1066 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
1067 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
1068 return fResult;
1069
1070 return GetWindowLongA( hwnd, DWL_MSGRESULT );
1071 }
1072
1073 /***********************************************************************
1074 * DIALOG_GetNextTabItem
1075 *
1076 * Helper for GetNextDlgTabItem
1077 */
1078 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1079 {
1080 LONG dsStyle;
1081 LONG exStyle;
1082 UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT;
1083 HWND retWnd = 0;
1084 HWND hChildFirst = 0;
1085
1086 if(!hwndCtrl)
1087 {
1088 hChildFirst = GetWindow(hwndDlg,GW_CHILD);
1089 if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST);
1090 }
1091 else if (IsChild( hwndMain, hwndCtrl ))
1092 {
1093 hChildFirst = GetWindow(hwndCtrl,wndSearch);
1094 if(!hChildFirst)
1095 {
1096 if(GetParent(hwndCtrl) != hwndMain)
1097 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
1098 else
1099 {
1100 if(fPrevious)
1101 hChildFirst = GetWindow(hwndCtrl,GW_HWNDLAST);
1102 else
1103 hChildFirst = GetWindow(hwndCtrl,GW_HWNDFIRST);
1104 }
1105 }
1106 }
1107
1108 while(hChildFirst)
1109 {
1110 BOOL bCtrl = FALSE;
1111 while(hChildFirst)
1112 {
1113 dsStyle = GetWindowLongA(hChildFirst,GWL_STYLE);
1114 exStyle = GetWindowLongA(hChildFirst,GWL_EXSTYLE);
1115 if( (dsStyle & DS_CONTROL || exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1116 {
1117 bCtrl=TRUE;
1118 break;
1119 }
1120 else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1121 break;
1122 hChildFirst = GetWindow(hChildFirst,wndSearch);
1123 }
1124 if(hChildFirst)
1125 {
1126 if(bCtrl)
1127 retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
1128 else
1129 retWnd = hChildFirst;
1130 }
1131 if(retWnd) break;
1132 hChildFirst = GetWindow(hChildFirst,wndSearch);
1133 }
1134 if(!retWnd && hwndCtrl)
1135 {
1136 HWND hParent = GetParent(hwndCtrl);
1137 while(hParent)
1138 {
1139 if(hParent == hwndMain) break;
1140 retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious );
1141 if(retWnd) break;
1142 hParent = GetParent(hParent);
1143 }
1144 if(!retWnd)
1145 retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
1146 }
1147 return retWnd;
1148 }
1149
1150 /**********************************************************************
1151 * DIALOG_DlgDirList
1152 *
1153 * Helper function for DlgDirList*
1154 */
1155 static INT DIALOG_DlgDirList( HWND hDlg, LPSTR spec, INT idLBox,
1156 INT idStatic, UINT attrib, BOOL combo )
1157 {
1158 HWND hwnd;
1159 LPSTR orig_spec = spec;
1160 char any[] = "*.*";
1161
1162 #define SENDMSG(msg,wparam,lparam) \
1163 ((attrib & DDL_POSTMSGS) ? PostMessageA( hwnd, msg, wparam, lparam ) \
1164 : SendMessageA( hwnd, msg, wparam, lparam ))
1165
1166 DPRINT("%p '%s' %d %d %04x\n",
1167 hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
1168
1169 /* If the path exists and is a directory, chdir to it */
1170 if (!spec || !spec[0] || SetCurrentDirectoryA( spec )) spec = any;
1171 else
1172 {
1173 char *p, *p2;
1174 p = spec;
1175 if ((p2 = strrchr( p, '\\' ))) p = p2;
1176 if ((p2 = strrchr( p, '/' ))) p = p2;
1177 if (p != spec)
1178 {
1179 char sep = *p;
1180 *p = 0;
1181 if (!SetCurrentDirectoryA( spec ))
1182 {
1183 *p = sep; /* Restore the original spec */
1184 return FALSE;
1185 }
1186 spec = p + 1;
1187 }
1188 }
1189
1190 DPRINT( "mask=%s\n", spec );
1191
1192 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1193 {
1194 SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
1195 if (attrib & DDL_DIRECTORY)
1196 {
1197 if (!(attrib & DDL_EXCLUSIVE))
1198 {
1199 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1200 attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1201 (LPARAM)spec ) == LB_ERR)
1202 return FALSE;
1203 }
1204 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1205 (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1206 (LPARAM)"*.*" ) == LB_ERR)
1207 return FALSE;
1208 }
1209 else
1210 {
1211 if (SENDMSG( combo ? CB_DIR : LB_DIR, attrib,
1212 (LPARAM)spec ) == LB_ERR)
1213 return FALSE;
1214 }
1215 }
1216
1217 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
1218 {
1219 char temp[MAX_PATH];
1220 GetCurrentDirectoryA( sizeof(temp), temp );
1221 CharLowerA( temp );
1222 /* Can't use PostMessage() here, because the string is on the stack */
1223 SetDlgItemTextA( hDlg, idStatic, temp );
1224 }
1225
1226 if (orig_spec && (spec != orig_spec))
1227 {
1228 /* Update the original file spec */
1229 char *p = spec;
1230 while ((*orig_spec++ = *p++));
1231 }
1232
1233 return TRUE;
1234 #undef SENDMSG
1235 }
1236
1237 /**********************************************************************
1238 * DIALOG_DlgDirListW
1239 *
1240 * Helper function for DlgDirList*W
1241 */
1242 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
1243 INT idStatic, UINT attrib, BOOL combo )
1244 {
1245 if (spec)
1246 {
1247 LPSTR specA;
1248 INT ret;
1249
1250 HEAP_strdupWtoA ( &specA, spec, lstrlenW(spec) );
1251 ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic,
1252 attrib, combo );
1253 MultiByteToWideChar( CP_ACP, 0, specA, -1, spec, 0x7fffffff );
1254 HEAP_free( specA );
1255 return ret;
1256 }
1257 return DIALOG_DlgDirList( hDlg, NULL, idLBox, idStatic, attrib, combo );
1258 }
1259
1260 /**********************************************************************
1261 * DIALOG_DlgDirSelect
1262 *
1263 * Helper function for DlgDirSelect*
1264 */
1265 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPSTR str, INT len,
1266 INT id, BOOL unicode, BOOL combo )
1267 {
1268 char *buffer, *ptr;
1269 INT item, size;
1270 BOOL ret;
1271 HWND listbox = GetDlgItem( hwnd, id );
1272
1273 DPRINT("%p '%s' %d\n", hwnd, str, id );
1274 if (!listbox) return FALSE;
1275
1276 item = SendMessageA(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 );
1277 if (item == LB_ERR) return FALSE;
1278 size = SendMessageA(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, 0, 0 );
1279 if (size == LB_ERR) return FALSE;
1280
1281 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size+1 ))) return FALSE;
1282
1283 SendMessageA( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer );
1284
1285 if ((ret = (buffer[0] == '['))) /* drive or directory */
1286 {
1287 if (buffer[1] == '-') /* drive */
1288 {
1289 buffer[3] = ':';
1290 buffer[4] = 0;
1291 ptr = buffer + 2;
1292 }
1293 else
1294 {
1295 buffer[strlen(buffer)-1] = '\\';
1296 ptr = buffer + 1;
1297 }
1298 }
1299 else ptr = buffer;
1300
1301 if (unicode)
1302 {
1303 if (len > 0 && !MultiByteToWideChar( CP_ACP, 0, ptr, -1, (LPWSTR)str, len ))
1304 ((LPWSTR)str)[len-1] = 0;
1305 }
1306 else lstrcpynA( str, ptr, len );
1307 HeapFree( GetProcessHeap(), 0, buffer );
1308 DPRINT("Returning %d '%s'\n", ret, str );
1309 return ret;
1310 }
1311
1312 /***********************************************************************
1313 * GetDlgItemEnumProc
1314 *
1315 * Callback for GetDlgItem
1316 */
1317 BOOL CALLBACK GetDlgItemEnumProc (HWND hwnd, LPARAM lParam )
1318 {
1319 GETDLGITEMINFO * info = (GETDLGITEMINFO *)lParam;
1320 if(info->nIDDlgItem == GetWindowLongW( hwnd, GWL_ID ))
1321 {
1322 info->control = hwnd;
1323 return FALSE;
1324 }
1325 return TRUE;
1326 }
1327
1328
1329 /* FUNCTIONS *****************************************************************/
1330
1331 /*
1332 * @implemented
1333 */
1334 HWND
1335 STDCALL
1336 CreateDialogIndirectParamA(
1337 HINSTANCE hInstance,
1338 LPCDLGTEMPLATE lpTemplate,
1339 HWND hWndParent,
1340 DLGPROC lpDialogFunc,
1341 LPARAM lParamInit)
1342 {
1343 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, FALSE, FALSE );
1344 }
1345
1346
1347 /*
1348 * @unimplemented
1349 */
1350 HWND
1351 STDCALL
1352 CreateDialogIndirectParamAorW(
1353 HINSTANCE hInstance,
1354 LPCDLGTEMPLATE lpTemplate,
1355 HWND hWndParent,
1356 DLGPROC lpDialogFunc,
1357 LPARAM lParamInit)
1358 {
1359 /* FIXME:
1360 This function might be obsolete since I don't think it is exported by NT
1361 Also wine has one more parameter identifying weather it should call
1362 the function with unicode or not */
1363 UNIMPLEMENTED;
1364 return (HWND)0;
1365 }
1366
1367
1368 /*
1369 * @implemented
1370 */
1371 HWND
1372 STDCALL
1373 CreateDialogIndirectParamW(
1374 HINSTANCE hInstance,
1375 LPCDLGTEMPLATE lpTemplate,
1376 HWND hWndParent,
1377 DLGPROC lpDialogFunc,
1378 LPARAM lParamInit)
1379 {
1380 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, TRUE, FALSE );
1381 }
1382
1383
1384 /*
1385 * @implemented
1386 */
1387 HWND
1388 STDCALL
1389 CreateDialogParamA(
1390 HINSTANCE hInstance,
1391 LPCSTR lpTemplateName,
1392 HWND hWndParent,
1393 DLGPROC lpDialogFunc,
1394 LPARAM dwInitParam)
1395 {
1396 HRSRC hrsrc;
1397 LPCDLGTEMPLATE ptr;
1398
1399 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1400 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1401 return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1402 }
1403
1404
1405 /*
1406 * @implemented
1407 */
1408 HWND
1409 STDCALL
1410 CreateDialogParamW(
1411 HINSTANCE hInstance,
1412 LPCWSTR lpTemplateName,
1413 HWND hWndParent,
1414 DLGPROC lpDialogFunc,
1415 LPARAM dwInitParam)
1416 {
1417 HRSRC hrsrc;
1418 LPCDLGTEMPLATE ptr;
1419
1420 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1421 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1422 return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1423 }
1424
1425
1426 /*
1427 * @implemented
1428 */
1429 LRESULT
1430 STDCALL
1431 DefDlgProcA(
1432 HWND hDlg,
1433 UINT Msg,
1434 WPARAM wParam,
1435 LPARAM lParam)
1436 {
1437 WNDPROC dlgproc;
1438 BOOL result = FALSE;
1439 DIALOGINFO * dlgInfo;
1440
1441 /* if there's no dialog info property then call default windows proc?? */
1442 if (!(dlgInfo = GETDLGINFO(hDlg)))
1443 return DefWindowProcA( hDlg, Msg, wParam, lParam );
1444
1445 SetWindowLongW( hDlg, DWL_MSGRESULT, 0 );
1446
1447 if ((dlgproc = (WNDPROC)GetWindowLongA( hDlg, DWL_DLGPROC )))
1448 {
1449 /* Call dialog procedure */
1450 result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam );
1451 }
1452
1453 if (!result && IsWindow(hDlg))
1454 {
1455 /* callback didn't process this message */
1456
1457 switch(Msg)
1458 {
1459 case WM_ERASEBKGND:
1460 case WM_SHOWWINDOW:
1461 case WM_ACTIVATE:
1462 case WM_SETFOCUS:
1463 case DM_SETDEFID:
1464 case DM_GETDEFID:
1465 case WM_NEXTDLGCTL:
1466 case WM_GETFONT:
1467 case WM_CLOSE:
1468 case WM_NCDESTROY:
1469 case WM_ENTERMENULOOP:
1470 case WM_LBUTTONDOWN:
1471 case WM_NCLBUTTONDOWN:
1472 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1473 case WM_INITDIALOG:
1474 case WM_VKEYTOITEM:
1475 case WM_COMPAREITEM:
1476 case WM_CHARTOITEM:
1477 break;
1478
1479 default:
1480 return DefWindowProcA( hDlg, Msg, wParam, lParam );
1481 }
1482 }
1483 return DEFDLG_Epilog(hDlg, Msg, result);
1484 }
1485
1486
1487 /*
1488 * @implemented
1489 */
1490 LRESULT
1491 STDCALL
1492 DefDlgProcW(
1493 HWND hDlg,
1494 UINT Msg,
1495 WPARAM wParam,
1496 LPARAM lParam)
1497 {
1498 WNDPROC dlgproc;
1499 BOOL result = FALSE;
1500 DIALOGINFO * dlgInfo;
1501
1502 /* if there's no dialog info property then call default windows proc?? */
1503 if (!(dlgInfo = GETDLGINFO(hDlg)))
1504 return DefWindowProcW( hDlg, Msg, wParam, lParam );
1505
1506 SetWindowLongW( hDlg, DWL_MSGRESULT, 0 );
1507
1508 if ((dlgproc = (WNDPROC)GetWindowLongW( hDlg, DWL_DLGPROC )))
1509 {
1510 /* Call dialog procedure */
1511 result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam );
1512 }
1513
1514 if (!result && IsWindow(hDlg))
1515 {
1516 /* callback didn't process this message */
1517
1518 switch(Msg)
1519 {
1520 case WM_ERASEBKGND:
1521 case WM_SHOWWINDOW:
1522 case WM_ACTIVATE:
1523 case WM_SETFOCUS:
1524 case DM_SETDEFID:
1525 case DM_GETDEFID:
1526 case WM_NEXTDLGCTL:
1527 case WM_GETFONT:
1528 case WM_CLOSE:
1529 case WM_NCDESTROY:
1530 case WM_ENTERMENULOOP:
1531 case WM_LBUTTONDOWN:
1532 case WM_NCLBUTTONDOWN:
1533 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1534 case WM_INITDIALOG:
1535 case WM_VKEYTOITEM:
1536 case WM_COMPAREITEM:
1537 case WM_CHARTOITEM:
1538 break;
1539
1540 default:
1541 return DefWindowProcW( hDlg, Msg, wParam, lParam );
1542 }
1543 }
1544 return DEFDLG_Epilog(hDlg, Msg, result);
1545 }
1546
1547
1548 /*
1549 * @implemented
1550 */
1551 INT_PTR
1552 STDCALL
1553 DialogBoxIndirectParamA(
1554 HINSTANCE hInstance,
1555 LPCDLGTEMPLATE hDialogTemplate,
1556 HWND hWndParent,
1557 DLGPROC lpDialogFunc,
1558 LPARAM dwInitParam)
1559 {
1560 HWND hwnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, FALSE, TRUE );
1561 if (hwnd) return DIALOG_DoDialogBox( hwnd, hWndParent );
1562 return -1;
1563 }
1564
1565
1566 /*
1567 * @unimplemented
1568 */
1569 INT_PTR
1570 STDCALL
1571 DialogBoxIndirectParamAorW(
1572 HINSTANCE hInstance,
1573 LPCDLGTEMPLATE hDialogTemplate,
1574 HWND hWndParent,
1575 DLGPROC lpDialogFunc,
1576 LPARAM dwInitParam)
1577 {
1578 /* FIXME:
1579 This function might be obsolete since I don't think it is exported by NT
1580 Also wine has one more parameter identifying weather it should call
1581 the function with unicode or not */
1582 UNIMPLEMENTED;
1583 return (INT_PTR)NULL;
1584 }
1585
1586
1587 /*
1588 * @implemented
1589 */
1590 INT_PTR
1591 STDCALL
1592 DialogBoxIndirectParamW(
1593 HINSTANCE hInstance,
1594 LPCDLGTEMPLATE hDialogTemplate,
1595 HWND hWndParent,
1596 DLGPROC lpDialogFunc,
1597 LPARAM dwInitParam)
1598 {
1599 HWND hwnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, TRUE, TRUE );
1600 if (hwnd) return DIALOG_DoDialogBox( hwnd, hWndParent );
1601 return -1;
1602 }
1603
1604
1605 /*
1606 * @implemented
1607 */
1608 INT_PTR
1609 STDCALL
1610 DialogBoxParamA(
1611 HINSTANCE hInstance,
1612 LPCSTR lpTemplateName,
1613 HWND hWndParent,
1614 DLGPROC lpDialogFunc,
1615 LPARAM dwInitParam)
1616 {
1617 HWND hwnd;
1618 HRSRC hrsrc;
1619 LPCDLGTEMPLATE ptr;
1620
1621 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1622 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1623 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, TRUE);
1624 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1625 return -1;
1626 }
1627
1628
1629 /*
1630 * @implemented
1631 */
1632 INT_PTR
1633 STDCALL
1634 DialogBoxParamW(
1635 HINSTANCE hInstance,
1636 LPCWSTR lpTemplateName,
1637 HWND hWndParent,
1638 DLGPROC lpDialogFunc,
1639 LPARAM dwInitParam)
1640 {
1641 HWND hwnd;
1642 HRSRC hrsrc;
1643 LPCDLGTEMPLATE ptr;
1644
1645 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1646 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1647 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, TRUE);
1648 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1649 return -1;
1650 }
1651
1652
1653 /*
1654 * @implemented
1655 */
1656 int
1657 STDCALL
1658 DlgDirListA(
1659 HWND hDlg,
1660 LPSTR lpPathSpec,
1661 int nIDListBox,
1662 int nIDStaticPath,
1663 UINT uFileType)
1664 {
1665 return DIALOG_DlgDirList( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1666 }
1667
1668
1669 /*
1670 * @unimplemented
1671 */
1672 int
1673 STDCALL
1674 DlgDirListComboBoxA(
1675 HWND hDlg,
1676 LPSTR lpPathSpec,
1677 int nIDComboBox,
1678 int nIDStaticPath,
1679 UINT uFiletype)
1680 {
1681 UNIMPLEMENTED;
1682 return 0;
1683 }
1684
1685
1686 /*
1687 * @unimplemented
1688 */
1689 int
1690 STDCALL
1691 DlgDirListComboBoxW(
1692 HWND hDlg,
1693 LPWSTR lpPathSpec,
1694 int nIDComboBox,
1695 int nIDStaticPath,
1696 UINT uFiletype)
1697 {
1698 UNIMPLEMENTED;
1699 return 0;
1700 }
1701
1702
1703 /*
1704 * @implemented
1705 */
1706 int
1707 STDCALL
1708 DlgDirListW(
1709 HWND hDlg,
1710 LPWSTR lpPathSpec,
1711 int nIDListBox,
1712 int nIDStaticPath,
1713 UINT uFileType)
1714 {
1715 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1716 }
1717
1718
1719 /*
1720 * @unimplemented
1721 */
1722 BOOL
1723 STDCALL
1724 DlgDirSelectComboBoxExA(
1725 HWND hDlg,
1726 LPSTR lpString,
1727 int nCount,
1728 int nIDComboBox)
1729 {
1730 UNIMPLEMENTED;
1731 return FALSE;
1732 }
1733
1734
1735 /*
1736 * @unimplemented
1737 */
1738 BOOL
1739 STDCALL
1740 DlgDirSelectComboBoxExW(
1741 HWND hDlg,
1742 LPWSTR lpString,
1743 int nCount,
1744 int nIDComboBox)
1745 {
1746 UNIMPLEMENTED;
1747 return FALSE;
1748 }
1749
1750
1751 /*
1752 * @implemented
1753 */
1754 BOOL
1755 STDCALL
1756 DlgDirSelectExA(
1757 HWND hDlg,
1758 LPSTR lpString,
1759 int nCount,
1760 int nIDListBox)
1761 {
1762 return DIALOG_DlgDirSelect( hDlg, lpString, nCount, nIDListBox, FALSE, FALSE );
1763 }
1764
1765
1766 /*
1767 * @implemented
1768 */
1769 BOOL
1770 STDCALL
1771 DlgDirSelectExW(
1772 HWND hDlg,
1773 LPWSTR lpString,
1774 int nCount,
1775 int nIDListBox)
1776 {
1777 return DIALOG_DlgDirSelect( hDlg, (LPSTR)lpString, nCount, nIDListBox, TRUE, FALSE );
1778 }
1779
1780
1781 /*
1782 * @implemented
1783 */
1784 BOOL
1785 STDCALL
1786 EndDialog(
1787 HWND hDlg,
1788 INT_PTR nResult)
1789 {
1790 BOOL wasEnabled = TRUE;
1791 DIALOGINFO * dlgInfo;
1792 HWND owner;
1793
1794 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
1795
1796 dlgInfo->idResult = nResult;
1797 dlgInfo->flags |= DF_END;
1798 wasEnabled = (dlgInfo->flags & DF_OWNERENABLED);
1799
1800 if (wasEnabled && (owner = GetWindow( hDlg, GW_OWNER )))
1801 DIALOG_EnableOwner( owner );
1802
1803 /* Windows sets the focus to the dialog itself in EndDialog */
1804
1805 if (IsChild(hDlg, GetFocus()))
1806 SetFocus( hDlg );
1807
1808 /* Don't have to send a ShowWindow(SW_HIDE), just do
1809 SetWindowPos with SWP_HIDEWINDOW as done in Windows */
1810
1811 SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
1812 | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
1813
1814 /* unblock dialog loop */
1815 PostMessageA(hDlg, WM_NULL, 0, 0);
1816 return TRUE;
1817 }
1818
1819
1820 /*
1821 * @implemented
1822 */
1823 LONG
1824 STDCALL
1825 GetDialogBaseUnits(VOID)
1826 {
1827 static DWORD units;
1828
1829 if (!units)
1830 {
1831 HDC hdc;
1832 SIZE size;
1833
1834 if ((hdc = GetDC(0)))
1835 {
1836 size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
1837 if (size.cx) units = MAKELONG( size.cx, size.cy );
1838 ReleaseDC( 0, hdc );
1839 }
1840 }
1841 return units;
1842 }
1843
1844
1845 /*
1846 * @implemented
1847 */
1848 int
1849 STDCALL
1850 GetDlgCtrlID(
1851 HWND hwndCtl)
1852 {
1853 return GetWindowLongW( hwndCtl, GWL_ID );
1854 }
1855
1856
1857 /*
1858 * @implemented
1859 */
1860 HWND
1861 STDCALL
1862 GetDlgItem(
1863 HWND hDlg,
1864 int nIDDlgItem)
1865 {
1866 GETDLGITEMINFO info;
1867 info.nIDDlgItem = nIDDlgItem;
1868 info.control = 0;
1869 if(hDlg && !EnumChildWindows(hDlg, (WNDENUMPROC)&GetDlgItemEnumProc, (LPARAM)&info))
1870 return info.control;
1871 else
1872 return 0;
1873 }
1874
1875
1876 /*
1877 * @implemented
1878 */
1879 UINT
1880 STDCALL
1881 GetDlgItemInt(
1882 HWND hDlg,
1883 int nIDDlgItem,
1884 BOOL *lpTranslated,
1885 BOOL bSigned)
1886 {
1887 char str[30];
1888 char * endptr;
1889 long result = 0;
1890
1891 if (lpTranslated) *lpTranslated = FALSE;
1892 if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str))
1893 return 0;
1894 if (bSigned)
1895 {
1896 result = strtol( str, &endptr, 10 );
1897 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
1898 return 0;
1899 /* FIXME: errno? */
1900 if (((result == 0) || (result == 0xFFFFFFFF))/* && (errno == ERANGE) */)
1901 return 0;
1902 }
1903 else
1904 {
1905 result = strtoul( str, &endptr, 10 );
1906 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
1907 return 0;
1908 /* FIXME: errno? */
1909 if ((result == 0xFFFFFFFF)/* && (errno == ERANGE) */) return 0;
1910 }
1911 if (lpTranslated) *lpTranslated = TRUE;
1912 return (UINT)result;
1913 }
1914
1915
1916 /*
1917 * @implemented
1918 */
1919 UINT
1920 STDCALL
1921 GetDlgItemTextA(
1922 HWND hDlg,
1923 int nIDDlgItem,
1924 LPSTR lpString,
1925 int nMaxCount)
1926 {
1927 return (UINT)SendDlgItemMessageA( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
1928 }
1929
1930
1931 /*
1932 * @implemented
1933 */
1934 UINT
1935 STDCALL
1936 GetDlgItemTextW(
1937 HWND hDlg,
1938 int nIDDlgItem,
1939 LPWSTR lpString,
1940 int nMaxCount)
1941 {
1942 return (UINT)SendDlgItemMessageW( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
1943 }
1944
1945
1946 /*
1947 * @implemented
1948 */
1949 HWND
1950 STDCALL
1951 GetNextDlgGroupItem(
1952 HWND hDlg,
1953 HWND hCtl,
1954 BOOL bPrevious)
1955 {
1956 HWND hwnd, retvalue;
1957
1958 if(hCtl)
1959 {
1960 /* if the hwndCtrl is the child of the control in the hwndDlg,
1961 * then the hwndDlg has to be the parent of the hwndCtrl */
1962 if(GetParent(hCtl) != hDlg && GetParent(GetParent(hCtl)) == hDlg)
1963 hDlg = GetParent(hCtl);
1964 }
1965
1966 if (hCtl)
1967 {
1968 /* Make sure hwndCtrl is a top-level child */
1969 HWND parent = GetParent( hCtl );
1970 while (parent && parent != hDlg) parent = GetParent(parent);
1971 if (parent != hDlg) return 0;
1972 }
1973 else
1974 {
1975 /* No ctrl specified -> start from the beginning */
1976 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
1977 if (bPrevious) hCtl = GetWindow( hCtl, GW_HWNDLAST );
1978 }
1979
1980 retvalue = hCtl;
1981 hwnd = GetWindow( hCtl, GW_HWNDNEXT );
1982 while (1)
1983 {
1984 if (!hwnd || (GetWindowLongW( hwnd, GWL_STYLE ) & WS_GROUP))
1985 {
1986 /* Wrap-around to the beginning of the group */
1987 HWND tmp;
1988
1989 hwnd = GetWindow( hDlg, GW_CHILD );
1990 for (tmp = hwnd; tmp; tmp = GetWindow( tmp, GW_HWNDNEXT ) )
1991 {
1992 if (GetWindowLongW( tmp, GWL_STYLE ) & WS_GROUP) hwnd = tmp;
1993 if (tmp == hCtl) break;
1994 }
1995 }
1996 if (hwnd == hCtl) break;
1997 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
1998 {
1999 retvalue = hwnd;
2000 if (!bPrevious) break;
2001 }
2002 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
2003 }
2004 return retvalue;
2005 }
2006
2007
2008 /*
2009 * @implemented
2010 */
2011 HWND
2012 STDCALL
2013 GetNextDlgTabItem(
2014 HWND hDlg,
2015 HWND hCtl,
2016 BOOL bPrevious)
2017 {
2018 return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious);
2019 }
2020
2021 #if 0
2022 BOOL
2023 STDCALL
2024 IsDialogMessage(
2025 HWND hDlg,
2026 LPMSG lpMsg)
2027 {
2028 return IsDialogMessageW(hDlg, lpMsg);
2029 }
2030 #endif
2031
2032
2033 /*
2034 * @implemented
2035 */
2036 BOOL
2037 STDCALL
2038 IsDialogMessageA(
2039 HWND hDlg,
2040 LPMSG lpMsg)
2041 {
2042 INT dlgCode = 0;
2043
2044 // FIXME: hooks
2045 if (CallMsgFilterA( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2046
2047 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
2048
2049 hDlg = DIALOG_FindMsgDestination(hDlg);
2050
2051 switch(lpMsg->message)
2052 {
2053 case WM_KEYDOWN:
2054 dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2055 if (dlgCode & DLGC_WANTMESSAGE) break;
2056
2057 switch(lpMsg->wParam)
2058 {
2059 case VK_TAB:
2060 if (!(dlgCode & DLGC_WANTTAB))
2061 {
2062 SendMessageA( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
2063 return TRUE;
2064 }
2065 break;
2066
2067 case VK_RIGHT:
2068 case VK_DOWN:
2069 case VK_LEFT:
2070 case VK_UP:
2071 if (!(dlgCode & DLGC_WANTARROWS))
2072 {
2073 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
2074 HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
2075 SendMessageA( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2076 return TRUE;
2077 }
2078 break;
2079
2080 case VK_CANCEL:
2081 case VK_ESCAPE:
2082 SendMessageA( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2083 return TRUE;
2084
2085 case VK_EXECUTE:
2086 case VK_RETURN:
2087 {
2088 DWORD dw = SendMessageA( hDlg, DM_GETDEFID, 0, 0 );
2089 if (HIWORD(dw) == DC_HASDEFID)
2090 {
2091 SendMessageA( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
2092 (LPARAM)GetDlgItem(hDlg, LOWORD(dw)));
2093 }
2094 else
2095 {
2096 SendMessageA( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2097
2098 }
2099 }
2100 return TRUE;
2101 }
2102 break;
2103
2104 case WM_CHAR:
2105 dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2106 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2107 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2108 /* drop through */
2109
2110 case WM_SYSCHAR:
2111 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2112 {
2113 /* don't translate or dispatch */
2114 return TRUE;
2115 }
2116 break;
2117 }
2118
2119 TranslateMessage( lpMsg );
2120 DispatchMessageA( lpMsg );
2121 return TRUE;
2122 }
2123
2124
2125 /*
2126 * @implemented
2127 */
2128 BOOL
2129 STDCALL
2130 IsDialogMessageW(
2131 HWND hDlg,
2132 LPMSG lpMsg)
2133 {
2134 INT dlgCode = 0;
2135
2136 // FIXME: hooks
2137 if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2138
2139 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
2140
2141 hDlg = DIALOG_FindMsgDestination(hDlg);
2142
2143 switch(lpMsg->message)
2144 {
2145 case WM_KEYDOWN:
2146 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2147 if (dlgCode & DLGC_WANTMESSAGE) break;
2148
2149 switch(lpMsg->wParam)
2150 {
2151 case VK_TAB:
2152 if (!(dlgCode & DLGC_WANTTAB))
2153 {
2154 SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
2155 return TRUE;
2156 }
2157 break;
2158
2159 case VK_RIGHT:
2160 case VK_DOWN:
2161 case VK_LEFT:
2162 case VK_UP:
2163 if (!(dlgCode & DLGC_WANTARROWS))
2164 {
2165 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
2166 HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
2167 SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2168 return TRUE;
2169 }
2170 break;
2171
2172 case VK_CANCEL:
2173 case VK_ESCAPE:
2174 SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2175 return TRUE;
2176
2177 case VK_EXECUTE:
2178 case VK_RETURN:
2179 {
2180 DWORD dw = SendMessageW( hDlg, DM_GETDEFID, 0, 0 );
2181 if (HIWORD(dw) == DC_HASDEFID)
2182 {
2183 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
2184 (LPARAM)GetDlgItem(hDlg, LOWORD(dw)));
2185 }
2186 else
2187 {
2188 SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2189
2190 }
2191 }
2192 return TRUE;
2193 }
2194 break;
2195
2196 case WM_CHAR:
2197 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2198 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2199 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2200 /* drop through */
2201
2202 case WM_SYSCHAR:
2203 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2204 {
2205 /* don't translate or dispatch */
2206 return TRUE;
2207 }
2208 break;
2209 }
2210
2211 TranslateMessage( lpMsg );
2212 DispatchMessageW( lpMsg );
2213 return TRUE;
2214 }
2215
2216
2217 /*
2218 * @implemented
2219 */
2220 UINT
2221 STDCALL
2222 IsDlgButtonChecked(
2223 HWND hDlg,
2224 int nIDButton)
2225 {
2226 return (UINT)SendDlgItemMessageA( hDlg, nIDButton, BM_GETCHECK, 0, 0 );
2227 }
2228
2229
2230 /*
2231 * @implemented
2232 */
2233 BOOL
2234 STDCALL
2235 MapDialogRect(
2236 HWND hDlg,
2237 LPRECT lpRect)
2238 {
2239 DIALOGINFO * dlgInfo;
2240 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
2241 lpRect->left = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4);
2242 lpRect->right = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4);
2243 lpRect->top = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8);
2244 lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8);
2245 return TRUE;
2246 }
2247
2248
2249 /*
2250 * @implemented
2251 */
2252 LRESULT
2253 STDCALL
2254 SendDlgItemMessageA(
2255 HWND hDlg,
2256 int nIDDlgItem,
2257 UINT Msg,
2258 WPARAM wParam,
2259 LPARAM lParam)
2260 {
2261 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2262 if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam );
2263 else return 0;
2264 }
2265
2266
2267 /*
2268 * @implemented
2269 */
2270 LRESULT
2271 STDCALL
2272 SendDlgItemMessageW(
2273 HWND hDlg,
2274 int nIDDlgItem,
2275 UINT Msg,
2276 WPARAM wParam,
2277 LPARAM lParam)
2278 {
2279 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2280 if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam );
2281 else return 0;
2282 }
2283
2284
2285 /*
2286 * @implemented
2287 */
2288 BOOL
2289 STDCALL
2290 SetDlgItemInt(
2291 HWND hDlg,
2292 int nIDDlgItem,
2293 UINT uValue,
2294 BOOL bSigned)
2295 {
2296 char str[20];
2297
2298 if (bSigned) sprintf( str, "%d", (INT)uValue );
2299 else sprintf( str, "%u", uValue );
2300 SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str );
2301 return TRUE;
2302 }
2303
2304
2305 /*
2306 * @implemented
2307 */
2308 BOOL
2309 STDCALL
2310 SetDlgItemTextA(
2311 HWND hDlg,
2312 int nIDDlgItem,
2313 LPCSTR lpString)
2314 {
2315 return SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)lpString );
2316 }
2317
2318
2319 /*
2320 * @implemented
2321 */
2322 BOOL
2323 STDCALL
2324 SetDlgItemTextW(
2325 HWND hDlg,
2326 int nIDDlgItem,
2327 LPCWSTR lpString)
2328 {
2329 return SendDlgItemMessageW( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)lpString );
2330 }
2331
2332
2333 /*
2334 * @implemented
2335 */
2336 BOOL
2337 STDCALL
2338 CheckDlgButton(
2339 HWND hDlg,
2340 int nIDButton,
2341 UINT uCheck)
2342 {
2343 SendDlgItemMessageA( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 );
2344 return TRUE;
2345 }
2346
2347 static BOOL CALLBACK CheckRB(HWND hwnd, LPARAM lParam)
2348 {
2349 LONG lChildID = GetWindowLongW(hwnd, GWL_ID);
2350 RADIOGROUP *lpRadioGroup = (RADIOGROUP *)lParam;
2351
2352 if((lChildID >= lpRadioGroup->firstID) &&
2353 (lChildID <= lpRadioGroup->lastID))
2354 {
2355 if (lChildID == lpRadioGroup->checkID)
2356 {
2357 SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0);
2358 }
2359 else
2360 {
2361 SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
2362 }
2363 }
2364
2365 return TRUE;
2366 }
2367
2368 /*
2369 * @implemented
2370 */
2371 BOOL
2372 STDCALL
2373 CheckRadioButton(
2374 HWND hDlg,
2375 int nIDFirstButton,
2376 int nIDLastButton,
2377 int nIDCheckButton)
2378 {
2379 RADIOGROUP radioGroup;
2380
2381 radioGroup.firstID = nIDFirstButton;
2382 radioGroup.lastID = nIDLastButton;
2383 radioGroup.checkID = nIDCheckButton;
2384
2385 return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup);
2386 }
2387