POSIX threads emulation, tricks glibc into being threadsafe.
[wine] / dlls / comctl32 / commctrl.c
1 /*              
2  * Common controls functions
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  * Copyright 1998 Eric Kohl
6  *
7  */
8
9 #include <string.h>
10
11 #include "winbase.h"
12 #include "heap.h"
13 #include "commctrl.h"
14 #include "animate.h"
15 #include "comboex.h"
16 #include "datetime.h"
17 #include "flatsb.h"
18 #include "header.h"
19 #include "hotkey.h"
20 #include "ipaddress.h"
21 #include "listview.h"
22 #include "monthcal.h"
23 #include "nativefont.h"
24 #include "pager.h"
25 #include "progress.h"
26 #include "rebar.h"
27 #include "status.h"
28 #include "tab.h"
29 #include "toolbar.h"
30 #include "tooltips.h"
31 #include "trackbar.h"
32 #include "treeview.h"
33 #include "updown.h"
34 #include "debugtools.h"
35 #include "winerror.h"
36
37 DEFAULT_DEBUG_CHANNEL(commctrl)
38
39
40 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
41 DWORD    COMCTL32_dwProcessesAttached = 0;
42 LPSTR    COMCTL32_aSubclass = (LPSTR)NULL;
43 HMODULE COMCTL32_hModule = 0;
44
45
46 /***********************************************************************
47  * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
48  *
49  * PARAMS
50  *     hinstDLL    [I] handle to the 'dlls' instance
51  *     fdwReason   [I]
52  *     lpvReserved [I] reserverd, must be NULL
53  *
54  * RETURNS
55  *     Success: TRUE
56  *     Failure: FALSE
57  */
58
59 BOOL WINAPI
60 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
61 {
62     TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
63
64     switch (fdwReason) {
65         case DLL_PROCESS_ATTACH:
66             if (COMCTL32_dwProcessesAttached == 0) {
67
68                 /* This will be wrong for any other process attching in this address-space! */
69                 COMCTL32_hModule = (HMODULE)hinstDLL;
70
71                 /* create private heap */
72                 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
73                 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
74
75                 /* add global subclassing atom (used by 'tooltip' and 'updown') */
76                 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
77                 TRACE("Subclassing atom added: %p\n",
78                        COMCTL32_aSubclass);
79
80                 /* register all Win95 common control classes */
81                 ANIMATE_Register ();
82                 FLATSB_Register ();
83                 HEADER_Register ();
84                 HOTKEY_Register ();
85                 LISTVIEW_Register ();
86                 PROGRESS_Register ();
87                 STATUS_Register ();
88                 TAB_Register ();
89                 TOOLBAR_Register ();
90                 TOOLTIPS_Register ();
91                 TRACKBAR_Register ();
92                 TREEVIEW_Register ();
93                 UPDOWN_Register ();
94             }
95             COMCTL32_dwProcessesAttached++;
96             break;
97
98         case DLL_PROCESS_DETACH:
99             COMCTL32_dwProcessesAttached--;
100             if (COMCTL32_dwProcessesAttached == 0) {
101                 /* unregister all common control classes */
102                 ANIMATE_Unregister ();
103                 COMBOEX_Unregister ();
104                 DATETIME_Unregister ();
105                 FLATSB_Unregister ();
106                 HEADER_Unregister ();
107                 HOTKEY_Unregister ();
108                 IPADDRESS_Unregister ();
109                 LISTVIEW_Unregister ();
110                 MONTHCAL_Unregister ();
111                 NATIVEFONT_Unregister ();
112                 PAGER_Unregister ();
113                 PROGRESS_Unregister ();
114                 REBAR_Unregister ();
115                 STATUS_Unregister ();
116                 TAB_Unregister ();
117                 TOOLBAR_Unregister ();
118                 TOOLTIPS_Unregister ();
119                 TRACKBAR_Unregister ();
120                 TREEVIEW_Unregister ();
121                 UPDOWN_Unregister ();
122
123                 /* delete global subclassing atom */
124                 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
125                 TRACE("Subclassing atom deleted: %p\n",
126                        COMCTL32_aSubclass);
127                 COMCTL32_aSubclass = (LPSTR)NULL;
128
129                 /* destroy private heap */
130                 HeapDestroy (COMCTL32_hHeap);
131                 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
132                 COMCTL32_hHeap = (HANDLE)NULL;
133             }
134             break;
135     }
136
137     return TRUE;
138 }
139
140
141 /***********************************************************************
142  * MenuHelp [COMCTL32.2]
143  *
144  * PARAMS
145  *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
146  *     wParam     [I] wParam of the message uMsg
147  *     lParam     [I] lParam of the message uMsg
148  *     hMainMenu  [I] handle to the application's main menu
149  *     hInst      [I] handle to the module that contains string resources
150  *     hwndStatus [I] handle to the status bar window
151  *     lpwIDs     [I] pointer to an array of intergers (see NOTES)
152  *
153  * RETURNS
154  *     No return value
155  *
156  * NOTES
157  *     The official documentation is incomplete!
158  *     This is the correct documentation:
159  *
160  *     uMsg:
161  *     MenuHelp() does NOT handle WM_COMMAND messages! It only handes
162  *     WM_MENUSELECT messages.
163  *
164  *     lpwIDs:
165  *     (will be written ...)
166  */
167
168 VOID WINAPI
169 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
170           HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
171 {
172     UINT uMenuID = 0;
173
174     if (!IsWindow (hwndStatus))
175         return;
176
177     switch (uMsg) {
178         case WM_MENUSELECT:
179             TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
180                    wParam, lParam);
181
182             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
183                 /* menu was closed */
184                 TRACE("menu was closed!\n");
185                 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
186             }
187             else {
188                 /* menu item was selected */
189                 if (HIWORD(wParam) & MF_POPUP)
190                     uMenuID = (UINT)*(lpwIDs+1);
191                 else
192                     uMenuID = (UINT)LOWORD(wParam);
193                 TRACE("uMenuID = %u\n", uMenuID);
194
195                 if (uMenuID) {
196                     CHAR szText[256];
197
198                     if (!LoadStringA (hInst, uMenuID, szText, 256))
199                         szText[0] = '\0';
200
201                     SendMessageA (hwndStatus, SB_SETTEXTA,
202                                     255 | SBT_NOBORDERS, (LPARAM)szText);
203                     SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
204                 }
205             }
206             break;
207
208         case WM_COMMAND :
209             TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
210                    wParam, lParam);
211             /* WM_COMMAND is not invalid since it is documented
212              * in the windows api reference. So don't output
213              * any FIXME for WM_COMMAND
214              */
215             WARN("We don't care about the WM_COMMAND\n");
216             break;
217
218         default:
219             FIXME("Invalid Message 0x%x!\n", uMsg);
220             break;
221     }
222 }
223
224
225 /***********************************************************************
226  * ShowHideMenuCtl [COMCTL32.3] 
227  *
228  * Shows or hides controls and updates the corresponding menu item.
229  *
230  * PARAMS
231  *     hwnd   [I] handle to the client window.
232  *     uFlags [I] menu command id.
233  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
234  *
235  * RETURNS
236  *     Success: TRUE
237  *     Failure: FALSE
238  *
239  * NOTES
240  *     The official documentation is incomplete!
241  *     This is the correct documentation:
242  *
243  *     hwnd
244  *     Handle to the window that contains the menu and controls.
245  *
246  *     uFlags
247  *     Identifier of the menu item to receive or loose a check mark.
248  *
249  *     lpInfo
250  *     The array of integers contains pairs of values. BOTH values of
251  *     the first pair must be the handles to the application's main menu.
252  *     Each subsequent pair consists of a menu id and control id.
253  */
254
255 BOOL WINAPI
256 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
257 {
258     LPINT lpMenuId;
259
260     TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
261
262     if (lpInfo == NULL)
263         return FALSE;
264
265     if (!(lpInfo[0]) || !(lpInfo[1]))
266         return FALSE;
267
268     /* search for control */
269     lpMenuId = &lpInfo[2];
270     while (*lpMenuId != uFlags)
271         lpMenuId += 2;
272
273     if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
274         /* uncheck menu item */
275         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
276
277         /* hide control */
278         lpMenuId++;
279         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
280                         SWP_HIDEWINDOW);
281     }
282     else {
283         /* check menu item */
284         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
285
286         /* show control */
287         lpMenuId++;
288         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
289                         SWP_SHOWWINDOW);
290     }
291
292     return TRUE;
293 }
294
295
296 /***********************************************************************
297  * GetEffectiveClientRect [COMCTL32.4]
298  *
299  * PARAMS
300  *     hwnd   [I] handle to the client window.
301  *     lpRect [O] pointer to the rectangle of the client window
302  *     lpInfo [I] pointer to an array of integers (see NOTES)
303  *
304  * RETURNS
305  *     No return value.
306  *
307  * NOTES
308  *     The official documentation is incomplete!
309  *     This is the correct documentation:
310  *
311  *     lpInfo
312  *     (will be written...)
313  */
314
315 VOID WINAPI
316 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
317 {
318     RECT rcCtrl;
319     INT  *lpRun;
320     HWND hwndCtrl;
321
322     TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
323            (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
324
325     GetClientRect (hwnd, lpRect);
326     lpRun = lpInfo;
327
328     do {
329         lpRun += 2;
330         if (*lpRun == 0)
331             return;
332         lpRun++;
333         hwndCtrl = GetDlgItem (hwnd, *lpRun);
334         if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
335             TRACE("control id 0x%x\n", *lpRun);
336             GetWindowRect (hwndCtrl, &rcCtrl);
337             MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
338             SubtractRect (lpRect, lpRect, &rcCtrl);
339         }
340         lpRun++;
341     } while (*lpRun);
342 }
343
344
345 /***********************************************************************
346  * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
347  *
348  * Draws text with borders, like in a status bar.
349  *
350  * PARAMS
351  *     hdc   [I] handle to the window's display context
352  *     lprc  [I] pointer to a rectangle
353  *     text  [I] pointer to the text
354  *     style [I] drawing style
355  *
356  * RETURNS
357  *     No return value.
358  *
359  * NOTES
360  *     The style variable can have one of the following values:
361  *     (will be written ...)
362  */
363
364 VOID WINAPI
365 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
366 {
367     RECT r = *lprc;
368     UINT border = BDR_SUNKENOUTER;
369
370     if (style & SBT_POPOUT)
371       border = BDR_RAISEDOUTER;
372     else if (style & SBT_NOBORDERS)
373       border = 0;
374
375     DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
376
377     /* now draw text */
378     if (text) {
379       int oldbkmode = SetBkMode (hdc, TRANSPARENT);
380       r.left += 3;
381       DrawTextA (hdc, text, lstrlenA(text),
382                    &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);  
383       if (oldbkmode != TRANSPARENT)
384         SetBkMode(hdc, oldbkmode);
385     }
386 }
387
388
389 /***********************************************************************
390  * DrawStatusTextW [COMCTL32.28]
391  *
392  * Draws text with borders, like in a status bar.
393  *
394  * PARAMS
395  *     hdc   [I] handle to the window's display context
396  *     lprc  [I] pointer to a rectangle
397  *     text  [I] pointer to the text
398  *     style [I] drawing style
399  *
400  * RETURNS
401  *     No return value.
402  */
403
404 VOID WINAPI
405 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
406 {
407     LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
408     DrawStatusTextA (hdc, lprc, p, style);
409     HeapFree (GetProcessHeap (), 0, p );
410 }
411
412
413 /***********************************************************************
414  * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
415  *
416  * Creates a status bar
417  *
418  * PARAMS
419  *     style  [I] window style
420  *     text   [I] pointer to the window text
421  *     parent [I] handle to the parent window
422  *     wid    [I] control id of the status bar
423  *
424  * RETURNS
425  *     Success: handle to the status window
426  *     Failure: 0
427  */
428
429 HWND WINAPI
430 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
431 {
432     return CreateWindowA(STATUSCLASSNAMEA, text, style, 
433                            CW_USEDEFAULT, CW_USEDEFAULT,
434                            CW_USEDEFAULT, CW_USEDEFAULT, 
435                            parent, wid, 0, 0);
436 }
437
438
439 /***********************************************************************
440  * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
441  *
442  * PARAMS
443  *     style  [I] window style
444  *     text   [I] pointer to the window text
445  *     parent [I] handle to the parent window
446  *     wid    [I] control id of the status bar
447  *
448  * RETURNS
449  *     Success: handle to the status window
450  *     Failure: 0
451  */
452
453 HWND WINAPI
454 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
455 {
456     return CreateWindowW(STATUSCLASSNAMEW, text, style,
457                            CW_USEDEFAULT, CW_USEDEFAULT,
458                            CW_USEDEFAULT, CW_USEDEFAULT,
459                            parent, wid, 0, 0);
460 }
461
462
463 /***********************************************************************
464  * CreateUpDownControl [COMCTL32.16] Creates an up-down control
465  *
466  * PARAMS
467  *     style  [I] window styles
468  *     x      [I] horizontal position of the control
469  *     y      [I] vertical position of the control
470  *     cx     [I] with of the control
471  *     cy     [I] height of the control
472  *     parent [I] handle to the parent window
473  *     id     [I] the control's identifier
474  *     inst   [I] handle to the application's module instance
475  *     buddy  [I] handle to the buddy window, can be NULL
476  *     maxVal [I] upper limit of the control
477  *     minVal [I] lower limit of the control
478  *     curVal [I] current value of the control
479  *
480  * RETURNS
481  *     Success: handle to the updown control
482  *     Failure: 0
483  */
484
485 HWND WINAPI
486 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
487                      HWND parent, INT id, HINSTANCE inst,
488                      HWND buddy, INT maxVal, INT minVal, INT curVal)
489 {
490     HWND hUD =
491         CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
492                          parent, id, inst, 0);
493     if (hUD) {
494         SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
495         SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
496         SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));     
497     }
498
499     return hUD;
500 }
501
502
503 /***********************************************************************
504  * InitCommonControls [COMCTL32.17]
505  *
506  * Registers the common controls.
507  *
508  * PARAMS
509  *     No parameters.
510  *
511  * RETURNS
512  *     No return values.
513  *
514  * NOTES
515  *     This function is just a dummy.
516  *     The Win95 controls are registered at the DLL's initialization.
517  *     To register other controls InitCommonControlsEx() must be used.
518  */
519
520 VOID WINAPI
521 InitCommonControls (void)
522 {
523 }
524
525
526 /***********************************************************************
527  * InitCommonControlsEx [COMCTL32.81]
528  *
529  * Registers the common controls.
530  *
531  * PARAMS
532  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
533  *
534  * RETURNS
535  *     Success: TRUE
536  *     Failure: FALSE
537  *
538  * NOTES
539  *     Only the additinal common controls are registered by this function.
540  *     The Win95 controls are registered at the DLL's initialization.
541  */
542
543 BOOL WINAPI
544 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
545 {
546     INT cCount;
547     DWORD dwMask;
548
549     if (!lpInitCtrls)
550         return FALSE;
551     if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
552         return FALSE;
553
554     TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
555
556     for (cCount = 0; cCount < 32; cCount++) {
557         dwMask = 1 << cCount;
558         if (!(lpInitCtrls->dwICC & dwMask))
559             continue;
560
561         switch (lpInitCtrls->dwICC & dwMask) {
562             /* dummy initialization */
563             case ICC_ANIMATE_CLASS:
564             case ICC_BAR_CLASSES:
565             case ICC_LISTVIEW_CLASSES:
566             case ICC_TREEVIEW_CLASSES:
567             case ICC_TAB_CLASSES:
568             case ICC_UPDOWN_CLASS:
569             case ICC_PROGRESS_CLASS:
570             case ICC_HOTKEY_CLASS:
571                 break;
572
573             /* advanced classes - not included in Win95 */
574             case ICC_DATE_CLASSES:
575                 MONTHCAL_Register ();
576                 DATETIME_Register ();
577                 break;
578
579             case ICC_USEREX_CLASSES:
580                 COMBOEX_Register ();
581                 break;
582
583             case ICC_COOL_CLASSES:
584                 REBAR_Register ();
585                 break;
586
587             case ICC_INTERNET_CLASSES:
588                 IPADDRESS_Register ();
589                 break;
590
591             case ICC_PAGESCROLLER_CLASS:
592                 PAGER_Register ();
593                 break;
594
595             case ICC_NATIVEFNTCTL_CLASS:
596                 NATIVEFONT_Register ();
597                 break;
598
599             default:
600                 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
601                 break;
602         }
603     }
604
605     return TRUE;
606 }
607
608
609 /***********************************************************************
610  * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
611  *
612  * PARAMS
613  *     hwnd
614  *     style
615  *     wID
616  *     nBitmaps
617  *     hBMInst
618  *     wBMID
619  *     lpButtons
620  *     iNumButtons
621  *     dxButton
622  *     dyButton
623  *     dxBitmap
624  *     dyBitmap
625  *     uStructSize
626  *
627  * RETURNS
628  *     Success: handle to the tool bar control
629  *     Failure: 0
630  */
631
632 HWND WINAPI
633 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
634                  HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
635                  INT iNumButtons, INT dxButton, INT dyButton,
636                  INT dxBitmap, INT dyBitmap, UINT uStructSize)
637 {
638     HWND hwndTB =
639         CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style, 0, 0, 0, 0,
640                            hwnd, (HMENU)wID, 0, NULL);
641     if(hwndTB) {
642         TBADDBITMAP tbab;
643
644         SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
645                         (WPARAM)uStructSize, 0);
646
647         /* set bitmap and button size */
648         /*If CreateToolbarEx receive 0, windows set default values*/
649         if (dyBitmap < 0)
650             dyBitmap = 16;
651         if (dxBitmap < 0)
652             dxBitmap = 16;
653
654             SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
655                             MAKELPARAM((WORD)dyBitmap, (WORD)dxBitmap));
656             SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
657                             MAKELPARAM((WORD)dyButton, (WORD)dxButton));
658
659
660         /* add bitmaps */
661         if (nBitmaps > 0)
662         {
663         tbab.hInst = hBMInst;
664         tbab.nID   = wBMID;
665
666         SendMessageA (hwndTB, TB_ADDBITMAP,
667                         (WPARAM)nBitmaps, (LPARAM)&tbab);
668         }
669         /* add buttons */
670         if(iNumButtons > 0)
671         SendMessageA (hwndTB, TB_ADDBUTTONSA,
672                         (WPARAM)iNumButtons, (LPARAM)lpButtons);
673     }
674
675     return hwndTB;
676 }
677
678
679 /***********************************************************************
680  * CreateMappedBitmap [COMCTL32.8]
681  *
682  * PARAMS
683  *     hInstance  [I]
684  *     idBitmap   [I]
685  *     wFlags     [I]
686  *     lpColorMap [I]
687  *     iNumMaps   [I]
688  *
689  * RETURNS
690  *     Success: handle to the new bitmap
691  *     Failure: 0
692  */
693
694 HBITMAP WINAPI
695 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
696                     LPCOLORMAP lpColorMap, INT iNumMaps)
697 {
698     HGLOBAL hglb;
699     HRSRC hRsrc;
700     LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
701     UINT nSize, nColorTableSize;
702     RGBQUAD *pColorTable;
703     INT iColor, i, iMaps, nWidth, nHeight;
704     HDC hdcScreen;
705     HBITMAP hbm;
706     LPCOLORMAP sysColorMap;
707     COLORREF cRef;
708     COLORMAP internalColorMap[4] =
709         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
710
711     /* initialize pointer to colortable and default color table */
712     if (lpColorMap) {
713         iMaps = iNumMaps;
714         sysColorMap = lpColorMap;
715     }
716     else {
717         internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
718         internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
719         internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
720         internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
721         iMaps = 4;
722         sysColorMap = (LPCOLORMAP)internalColorMap;
723     }
724
725     hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
726     if (hRsrc == 0)
727         return 0;
728     hglb = LoadResource (hInstance, hRsrc);
729     if (hglb == 0)
730         return 0;
731     lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
732     if (lpBitmap == NULL)
733         return 0;
734
735     nColorTableSize = (1 << lpBitmap->biBitCount);
736     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
737     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
738     if (lpBitmapInfo == NULL)
739         return 0;
740     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
741
742     pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
743
744     for (iColor = 0; iColor < nColorTableSize; iColor++) {
745         for (i = 0; i < iMaps; i++) {
746             cRef = RGB(pColorTable[iColor].rgbRed,
747                        pColorTable[iColor].rgbGreen,
748                        pColorTable[iColor].rgbBlue);
749             if ( cRef  == sysColorMap[i].from) {
750 #if 0
751                 if (wFlags & CBS_MASKED) {
752                     if (sysColorMap[i].to != COLOR_BTNTEXT)
753                         pColorTable[iColor] = RGB(255, 255, 255);
754                 }
755                 else
756 #endif
757                     pColorTable[iColor].rgbBlue  = GetBValue(sysColorMap[i].to);
758                     pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
759                     pColorTable[iColor].rgbRed   = GetRValue(sysColorMap[i].to);
760                 break;
761             }
762         }
763     }
764     nWidth  = (INT)lpBitmapInfo->biWidth;
765     nHeight = (INT)lpBitmapInfo->biHeight;
766     hdcScreen = GetDC ((HWND)0);
767     hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
768     if (hbm) {
769         HDC hdcDst = CreateCompatibleDC (hdcScreen);
770         HBITMAP hbmOld = SelectObject (hdcDst, hbm);
771         LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
772         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
773         StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
774                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
775                          SRCCOPY);
776         SelectObject (hdcDst, hbmOld);
777         DeleteDC (hdcDst);
778     }
779     ReleaseDC ((HWND)0, hdcScreen);
780     GlobalFree ((HGLOBAL)lpBitmapInfo);
781     FreeResource (hglb);
782
783     return hbm;
784 }
785
786
787 /***********************************************************************
788  * CreateToolbar [COMCTL32.7] Creates a tool bar control
789  *
790  * PARAMS
791  *     hwnd
792  *     style
793  *     wID
794  *     nBitmaps
795  *     hBMInst
796  *     wBMID
797  *     lpButtons
798  *     iNumButtons
799  *
800  * RETURNS
801  *     Success: handle to the tool bar control
802  *     Failure: 0
803  *
804  * NOTES
805  *     Do not use this functions anymore. Use CreateToolbarEx instead.
806  */
807
808 HWND WINAPI
809 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
810                HINSTANCE hBMInst, UINT wBMID,
811                LPCOLDTBBUTTON lpButtons,INT iNumButtons)
812 {
813     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
814                             hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
815                             iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
816 }
817
818
819 /***********************************************************************
820  * DllGetVersion [COMCTL32.25]
821  *
822  * Retrieves version information of the 'COMCTL32.DLL'
823  *
824  * PARAMS
825  *     pdvi [O] pointer to version information structure.
826  *
827  * RETURNS
828  *     Success: S_OK
829  *     Failure: E_INVALIDARG
830  *
831  * NOTES
832  *     Returns version of a comctl32.dll from IE4.01 SP1.
833  */
834
835 HRESULT WINAPI
836 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
837 {
838     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
839         WARN("wrong DLLVERSIONINFO size from app");
840         return E_INVALIDARG;
841     }
842
843     pdvi->dwMajorVersion = 4;
844     pdvi->dwMinorVersion = 72;
845     pdvi->dwBuildNumber = 3110;
846     pdvi->dwPlatformID = 1;
847
848     TRACE("%lu.%lu.%lu.%lu\n",
849            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
850            pdvi->dwBuildNumber, pdvi->dwPlatformID);
851
852     return S_OK;
853 }
854
855
856 static int iTrackMax = 0;
857 static HWND TrackingList[10];
858 static UINT_PTR timer;
859
860 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
861         int i = 0;
862         POINT pos;
863         HWND hwnd;
864         BOOL keepTracking = FALSE;
865         GetCursorPos(&pos);
866         hwnd = WindowFromPoint(pos);
867         /* Loop through the list of windows waiting on mouse exit */
868         while (i < iTrackMax) {
869                 if (TrackingList[i] != hwnd) 
870                         PostMessageA(TrackingList[i], WM_MOUSELEAVE, 0, 0);
871                 else
872                         keepTracking = TRUE;
873
874
875                 i++;
876         }
877         
878         if (keepTracking) {
879                 iTrackMax = 1;
880                 TrackingList[0] = hwnd;
881         }
882         else
883                 KillTimer(0, timer);
884 }
885
886 /***********************************************************************
887  * _TrackMouseEvent [COMCTL32.25]
888  *
889  * Requests notification of mouse events
890  *
891  * PARAMS
892  *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
893  *
894  * RETURNS
895  *     Success: non-zero
896  *     Failure: zero
897  *
898  */
899
900 BOOL WINAPI
901 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
902 {
903     DWORD flags = 0;
904         int i;
905         BOOL cancel = 0, hover = 0, leave = 0, query = 0;
906         if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
907         WARN("wrong TRACKMOUSEEVENT size from app");
908         return E_INVALIDARG;
909     }
910
911     TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
912
913         flags = ptme->dwFlags;
914     if ( flags & TME_CANCEL ) {
915                 cancel = 1;
916                 flags &= ~ TME_CANCEL;
917         }
918     if ( flags & TME_HOVER  ) {
919                 hover = 1;
920                 flags &= ~ TME_HOVER;
921                 FIXME("TME_HOVER unimplemented\n" );
922         }
923     if ( flags & TME_LEAVE ) {
924                 leave = 1;
925                 flags &= ~ TME_LEAVE;
926         }
927     if ( flags & TME_QUERY ) {
928                 query = 1;
929                 flags &= ~ TME_QUERY;
930                 FIXME("TME_QUERY unimplemented\n" );
931         }
932
933         if ( flags )
934                 FIXME("Unknown flag(s) %ld\n", flags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_QUERY) );
935
936         if (leave) {
937                 if (cancel) {
938                         for (i = 0; i < iTrackMax; i++) 
939                                 if (TrackingList[i] == ptme->hwndTrack) 
940                                         TrackingList[i] = TrackingList[--iTrackMax];
941                 }
942                 else {
943                         if (iTrackMax == sizeof (TrackingList) / sizeof *TrackingList) 
944                                 return FALSE;
945
946                         /* Add hwndTrack to the track list */
947                         TrackingList[iTrackMax++] = ptme->hwndTrack;
948                         if (!timer)
949                                 timer = SetTimer(0, 0, 50, TrackMouseEventProc);
950                 }
951         }
952
953         return TRUE;
954 }
955