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