crypt32: Add and use a helper function for getting cert properties.
[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  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * NOTES
22  * 
23  * This code was audited for completeness against the documented features
24  * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
25  *
26  * Unless otherwise noted, we believe this code to be complete, as per
27  * the specification mentioned above.
28  * If you discover missing features, or bugs, please note them below.
29  *
30  * TODO
31  *   -- implement GetMUILanguage + InitMUILanguage
32  *   -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
33  *   -- FIXMEs + BUGS (search for them)
34  *
35  * Control Classes
36  *   -- ICC_ANIMATE_CLASS
37  *   -- ICC_BAR_CLASSES
38  *   -- ICC_COOL_CLASSES
39  *   -- ICC_DATE_CLASSES
40  *   -- ICC_HOTKEY_CLASS
41  *   -- ICC_INTERNET_CLASSES
42  *   -- ICC_LINK_CLASS
43  *   -- ICC_LISTVIEW_CLASSES
44  *   -- ICC_NATIVEFNTCTL_CLASS
45  *   -- ICC_PAGESCROLLER_CLASS
46  *   -- ICC_PROGRESS_CLASS
47  *   -- ICC_STANDARD_CLASSES (not yet implemented)
48  *   -- ICC_TAB_CLASSES
49  *   -- ICC_TREEVIEW_CLASSES
50  *   -- ICC_UPDOWN_CLASS
51  *   -- ICC_USEREX_CLASSES
52  *   -- ICC_WIN95_CLASSES
53  */
54
55 #include <stdarg.h>
56 #include <string.h>
57 #include <stdlib.h>
58
59 #include "windef.h"
60 #include "winbase.h"
61 #include "wingdi.h"
62 #include "winuser.h"
63 #include "winnls.h"
64 #include "commctrl.h"
65 #include "winerror.h"
66 #include "winreg.h"
67 #define NO_SHLWAPI_STREAM
68 #include "shlwapi.h"
69 #include "comctl32.h"
70 #include "wine/debug.h"
71
72 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
73
74 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
75
76 LPWSTR  COMCTL32_wSubclass = NULL;
77 HMODULE COMCTL32_hModule = 0;
78 LANGID  COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
79 HBRUSH  COMCTL32_hPattern55AABrush = NULL;
80 COMCTL32_SysColor  comctl32_color;
81
82 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
83
84 static const WORD wPattern55AA[] =
85 {
86     0x5555, 0xaaaa, 0x5555, 0xaaaa,
87     0x5555, 0xaaaa, 0x5555, 0xaaaa
88 };
89
90 static const WCHAR strCC32SubclassInfo[] = {
91     'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
92 };
93
94 /***********************************************************************
95  * DllMain [Internal]
96  *
97  * Initializes the internal 'COMCTL32.DLL'.
98  *
99  * PARAMS
100  *     hinstDLL    [I] handle to the 'dlls' instance
101  *     fdwReason   [I]
102  *     lpvReserved [I] reserverd, must be NULL
103  *
104  * RETURNS
105  *     Success: TRUE
106  *     Failure: FALSE
107  */
108
109 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
110 {
111     TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
112
113     switch (fdwReason) {
114         case DLL_PROCESS_ATTACH:
115             DisableThreadLibraryCalls(hinstDLL);
116
117             COMCTL32_hModule = (HMODULE)hinstDLL;
118
119             /* add global subclassing atom (used by 'tooltip' and 'updown') */
120             COMCTL32_wSubclass = (LPWSTR)(DWORD_PTR)GlobalAddAtomW (strCC32SubclassInfo);
121             TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
122
123             /* create local pattern brush */
124             COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
125             COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
126
127             /* Get all the colors at DLL load */
128             COMCTL32_RefreshSysColors();
129
130             /* like comctl32 5.82+ register all the common control classes */
131             ANIMATE_Register ();
132             COMBOEX_Register ();
133             DATETIME_Register ();
134             FLATSB_Register ();
135             HEADER_Register ();
136             HOTKEY_Register ();
137             IPADDRESS_Register ();
138             LISTVIEW_Register ();
139             MONTHCAL_Register ();
140             NATIVEFONT_Register ();
141             PAGER_Register ();
142             PROGRESS_Register ();
143             REBAR_Register ();
144             STATUS_Register ();
145             SYSLINK_Register ();
146             TAB_Register ();
147             TOOLBAR_Register ();
148             TOOLTIPS_Register ();
149             TRACKBAR_Register ();
150             TREEVIEW_Register ();
151             UPDOWN_Register ();
152
153             /* subclass user32 controls */
154             THEMING_Initialize ();
155             break;
156
157         case DLL_PROCESS_DETACH:
158             /* clean up subclassing */ 
159             THEMING_Uninitialize();
160
161             /* unregister all common control classes */
162             ANIMATE_Unregister ();
163             COMBOEX_Unregister ();
164             DATETIME_Unregister ();
165             FLATSB_Unregister ();
166             HEADER_Unregister ();
167             HOTKEY_Unregister ();
168             IPADDRESS_Unregister ();
169             LISTVIEW_Unregister ();
170             MONTHCAL_Unregister ();
171             NATIVEFONT_Unregister ();
172             PAGER_Unregister ();
173             PROGRESS_Unregister ();
174             REBAR_Unregister ();
175             STATUS_Unregister ();
176             SYSLINK_Unregister ();
177             TAB_Unregister ();
178             TOOLBAR_Unregister ();
179             TOOLTIPS_Unregister ();
180             TRACKBAR_Unregister ();
181             TREEVIEW_Unregister ();
182             UPDOWN_Unregister ();
183
184             /* delete local pattern brush */
185             DeleteObject (COMCTL32_hPattern55AABrush);
186             COMCTL32_hPattern55AABrush = NULL;
187             DeleteObject (COMCTL32_hPattern55AABitmap);
188             COMCTL32_hPattern55AABitmap = NULL;
189
190             /* delete global subclassing atom */
191             GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
192             TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
193             COMCTL32_wSubclass = NULL;
194             break;
195     }
196
197     return TRUE;
198 }
199
200
201 /***********************************************************************
202  * MenuHelp [COMCTL32.2]
203  *
204  * Handles the setting of status bar help messages when the user
205  * selects menu items.
206  *
207  * PARAMS
208  *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
209  *     wParam     [I] wParam of the message uMsg
210  *     lParam     [I] lParam of the message uMsg
211  *     hMainMenu  [I] handle to the application's main menu
212  *     hInst      [I] handle to the module that contains string resources
213  *     hwndStatus [I] handle to the status bar window
214  *     lpwIDs     [I] pointer to an array of integers (see NOTES)
215  *
216  * RETURNS
217  *     No return value
218  *
219  * NOTES
220  *     The official documentation is incomplete!
221  *     This is the correct documentation:
222  *
223  *     uMsg:
224  *     MenuHelp() does NOT handle WM_COMMAND messages! It only handles
225  *     WM_MENUSELECT messages.
226  *
227  *     lpwIDs:
228  *     (will be written ...)
229  */
230
231 VOID WINAPI
232 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
233           HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
234 {
235     UINT uMenuID = 0;
236
237     if (!IsWindow (hwndStatus))
238         return;
239
240     switch (uMsg) {
241         case WM_MENUSELECT:
242             TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
243                    wParam, lParam);
244
245             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
246                 /* menu was closed */
247                 TRACE("menu was closed!\n");
248                 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
249             }
250             else {
251                 /* menu item was selected */
252                 if (HIWORD(wParam) & MF_POPUP)
253                     uMenuID = (UINT)*(lpwIDs+1);
254                 else
255                     uMenuID = (UINT)LOWORD(wParam);
256                 TRACE("uMenuID = %u\n", uMenuID);
257
258                 if (uMenuID) {
259                     WCHAR szText[256];
260
261                     if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
262                         szText[0] = '\0';
263
264                     SendMessageW (hwndStatus, SB_SETTEXTW,
265                                     255 | SBT_NOBORDERS, (LPARAM)szText);
266                     SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
267                 }
268             }
269             break;
270
271         case WM_COMMAND :
272             TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
273                    wParam, lParam);
274             /* WM_COMMAND is not invalid since it is documented
275              * in the windows api reference. So don't output
276              * any FIXME for WM_COMMAND
277              */
278             WARN("We don't care about the WM_COMMAND\n");
279             break;
280
281         default:
282             FIXME("Invalid Message 0x%x!\n", uMsg);
283             break;
284     }
285 }
286
287
288 /***********************************************************************
289  * ShowHideMenuCtl [COMCTL32.3]
290  *
291  * Shows or hides controls and updates the corresponding menu item.
292  *
293  * PARAMS
294  *     hwnd   [I] handle to the client window.
295  *     uFlags [I] menu command id.
296  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
297  *
298  * RETURNS
299  *     Success: TRUE
300  *     Failure: FALSE
301  *
302  * NOTES
303  *     The official documentation is incomplete!
304  *     This is the correct documentation:
305  *
306  *     hwnd
307  *     Handle to the window that contains the menu and controls.
308  *
309  *     uFlags
310  *     Identifier of the menu item to receive or lose a check mark.
311  *
312  *     lpInfo
313  *     The array of integers contains pairs of values. BOTH values of
314  *     the first pair must be the handles to the application's main menu.
315  *     Each subsequent pair consists of a menu id and control id.
316  */
317
318 BOOL WINAPI
319 ShowHideMenuCtl (HWND hwnd, UINT_PTR uFlags, LPINT lpInfo)
320 {
321     LPINT lpMenuId;
322
323     TRACE("%p, %lx, %p\n", hwnd, uFlags, lpInfo);
324
325     if (lpInfo == NULL)
326         return FALSE;
327
328     if (!(lpInfo[0]) || !(lpInfo[1]))
329         return FALSE;
330
331     /* search for control */
332     lpMenuId = &lpInfo[2];
333     while (*lpMenuId != uFlags)
334         lpMenuId += 2;
335
336     if (GetMenuState ((HMENU)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
337         /* uncheck menu item */
338         CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
339
340         /* hide control */
341         lpMenuId++;
342         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
343                         SWP_HIDEWINDOW);
344     }
345     else {
346         /* check menu item */
347         CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
348
349         /* show control */
350         lpMenuId++;
351         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
352                         SWP_SHOWWINDOW);
353     }
354
355     return TRUE;
356 }
357
358
359 /***********************************************************************
360  * GetEffectiveClientRect [COMCTL32.4]
361  *
362  * Calculates the coordinates of a rectangle in the client area.
363  *
364  * PARAMS
365  *     hwnd   [I] handle to the client window.
366  *     lpRect [O] pointer to the rectangle of the client window
367  *     lpInfo [I] pointer to an array of integers (see NOTES)
368  *
369  * RETURNS
370  *     No return value.
371  *
372  * NOTES
373  *     The official documentation is incomplete!
374  *     This is the correct documentation:
375  *
376  *     lpInfo
377  *     (will be written ...)
378  */
379
380 VOID WINAPI
381 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, const INT *lpInfo)
382 {
383     RECT rcCtrl;
384     const INT *lpRun;
385     HWND hwndCtrl;
386
387     TRACE("(%p %p %p)\n",
388            hwnd, lpRect, lpInfo);
389
390     GetClientRect (hwnd, lpRect);
391     lpRun = lpInfo;
392
393     do {
394         lpRun += 2;
395         if (*lpRun == 0)
396             return;
397         lpRun++;
398         hwndCtrl = GetDlgItem (hwnd, *lpRun);
399         if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
400             TRACE("control id 0x%x\n", *lpRun);
401             GetWindowRect (hwndCtrl, &rcCtrl);
402             MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
403             SubtractRect (lpRect, lpRect, &rcCtrl);
404         }
405         lpRun++;
406     } while (*lpRun);
407 }
408
409
410 /***********************************************************************
411  * DrawStatusTextW [COMCTL32.@]
412  *
413  * Draws text with borders, like in a status bar.
414  *
415  * PARAMS
416  *     hdc   [I] handle to the window's display context
417  *     lprc  [I] pointer to a rectangle
418  *     text  [I] pointer to the text
419  *     style [I] drawing style
420  *
421  * RETURNS
422  *     No return value.
423  *
424  * NOTES
425  *     The style variable can have one of the following values:
426  *     (will be written ...)
427  */
428
429 void WINAPI DrawStatusTextW (HDC hdc, LPCRECT lprc, LPCWSTR text, UINT style)
430 {
431     RECT r = *lprc;
432     UINT border = BDR_SUNKENOUTER;
433
434     if (style & SBT_POPOUT)
435         border = BDR_RAISEDOUTER;
436     else if (style & SBT_NOBORDERS)
437         border = 0;
438
439     DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
440
441     /* now draw text */
442     if (text) {
443         int oldbkmode = SetBkMode (hdc, TRANSPARENT);
444         UINT align = DT_LEFT;
445         if (*text == '\t') {
446             text++;
447             align = DT_CENTER;
448             if (*text == '\t') {
449                 text++;
450                 align = DT_RIGHT;
451             }
452         }
453         r.left += 3;
454         if (style & SBT_RTLREADING)
455             FIXME("Unsupported RTL style!\n");
456         DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
457         SetBkMode(hdc, oldbkmode);
458     }
459 }
460
461
462 /***********************************************************************
463  * DrawStatusText  [COMCTL32.@]
464  * DrawStatusTextA [COMCTL32.5]
465  *
466  * Draws text with borders, like in a status bar.
467  *
468  * PARAMS
469  *     hdc   [I] handle to the window's display context
470  *     lprc  [I] pointer to a rectangle
471  *     text  [I] pointer to the text
472  *     style [I] drawing style
473  *
474  * RETURNS
475  *     No return value.
476  */
477
478 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
479 {
480     INT len;
481     LPWSTR textW = NULL;
482
483     if ( text ) {
484         if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
485             if ( (textW = Alloc( len * sizeof(WCHAR) )) )
486                 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
487         }
488     }
489     DrawStatusTextW( hdc, lprc, textW, style );
490     Free( textW );
491 }
492
493
494 /***********************************************************************
495  * CreateStatusWindow  [COMCTL32.@]
496  * CreateStatusWindowA [COMCTL32.6]
497  *
498  * Creates a status bar
499  *
500  * PARAMS
501  *     style  [I] window style
502  *     text   [I] pointer to the window text
503  *     parent [I] handle to the parent window
504  *     wid    [I] control id of the status bar
505  *
506  * RETURNS
507  *     Success: handle to the status window
508  *     Failure: 0
509  */
510
511 HWND WINAPI
512 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
513 {
514     return CreateWindowA(STATUSCLASSNAMEA, text, style,
515                            CW_USEDEFAULT, CW_USEDEFAULT,
516                            CW_USEDEFAULT, CW_USEDEFAULT,
517                            parent, (HMENU)(DWORD_PTR)wid, 0, 0);
518 }
519
520
521 /***********************************************************************
522  * CreateStatusWindowW [COMCTL32.@]
523  *
524  * Creates a status bar control
525  *
526  * PARAMS
527  *     style  [I] window style
528  *     text   [I] pointer to the window text
529  *     parent [I] handle to the parent window
530  *     wid    [I] control id of the status bar
531  *
532  * RETURNS
533  *     Success: handle to the status window
534  *     Failure: 0
535  */
536
537 HWND WINAPI
538 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
539 {
540     return CreateWindowW(STATUSCLASSNAMEW, text, style,
541                            CW_USEDEFAULT, CW_USEDEFAULT,
542                            CW_USEDEFAULT, CW_USEDEFAULT,
543                            parent, (HMENU)(DWORD_PTR)wid, 0, 0);
544 }
545
546
547 /***********************************************************************
548  * CreateUpDownControl [COMCTL32.16]
549  *
550  * Creates an up-down control
551  *
552  * PARAMS
553  *     style  [I] window styles
554  *     x      [I] horizontal position of the control
555  *     y      [I] vertical position of the control
556  *     cx     [I] with of the control
557  *     cy     [I] height of the control
558  *     parent [I] handle to the parent window
559  *     id     [I] the control's identifier
560  *     inst   [I] handle to the application's module instance
561  *     buddy  [I] handle to the buddy window, can be NULL
562  *     maxVal [I] upper limit of the control
563  *     minVal [I] lower limit of the control
564  *     curVal [I] current value of the control
565  *
566  * RETURNS
567  *     Success: handle to the updown control
568  *     Failure: 0
569  */
570
571 HWND WINAPI
572 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
573                      HWND parent, INT id, HINSTANCE inst,
574                      HWND buddy, INT maxVal, INT minVal, INT curVal)
575 {
576     HWND hUD =
577         CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
578                          parent, (HMENU)(DWORD_PTR)id, inst, 0);
579     if (hUD) {
580         SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
581         SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
582         SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
583     }
584
585     return hUD;
586 }
587
588
589 /***********************************************************************
590  * InitCommonControls [COMCTL32.17]
591  *
592  * Registers the common controls.
593  *
594  * PARAMS
595  *     No parameters.
596  *
597  * RETURNS
598  *     No return values.
599  *
600  * NOTES
601  *     This function is just a dummy - all the controls are registered at
602  *     the DLL's initialization. See InitCommonContolsEx for details.
603  */
604
605 VOID WINAPI
606 InitCommonControls (void)
607 {
608 }
609
610
611 /***********************************************************************
612  * InitCommonControlsEx [COMCTL32.@]
613  *
614  * Registers the common controls.
615  *
616  * PARAMS
617  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
618  *
619  * RETURNS
620  *     Success: TRUE
621  *     Failure: FALSE
622  *
623  * NOTES
624  *     Probaly all versions of comctl32 initializes the Win95 controls in DllMain
625  *     during DLL initializaiton. Starting from comctl32 v5.82 all the controls
626  *     are initialized there. We follow this behaviour and this function is just
627  *     a dummy.
628  *
629  *     Note: when writing programs under Windows, if you don't call any function
630  *     from comctl32 the linker may not link this DLL. If InitCommonControlsEx
631  *     was the only comctl32 function you were calling and you remove it you may
632  *     have a false impression that InitCommonControlsEx actually did something.
633  */
634
635 BOOL WINAPI
636 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
637 {
638     if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
639         return FALSE;
640
641     TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
642     return TRUE;
643 }
644
645
646 /***********************************************************************
647  * CreateToolbarEx [COMCTL32.@]
648  *
649  * Creates a toolbar window.
650  *
651  * PARAMS
652  *     hwnd
653  *     style
654  *     wID
655  *     nBitmaps
656  *     hBMInst
657  *     wBMID
658  *     lpButtons
659  *     iNumButtons
660  *     dxButton
661  *     dyButton
662  *     dxBitmap
663  *     dyBitmap
664  *     uStructSize
665  *
666  * RETURNS
667  *     Success: handle to the tool bar control
668  *     Failure: 0
669  */
670
671 HWND WINAPI
672 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
673                  HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
674                  INT iNumButtons, INT dxButton, INT dyButton,
675                  INT dxBitmap, INT dyBitmap, UINT uStructSize)
676 {
677     HWND hwndTB;
678
679     hwndTB =
680         CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
681                         hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
682     if(hwndTB) {
683         TBADDBITMAP tbab;
684
685         SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
686
687        /* set bitmap and button size */
688        /*If CreateToolbarEx receives 0, windows sets default values*/
689        if (dxBitmap < 0)
690            dxBitmap = 16;
691        if (dyBitmap < 0)
692            dyBitmap = 16;
693        if (dxBitmap == 0 || dyBitmap == 0)
694            dxBitmap = dyBitmap = 16;
695        SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
696
697        if (dxButton < 0)
698            dxButton = dxBitmap;
699        if (dyButton < 0)
700            dyButton = dyBitmap;
701        /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
702        if (dxButton != 0 && dyButton != 0)
703             SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
704
705
706         /* add bitmaps */
707         if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
708         {
709             tbab.hInst = hBMInst;
710             tbab.nID   = wBMID;
711
712             SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
713         }
714         /* add buttons */
715         if(iNumButtons > 0)
716         SendMessageW (hwndTB, TB_ADDBUTTONSW,
717                         (WPARAM)iNumButtons, (LPARAM)lpButtons);
718     }
719
720     return hwndTB;
721 }
722
723
724 /***********************************************************************
725  * CreateMappedBitmap [COMCTL32.8]
726  *
727  * Loads a bitmap resource using a colour map.
728  *
729  * PARAMS
730  *     hInstance  [I] Handle to the module containing the bitmap.
731  *     idBitmap   [I] The bitmap resource ID.
732  *     wFlags     [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
733  *     lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
734  *     iNumMaps   [I] Number of COLORMAP's pointed to by lpColorMap.
735  *
736  * RETURNS
737  *     Success: handle to the new bitmap
738  *     Failure: 0
739  */
740
741 HBITMAP WINAPI
742 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
743                     LPCOLORMAP lpColorMap, INT iNumMaps)
744 {
745     HGLOBAL hglb;
746     HRSRC hRsrc;
747     const BITMAPINFOHEADER *lpBitmap;
748     LPBITMAPINFOHEADER lpBitmapInfo;
749     UINT nSize, nColorTableSize, iColor;
750     RGBQUAD *pColorTable;
751     INT i, iMaps, nWidth, nHeight;
752     HDC hdcScreen;
753     HBITMAP hbm;
754     LPCOLORMAP sysColorMap;
755     COLORREF cRef;
756     COLORMAP internalColorMap[4] =
757         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
758
759     /* initialize pointer to colortable and default color table */
760     if (lpColorMap) {
761         iMaps = iNumMaps;
762         sysColorMap = lpColorMap;
763     }
764     else {
765         internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
766         internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
767         internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
768         internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
769         iMaps = 4;
770         sysColorMap = (LPCOLORMAP)internalColorMap;
771     }
772
773     hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
774     if (hRsrc == 0)
775         return 0;
776     hglb = LoadResource (hInstance, hRsrc);
777     if (hglb == 0)
778         return 0;
779     lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
780     if (lpBitmap == NULL)
781         return 0;
782
783     if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
784         nColorTableSize = lpBitmap->biClrUsed;
785     else if (lpBitmap->biBitCount <= 8) 
786         nColorTableSize = (1 << lpBitmap->biBitCount);
787     else
788         nColorTableSize = 0;
789     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
790     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
791     if (lpBitmapInfo == NULL)
792         return 0;
793     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
794
795     pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
796
797     for (iColor = 0; iColor < nColorTableSize; iColor++) {
798         for (i = 0; i < iMaps; i++) {
799             cRef = RGB(pColorTable[iColor].rgbRed,
800                        pColorTable[iColor].rgbGreen,
801                        pColorTable[iColor].rgbBlue);
802             if ( cRef  == sysColorMap[i].from) {
803 #if 0
804                 if (wFlags & CBS_MASKED) {
805                     if (sysColorMap[i].to != COLOR_BTNTEXT)
806                         pColorTable[iColor] = RGB(255, 255, 255);
807                 }
808                 else
809 #endif
810                     pColorTable[iColor].rgbBlue  = GetBValue(sysColorMap[i].to);
811                     pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
812                     pColorTable[iColor].rgbRed   = GetRValue(sysColorMap[i].to);
813                 break;
814             }
815         }
816     }
817     nWidth  = (INT)lpBitmapInfo->biWidth;
818     nHeight = (INT)lpBitmapInfo->biHeight;
819     hdcScreen = GetDC (NULL);
820     hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
821     if (hbm) {
822         HDC hdcDst = CreateCompatibleDC (hdcScreen);
823         HBITMAP hbmOld = SelectObject (hdcDst, hbm);
824         const BYTE *lpBits = (const BYTE *)(lpBitmap + 1);
825         lpBits += nColorTableSize * sizeof(RGBQUAD);
826         StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
827                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
828                          SRCCOPY);
829         SelectObject (hdcDst, hbmOld);
830         DeleteDC (hdcDst);
831     }
832     ReleaseDC (NULL, hdcScreen);
833     GlobalFree ((HGLOBAL)lpBitmapInfo);
834     FreeResource (hglb);
835
836     return hbm;
837 }
838
839
840 /***********************************************************************
841  * CreateToolbar [COMCTL32.7]
842  *
843  * Creates a toolbar control.
844  *
845  * PARAMS
846  *     hwnd
847  *     style
848  *     wID
849  *     nBitmaps
850  *     hBMInst
851  *     wBMID
852  *     lpButtons
853  *     iNumButtons
854  *
855  * RETURNS
856  *     Success: handle to the tool bar control
857  *     Failure: 0
858  *
859  * NOTES
860  *     Do not use this functions anymore. Use CreateToolbarEx instead.
861  */
862
863 HWND WINAPI
864 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
865                HINSTANCE hBMInst, UINT wBMID,
866                LPCTBBUTTON lpButtons,INT iNumButtons)
867 {
868     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
869                             hBMInst, wBMID, lpButtons,
870                             iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
871 }
872
873
874 /***********************************************************************
875  * DllGetVersion [COMCTL32.@]
876  *
877  * Retrieves version information of the 'COMCTL32.DLL'
878  *
879  * PARAMS
880  *     pdvi [O] pointer to version information structure.
881  *
882  * RETURNS
883  *     Success: S_OK
884  *     Failure: E_INVALIDARG
885  *
886  * NOTES
887  *     Returns version of a comctl32.dll from IE4.01 SP1.
888  */
889
890 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
891 {
892     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
893         WARN("wrong DLLVERSIONINFO size from app\n");
894         return E_INVALIDARG;
895     }
896
897     pdvi->dwMajorVersion = COMCTL32_VERSION;
898     pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
899     pdvi->dwBuildNumber = 2919;
900     pdvi->dwPlatformID = 6304;
901
902     TRACE("%u.%u.%u.%u\n",
903            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
904            pdvi->dwBuildNumber, pdvi->dwPlatformID);
905
906     return S_OK;
907 }
908
909 /***********************************************************************
910  *              DllInstall (COMCTL32.@)
911  *
912  * Installs the ComCtl32 DLL.
913  *
914  * RETURNS
915  *     Success: S_OK
916  *     Failure: A HRESULT error
917  */
918 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
919 {
920   FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
921         debugstr_w(cmdline));
922
923   return S_OK;
924 }
925
926 /***********************************************************************
927  * _TrackMouseEvent [COMCTL32.@]
928  *
929  * Requests notification of mouse events
930  *
931  * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
932  * to the hwnd specified in the ptme structure.  After the event message
933  * is posted to the hwnd, the entry in the queue is removed.
934  *
935  * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
936  * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
937  * immediately and the TME_LEAVE flag being ignored.
938  *
939  * PARAMS
940  *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
941  *
942  * RETURNS
943  *     Success: non-zero
944  *     Failure: zero
945  *
946  * IMPLEMENTATION moved to USER32.TrackMouseEvent
947  *
948  */
949
950 BOOL WINAPI
951 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
952 {
953     return TrackMouseEvent (ptme);
954 }
955
956 /*************************************************************************
957  * GetMUILanguage [COMCTL32.@]
958  *
959  * Returns the user interface language in use by the current process.
960  *
961  * RETURNS
962  *      Language ID in use by the current process.
963  */
964 LANGID WINAPI GetMUILanguage (VOID)
965 {
966     return COMCTL32_uiLang;
967 }
968
969
970 /*************************************************************************
971  * InitMUILanguage [COMCTL32.@]
972  *
973  * Sets the user interface language to be used by the current process.
974  *
975  * RETURNS
976  *      Nothing.
977  */
978 VOID WINAPI InitMUILanguage (LANGID uiLang)
979 {
980    COMCTL32_uiLang = uiLang;
981 }
982
983
984 /***********************************************************************
985  * SetWindowSubclass [COMCTL32.410]
986  *
987  * Starts a window subclass
988  *
989  * PARAMS
990  *     hWnd [in] handle to window subclass.
991  *     pfnSubclass [in] Pointer to new window procedure.
992  *     uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
993  *     dwRef [in] Reference data to pass to window procedure.
994  *
995  * RETURNS
996  *     Success: non-zero
997  *     Failure: zero
998  *
999  * BUGS
1000  *     If an application manually subclasses a window after subclassing it with
1001  *     this API and then with this API again, then none of the previous 
1002  *     subclasses get called or the origional window procedure.
1003  */
1004
1005 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1006                         UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1007 {
1008    LPSUBCLASS_INFO stack;
1009    LPSUBCLASSPROCS proc;
1010
1011    TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1012
1013    /* Since the window procedure that we set here has two additional arguments,
1014     * we can't simply set it as the new window procedure of the window. So we
1015     * set our own window procedure and then calculate the other two arguments
1016     * from there. */
1017
1018    /* See if we have been called for this window */
1019    stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1020    if (!stack) {
1021       /* allocate stack */
1022       stack = Alloc (sizeof(SUBCLASS_INFO));
1023       if (!stack) {
1024          ERR ("Failed to allocate our Subclassing stack\n");
1025          return FALSE;
1026       }
1027       SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
1028
1029       /* set window procedure to our own and save the current one */
1030       if (IsWindowUnicode (hWnd))
1031          stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1032                                                    (DWORD_PTR)COMCTL32_SubclassProc);
1033       else
1034          stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1035                                                    (DWORD_PTR)COMCTL32_SubclassProc);
1036    }
1037    else {
1038       /* Check to see if we have called this function with the same uIDSubClass
1039        * and pfnSubclass */
1040       proc = stack->SubclassProcs;
1041       while (proc) {
1042          if ((proc->id == uIDSubclass) &&
1043             (proc->subproc == pfnSubclass)) {
1044             proc->ref = dwRef;
1045             return TRUE;
1046          }
1047          proc = proc->next;
1048       }
1049    }
1050    
1051    proc = Alloc(sizeof(SUBCLASSPROCS));
1052    if (!proc) {
1053       ERR ("Failed to allocate subclass entry in stack\n");
1054       if (IsWindowUnicode (hWnd))
1055          SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1056       else
1057          SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1058       Free (stack);
1059       RemovePropW( hWnd, COMCTL32_wSubclass );
1060       return FALSE;
1061    }
1062    
1063    proc->subproc = pfnSubclass;
1064    proc->ref = dwRef;
1065    proc->id = uIDSubclass;
1066    proc->next = stack->SubclassProcs;
1067    stack->SubclassProcs = proc;
1068
1069    return TRUE;
1070 }
1071
1072
1073 /***********************************************************************
1074  * GetWindowSubclass [COMCTL32.411]
1075  *
1076  * Gets the Reference data from a subclass.
1077  *
1078  * PARAMS
1079  *     hWnd [in] Handle to window which were subclassing
1080  *     pfnSubclass [in] Pointer to the subclass procedure
1081  *     uID [in] Unique indentifier of the subclassing procedure
1082  *     pdwRef [out] Pointer to the reference data
1083  *
1084  * RETURNS
1085  *     Success: Non-zero
1086  *     Failure: 0
1087  */
1088
1089 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1090                               UINT_PTR uID, DWORD_PTR *pdwRef)
1091 {
1092    const SUBCLASS_INFO *stack;
1093    const SUBCLASSPROCS *proc;
1094
1095    TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1096
1097    /* See if we have been called for this window */
1098    stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1099    if (!stack)
1100       return FALSE;
1101
1102    proc = stack->SubclassProcs;
1103    while (proc) {
1104       if ((proc->id == uID) &&
1105          (proc->subproc == pfnSubclass)) {
1106          *pdwRef = proc->ref;
1107          return TRUE;
1108       }
1109       proc = proc->next;
1110    }
1111
1112    return FALSE;
1113 }
1114
1115
1116 /***********************************************************************
1117  * RemoveWindowSubclass [COMCTL32.412]
1118  *
1119  * Removes a window subclass.
1120  *
1121  * PARAMS
1122  *     hWnd [in] Handle to the window were subclassing
1123  *     pfnSubclass [in] Pointer to the subclass procedure
1124  *     uID [in] Unique identifier of this subclass
1125  *
1126  * RETURNS
1127  *     Success: non-zero
1128  *     Failure: zero
1129  */
1130
1131 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1132 {
1133    LPSUBCLASS_INFO stack;
1134    LPSUBCLASSPROCS prevproc = NULL;
1135    LPSUBCLASSPROCS proc;
1136    BOOL ret = FALSE;
1137
1138    TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1139
1140    /* Find the Subclass to remove */
1141    stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1142    if (!stack)
1143       return FALSE;
1144
1145    proc = stack->SubclassProcs;
1146    while (proc) {
1147       if ((proc->id == uID) &&
1148          (proc->subproc == pfnSubclass)) {
1149          
1150          if (!prevproc)
1151             stack->SubclassProcs = proc->next;
1152          else
1153             prevproc->next = proc->next;
1154           
1155          if (stack->stackpos == proc)
1156             stack->stackpos = stack->stackpos->next;
1157             
1158          Free (proc);
1159          ret = TRUE;
1160          break;
1161       }
1162       prevproc = proc;
1163       proc = proc->next;
1164    }
1165    
1166    if (!stack->SubclassProcs && !stack->running) {
1167       TRACE("Last Subclass removed, cleaning up\n");
1168       /* clean up our heap and reset the origional window procedure */
1169       if (IsWindowUnicode (hWnd))
1170          SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1171       else
1172          SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1173       Free (stack);
1174       RemovePropW( hWnd, COMCTL32_wSubclass );
1175    }
1176    
1177    return ret;
1178 }
1179
1180 /***********************************************************************
1181  * COMCTL32_SubclassProc (internal)
1182  *
1183  * Window procedure for all subclassed windows. 
1184  * Saves the current subclassing stack position to support nested messages
1185  */
1186 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1187 {
1188    LPSUBCLASS_INFO stack;
1189    LPSUBCLASSPROCS proc;
1190    LRESULT ret;
1191     
1192    TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1193
1194    stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1195    if (!stack) {
1196       ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1197       return 0;
1198    }
1199     
1200    /* Save our old stackpos to properly handle nested messages */
1201    proc = stack->stackpos;
1202    stack->stackpos = stack->SubclassProcs;
1203    stack->running++;
1204    ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1205    stack->running--;
1206    stack->stackpos = proc;
1207     
1208    if (!stack->SubclassProcs && !stack->running) {
1209       TRACE("Last Subclass removed, cleaning up\n");
1210       /* clean up our heap and reset the origional window procedure */
1211       if (IsWindowUnicode (hWnd))
1212          SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1213       else
1214          SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1215       Free (stack);
1216       RemovePropW( hWnd, COMCTL32_wSubclass );
1217    }
1218    return ret;
1219 }
1220
1221 /***********************************************************************
1222  * DefSubclassProc [COMCTL32.413]
1223  *
1224  * Calls the next window procedure (ie. the one before this subclass)
1225  *
1226  * PARAMS
1227  *     hWnd [in] The window that we're subclassing
1228  *     uMsg [in] Message
1229  *     wParam [in] WPARAM
1230  *     lParam [in] LPARAM
1231  *
1232  * RETURNS
1233  *     Success: non-zero
1234  *     Failure: zero
1235  */
1236
1237 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1238 {
1239    LPSUBCLASS_INFO stack;
1240    LRESULT ret;
1241    
1242    TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1243
1244    /* retrieve our little stack from the Properties */
1245    stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1246    if (!stack) {
1247       ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1248       return 0;
1249    }
1250
1251    /* If we are at the end of stack then we have to call the original
1252     * window procedure */
1253    if (!stack->stackpos) {
1254       if (IsWindowUnicode (hWnd))
1255          ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1256       else
1257          ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1258    } else {
1259       const SUBCLASSPROCS *proc = stack->stackpos;
1260       stack->stackpos = stack->stackpos->next; 
1261       /* call the Subclass procedure from the stack */
1262       ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1263             proc->id, proc->ref);
1264    }
1265
1266    return ret;
1267 }
1268
1269
1270 /***********************************************************************
1271  * COMCTL32_CreateToolTip [NOT AN API]
1272  *
1273  * Creates a tooltip for the control specified in hwnd and does all
1274  * necessary setup and notifications.
1275  *
1276  * PARAMS
1277  *     hwndOwner [I] Handle to the window that will own the tool tip.
1278  *
1279  * RETURNS
1280  *     Success: Handle of tool tip window.
1281  *     Failure: NULL
1282  */
1283
1284 HWND
1285 COMCTL32_CreateToolTip(HWND hwndOwner)
1286 {
1287     HWND hwndToolTip;
1288
1289     hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1290                                   CW_USEDEFAULT, CW_USEDEFAULT,
1291                                   CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1292                                   0, 0, 0);
1293
1294     /* Send NM_TOOLTIPSCREATED notification */
1295     if (hwndToolTip)
1296     {
1297         NMTOOLTIPSCREATED nmttc;
1298         /* true owner can be different if hwndOwner is a child window */
1299         HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1300         nmttc.hdr.hwndFrom = hwndTrueOwner;
1301         nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1302         nmttc.hdr.code = NM_TOOLTIPSCREATED;
1303         nmttc.hwndToolTips = hwndToolTip;
1304
1305        SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1306                     (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
1307                     (LPARAM)&nmttc);
1308     }
1309
1310     return hwndToolTip;
1311 }
1312
1313
1314 /***********************************************************************
1315  * COMCTL32_RefreshSysColors [NOT AN API]
1316  *
1317  * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1318  * refresh the color values in the color structure
1319  *
1320  * PARAMS
1321  *     none
1322  *
1323  * RETURNS
1324  *     none
1325  */
1326
1327 VOID
1328 COMCTL32_RefreshSysColors(void)
1329 {
1330     comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1331     comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1332     comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1333     comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1334     comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1335     comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1336     comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1337     comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1338     comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1339     comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1340     comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1341     comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1342     comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1343     comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1344     comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1345     comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1346 }
1347
1348 /***********************************************************************
1349  * COMCTL32_DrawInsertMark [NOT AN API]
1350  *
1351  * Draws an insertion mark (which looks similar to an 'I').
1352  *
1353  * PARAMS
1354  *     hDC           [I] Device context to draw onto.
1355  *     lpRect        [I] Co-ordinates of insertion mark.
1356  *     clrInsertMark [I] Colour of the insertion mark.
1357  *     bHorizontal   [I] True if insert mark should be drawn horizontally,
1358  *                       vertical otherwise.
1359  *
1360  * RETURNS
1361  *     none
1362  *
1363  * NOTES
1364  *     Draws up to but not including the bottom co-ordinate when drawing
1365  *     vertically or the right co-ordinate when horizontal.
1366  */
1367 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1368 {
1369     HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1370     HPEN hOldPen;
1371     static const DWORD adwPolyPoints[] = {4,4,4};
1372     LONG lCentre = (bHorizontal ? 
1373         lpRect->top + (lpRect->bottom - lpRect->top)/2 : 
1374         lpRect->left + (lpRect->right - lpRect->left)/2);
1375     LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1376     LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1377     const POINT aptInsertMark[] =
1378     {
1379         /* top (V) or left (H) arrow */
1380         {lCentre    , l1 + 2},
1381         {lCentre - 2, l1    },
1382         {lCentre + 3, l1    },
1383         {lCentre + 1, l1 + 2},
1384         /* middle line */
1385         {lCentre    , l2 - 2},
1386         {lCentre    , l1 - 1},
1387         {lCentre + 1, l1 - 1},
1388         {lCentre + 1, l2 - 2},
1389         /* bottom (V) or right (H) arrow */
1390         {lCentre    , l2 - 3},
1391         {lCentre - 2, l2 - 1},
1392         {lCentre + 3, l2 - 1},
1393         {lCentre + 1, l2 - 3},
1394     };
1395     hOldPen = SelectObject(hDC, hPen);
1396     PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1397     SelectObject(hDC, hOldPen);
1398     DeleteObject(hPen);
1399 }
1400
1401 /***********************************************************************
1402  * COMCTL32_EnsureBitmapSize [internal]
1403  *
1404  * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1405  * the height is at least cyMinHeight. If the bitmap already has these
1406  * dimensions nothing changes.
1407  *
1408  * PARAMS
1409  *     hBitmap       [I/O] Bitmap to modify. The handle may change
1410  *     cxMinWidth    [I]   If the width of the bitmap is smaller, then it will
1411  *                         be enlarged to this value
1412  *     cyMinHeight   [I]   If the height of the bitmap is smaller, then it will
1413  *                         be enlarged to this value
1414  *     cyBackground  [I]   The color with which the new area will be filled
1415  *
1416  * RETURNS
1417  *     none
1418  */
1419 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1420 {
1421     int cxNew, cyNew;
1422     BITMAP bmp;
1423     HBITMAP hNewBitmap;
1424     HBITMAP hNewDCBitmap, hOldDCBitmap;
1425     HBRUSH hNewDCBrush;
1426     HDC hdcNew, hdcOld;
1427
1428     if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1429         return;
1430     cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1431     cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1432     if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1433         return;
1434
1435     hdcNew = CreateCompatibleDC(NULL);
1436     hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1437     hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1438     hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1439
1440     hdcOld = CreateCompatibleDC(NULL);
1441     hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1442
1443     BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1444     if (bmp.bmWidth < cxMinWidth)
1445         PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1446     if (bmp.bmHeight < cyMinHeight)
1447         PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1448     if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1449         PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1450
1451     SelectObject(hdcNew, hNewDCBitmap);
1452     DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1453     DeleteDC(hdcNew);
1454     SelectObject(hdcOld, hOldDCBitmap);
1455     DeleteDC(hdcOld);
1456
1457     DeleteObject(*pBitmap);    
1458     *pBitmap = hNewBitmap;
1459     return;
1460 }
1461
1462 /***********************************************************************
1463  * MirrorIcon [COMCTL32.414]
1464  *
1465  * Mirrors an icon so that it will appear correctly on a mirrored DC.
1466  *
1467  * PARAMS
1468  *     phicon1 [I/O] Icon.
1469  *     phicon2 [I/O] Icon.
1470  *
1471  * RETURNS
1472  *     Success: TRUE.
1473  *     Failure: FALSE.
1474  */
1475 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1476 {
1477     FIXME("(%p, %p): stub\n", phicon1, phicon2);
1478     return FALSE;
1479 }
1480
1481 static inline int IsDelimiter(WCHAR c)
1482 {
1483     switch(c)
1484     {
1485         case '/':
1486         case '\\':
1487         case '.':
1488         case ' ':
1489             return TRUE;
1490     }
1491     return FALSE;
1492 }
1493
1494 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1495 {
1496     if (code == WB_ISDELIMITER)
1497         return IsDelimiter(lpch[ichCurrent]);
1498     else
1499     {
1500         int dir = (code == WB_LEFT) ? -1 : 1;
1501         for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1502             if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1503     }
1504     return ichCurrent;
1505 }
1506
1507 /***********************************************************************
1508  * SetPathWordBreakProc [COMCTL32.384]
1509  *
1510  * Sets the word break procedure for an edit control to one that understands
1511  * paths so that the user can jump over directories.
1512  *
1513  * PARAMS
1514  *     hwnd [I] Handle to edit control.
1515  *     bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1516  *
1517  * RETURNS
1518  *     Result from EM_SETWORDBREAKPROC message.
1519  */
1520 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1521 {
1522     return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1523         (LPARAM)(bSet ? PathWordBreakProc : NULL));
1524 }
1525
1526 /***********************************************************************
1527  * DrawShadowText [COMCTL32.@]
1528  *
1529  * Draw text with shadow.
1530  */
1531 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1532                           COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1533 {
1534     FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1535                                                                   crText, crShadow, ixOffset, iyOffset);
1536     return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);
1537 }