source: trunk/src/user32/new/dialog.cpp@ 649

Last change on this file since 649 was 649, checked in by phaller, 26 years ago

.

File size: 50.3 KB
Line 
1/*
2 * Dialog functions
3 *
4 * Copyright 1993, 1994, 1996 Alexandre Julliard
5 */
6
7#include <os2win.h>
8#include <ctype.h>
9#include <errno.h>
10#include <limits.h>
11#include <stdlib.h>
12#include <string.h>
13#include <stdio.h>
14#include <heapstring.h>
15#include <winuser.h>
16#include <direct.h>
17#include "dialog.h"
18#include "heap.h"
19#include "win.h"
20#include "ldt.h"
21#include "user.h"
22#include "winproc.h"
23
24//ODINDEBUGCHANNEL(USER32-DIALOG)
25
26
27#define SelectFont(hdc, hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT) (hfont)))
28
29int DRIVE_GetCurrentDrive(void) {return(_getdrive());}
30int DRIVE_SetCurrentDrive( int drive ) {return(_chdrive(drive));}
31
32const char * DRIVE_GetDosCwd( int drive )
33{
34 static char szBuf[256];
35 return (_getcwd(szBuf,drive));
36}
37
38int DRIVE_Chdir( int drive, const char *path )
39{
40 _chdrive(drive);
41 return(_chdir((char*)path));
42}
43
44
45
46
47
48
49 /* Dialog control information */
50typedef struct
51{
52 DWORD style;
53 DWORD exStyle;
54 DWORD helpId;
55 INT16 x;
56 INT16 y;
57 INT16 cx;
58 INT16 cy;
59 UINT id;
60 LPCSTR className;
61 LPCSTR windowName;
62 LPVOID data;
63} DLG_CONTROL_INFO;
64
65 /* Dialog template */
66typedef struct
67{
68 DWORD style;
69 DWORD exStyle;
70 DWORD helpId;
71 UINT16 nbItems;
72 INT16 x;
73 INT16 y;
74 INT16 cx;
75 INT16 cy;
76 LPCSTR menuName;
77 LPCSTR className;
78 LPCSTR caption;
79 WORD pointSize;
80 WORD weight;
81 BOOL italic;
82 LPCSTR faceName;
83 BOOL dialogEx;
84} DLG_TEMPLATE;
85
86 /* Radio button group */
87typedef struct
88{
89 UINT firstID;
90 UINT lastID;
91 UINT checkID;
92} RADIOGROUP;
93
94 /* Dialog base units */
95static WORD xBaseUnit = 0, yBaseUnit = 0;
96
97
98
99
100
101
102
103/***********************************************************************
104 * DIALOG_GetCharSizeFromDC
105 *
106 *
107 * Calculates the *true* average size of English characters in the
108 * specified font as oppposed to the one returned by GetTextMetrics.
109 */
110static BOOL DIALOG_GetCharSizeFromDC( HDC hDC, HFONT hFont, SIZE * pSize )
111{
112 BOOL Success = FALSE;
113 HFONT hFontPrev = 0;
114 pSize->cx = xBaseUnit;
115 pSize->cy = yBaseUnit;
116 if ( hDC )
117 {
118 /* select the font */
119 TEXTMETRICA tm;
120 memset(&tm,0,sizeof(tm));
121 if (hFont) hFontPrev = SelectFont(hDC,hFont);
122 if (GetTextMetricsA(hDC,&tm))
123 {
124 pSize->cx = tm.tmAveCharWidth;
125 pSize->cy = tm.tmHeight;
126
127 /* if variable width font */
128 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
129 {
130 SIZE total;
131 static const char szAvgChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
132
133 /* Calculate a true average as opposed to the one returned
134 * by tmAveCharWidth. This works better when dealing with
135 * proportional spaced fonts and (more important) that's
136 * how Microsoft's dialog creation code calculates the size
137 * of the font
138 */
139 if (GetTextExtentPointA(hDC,szAvgChars,sizeof(szAvgChars),&total))
140 {
141 /* round up */
142 pSize->cx = ((2*total.cx/sizeof(szAvgChars)) + 1)/2;
143 Success = TRUE;
144 }
145 }
146 else
147 {
148 Success = TRUE;
149 }
150 }
151
152 /* select the original font */
153 if (hFontPrev) SelectFont(hDC,hFontPrev);
154 }
155 return (Success);
156}
157
158
159/***********************************************************************
160 * DIALOG_GetCharSize
161 *
162 *
163 * Calculates the *true* average size of English characters in the
164 * specified font as oppposed to the one returned by GetTextMetrics.
165 * A convenient variant of DIALOG_GetCharSizeFromDC.
166 */
167static BOOL DIALOG_GetCharSize( HFONT hFont, SIZE * pSize )
168{
169 HDC hDC = GetDC(0);
170 BOOL Success = DIALOG_GetCharSizeFromDC( hDC, hFont, pSize );
171 ReleaseDC(0, hDC);
172 return Success;
173}
174
175
176/***********************************************************************
177 * DIALOG_Init
178 *
179 * Initialisation of the dialog manager.
180 */
181BOOL DIALOG_Init(void)
182{
183 HDC hdc;
184 SIZE size;
185
186 /* Calculate the dialog base units */
187
188 if (!(hdc = O32_CreateDC( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
189 if (!DIALOG_GetCharSizeFromDC( hdc, 0, &size )) return FALSE;
190 DeleteDC( hdc );
191 xBaseUnit = size.cx;
192 yBaseUnit = size.cy;
193
194 dprintf(("USER32: base units = %d,%d\n", xBaseUnit, yBaseUnit ));
195 return TRUE;
196}
197
198
199/***********************************************************************
200 * DIALOG_GetControl32
201 *
202 * Return the class and text of the control pointed to by ptr,
203 * fill the header structure and return a pointer to the next control.
204 */
205static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
206 BOOL dialogEx )
207{
208 if (dialogEx)
209 {
210 info->helpId = GET_DWORD(p); p += 2;
211 info->exStyle = GET_DWORD(p); p += 2;
212 info->style = GET_DWORD(p); p += 2;
213 }
214 else
215 {
216 info->helpId = 0;
217 info->style = GET_DWORD(p); p += 2;
218 info->exStyle = GET_DWORD(p); p += 2;
219 }
220 info->x = GET_WORD(p); p++;
221 info->y = GET_WORD(p); p++;
222 info->cx = GET_WORD(p); p++;
223 info->cy = GET_WORD(p); p++;
224
225 if (dialogEx)
226 {
227 /* id is a DWORD for DIALOGEX */
228 info->id = GET_DWORD(p);
229 p += 2;
230 }
231 else
232 {
233 info->id = GET_WORD(p);
234 p++;
235 }
236
237 if (GET_WORD(p) == 0xffff)
238 {
239 static const WCHAR class_names[6][10] =
240 {
241 { 'B','u','t','t','o','n', }, /* 0x80 */
242 { 'E','d','i','t', }, /* 0x81 */
243 { 'S','t','a','t','i','c', }, /* 0x82 */
244 { 'L','i','s','t','B','o','x', }, /* 0x83 */
245 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
246 { 'C','o','m','b','o','B','o','x', } /* 0x85 */
247 };
248 WORD id = GET_WORD(p+1);
249 if ((id >= 0x80) && (id <= 0x85))
250 info->className = (LPCSTR)class_names[id - 0x80];
251 else
252 {
253 info->className = NULL;
254 dprintf(("USER32: Error-Unknown built-in class id %04x\n", id ));
255 }
256 p += 2;
257 }
258 else
259 {
260 info->className = (LPCSTR)p;
261 p += lstrlenW( (LPCWSTR)p ) + 1;
262 }
263
264 if (GET_WORD(p) == 0xffff) /* Is it an integer id? */
265 {
266 info->windowName = (LPCSTR)(UINT)GET_WORD(p + 1);
267 p += 2;
268 }
269 else
270 {
271 info->windowName = (LPCSTR)p;
272 p += lstrlenW( (LPCWSTR)p ) + 1;
273 }
274
275 dprintf(("USER32: %ls %ls %d, %d, %d, %d, %d, %08lx, %08lx, %08lx\n",
276 (LPCWSTR)info->className,
277 (LPCWSTR)info->windowName,
278 info->id, info->x, info->y, info->cx, info->cy,
279 info->style, info->exStyle, info->helpId ));
280
281 if (GET_WORD(p))
282 {
283 info->data = (LPVOID)(p + 1);
284 p += GET_WORD(p) / sizeof(WORD);
285 }
286 else info->data = NULL;
287 p++;
288
289 /* Next control is on dword boundary */
290 return (const WORD *)((((int)p) + 3) & ~3);
291}
292
293
294/***********************************************************************
295 * DIALOG_CreateControls
296 *
297 * Create the control windows for a dialog.
298 */
299static BOOL DIALOG_CreateControls( WND *pWnd, LPCSTR strTemplate,
300 const DLG_TEMPLATE *dlgTemplate,
301 HINSTANCE hInst)
302{
303 DIALOGINFO *dlgInfo = (DIALOGINFO *)pWnd->wExtra;
304 DLG_CONTROL_INFO info;
305 HWND hwndCtrl, hwndDefButton = 0;
306 INT items = dlgTemplate->nbItems;
307
308 dprintf(("USER32: BEGIN\n" ));
309 while (items--)
310 {
311 {
312 strTemplate = (LPCSTR)DIALOG_GetControl32( (WORD *)strTemplate, &info,
313 dlgTemplate->dialogEx );
314 hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
315 (LPCWSTR)info.className,
316 (LPCWSTR)info.windowName,
317 info.style | WS_CHILD,
318 info.x * dlgInfo->xBaseUnit / 4,
319 info.y * dlgInfo->yBaseUnit / 8,
320 info.cx * dlgInfo->xBaseUnit / 4,
321 info.cy * dlgInfo->yBaseUnit / 8,
322 pWnd->hwndSelf, (HMENU)info.id,
323 hInst, info.data );
324 }
325 if (!hwndCtrl) return FALSE;
326
327 /* Send initialisation messages to the control */
328 if (dlgInfo->hUserFont) SendMessageA( hwndCtrl, WM_SETFONT,
329 (WPARAM)dlgInfo->hUserFont, 0 );
330 if (SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
331 {
332 /* If there's already a default push-button, set it back */
333 /* to normal and use this one instead. */
334 if (hwndDefButton)
335 SendMessageA( hwndDefButton, BM_SETSTYLE,
336 BS_PUSHBUTTON,FALSE );
337 hwndDefButton = hwndCtrl;
338 dlgInfo->idResult = GetWindowWord( hwndCtrl, GWW_ID );
339 }
340 }
341 dprintf(("USER32: END\n" ));
342 return TRUE;
343}
344
345
346/***********************************************************************
347 * DIALOG_ParseTemplate32
348 *
349 * Fill a DLG_TEMPLATE structure from the dialog template, and return
350 * a pointer to the first control.
351 */
352static LPCSTR DIALOG_ParseTemplate32( LPCSTR strTemplate, DLG_TEMPLATE * result )
353{
354 const WORD *p = (const WORD *)strTemplate;
355
356 result->style = GET_DWORD(p); p += 2;
357 if (result->style == 0xffff0001) /* DIALOGEX resource */
358 {
359 result->dialogEx = TRUE;
360 result->helpId = GET_DWORD(p); p += 2;
361 result->exStyle = GET_DWORD(p); p += 2;
362 result->style = GET_DWORD(p); p += 2;
363 }
364 else
365 {
366 result->dialogEx = FALSE;
367 result->helpId = 0;
368 result->exStyle = GET_DWORD(p); p += 2;
369 }
370 result->nbItems = GET_WORD(p); p++;
371 result->x = GET_WORD(p); p++;
372 result->y = GET_WORD(p); p++;
373 result->cx = GET_WORD(p); p++;
374 result->cy = GET_WORD(p); p++;
375 dprintf(("USER32:DIALOG%s %d, %d, %d, %d, %ld\n",
376 result->dialogEx ? "EX" : "", result->x, result->y,
377 result->cx, result->cy, result->helpId ));
378 dprintf(("USER32: STYLE 0x%08lx\n", result->style ));
379 dprintf(("USER32: EXSTYLE 0x%08lx\n", result->exStyle ));
380
381 /* Get the menu name */
382
383 switch(GET_WORD(p))
384 {
385 case 0x0000:
386 result->menuName = NULL;
387 p++;
388 break;
389 case 0xffff:
390 result->menuName = (LPCSTR)(UINT)GET_WORD( p + 1 );
391 p += 2;
392 dprintf(("USER32: MENU %04x\n", LOWORD(result->menuName) ));
393 break;
394 default:
395 result->menuName = (LPCSTR)p;
396 dprintf(("USER32: MENU %ls\n", (LPCWSTR)p ));
397 p += lstrlenW( (LPCWSTR)p ) + 1;
398 break;
399 }
400
401 /* Get the class name */
402
403 switch(GET_WORD(p))
404 {
405 case 0x0000:
406 result->className = DIALOG_CLASS_ATOM;
407 p++;
408 break;
409 case 0xffff:
410 result->className = (LPCSTR)(UINT)GET_WORD( p + 1 );
411 p += 2;
412 dprintf(("USER32: CLASS %04x\n", LOWORD(result->className) ));
413 break;
414 default:
415 result->className = (LPCSTR)p;
416 dprintf(("USER32: CLASS %ls\n", (LPCWSTR)p ));
417 p += lstrlenW( (LPCWSTR)p ) + 1;
418 break;
419 }
420
421 /* Get the window caption */
422
423 result->caption = (LPCSTR)p;
424 p += lstrlenW( (LPCWSTR)p ) + 1;
425 dprintf(("USER32: CAPTION %ls\n", (LPCWSTR)result->caption ));
426
427 /* Get the font name */
428
429 if (result->style & DS_SETFONT)
430 {
431 result->pointSize = GET_WORD(p);
432 p++;
433 if (result->dialogEx)
434 {
435 result->weight = GET_WORD(p); p++;
436 result->italic = LOBYTE(GET_WORD(p)); p++;
437 }
438 else
439 {
440 result->weight = FW_DONTCARE;
441 result->italic = FALSE;
442 }
443 result->faceName = (LPCSTR)p;
444 p += lstrlenW( (LPCWSTR)p ) + 1;
445 dprintf(("USER32: FONT %d, %ls, %d, %s\n",
446 result->pointSize, (LPCWSTR)result->faceName,
447 result->weight, result->italic ? "TRUE" : "FALSE" ));
448 }
449
450 /* First control is on dword boundary */
451 return (LPCSTR)((((int)p) + 3) & ~3);
452}
453
454
455/***********************************************************************
456 * DIALOG_CreateIndirect
457 */
458HWND DIALOG_CreateIndirect( HINSTANCE hInst,
459 LPCSTR dlgTemplate,
460 HWND owner,
461 DLGPROC16 dlgProc,
462 LPARAM param,
463 WINDOWPROCTYPE procType )
464{
465 HMENU16 hMenu = 0;
466 HFONT16 hFont = 0;
467 HWND hwnd;
468 RECT rect;
469 WND * wndPtr;
470 DLG_TEMPLATE strTemplate;
471 DIALOGINFO * dlgInfo;
472 WORD xUnit = xBaseUnit;
473 WORD yUnit = yBaseUnit;
474
475 /* Parse dialog template */
476
477 if (!dlgTemplate) return 0;
478 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &strTemplate );
479
480 /* Load menu */
481
482 if (strTemplate.menuName)
483 hMenu = LoadMenuW( hInst, (LPCWSTR)strTemplate.menuName );
484
485 /* Create custom font if needed */
486
487 if (strTemplate.style & DS_SETFONT)
488 {
489 /* The font height must be negative as it is a point size */
490 /* (see CreateFont() documentation in the Windows SDK). */
491
492 hFont = CreateFontW( -strTemplate.pointSize, 0, 0, 0,
493 strTemplate.weight, strTemplate.italic, FALSE,
494 FALSE, DEFAULT_CHARSET, 0, 0, PROOF_QUALITY,
495 FF_DONTCARE, (LPCWSTR)strTemplate.faceName );
496 }
497
498 /* Create dialog main window */
499
500 rect.left = rect.top = 0;
501 rect.right = strTemplate.cx * xUnit / 4;
502 rect.bottom = strTemplate.cy * yUnit / 8;
503 if (strTemplate.style & DS_MODALFRAME)
504 strTemplate.exStyle |= WS_EX_DLGMODALFRAME;
505 AdjustWindowRectEx( &rect, strTemplate.style,
506 hMenu ? TRUE : FALSE , strTemplate.exStyle );
507 rect.right -= rect.left;
508 rect.bottom -= rect.top;
509
510 if ((INT16)strTemplate.x == CW_USEDEFAULT16)
511 {
512 rect.left = rect.top = CW_USEDEFAULT;
513 }
514 else
515 {
516 if (strTemplate.style & DS_CENTER)
517 {
518 rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
519 rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
520 }
521 else
522 {
523 rect.left += strTemplate.x * xUnit / 4;
524 rect.top += strTemplate.y * yUnit / 8;
525 }
526 if ( !(strTemplate.style & WS_CHILD) )
527 {
528 INT16 dX, dY;
529
530 if( !(strTemplate.style & DS_ABSALIGN) )
531 ClientToScreen( owner, (POINT *)&rect );
532
533 /* try to fit it into the desktop */
534
535 if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
536 - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
537 if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
538 - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
539 if( rect.left < 0 ) rect.left = 0;
540 if( rect.top < 0 ) rect.top = 0;
541 }
542 }
543
544 hwnd = CreateWindowExW(strTemplate.exStyle, (LPCWSTR)strTemplate.className,
545 (LPCWSTR)strTemplate.caption,
546 strTemplate.style & ~WS_VISIBLE,
547 rect.left, rect.top, rect.right, rect.bottom,
548 owner, hMenu, hInst, NULL );
549
550 if (!hwnd)
551 {
552 if (hFont) DeleteObject( hFont );
553 if (hMenu) DestroyMenu( hMenu );
554 return 0;
555 }
556
557 wndPtr = WIN_FindWndPtr( hwnd );
558 wndPtr->flags |= WIN_ISDIALOG;
559 wndPtr->helpContext = strTemplate.helpId;
560
561 /* Initialise dialog extra data */
562
563 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
564 WINPROC_SetProc( &dlgInfo->dlgProc, (WNDPROC16)dlgProc, procType, WIN_PROC_WINDOW );
565 dlgInfo->hUserFont = hFont;
566 dlgInfo->hMenu = hMenu;
567 dlgInfo->xBaseUnit = xUnit;
568 dlgInfo->yBaseUnit = yUnit;
569 dlgInfo->msgResult = 0;
570 dlgInfo->idResult = 0;
571 dlgInfo->flags = 0;
572 dlgInfo->hDialogHeap = 0;
573
574 if (dlgInfo->hUserFont)
575 SendMessageA( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
576
577 /* Create controls */
578
579 if (DIALOG_CreateControls( wndPtr, dlgTemplate, &strTemplate,
580 hInst))
581 {
582 /* Send initialisation messages and set focus */
583
584 dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
585
586 if (SendMessageA( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
587 SetFocus( dlgInfo->hwndFocus );
588
589 if (strTemplate.style & WS_VISIBLE && !(wndPtr->dwStyle & WS_VISIBLE))
590 {
591 ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
592 UpdateWindow( hwnd );
593 }
594 WIN_ReleaseWndPtr(wndPtr);
595 return hwnd;
596 }
597 WIN_ReleaseWndPtr(wndPtr);
598 if( IsWindow(hwnd) ) DestroyWindow( hwnd );
599 return 0;
600}
601
602
603/***********************************************************************
604 * CreateDialogParam32A (USER32.73)
605 */
606HWND WINAPI CreateDialogParamA( HINSTANCE hInst, LPCSTR name,
607 HWND owner, DLGPROC dlgProc,
608 LPARAM param )
609{
610 HANDLE hrsrc = FindResourceA( hInst, name, RT_DIALOGA );
611 if (!hrsrc) return 0;
612 return CreateDialogIndirectParamA( hInst,
613 (DLGTEMPLATE*)LoadResource(hInst, hrsrc),
614 owner, dlgProc, param );
615}
616
617
618/***********************************************************************
619 * CreateDialogParam32W (USER32.74)
620 */
621HWND WINAPI CreateDialogParamW( HINSTANCE hInst, LPCWSTR name,
622 HWND owner, DLGPROC dlgProc,
623 LPARAM param )
624{
625 HANDLE hrsrc = FindResourceW( hInst, name, RT_DIALOGW );
626 if (!hrsrc) return 0;
627 return CreateDialogIndirectParamW( hInst,
628 (DLGTEMPLATE*)LoadResource(hInst, hrsrc),
629 owner, dlgProc, param );
630}
631
632
633/***********************************************************************
634 * CreateDialogIndirectParam32A (USER32.69)
635 */
636
637HWND WINAPI CreateDialogIndirectParamA( HINSTANCE hInst,
638 DLGTEMPLATE* dlgTemplate,
639 HWND owner,
640 DLGPROC dlgProc,
641 LPARAM param )
642{
643 return DIALOG_CreateIndirect( hInst, (LPCSTR)dlgTemplate, owner,
644 (DLGPROC16)dlgProc, param, WIN_PROC_32A );
645}
646
647/***********************************************************************
648 * CreateDialogIndirectParam32AorW (USER32.71)
649 */
650HWND WINAPI CreateDialogIndirectParamAorW( HINSTANCE hInst,
651 DLGTEMPLATE* dlgTemplate,
652 HWND owner, DLGPROC dlgProc,
653 LPARAM param )
654{
655 dprintf(("USER32- FIXME-assume WIN_PROC_32W\n"));
656 return DIALOG_CreateIndirect( hInst, (LPCSTR)dlgTemplate, owner,
657 (DLGPROC16)dlgProc, param, WIN_PROC_32W );
658}
659
660/***********************************************************************
661 * CreateDialogIndirectParam32W (USER32.72)
662 */
663HWND WINAPI CreateDialogIndirectParamW( HINSTANCE hInst,
664 DLGTEMPLATE* dlgTemplate,
665 HWND owner, DLGPROC dlgProc,
666 LPARAM param )
667{
668 return DIALOG_CreateIndirect( hInst, (LPCSTR)dlgTemplate, owner,
669 (DLGPROC16)dlgProc, param, WIN_PROC_32W );
670}
671
672
673/***********************************************************************
674 * DIALOG_DoDialogBox
675 */
676INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
677{
678 WND * wndPtr;
679 DIALOGINFO * dlgInfo;
680 MSG msg;
681 INT retval;
682
683 /* Owner must be a top-level window */
684 owner = WIN_GetTopParent( owner );
685 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
686 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
687
688 if (!dlgInfo->flags & DF_END) /* was EndDialog called in WM_INITDIALOG ? */
689 {
690 EnableWindow( owner, FALSE );
691 ShowWindow( hwnd, SW_SHOW );
692
693// while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX,
694// PM_REMOVE, !(wndPtr->dwStyle & DS_NOIDLEMSG), NULL ))
695 while (GetMessageA(&msg, hwnd, owner, MSGF_DIALOGBOX))
696 {
697 if (!IsDialogMessageA( hwnd, &msg))
698 {
699 TranslateMessage( &msg );
700 DispatchMessageA( &msg );
701 }
702 if (dlgInfo->flags & DF_END) break;
703 }
704 EnableWindow( owner, TRUE );
705 }
706 retval = dlgInfo->idResult;
707 WIN_ReleaseWndPtr(wndPtr);
708 DestroyWindow( hwnd );
709 return retval;
710}
711
712
713/***********************************************************************
714 * DialogBoxParam32A (USER32.139)
715 */
716INT WINAPI DialogBoxParamA( HINSTANCE hInst, LPCSTR name,
717 HWND owner, DLGPROC dlgProc, LPARAM param )
718{
719 HWND hwnd = CreateDialogParamA( hInst, name, owner, dlgProc, param );
720 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
721 return -1;
722}
723
724
725/***********************************************************************
726 * DialogBoxParam32W (USER32.140)
727 */
728INT WINAPI DialogBoxParamW( HINSTANCE hInst, LPCWSTR name,
729 HWND owner, DLGPROC dlgProc, LPARAM param )
730{
731 HWND hwnd = CreateDialogParamW( hInst, name, owner, dlgProc, param );
732 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
733 return -1;
734}
735
736
737/***********************************************************************
738 * DialogBoxIndirectParam32A (USER32.136)
739 */
740INT WINAPI DialogBoxIndirectParamA(HINSTANCE hInstance,
741 DLGTEMPLATE* strTemplate,
742 HWND owner,
743 DLGPROC dlgProc,
744 LPARAM param )
745{
746 HWND hwnd = CreateDialogIndirectParamA( hInstance, strTemplate,
747 owner, dlgProc, param );
748 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
749 return -1;
750}
751
752
753/***********************************************************************
754 * DialogBoxIndirectParam32W (USER32.138)
755 */
756INT WINAPI DialogBoxIndirectParamW(HINSTANCE hInstance,
757 DLGTEMPLATE* strTemplate,
758 HWND owner,
759 DLGPROC dlgProc,
760 LPARAM param )
761{
762 HWND hwnd = CreateDialogIndirectParamW( hInstance, strTemplate,
763 owner, dlgProc, param );
764 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
765 return -1;
766}
767
768
769/***********************************************************************
770 * EndDialog32 (USER32.173)
771 */
772BOOL WINAPI EndDialog( HWND hwnd, INT retval )
773{
774 WND * wndPtr = WIN_FindWndPtr( hwnd );
775 DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
776
777 dprintf(("USER32:%04x %d\n", hwnd, retval ));
778
779 if( dlgInfo )
780 {
781 dlgInfo->idResult = retval;
782 dlgInfo->flags |= DF_END;
783 }
784
785 /* Windows sets the focus to the dialog itself first in EndDialog */
786
787 if (IsChild(hwnd, GetFocus()))
788 SetFocus(wndPtr->hwndSelf);
789
790 /* Paint Shop Pro 4.14 calls EndDialog for a CreateDialog* dialog,
791 * which isn't "normal". Only DialogBox* dialogs may be EndDialog()ed.
792 * Just hide the window
793 * and re-enable the owner as windows does it...
794 */
795 ShowWindow(hwnd, SW_HIDE);
796
797 if(wndPtr->owner)
798 {
799 HWND hOwner;
800 /* Owner must be a top-level window */
801 hOwner = WIN_GetTopParent( wndPtr->owner->hwndSelf );
802 EnableWindow( hOwner, TRUE );
803 }
804
805 WIN_ReleaseWndPtr(wndPtr);
806
807 return TRUE;
808}
809
810
811/***********************************************************************
812 * DIALOG_IsAccelerator
813 */
814static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM vKey )
815{
816 HWND hwndControl = hwnd;
817 HWND hwndNext;
818 WND *wndPtr;
819 BOOL RetVal = FALSE;
820 INT dlgCode;
821
822 if (vKey == VK_SPACE)
823 {
824 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
825 if (dlgCode & DLGC_BUTTON)
826 {
827 SendMessageA( hwndControl, WM_LBUTTONDOWN, 0, 0);
828 SendMessageA( hwndControl, WM_LBUTTONUP, 0, 0);
829 RetVal = TRUE;
830 }
831 }
832 else
833 {
834 do
835 {
836 wndPtr = WIN_FindWndPtr( hwndControl );
837 if ( (wndPtr != NULL) &&
838 ((wndPtr->dwStyle & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) )
839 {
840 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
841 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
842 (wndPtr->text!=NULL))
843 {
844 /* find the accelerator key */
845 LPSTR p = wndPtr->text - 2;
846 do
847 {
848 p = strchr( p + 2, '&' );
849 }
850 while (p != NULL && p[1] == '&');
851
852 /* and check if it's the one we're looking for */
853 if (p != NULL && toupper( p[1] ) == toupper( vKey ) )
854 {
855 if ((dlgCode & DLGC_STATIC) ||
856 (wndPtr->dwStyle & 0x0f) == BS_GROUPBOX )
857 {
858 /* set focus to the control */
859 SendMessageA( hwndDlg, WM_NEXTDLGCTL,
860 hwndControl, 1);
861 /* and bump it on to next */
862 SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
863 }
864 else if (dlgCode &
865 (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON))
866 {
867 /* send command message as from the control */
868 SendMessageA( hwndDlg, WM_COMMAND,
869 MAKEWPARAM( LOWORD(wndPtr->wIDmenu),
870 BN_CLICKED ),
871 (LPARAM)hwndControl );
872 }
873 else
874 {
875 /* click the control */
876 SendMessageA( hwndControl, WM_LBUTTONDOWN, 0, 0);
877 SendMessageA( hwndControl, WM_LBUTTONUP, 0, 0);
878 }
879 RetVal = TRUE;
880 WIN_ReleaseWndPtr(wndPtr);
881 break;
882 }
883 }
884 hwndNext = GetWindow( hwndControl, GW_CHILD );
885 }
886 else
887 {
888 hwndNext = 0;
889 }
890 WIN_ReleaseWndPtr(wndPtr);
891 if (!hwndNext)
892 {
893 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
894 }
895 while (!hwndNext)
896 {
897 hwndControl = GetParent( hwndControl );
898 if (hwndControl == hwndDlg)
899 {
900 if(hwnd==hwndDlg){ /* prevent endless loop */
901 hwndNext=hwnd;
902 break;
903 }
904 hwndNext = GetWindow( hwndDlg, GW_CHILD );
905 }
906 else
907 {
908 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
909 }
910 }
911 hwndControl = hwndNext;
912 }
913 while (hwndControl != hwnd);
914 }
915 return RetVal;
916}
917
918
919/***********************************************************************
920 * DIALOG_IsDialogMessage
921 */
922static BOOL DIALOG_IsDialogMessage( HWND hwnd, HWND hwndDlg,
923 UINT message, WPARAM wParam,
924 LPARAM lParam, BOOL *translate,
925 BOOL *dispatch, INT dlgCode )
926{
927 *translate = *dispatch = FALSE;
928
929 if (message == WM_PAINT)
930 {
931 /* Apparently, we have to handle this one as well */
932 *dispatch = TRUE;
933 return TRUE;
934 }
935
936 /* Only the key messages get special processing */
937 if ((message != WM_KEYDOWN) &&
938 (message != WM_SYSCHAR) &&
939 (message != WM_CHAR))
940 return FALSE;
941
942 if (dlgCode & DLGC_WANTMESSAGE)
943 {
944 *translate = *dispatch = TRUE;
945 return TRUE;
946 }
947
948 switch(message)
949 {
950 case WM_KEYDOWN:
951 switch(wParam)
952 {
953 case VK_TAB:
954 if (!(dlgCode & DLGC_WANTTAB))
955 {
956 SendMessageA( hwndDlg, WM_NEXTDLGCTL,
957 (GetKeyState(VK_SHIFT) & 0x8000), 0 );
958 return TRUE;
959 }
960 break;
961
962 case VK_RIGHT:
963 case VK_DOWN:
964 case VK_LEFT:
965 case VK_UP:
966 if (!(dlgCode & DLGC_WANTARROWS))
967 {
968 BOOL fPrevious = (wParam == VK_LEFT || wParam == VK_UP);
969 HWND hwndNext =
970 GetNextDlgGroupItem (hwndDlg, GetFocus(), fPrevious );
971 SendMessageA( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
972 return TRUE;
973 }
974 break;
975
976 case VK_ESCAPE:
977 SendMessageA( hwndDlg, WM_COMMAND, IDCANCEL,
978 (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
979 return TRUE;
980
981 case VK_RETURN:
982 {
983 DWORD dw = SendMessageA( hwndDlg, DM_GETDEFID, 0, 0 );
984 if (HIWORD(dw) == DC_HASDEFID)
985 {
986 SendMessageA( hwndDlg, WM_COMMAND,
987 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
988 (LPARAM)GetDlgItem(hwndDlg, LOWORD(dw)));
989 }
990 else
991 {
992 SendMessageA( hwndDlg, WM_COMMAND, IDOK,
993 (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
994
995 }
996 }
997 return TRUE;
998 }
999 *translate = TRUE;
1000 break; /* case WM_KEYDOWN */
1001
1002 case WM_CHAR:
1003 if (dlgCode & DLGC_WANTCHARS) break;
1004 /* drop through */
1005
1006 case WM_SYSCHAR:
1007 if (DIALOG_IsAccelerator( hwnd, hwndDlg, wParam ))
1008 {
1009 /* don't translate or dispatch */
1010 return TRUE;
1011 }
1012 break;
1013 }
1014
1015 /* If we get here, the message has not been treated specially */
1016 /* and can be sent to its destination window. */
1017 *dispatch = TRUE;
1018 return TRUE;
1019}
1020
1021
1022/***********************************************************************
1023 * IsDialogMessage32A (USER32.342)
1024 */
1025BOOL WINAPI IsDialogMessageA( HWND hwndDlg, LPMSG msg )
1026{
1027 BOOL ret, translate, dispatch;
1028 INT dlgCode;
1029
1030 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
1031 return FALSE;
1032
1033 dlgCode = SendMessageA( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
1034 ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1035 msg->wParam, msg->lParam,
1036 &translate, &dispatch, dlgCode );
1037 if (translate) TranslateMessage( msg );
1038 if (dispatch) DispatchMessageA( msg );
1039 return ret;
1040}
1041
1042
1043/***********************************************************************
1044 * IsDialogMessage32W (USER32.343)
1045 */
1046BOOL WINAPI IsDialogMessageW( HWND hwndDlg, LPMSG msg )
1047{
1048 BOOL ret, translate, dispatch;
1049 INT dlgCode;
1050
1051 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
1052 return FALSE;
1053
1054 dlgCode = SendMessageW( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
1055 ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
1056 msg->wParam, msg->lParam,
1057 &translate, &dispatch, dlgCode );
1058 if (translate) TranslateMessage( msg );
1059 if (dispatch) DispatchMessageW( msg );
1060 return ret;
1061}
1062
1063
1064/****************************************************************
1065 * GetDlgCtrlID32 (USER32.234)
1066 */
1067INT WINAPI GetDlgCtrlID( HWND hwnd )
1068{
1069 INT retvalue;
1070 WND *wndPtr = WIN_FindWndPtr(hwnd);
1071 if (!wndPtr) return 0;
1072 retvalue = wndPtr->wIDmenu;
1073 WIN_ReleaseWndPtr(wndPtr);
1074 return retvalue;
1075}
1076
1077
1078/***********************************************************************
1079 * GetDlgItem32 (USER32.235)
1080 */
1081HWND WINAPI GetDlgItem( HWND hwndDlg, INT id )
1082{
1083 WND *pWnd;
1084
1085 if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
1086 for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
1087 if (pWnd->wIDmenu == (UINT16)id)
1088 {
1089 HWND retvalue = pWnd->hwndSelf;
1090 WIN_ReleaseWndPtr(pWnd);
1091 return retvalue;
1092 }
1093 return 0;
1094}
1095
1096
1097/*******************************************************************
1098 * SendDlgItemMessage32A (USER32.452)
1099 */
1100LRESULT WINAPI SendDlgItemMessageA( HWND hwnd, INT id, UINT msg,
1101 WPARAM wParam, LPARAM lParam )
1102{
1103 HWND hwndCtrl = GetDlgItem( hwnd, id );
1104 if (hwndCtrl) return SendMessageA( hwndCtrl, msg, wParam, lParam );
1105 else return 0;
1106}
1107
1108
1109/*******************************************************************
1110 * SendDlgItemMessage32W (USER32.453)
1111 */
1112LRESULT WINAPI SendDlgItemMessageW( HWND hwnd, INT id, UINT msg,
1113 WPARAM wParam, LPARAM lParam )
1114{
1115 HWND hwndCtrl = GetDlgItem( hwnd, id );
1116 if (hwndCtrl) return SendMessageW( hwndCtrl, msg, wParam, lParam );
1117 else return 0;
1118}
1119
1120
1121/*******************************************************************
1122 * SetDlgItemText32A (USER32.478)
1123 */
1124BOOL WINAPI SetDlgItemTextA( HWND hwnd, INT id, LPCSTR lpString )
1125{
1126 return SendDlgItemMessageA( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1127}
1128
1129
1130/*******************************************************************
1131 * SetDlgItemText32W (USER32.479)
1132 */
1133BOOL WINAPI SetDlgItemTextW( HWND hwnd, INT id, LPCWSTR lpString )
1134{
1135 return SendDlgItemMessageW( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1136}
1137
1138
1139/***********************************************************************
1140 * GetDlgItemText32A (USER32.237)
1141 */
1142UINT WINAPI GetDlgItemTextA( HWND hwnd, INT id, LPSTR str, UINT len )
1143{
1144 return (UINT)SendDlgItemMessageA( hwnd, id, WM_GETTEXT,
1145 len, (LPARAM)str );
1146}
1147
1148
1149/***********************************************************************
1150 * GetDlgItemText32W (USER32.238)
1151 */
1152UINT WINAPI GetDlgItemTextW( HWND hwnd, INT id, LPWSTR str, UINT len )
1153{
1154 return (UINT)SendDlgItemMessageW( hwnd, id, WM_GETTEXT,
1155 len, (LPARAM)str );
1156}
1157
1158
1159/*******************************************************************
1160 * SetDlgItemInt32 (USER32.477)
1161 */
1162BOOL WINAPI SetDlgItemInt( HWND hwnd, INT id, UINT value,
1163 BOOL fSigned )
1164{
1165 char str[20];
1166
1167 if (fSigned) sprintf( str, "%d", (INT)value );
1168 else sprintf( str, "%u", value );
1169 SendDlgItemMessageA( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
1170 return TRUE;
1171}
1172
1173
1174/***********************************************************************
1175 * GetDlgItemInt32 (USER32.236)
1176 */
1177UINT WINAPI GetDlgItemInt( HWND hwnd, INT id, BOOL *translated,
1178 BOOL fSigned )
1179{
1180 char str[30];
1181 char * endptr;
1182 long result = 0;
1183
1184 if (translated) *translated = FALSE;
1185 if (!SendDlgItemMessageA(hwnd, id, WM_GETTEXT, sizeof(str), (LPARAM)str))
1186 return 0;
1187 if (fSigned)
1188 {
1189 result = strtol( str, &endptr, 10 );
1190 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
1191 return 0;
1192 if (((result == LONG_MIN) || (result == LONG_MAX)) && (errno==ERANGE))
1193 return 0;
1194 }
1195 else
1196 {
1197 result = strtoul( str, &endptr, 10 );
1198 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
1199 return 0;
1200 if ((result == ULONG_MAX) && (errno == ERANGE)) return 0;
1201 }
1202 if (translated) *translated = TRUE;
1203 return (UINT)result;
1204}
1205
1206
1207/***********************************************************************
1208 * CheckDlgButton32 (USER32.45)
1209 */
1210BOOL WINAPI CheckDlgButton( HWND hwnd, INT id, UINT check )
1211{
1212 SendDlgItemMessageA( hwnd, id, BM_SETCHECK, check, 0 );
1213 return TRUE;
1214}
1215
1216
1217/***********************************************************************
1218 * IsDlgButtonChecked32 (USER32.344)
1219 */
1220BOOL WINAPI IsDlgButtonChecked( HWND hwnd, UINT id )
1221{
1222 return (BOOL)SendDlgItemMessageA( hwnd, id, BM_GETCHECK, 0, 0 );
1223}
1224
1225
1226/***********************************************************************
1227 * CheckRB
1228 *
1229 * Callback function used to check/uncheck radio buttons that fall
1230 * within a specific range of IDs.
1231 */
1232static BOOL CALLBACK CheckRB(HWND hwndChild, LPARAM lParam)
1233{
1234 LONG lChildID = GetWindowLongA(hwndChild, GWL_ID);
1235 RADIOGROUP *lpRadioGroup = (RADIOGROUP *) lParam;
1236
1237 if ((lChildID >= lpRadioGroup->firstID) &&
1238 (lChildID <= lpRadioGroup->lastID))
1239 {
1240 if (lChildID == lpRadioGroup->checkID)
1241 {
1242 SendMessageA(hwndChild, BM_SETCHECK, BST_CHECKED, 0);
1243 }
1244 else
1245 {
1246 SendMessageA(hwndChild, BM_SETCHECK, BST_UNCHECKED, 0);
1247 }
1248 }
1249
1250 return TRUE;
1251}
1252
1253
1254/***********************************************************************
1255 * CheckRadioButton32 (USER32.48)
1256 */
1257BOOL WINAPI CheckRadioButton( HWND hwndDlg, UINT firstID,
1258 UINT lastID, UINT checkID )
1259{
1260 RADIOGROUP radioGroup;
1261
1262 /* perform bounds checking for a radio button group */
1263 radioGroup.firstID = min(min(firstID, lastID), checkID);
1264 radioGroup.lastID = max(max(firstID, lastID), checkID);
1265 radioGroup.checkID = checkID;
1266
1267 return EnumChildWindows(hwndDlg, (WNDENUMPROC)CheckRB,
1268 (LPARAM)&radioGroup);
1269}
1270
1271
1272/***********************************************************************
1273 * GetDialogBaseUnits (USER.243) (USER32.233)
1274 */
1275DWORD WINAPI GetDialogBaseUnits(void)
1276{
1277 return MAKELONG( xBaseUnit, yBaseUnit );
1278}
1279
1280
1281/***********************************************************************
1282 * MapDialogRect32 (USER32.382)
1283 */
1284BOOL WINAPI MapDialogRect( HWND hwnd, LPRECT rect )
1285{
1286 DIALOGINFO * dlgInfo;
1287 WND * wndPtr = WIN_FindWndPtr( hwnd );
1288 if (!wndPtr) return FALSE;
1289 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1290 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1291 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1292 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1293 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1294 WIN_ReleaseWndPtr(wndPtr);
1295 return TRUE;
1296}
1297
1298
1299/***********************************************************************
1300 * GetNextDlgGroupItem32 (USER32.275)
1301 */
1302HWND WINAPI GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl,
1303 BOOL fPrevious )
1304{
1305 WND *pWnd = NULL,
1306 *pWndLast = NULL,
1307 *pWndCtrl = NULL,
1308 *pWndDlg = NULL;
1309 HWND retvalue;
1310
1311 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1312 if (hwndCtrl)
1313 {
1314 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl )))
1315 {
1316 retvalue = 0;
1317 goto END;
1318 }
1319 /* Make sure hwndCtrl is a top-level child */
1320 while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1321 WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->parent);
1322 if (pWndCtrl->parent != pWndDlg)
1323 {
1324 retvalue = 0;
1325 goto END;
1326 }
1327 }
1328 else
1329 {
1330 /* No ctrl specified -> start from the beginning */
1331 if (!(pWndCtrl = WIN_LockWndPtr(pWndDlg->child)))
1332 {
1333 retvalue = 0;
1334 goto END;
1335 }
1336 if (fPrevious)
1337 while (pWndCtrl->next) WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->next);
1338 }
1339
1340 pWndLast = WIN_LockWndPtr(pWndCtrl);
1341 pWnd = WIN_LockWndPtr(pWndCtrl->next);
1342
1343 while (1)
1344 {
1345 if (!pWnd || (pWnd->dwStyle & WS_GROUP))
1346 {
1347 /* Wrap-around to the beginning of the group */
1348 WND *pWndTemp;
1349
1350 WIN_UpdateWndPtr( &pWnd, pWndDlg->child );
1351 for ( pWndTemp = WIN_LockWndPtr( pWnd );
1352 pWndTemp;
1353 WIN_UpdateWndPtr( &pWndTemp, pWndTemp->next) )
1354 {
1355 if (pWndTemp->dwStyle & WS_GROUP) WIN_UpdateWndPtr( &pWnd, pWndTemp );
1356 if (pWndTemp == pWndCtrl) break;
1357 }
1358 WIN_ReleaseWndPtr( pWndTemp );
1359 }
1360 if (pWnd == pWndCtrl) break;
1361 if ((pWnd->dwStyle & WS_VISIBLE) && !(pWnd->dwStyle & WS_DISABLED))
1362 {
1363 WIN_UpdateWndPtr(&pWndLast,pWnd);
1364 if (!fPrevious) break;
1365 }
1366 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1367 }
1368 retvalue = pWndLast->hwndSelf;
1369
1370 WIN_ReleaseWndPtr(pWndLast);
1371 WIN_ReleaseWndPtr(pWnd);
1372END:
1373 WIN_ReleaseWndPtr(pWndCtrl);
1374 WIN_ReleaseWndPtr(pWndDlg);
1375
1376 return retvalue;
1377}
1378
1379
1380/***********************************************************************
1381 * GetNextDlgTabItem32 (USER32.276)
1382 */
1383HWND WINAPI GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl,
1384 BOOL fPrevious )
1385{
1386 WND *pWnd = NULL,
1387 *pWndLast = NULL,
1388 *pWndCtrl = NULL,
1389 *pWndDlg = NULL;
1390 HWND retvalue;
1391
1392 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1393 if (hwndCtrl)
1394 {
1395 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl )))
1396 {
1397 retvalue = 0;
1398 goto END;
1399 }
1400 /* Make sure hwndCtrl is a top-level child */
1401 while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1402 WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->parent);
1403 if (pWndCtrl->parent != pWndDlg)
1404 {
1405 retvalue = 0;
1406 goto END;
1407 }
1408 }
1409 else
1410 {
1411 /* No ctrl specified -> start from the beginning */
1412 if (!(pWndCtrl = WIN_LockWndPtr(pWndDlg->child)))
1413 {
1414 retvalue = 0;
1415 goto END;
1416 }
1417
1418 if (!fPrevious)
1419 while (pWndCtrl->next) WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->next);
1420 }
1421
1422 pWndLast = WIN_LockWndPtr(pWndCtrl);
1423 pWnd = WIN_LockWndPtr(pWndCtrl->next);
1424 while (1)
1425 {
1426 if (!pWnd) pWnd = WIN_LockWndPtr(pWndDlg->child);
1427 if (pWnd == pWndCtrl) break;
1428 if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE) &&
1429 !(pWnd->dwStyle & WS_DISABLED))
1430 {
1431 WIN_UpdateWndPtr(&pWndLast,pWnd);
1432 if (!fPrevious) break;
1433 }
1434 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1435 }
1436 retvalue = pWndLast->hwndSelf;
1437
1438 WIN_ReleaseWndPtr(pWndLast);
1439 WIN_ReleaseWndPtr(pWnd);
1440END:
1441 WIN_ReleaseWndPtr(pWndCtrl);
1442 WIN_ReleaseWndPtr(pWndDlg);
1443
1444 return retvalue;
1445
1446}
1447
1448
1449/**********************************************************************
1450 * DIALOG_DlgDirSelect
1451 *
1452 * Helper function for DlgDirSelect*
1453 */
1454static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPSTR str, INT len,
1455 INT id, BOOL unicode,
1456 BOOL combo )
1457{
1458 char *buffer, *ptr;
1459 INT item, size;
1460 BOOL ret;
1461 HWND listbox = GetDlgItem( hwnd, id );
1462
1463 dprintf(("USER32:%04x '%s' %d\n", hwnd, str, id ));
1464 if (!listbox) return FALSE;
1465
1466 item = SendMessageA(listbox, combo ? CB_GETCURSEL
1467 : LB_GETCURSEL, 0, 0 );
1468 if (item == LB_ERR) return FALSE;
1469 size = SendMessageA(listbox, combo ? CB_GETLBTEXTLEN
1470 : LB_GETTEXTLEN, 0, 0 );
1471 if (size == LB_ERR) return FALSE;
1472
1473 if (!(buffer = (char*)HEAP_malloc( size+1 ))) return FALSE;
1474
1475 SendMessageA( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT,
1476 item, (LPARAM)buffer );
1477
1478 if ((ret = (buffer[0] == '['))) /* drive or directory */
1479 {
1480 if (buffer[1] == '-') /* drive */
1481 {
1482 buffer[3] = ':';
1483 buffer[4] = 0;
1484 ptr = buffer + 2;
1485 }
1486 else
1487 {
1488 buffer[strlen(buffer)-1] = '\\';
1489 ptr = buffer + 1;
1490 }
1491 }
1492 else ptr = buffer;
1493
1494 if (unicode) lstrcpynAtoW( (LPWSTR)str, ptr, len );
1495 else lstrcpynA( str, ptr, len );
1496 HEAP_free( buffer );
1497 dprintf(("USER32:Returning %d '%s'\n", ret, str ));
1498 return ret;
1499}
1500
1501
1502/**********************************************************************
1503 * DIALOG_DlgDirList
1504 *
1505 * Helper function for DlgDirList*
1506 */
1507static INT DIALOG_DlgDirList( HWND hDlg, LPSTR spec, INT idLBox,
1508 INT idStatic, UINT attrib, BOOL combo )
1509{
1510 int drive;
1511 HWND hwnd;
1512 LPSTR orig_spec = spec;
1513
1514#define SENDMSG(msg,wparam,lparam) \
1515 ((attrib & DDL_POSTMSGS) ? PostMessageA( hwnd, msg, wparam, lparam ) \
1516 : SendMessageA( hwnd, msg, wparam, lparam ))
1517
1518 dprintf(("USER32:%04x '%s' %d %d %04x\n",
1519 hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib ));
1520
1521 if (spec && spec[0] && (spec[1] == ':'))
1522 {
1523 drive = toupper( spec[0] ) - 'A';
1524 spec += 2;
1525 if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
1526 }
1527 else drive = DRIVE_GetCurrentDrive();
1528
1529 /* If the path exists and is a directory, chdir to it */
1530 if (!spec || !spec[0] || DRIVE_Chdir( drive, spec )) spec = "*.*";
1531 else
1532 {
1533 char *p, *p2;
1534 p = spec;
1535 if ((p2 = strrchr( p, '\\' ))) p = p2;
1536 if ((p2 = strrchr( p, '/' ))) p = p2;
1537 if (p != spec)
1538 {
1539 char sep = *p;
1540 *p = 0;
1541 if (!DRIVE_Chdir( drive, spec ))
1542 {
1543 *p = sep; /* Restore the original spec */
1544 return FALSE;
1545 }
1546 spec = p + 1;
1547 }
1548 }
1549
1550 dprintf(("USER32:path=%c:\\%s mask=%s\n",
1551 'A' + drive, DRIVE_GetDosCwd(drive), spec ));
1552
1553 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1554 {
1555 SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
1556 if (attrib & DDL_DIRECTORY)
1557 {
1558 if (!(attrib & DDL_EXCLUSIVE))
1559 {
1560 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1561 attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1562 (LPARAM)spec ) == LB_ERR)
1563 return FALSE;
1564 }
1565 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1566 (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1567 (LPARAM)"*.*" ) == LB_ERR)
1568 return FALSE;
1569 }
1570 else
1571 {
1572 if (SENDMSG( combo ? CB_DIR : LB_DIR, attrib,
1573 (LPARAM)spec ) == LB_ERR)
1574 return FALSE;
1575 }
1576 }
1577
1578 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
1579 {
1580 char temp[512];
1581 int drive = DRIVE_GetCurrentDrive();
1582 strcpy( temp, "A:\\" );
1583 temp[0] += drive;
1584 lstrcpynA( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
1585 CharLowerA( temp );
1586 /* Can't use PostMessage() here, because the string is on the stack */
1587 SetDlgItemTextA( hDlg, idStatic, temp );
1588 }
1589
1590 if (orig_spec && (spec != orig_spec))
1591 {
1592 /* Update the original file spec */
1593 char *p = spec;
1594 while ((*orig_spec++ = *p++));
1595 }
1596
1597 return TRUE;
1598#undef SENDMSG
1599}
1600
1601
1602/**********************************************************************
1603 * DIALOG_DlgDirListW
1604 *
1605 * Helper function for DlgDirList*32W
1606 */
1607static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
1608 INT idStatic, UINT attrib, BOOL combo )
1609{
1610 if (spec)
1611 {
1612 LPSTR specA = HEAP_strdupWtoA( GetProcessHeap(), 0, spec );
1613 INT ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic,
1614 attrib, combo );
1615 lstrcpyAtoW( spec, specA );
1616 HeapFree( GetProcessHeap(), 0, specA );
1617 return ret;
1618 }
1619 return DIALOG_DlgDirList( hDlg, NULL, idLBox, idStatic, attrib, combo );
1620}
1621
1622
1623
1624/**********************************************************************
1625 * DlgDirSelectEx32A (USER32.149)
1626 */
1627BOOL WINAPI DlgDirSelectExA( HWND hwnd, LPSTR str, INT len, INT id )
1628{
1629 return DIALOG_DlgDirSelect( hwnd, str, len, id, FALSE, FALSE );
1630}
1631
1632
1633/**********************************************************************
1634 * DlgDirSelectEx32W (USER32.150)
1635 */
1636BOOL WINAPI DlgDirSelectExW( HWND hwnd, LPWSTR str, INT len, INT id )
1637{
1638 return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, FALSE );
1639}
1640
1641
1642/**********************************************************************
1643 * DlgDirSelectComboBoxEx32A (USER32.147)
1644 */
1645BOOL WINAPI DlgDirSelectComboBoxExA( HWND hwnd, LPSTR str, INT len,
1646 INT id )
1647{
1648 return DIALOG_DlgDirSelect( hwnd, str, len, id, FALSE, TRUE );
1649}
1650
1651
1652/**********************************************************************
1653 * DlgDirSelectComboBoxEx32W (USER32.148)
1654 */
1655BOOL WINAPI DlgDirSelectComboBoxExW( HWND hwnd, LPWSTR str, INT len,
1656 INT id)
1657{
1658 return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE );
1659}
1660
1661
1662/**********************************************************************
1663 * DlgDirList32A (USER32.143)
1664 */
1665INT WINAPI DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox,
1666 INT idStatic, UINT attrib )
1667{
1668 return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
1669}
1670
1671
1672/**********************************************************************
1673 * DlgDirList32W (USER32.146)
1674 */
1675INT WINAPI DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
1676 INT idStatic, UINT attrib )
1677{
1678 return DIALOG_DlgDirListW( hDlg, spec, idLBox, idStatic, attrib, FALSE );
1679}
1680
1681
1682/**********************************************************************
1683 * DlgDirListComboBox32A (USER32.144)
1684 */
1685INT WINAPI DlgDirListComboBoxA( HWND hDlg, LPSTR spec, INT idCBox,
1686 INT idStatic, UINT attrib )
1687{
1688 return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
1689}
1690
1691
1692/**********************************************************************
1693 * DlgDirListComboBox32W (USER32.145)
1694 */
1695INT WINAPI DlgDirListComboBoxW( HWND hDlg, LPWSTR spec, INT idCBox,
1696 INT idStatic, UINT attrib )
1697{
1698 return DIALOG_DlgDirListW( hDlg, spec, idCBox, idStatic, attrib, TRUE );
1699}
Note: See TracBrowser for help on using the repository browser.