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

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

.

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