Implement ResetDC and PHYSICALOFFSET[X|Y] devcaps.
[wine] / dlls / comctl32 / status.c
1 /*
2  * Interface code to StatusWindow widget/control
3  *
4  * Copyright 1996 Bruce Milner
5  * Copyright 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 /*
22  * FIXME/TODO
23  * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
24  * 2) Tooltip support (almost done).
25  * 3) where else should we use infoPtr->hwndParent instead of GetParent() ?
26  * 4) send WM_QUERYFORMAT
27  */
28
29 #include <string.h>
30 #include "winbase.h"
31 #include "wine/unicode.h"
32 #include "commctrl.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(statusbar);
36
37 typedef struct
38 {
39     INT x;
40     INT style;
41     RECT        bound;
42     LPWSTR      text;
43     HICON     hIcon;
44 } STATUSWINDOWPART;
45
46 typedef struct
47 {
48     HWND              hwndParent;
49     WORD              numParts;
50     WORD              textHeight;
51     UINT              height;
52     BOOL              simple;
53     HWND              hwndToolTip;
54     HFONT             hFont;
55     HFONT             hDefaultFont;
56     COLORREF            clrBk;     /* background color */
57     BOOL              bUnicode;  /* unicode flag */
58     STATUSWINDOWPART    part0;     /* simple window */
59     STATUSWINDOWPART   *parts;
60 } STATUSWINDOWINFO;
61
62 /*
63  * Run tests using Waite Group Windows95 API Bible Vol. 1&2
64  * The second cdrom contains executables drawstat.exe, gettext.exe,
65  * simple.exe, getparts.exe, setparts.exe, statwnd.exe
66  */
67
68 #define HORZ_BORDER 0
69 #define VERT_BORDER 2
70 #define HORZ_GAP    2
71
72 #define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
73
74 /* prototype */
75 static void
76 STATUSBAR_SetPartBounds (STATUSWINDOWINFO *infoPtr, HWND hwnd);
77
78 static void
79 STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
80 {
81     HPEN hOldPen;
82     POINT pt;
83     INT i;
84
85     TRACE("draw size grip %d,%d - %d,%d\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
86     pt.x = lpRect->right - 1;
87     pt.y = lpRect->bottom - 1;
88
89     hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
90     MoveToEx (hdc, pt.x - 12, pt.y, NULL);
91     LineTo (hdc, pt.x, pt.y);
92     LineTo (hdc, pt.x, pt.y - 12);
93
94     pt.x--;
95     pt.y--;
96
97     SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
98     for (i = 1; i < 11; i += 4) {
99         MoveToEx (hdc, pt.x - i, pt.y, NULL);
100         LineTo (hdc, pt.x, pt.y - i);
101
102         MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
103         LineTo (hdc, pt.x, pt.y - i-1);
104     }
105
106     SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
107     for (i = 3; i < 13; i += 4) {
108         MoveToEx (hdc, pt.x - i, pt.y, NULL);
109         LineTo (hdc, pt.x, pt.y - i);
110     }
111
112     SelectObject (hdc, hOldPen);
113 }
114
115
116 static void 
117 STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
118 {
119     RECT r = part->bound;
120     UINT border = BDR_SUNKENOUTER;
121
122     TRACE("part bound %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom);
123     if (part->style & SBT_POPOUT)
124       border = BDR_RAISEDOUTER;
125     else if (part->style & SBT_NOBORDERS)
126       border = 0;
127
128     DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
129
130     /* draw the icon */
131     if (part->hIcon) {
132         INT cy = r.bottom - r.top;
133
134         r.left += 2;
135         DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
136         r.left += cy;
137     }
138
139     /* now draw text */
140     if (part->text) {
141       int oldbkmode = SetBkMode(hdc, TRANSPARENT);
142       LPWSTR p = (LPWSTR)part->text;
143       UINT align = DT_LEFT;
144       if (*p == L'\t') {
145         p++;
146         align = DT_CENTER;
147
148         if (*p == L'\t') {
149           p++;
150           align = DT_RIGHT;
151         }
152       }
153       r.left += 3;
154       TRACE("%s at %d,%d - %d,%d\n", debugstr_w(p), r.left, r.top, r.right, r.bottom);
155       DrawTextW (hdc, p, -1, &r, align|DT_VCENTER|DT_SINGLELINE);
156       if (oldbkmode != TRANSPARENT)
157         SetBkMode(hdc, oldbkmode);
158     }
159 }
160
161
162 static VOID
163 STATUSBAR_RefreshPart (STATUSWINDOWINFO *infoPtr, HWND hwnd, STATUSWINDOWPART *part, HDC hdc, int itemID)
164 {
165     HBRUSH hbrBk;
166     HFONT  hOldFont;
167
168     TRACE("item %d\n", itemID);
169     if (!IsWindowVisible (hwnd))
170         return;
171
172     if (part->bound.right < part->bound.left) return;
173
174     if (infoPtr->clrBk != CLR_DEFAULT)
175         hbrBk = CreateSolidBrush (infoPtr->clrBk);
176     else
177         hbrBk = GetSysColorBrush (COLOR_3DFACE);
178     FillRect(hdc, &part->bound, hbrBk);
179
180     hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
181
182     if (part->style & SBT_OWNERDRAW) {
183         DRAWITEMSTRUCT dis;
184
185         dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
186         dis.itemID = itemID;
187         dis.hwndItem = hwnd;
188         dis.hDC = hdc;
189         dis.rcItem = part->bound;
190         dis.itemData = (INT)part->text;
191         SendMessageA (GetParent (hwnd), WM_DRAWITEM,
192                 (WPARAM)dis.CtlID, (LPARAM)&dis);
193     } else
194         STATUSBAR_DrawPart (hdc, part);
195
196     SelectObject (hdc, hOldFont);
197
198     if (infoPtr->clrBk != CLR_DEFAULT)
199         DeleteObject (hbrBk);
200
201     if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
202         RECT rect;
203
204         GetClientRect (hwnd, &rect);
205         STATUSBAR_DrawSizeGrip (hdc, &rect);
206     }
207 }
208
209
210 static BOOL
211 STATUSBAR_Refresh (STATUSWINDOWINFO *infoPtr, HWND hwnd, HDC hdc)
212 {
213     int      i;
214     RECT   rect;
215     HBRUSH hbrBk;
216     HFONT  hOldFont;
217
218     TRACE("\n");
219     if (!IsWindowVisible(hwnd))
220         return (TRUE);
221
222     STATUSBAR_SetPartBounds(infoPtr, hwnd);
223
224     GetClientRect (hwnd, &rect);
225
226     if (infoPtr->clrBk != CLR_DEFAULT)
227         hbrBk = CreateSolidBrush (infoPtr->clrBk);
228     else
229         hbrBk = GetSysColorBrush (COLOR_3DFACE);
230     FillRect(hdc, &rect, hbrBk);
231
232     hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
233
234     if (infoPtr->simple) {
235         STATUSBAR_RefreshPart (infoPtr, hwnd, &infoPtr->part0, hdc, 0);
236     } else {
237         for (i = 0; i < infoPtr->numParts; i++) {
238             if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
239                 DRAWITEMSTRUCT dis;
240
241                 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
242                 dis.itemID = i;
243                 dis.hwndItem = hwnd;
244                 dis.hDC = hdc;
245                 dis.rcItem = infoPtr->parts[i].bound;
246                 dis.itemData = (INT)infoPtr->parts[i].text;
247                 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
248                         (WPARAM)dis.CtlID, (LPARAM)&dis);
249             } else
250                 STATUSBAR_RefreshPart (infoPtr, hwnd, &infoPtr->parts[i], hdc, i);
251         }
252     }
253
254     SelectObject (hdc, hOldFont);
255
256     if (infoPtr->clrBk != CLR_DEFAULT)
257         DeleteObject (hbrBk);
258
259     if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
260         STATUSBAR_DrawSizeGrip (hdc, &rect);
261
262     return TRUE;
263 }
264
265
266 static void
267 STATUSBAR_SetPartBounds (STATUSWINDOWINFO *infoPtr, HWND hwnd)
268 {
269     STATUSWINDOWPART *part;
270     RECT rect, *r;
271     int i;
272
273     /* get our window size */
274     GetClientRect (hwnd, &rect);
275     TRACE("client wnd size is %d,%d - %d,%d\n", rect.left, rect.top, rect.right, rect.bottom);
276
277     rect.top += VERT_BORDER;
278
279     /* set bounds for simple rectangle */
280     infoPtr->part0.bound = rect;
281
282     /* set bounds for non-simple rectangles */
283     for (i = 0; i < infoPtr->numParts; i++) {
284         part = &infoPtr->parts[i];
285         r = &infoPtr->parts[i].bound;
286         r->top = rect.top;
287         r->bottom = rect.bottom;
288         if (i == 0)
289             r->left = 0;
290         else
291             r->left = infoPtr->parts[i-1].bound.right + HORZ_GAP;
292         if (part->x == -1)
293             r->right = rect.right;
294         else
295             r->right = part->x;
296
297         if (infoPtr->hwndToolTip) {
298             TTTOOLINFOA ti;
299
300             ti.cbSize = sizeof(TTTOOLINFOA);
301             ti.hwnd = hwnd;
302             ti.uId = i;
303             ti.rect = *r;
304             SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
305                             0, (LPARAM)&ti);
306         }
307     }
308 }
309
310
311 static VOID
312 STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
313                       WPARAM wParam, LPARAM lParam)
314 {
315     MSG msg;
316
317     msg.hwnd = hwndMsg;
318     msg.message = uMsg;
319     msg.wParam = wParam;
320     msg.lParam = lParam;
321     msg.time = GetMessageTime ();
322     msg.pt.x = LOWORD(GetMessagePos ());
323     msg.pt.y = HIWORD(GetMessagePos ());
324
325     SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
326 }
327
328
329 inline static LRESULT
330 STATUSBAR_GetBorders (LPARAM lParam)
331 {
332     LPINT out = (LPINT) lParam;
333
334     TRACE("\n");
335     out[0] = HORZ_BORDER; /* horizontal border width */
336     out[1] = VERT_BORDER; /* vertical border width */
337     out[2] = HORZ_GAP; /* width of border between rectangles */
338
339     return TRUE;
340 }
341
342
343 static LRESULT
344 STATUSBAR_GetIcon (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
345 {
346     INT nPart;
347
348     nPart = (INT)wParam & 0x00ff;
349     TRACE("%d\n", nPart);
350     if ((nPart < -1) || (nPart >= infoPtr->numParts))
351         return 0;
352
353     if (nPart == -1)
354         return (infoPtr->part0.hIcon);
355     else
356         return (infoPtr->parts[nPart].hIcon);
357 }
358
359
360 static LRESULT
361 STATUSBAR_GetParts (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
362 {
363     LPINT parts;
364     INT   num_parts;
365     INT   i;
366
367     num_parts = (INT) wParam;
368     TRACE("(%d)\n", num_parts);
369     parts = (LPINT) lParam;
370     if (parts) {
371         for (i = 0; i < num_parts; i++) {
372             parts[i] = infoPtr->parts[i].x;
373         }
374     }
375     return (infoPtr->numParts);
376 }
377
378
379 static LRESULT
380 STATUSBAR_GetRect (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
381 {
382     int nPart;
383     LPRECT  rect;
384
385     nPart = ((INT) wParam) & 0x00ff;
386     TRACE("part %d\n", nPart);
387     rect = (LPRECT) lParam;
388     if (infoPtr->simple)
389         *rect = infoPtr->part0.bound;
390     else
391         *rect = infoPtr->parts[nPart].bound;
392     return TRUE;
393 }
394
395
396 static LRESULT
397 STATUSBAR_GetTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
398 {
399     STATUSWINDOWPART *part;
400     INT   nPart;
401     LRESULT result;
402
403     nPart = ((INT) wParam) & 0x00ff;
404     TRACE("part %d\n", nPart);
405     if (infoPtr->simple)
406         part = &infoPtr->part0;
407     else
408         part = &infoPtr->parts[nPart];
409
410     if (part->style & SBT_OWNERDRAW)
411         result = (LRESULT)part->text;
412     else {
413         DWORD len = part->text ? WideCharToMultiByte( CP_ACP, 0, part->text, -1,
414                                                       NULL, 0, NULL, NULL ) - 1 : 0;
415         result = MAKELONG( len, part->style );
416         if (lParam && len)
417             WideCharToMultiByte( CP_ACP, 0, part->text, -1, (LPSTR)lParam, len+1, NULL, NULL );
418     }
419     return result;
420 }
421
422
423 static LRESULT
424 STATUSBAR_GetTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
425 {
426     STATUSWINDOWPART *part;
427     INT   nPart;
428     LRESULT result;
429
430     nPart = ((INT)wParam) & 0x00ff;
431     TRACE("part %d\n", nPart);
432     if (infoPtr->simple)
433         part = &infoPtr->part0;
434     else
435         part = &infoPtr->parts[nPart];
436
437     if (part->style & SBT_OWNERDRAW)
438         result = (LRESULT)part->text;
439     else {
440         result = part->text ? strlenW (part->text) : 0;
441         result |= (part->style << 16);
442         if (part->text && lParam)
443             strcpyW ((LPWSTR)lParam, part->text);
444     }
445     return result;
446 }
447
448
449 static LRESULT
450 STATUSBAR_GetTextLength (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
451 {
452     STATUSWINDOWPART *part;
453     INT nPart;
454     DWORD result;
455
456     nPart = ((INT) wParam) & 0x00ff;
457
458     TRACE("part %d\n", nPart);
459     if (infoPtr->simple)
460         part = &infoPtr->part0;
461     else
462         part = &infoPtr->parts[nPart];
463
464     if (part->text)
465         result = strlenW(part->text);
466     else
467         result = 0;
468
469     result |= (part->style << 16);
470     return result;
471 }
472
473
474 static LRESULT
475 STATUSBAR_GetTipTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
476 {
477     LPSTR tip = (LPSTR)lParam;
478
479     if (tip) {
480         CHAR buf[INFOTIPSIZE];
481         buf[0]='\0';
482
483         if (infoPtr->hwndToolTip) {
484             TTTOOLINFOA ti;
485             ti.cbSize = sizeof(TTTOOLINFOA);
486             ti.hwnd = hwnd;
487             ti.uId = LOWORD(wParam);
488             ti.lpszText = buf;
489             SendMessageA(infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
490         }
491         lstrcpynA(tip, buf, HIWORD(wParam));
492     }
493     return 0;
494 }
495
496
497 static LRESULT
498 STATUSBAR_GetTipTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
499 {
500     LPWSTR tip = (LPWSTR)lParam;
501
502     TRACE("\n");
503     if (tip) {
504         WCHAR buf[INFOTIPSIZE];
505         buf[0]=0;
506
507         if (infoPtr->hwndToolTip) {
508             TTTOOLINFOW ti;
509             ti.cbSize = sizeof(TTTOOLINFOW);
510             ti.hwnd = hwnd;
511             ti.uId = LOWORD(wParam);
512             ti.lpszText = buf;
513             SendMessageW(infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
514         }
515         lstrcpynW(tip, buf, HIWORD(wParam));
516     }
517
518     return 0;
519 }
520
521
522 inline static LRESULT
523 STATUSBAR_GetUnicodeFormat (STATUSWINDOWINFO *infoPtr, HWND hwnd)
524 {
525     return infoPtr->bUnicode;
526 }
527
528
529 inline static LRESULT
530 STATUSBAR_IsSimple (STATUSWINDOWINFO *infoPtr, HWND hwnd)
531 {
532     return infoPtr->simple;
533 }
534
535
536 static LRESULT
537 STATUSBAR_SetBkColor (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
538 {
539     COLORREF oldBkColor;
540
541     oldBkColor = infoPtr->clrBk;
542     infoPtr->clrBk = (COLORREF)lParam;
543     InvalidateRect(hwnd, NULL, FALSE);
544
545     TRACE("CREF: %08lx -> %08lx\n", oldBkColor, infoPtr->clrBk);
546     return oldBkColor;
547 }
548
549
550 static LRESULT
551 STATUSBAR_SetIcon (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
552 {
553     INT nPart = (INT)wParam & 0x00ff;
554
555     if ((nPart < -1) || (nPart >= infoPtr->numParts))
556         return FALSE;
557
558     TRACE("setting part %d, icon %lx\n",nPart,lParam);
559
560     if (nPart == -1) {
561         if (infoPtr->part0.hIcon == (HICON)lParam) /* same as - no redraw */
562             return TRUE;
563         infoPtr->part0.hIcon = (HICON)lParam;
564         if (infoPtr->simple)
565             InvalidateRect(hwnd, &infoPtr->part0.bound, FALSE);
566     } else {
567         if (infoPtr->parts[nPart].hIcon == (HICON)lParam) /* same as - no redraw */
568             return TRUE;
569
570         infoPtr->parts[nPart].hIcon = (HICON)lParam;
571         if (!(infoPtr->simple))
572             InvalidateRect(hwnd, &infoPtr->parts[nPart].bound, FALSE);
573     }
574     return TRUE;
575 }
576
577
578 static LRESULT
579 STATUSBAR_SetMinHeight (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
580 {
581
582     TRACE("\n");
583     if (IsWindowVisible (hwnd)) {
584         HWND parent = GetParent (hwnd);
585         INT  width, x, y;
586         RECT parent_rect;
587
588         GetClientRect (parent, &parent_rect);
589         infoPtr->height = (INT)wParam + VERT_BORDER;
590         width = parent_rect.right - parent_rect.left;
591         x = parent_rect.left;
592         y = parent_rect.bottom - infoPtr->height;
593         MoveWindow (hwnd, parent_rect.left,
594                       parent_rect.bottom - infoPtr->height,
595                       width, infoPtr->height, TRUE);
596         STATUSBAR_SetPartBounds (infoPtr, hwnd);
597     }
598
599     return TRUE;
600 }
601
602
603 static LRESULT
604 STATUSBAR_SetParts (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
605 {
606     STATUSWINDOWPART *tmp;
607     LPINT parts;
608     int i;
609     int oldNumParts;
610
611     TRACE("(%d,%p)\n",wParam,(LPVOID)lParam);
612
613     /* FIXME: should return FALSE sometimes (maybe when wParam == 0 ?) */
614     if (infoPtr->simple)
615         infoPtr->simple = FALSE;
616
617     oldNumParts = infoPtr->numParts;
618     infoPtr->numParts = (INT) wParam;
619     parts = (LPINT) lParam;
620     if (oldNumParts > infoPtr->numParts) {
621         for (i = infoPtr->numParts ; i < oldNumParts; i++) {
622             if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
623                 COMCTL32_Free (infoPtr->parts[i].text);
624         }
625     }
626     if (oldNumParts < infoPtr->numParts) {
627         tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * infoPtr->numParts);
628         for (i = 0; i < oldNumParts; i++) {
629             tmp[i] = infoPtr->parts[i];
630         }
631         if (infoPtr->parts)
632             COMCTL32_Free (infoPtr->parts);
633         infoPtr->parts = tmp;
634     }
635     if (oldNumParts == infoPtr->numParts) {
636         for (i=0;i<oldNumParts;i++)
637             if (infoPtr->parts[i].x != parts[i])
638                 break;
639         if (i==oldNumParts) /* Unchanged? no need to redraw! */
640             return TRUE;
641     }
642     
643     for (i = 0; i < infoPtr->numParts; i++)
644         infoPtr->parts[i].x = parts[i];
645
646     if (infoPtr->hwndToolTip) {
647         INT nTipCount =
648             SendMessageA (infoPtr->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
649
650         if (nTipCount < infoPtr->numParts) {
651             /* add tools */
652             TTTOOLINFOA ti;
653             INT i;
654
655             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
656             ti.cbSize = sizeof(TTTOOLINFOA);
657             ti.hwnd = hwnd;
658             for (i = nTipCount; i < infoPtr->numParts; i++) {
659                 TRACE("add tool %d\n", i);
660                 ti.uId = i;
661                 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
662                                 0, (LPARAM)&ti);
663             }
664         }
665         else if (nTipCount > infoPtr->numParts) {
666             /* delete tools */
667             INT i;
668
669             for (i = nTipCount - 1; i >= infoPtr->numParts; i--) {
670                 FIXME("delete tool %d\n", i);
671             }
672         }
673     }
674     STATUSBAR_SetPartBounds (infoPtr, hwnd);
675     InvalidateRect(hwnd, NULL, FALSE);
676     return TRUE;
677 }
678
679
680 static LRESULT
681 STATUSBAR_SetTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
682 {
683     STATUSWINDOWPART *part=NULL;
684     int nPart;
685     int style;
686     LPSTR text;
687     BOOL        changed = FALSE;
688
689     text = (LPSTR) lParam;
690     nPart = ((INT) wParam) & 0x00ff;
691     style = ((INT) wParam) & 0xff00;
692
693     TRACE("part %d, text %s\n",nPart,debugstr_a(text));
694
695     if (nPart==255)
696         part = &infoPtr->part0;
697     else if (!infoPtr->simple && infoPtr->parts!=NULL)
698         part = &infoPtr->parts[nPart];
699     if (!part) return FALSE;
700
701     if (part->style != style)
702         changed = TRUE;
703
704     part->style = style;
705     if (style & SBT_OWNERDRAW) {
706         if (part->text == (LPWSTR)text)
707             return TRUE;
708         part->text = (LPWSTR)text;
709     } else {
710         LPWSTR ntext;
711
712         /* check if text is unchanged -> no need to redraw */
713         if (text) {
714             DWORD len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
715             LPWSTR tmptext = COMCTL32_Alloc(len*sizeof(WCHAR));
716             MultiByteToWideChar( CP_ACP, 0, text, -1, tmptext, len );
717
718             if (!changed && part->text && !lstrcmpW(tmptext,part->text)) {
719                 COMCTL32_Free(tmptext);
720                 return TRUE;
721             }
722             ntext = tmptext;
723         } else {
724             if (!changed && !part->text) 
725                 return TRUE;
726             ntext = 0;
727         }
728
729         if (part->text)
730             COMCTL32_Free (part->text);
731         part->text = ntext;
732     }
733     InvalidateRect(hwnd, &part->bound, FALSE);
734
735     return TRUE;
736 }
737
738
739 static LRESULT
740 STATUSBAR_SetTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
741 {
742     STATUSWINDOWPART *part;
743     INT  nPart, style, len;
744     LPWSTR text;
745     BOOL bRedraw = FALSE;
746
747     text = (LPWSTR) lParam;
748     nPart = ((INT) wParam) & 0x00ff;
749     style = ((INT) wParam) & 0xff00;
750
751     TRACE("part %d -> %s with style %04x\n", nPart, debugstr_w(text), style);
752     if ((infoPtr->simple) || (infoPtr->parts==NULL) || (nPart==255))
753         part = &infoPtr->part0;
754     else
755         part = &infoPtr->parts[nPart];
756     if (!part) return FALSE;
757
758     if(part->style != style)
759         bRedraw = TRUE;
760
761     part->style = style;
762
763     /* FIXME: not sure how/if we can check for change in string with ownerdraw(remove this if we can't)... */
764     if (style & SBT_OWNERDRAW)
765     {
766         part->text = text;
767         bRedraw = TRUE;
768     } else if(!text)
769     {
770         if(part->text)
771         {
772             COMCTL32_Free(part->text);
773             bRedraw = TRUE;
774         }
775         part->text = 0;
776     } else if(!part->text || strcmpW(part->text, text)) /* see if the new string differs from the existing string */
777     {
778         if(part->text) COMCTL32_Free(part->text);
779
780         len = strlenW(text);
781         part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
782         strcpyW(part->text, text);
783         bRedraw = TRUE;
784     }
785
786     if(bRedraw)
787         InvalidateRect(hwnd, &part->bound, FALSE);
788
789     return TRUE;
790 }
791
792
793 static LRESULT
794 STATUSBAR_SetTipTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
795 {
796     TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
797     if (infoPtr->hwndToolTip) {
798         TTTOOLINFOA ti;
799         ti.cbSize = sizeof(TTTOOLINFOA);
800         ti.hwnd = hwnd;
801         ti.uId = (INT)wParam;
802         ti.hinst = 0;
803         ti.lpszText = (LPSTR)lParam;
804         SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
805                         0, (LPARAM)&ti);
806     }
807
808     return 0;
809 }
810
811
812 static LRESULT
813 STATUSBAR_SetTipTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
814 {
815     TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
816     if (infoPtr->hwndToolTip) {
817         TTTOOLINFOW ti;
818         ti.cbSize = sizeof(TTTOOLINFOW);
819         ti.hwnd = hwnd;
820         ti.uId = (INT)wParam;
821         ti.hinst = 0;
822         ti.lpszText = (LPWSTR)lParam;
823         SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
824                         0, (LPARAM)&ti);
825     }
826
827     return 0;
828 }
829
830
831 inline static LRESULT
832 STATUSBAR_SetUnicodeFormat (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
833 {
834     BOOL bOld = infoPtr->bUnicode;
835
836     TRACE("(0x%x)\n", (BOOL)wParam);
837     infoPtr->bUnicode = (BOOL)wParam;
838
839     return bOld;
840 }
841
842
843 static LRESULT
844 STATUSBAR_Simple (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
845 {
846     NMHDR  nmhdr;
847
848     TRACE("(is simple: %d)\n", wParam);
849     if (infoPtr->simple == wParam) /* no need to change */
850         return TRUE;
851
852     infoPtr->simple = (BOOL)wParam;
853
854     /* send notification */
855     nmhdr.hwndFrom = hwnd;
856     nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
857     nmhdr.code = SBN_SIMPLEMODECHANGE;
858     SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
859     InvalidateRect(hwnd, NULL, FALSE);
860     return TRUE;
861 }
862
863
864 static LRESULT
865 STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
866 {
867     LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
868     NONCLIENTMETRICSA nclm;
869     DWORD dwStyle;
870     RECT        rect;
871     int         width, len;
872     HDC hdc;
873     STATUSWINDOWINFO *infoPtr;
874
875     TRACE("\n");
876     infoPtr = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
877     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
878
879     infoPtr->hwndParent = lpCreate->hwndParent;
880     infoPtr->numParts = 1;
881     infoPtr->parts = 0;
882     infoPtr->simple = FALSE;
883     infoPtr->clrBk = CLR_DEFAULT;
884     infoPtr->hFont = 0;
885
886     /* TODO: send unicode parent notification query (WM_QUERYFORMAT) here */
887
888     GetClientRect (hwnd, &rect);
889     InvalidateRect (hwnd, &rect, 0);
890     UpdateWindow(hwnd);
891
892     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
893     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0);
894     infoPtr->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
895
896     /* initialize simple case */
897     infoPtr->part0.bound = rect;
898     infoPtr->part0.text = 0;
899     infoPtr->part0.x = 0;
900     infoPtr->part0.style = 0;
901     infoPtr->part0.hIcon = 0;
902
903     /* initialize first part */
904     infoPtr->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
905     infoPtr->parts[0].bound = rect;
906     infoPtr->parts[0].text = 0;
907     infoPtr->parts[0].x = -1;
908     infoPtr->parts[0].style = 0;
909     infoPtr->parts[0].hIcon = 0;
910
911     if (IsWindowUnicode (hwnd)) {
912         infoPtr->bUnicode = TRUE;
913         if (lpCreate->lpszName &&
914             (len = strlenW ((LPCWSTR)lpCreate->lpszName))) {
915             infoPtr->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
916             strcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName);
917         }
918     }
919     else {
920         if (lpCreate->lpszName &&
921             (len = strlen((LPCSTR)lpCreate->lpszName))) {
922             DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1, NULL, 0 );
923             infoPtr->parts[0].text = COMCTL32_Alloc (lenW*sizeof(WCHAR));
924             MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1,
925                                  infoPtr->parts[0].text, lenW );
926         }
927     }
928
929     dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
930
931     /* statusbars on managed windows should not have SIZEGRIP style */
932     if ((dwStyle & SBARS_SIZEGRIP) && lpCreate->hwndParent)
933         if (GetWindowLongA(lpCreate->hwndParent, GWL_EXSTYLE) & WS_EX_MANAGED)
934             SetWindowLongA (hwnd, GWL_STYLE, dwStyle & ~SBARS_SIZEGRIP);
935
936     if ((hdc = GetDC (0))) {
937         TEXTMETRICA tm;
938         HFONT hOldFont;
939
940         hOldFont = SelectObject (hdc,infoPtr->hDefaultFont);
941         GetTextMetricsA(hdc, &tm);
942         infoPtr->textHeight = tm.tmHeight;
943         SelectObject (hdc, hOldFont);
944         ReleaseDC(0, hdc);
945     }
946
947     if (dwStyle & SBT_TOOLTIPS) {
948         infoPtr->hwndToolTip =
949             CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
950                                CW_USEDEFAULT, CW_USEDEFAULT,
951                                CW_USEDEFAULT, CW_USEDEFAULT,
952                              hwnd, 0,
953                              GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
954
955         if (infoPtr->hwndToolTip) {
956             NMTOOLTIPSCREATED nmttc;
957
958             nmttc.hdr.hwndFrom = hwnd;
959             nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
960             nmttc.hdr.code = NM_TOOLTIPSCREATED;
961             nmttc.hwndToolTips = infoPtr->hwndToolTip;
962
963             SendMessageA (lpCreate->hwndParent, WM_NOTIFY,
964                             (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
965         }
966     }
967
968     if (!(dwStyle & CCS_NORESIZE)) /* don't resize wnd if it doesn't want it ! */
969     {
970         GetClientRect (GetParent (hwnd), &rect);
971         width = rect.right - rect.left;
972         infoPtr->height = infoPtr->textHeight + 4 + VERT_BORDER;
973         SetWindowPos(hwnd, 0, lpCreate->x, lpCreate->y - 1,
974                         width, infoPtr->height, SWP_NOZORDER);
975         STATUSBAR_SetPartBounds (infoPtr, hwnd);
976     }
977
978     return 0;
979 }
980
981
982 static LRESULT
983 STATUSBAR_WMDestroy (STATUSWINDOWINFO *infoPtr, HWND hwnd)
984 {
985     int i;
986
987     TRACE("\n");
988     for (i = 0; i < infoPtr->numParts; i++) {
989         if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
990             COMCTL32_Free (infoPtr->parts[i].text);
991     }
992     if (infoPtr->part0.text && !(infoPtr->part0.style & SBT_OWNERDRAW))
993         COMCTL32_Free (infoPtr->part0.text);
994     COMCTL32_Free (infoPtr->parts);
995
996     /* delete default font */
997     if (infoPtr->hDefaultFont)
998         DeleteObject (infoPtr->hDefaultFont);
999
1000     /* delete tool tip control */
1001     if (infoPtr->hwndToolTip)
1002         DestroyWindow (infoPtr->hwndToolTip);
1003
1004     COMCTL32_Free (infoPtr);
1005     SetWindowLongA(hwnd, 0, 0);
1006     return 0;
1007 }
1008
1009
1010 static inline LRESULT
1011 STATUSBAR_WMGetFont (STATUSWINDOWINFO *infoPtr, HWND hwnd)
1012 {
1013     TRACE("\n");
1014     return infoPtr->hFont? infoPtr->hFont : infoPtr->hDefaultFont;
1015 }
1016
1017
1018 /* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text
1019  * of the first part only (usual behaviour) */
1020 static LRESULT
1021 STATUSBAR_WMGetText (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1022 {
1023     INT len;
1024
1025     TRACE("\n");
1026     if (!(infoPtr->parts[0].text))
1027         return 0;
1028     if (infoPtr->bUnicode)
1029         len = strlenW (infoPtr->parts[0].text);
1030     else
1031         len = WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1, NULL, 0, NULL, NULL )-1;
1032
1033     if (wParam > len) {
1034         if (infoPtr->bUnicode)
1035             strcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
1036         else
1037             WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1,
1038                                  (LPSTR)lParam, len+1, NULL, NULL );
1039         return len;
1040     }
1041
1042     return -1;
1043 }
1044
1045
1046 inline static LRESULT
1047 STATUSBAR_WMMouseMove (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1048 {
1049     if (infoPtr->hwndToolTip)
1050         STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
1051                               WM_MOUSEMOVE, wParam, lParam);
1052     return 0;
1053 }
1054
1055
1056 static LRESULT
1057 STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1058 {
1059     if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
1060         RECT  rect;
1061         POINT pt;
1062
1063         GetClientRect (hwnd, &rect);
1064
1065         pt.x = (INT)LOWORD(lParam);
1066         pt.y = (INT)HIWORD(lParam);
1067         ScreenToClient (hwnd, &pt);
1068
1069         rect.left = rect.right - 13;
1070         rect.top += 2;
1071
1072         if (PtInRect (&rect, pt))
1073             return HTBOTTOMRIGHT;
1074     }
1075
1076     /* FIXME: instead check result in StatusWindowProc and call if needed ? */
1077     return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1078 }
1079
1080
1081 static inline LRESULT
1082 STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1083 {
1084     TRACE("\n");
1085     PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
1086     return 0;
1087 }
1088
1089
1090 static inline LRESULT
1091 STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1092 {
1093     TRACE("\n");
1094     PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
1095     return 0;
1096 }
1097
1098
1099 static LRESULT
1100 STATUSBAR_WMPaint (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
1101 {
1102     HDC hdc;
1103     PAINTSTRUCT ps;
1104
1105     TRACE("\n");
1106     hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1107     STATUSBAR_Refresh (infoPtr, hwnd, hdc);
1108     if (!wParam)
1109         EndPaint (hwnd, &ps);
1110
1111     return 0;
1112 }
1113
1114
1115 static LRESULT
1116 STATUSBAR_WMSetFont (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1117 {
1118     infoPtr->hFont = (HFONT)wParam;
1119     TRACE("%04x\n", infoPtr->hFont);
1120     if (LOWORD(lParam) == TRUE)
1121         InvalidateRect(hwnd, NULL, FALSE);
1122
1123     return 0;
1124 }
1125
1126
1127 static LRESULT
1128 STATUSBAR_WMSetText (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1129 {
1130     STATUSWINDOWPART *part;
1131     int len;
1132
1133     TRACE("\n");
1134     if (infoPtr->numParts == 0)
1135         return FALSE;
1136
1137     part = &infoPtr->parts[0];
1138     /* duplicate string */
1139     if (part->text)
1140         COMCTL32_Free (part->text);
1141     part->text = 0;
1142     if (infoPtr->bUnicode) {
1143         if (lParam && (len = strlenW((LPCWSTR)lParam))) {
1144             part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1145             strcpyW (part->text, (LPCWSTR)lParam);
1146         }
1147     }
1148     else {
1149         if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
1150             DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lParam, -1, NULL, 0 );
1151             part->text = COMCTL32_Alloc (lenW*sizeof(WCHAR));
1152             MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lParam, -1, part->text, lenW );
1153         }
1154     }
1155
1156     InvalidateRect(hwnd, &part->bound, FALSE);
1157
1158     return TRUE;
1159 }
1160
1161
1162 static LRESULT
1163 STATUSBAR_WMSize (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
1164 {
1165     INT  width, x, y, flags;
1166     RECT parent_rect;
1167     DWORD dwStyle;
1168
1169     /* Need to resize width to match parent */
1170     flags = (INT) wParam;
1171
1172     TRACE("flags %04x\n", flags);
1173     /* FIXME for flags =
1174      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
1175      */
1176
1177     dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
1178     if (!(dwStyle & CCS_NORESIZE)) /* don't resize wnd if it doesn't want it ! */
1179     {
1180         if (flags == SIZE_RESTORED) {
1181             /* width and height don't apply */
1182             GetClientRect (infoPtr->hwndParent, &parent_rect);
1183             width = parent_rect.right - parent_rect.left;
1184             x = parent_rect.left;
1185             y = parent_rect.bottom - infoPtr->height;
1186             MoveWindow (hwnd, parent_rect.left, 
1187                       parent_rect.bottom - infoPtr->height,
1188                       width, infoPtr->height, TRUE);
1189             STATUSBAR_SetPartBounds (infoPtr, hwnd);
1190         }
1191         return 0; /* FIXME: ok to return here ? */
1192     }
1193
1194     /* FIXME: instead check result in StatusWindowProc and call if needed ? */
1195     return DefWindowProcA (hwnd, WM_SIZE, wParam, lParam);
1196 }
1197
1198
1199 static LRESULT
1200 STATUSBAR_SendNotify (HWND hwnd, UINT code)
1201 {
1202     NMHDR  nmhdr;
1203
1204     TRACE("code %04x\n", code);
1205     nmhdr.hwndFrom = hwnd;
1206     nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1207     nmhdr.code = code;
1208     SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
1209     return 0;
1210 }
1211
1212
1213
1214 static LRESULT WINAPI
1215 StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1216 {
1217     STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr(hwnd);
1218
1219     TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, msg, wParam, lParam);
1220     if (!(infoPtr) && (msg != WM_CREATE))
1221         return DefWindowProcA (hwnd, msg, wParam, lParam);
1222
1223     switch (msg) {
1224         case SB_GETBORDERS:
1225             return STATUSBAR_GetBorders (lParam);
1226
1227         case SB_GETICON:
1228             return STATUSBAR_GetIcon (infoPtr, hwnd, wParam);
1229
1230         case SB_GETPARTS:
1231             return STATUSBAR_GetParts (infoPtr, hwnd, wParam, lParam);
1232
1233         case SB_GETRECT:
1234             return STATUSBAR_GetRect (infoPtr, hwnd, wParam, lParam);
1235
1236         case SB_GETTEXTA:
1237             return STATUSBAR_GetTextA (infoPtr, hwnd, wParam, lParam);
1238
1239         case SB_GETTEXTW:
1240             return STATUSBAR_GetTextW (infoPtr, hwnd, wParam, lParam);
1241
1242         case SB_GETTEXTLENGTHA:
1243         case SB_GETTEXTLENGTHW:
1244             return STATUSBAR_GetTextLength (infoPtr, hwnd, wParam);
1245
1246         case SB_GETTIPTEXTA:
1247             return STATUSBAR_GetTipTextA (infoPtr, hwnd, wParam, lParam);
1248
1249         case SB_GETTIPTEXTW:
1250             return STATUSBAR_GetTipTextW (infoPtr, hwnd, wParam, lParam);
1251
1252         case SB_GETUNICODEFORMAT:
1253             return STATUSBAR_GetUnicodeFormat (infoPtr, hwnd);
1254
1255         case SB_ISSIMPLE:
1256             return STATUSBAR_IsSimple (infoPtr, hwnd);
1257
1258         case SB_SETBKCOLOR:
1259             return STATUSBAR_SetBkColor (infoPtr, hwnd, wParam, lParam);
1260
1261         case SB_SETICON:
1262             return STATUSBAR_SetIcon (infoPtr, hwnd, wParam, lParam);
1263
1264         case SB_SETMINHEIGHT:
1265             return STATUSBAR_SetMinHeight (infoPtr, hwnd, wParam, lParam);
1266
1267         case SB_SETPARTS:       
1268             return STATUSBAR_SetParts (infoPtr, hwnd, wParam, lParam);
1269
1270         case SB_SETTEXTA:
1271             return STATUSBAR_SetTextA (infoPtr, hwnd, wParam, lParam);
1272
1273         case SB_SETTEXTW:
1274             return STATUSBAR_SetTextW (infoPtr, hwnd, wParam, lParam);
1275
1276         case SB_SETTIPTEXTA:
1277             return STATUSBAR_SetTipTextA (infoPtr, hwnd, wParam, lParam);
1278
1279         case SB_SETTIPTEXTW:
1280             return STATUSBAR_SetTipTextW (infoPtr, hwnd, wParam, lParam);
1281
1282         case SB_SETUNICODEFORMAT:
1283             return STATUSBAR_SetUnicodeFormat (infoPtr, hwnd, wParam);
1284
1285         case SB_SIMPLE:
1286             return STATUSBAR_Simple (infoPtr, hwnd, wParam, lParam);
1287
1288
1289         case WM_CREATE:
1290             return STATUSBAR_WMCreate (hwnd, wParam, lParam);
1291
1292         case WM_DESTROY:
1293             return STATUSBAR_WMDestroy (infoPtr, hwnd);
1294
1295         case WM_GETFONT:
1296             return STATUSBAR_WMGetFont (infoPtr, hwnd);
1297
1298         case WM_GETTEXT:
1299             return STATUSBAR_WMGetText (infoPtr, hwnd, wParam, lParam);
1300
1301         case WM_GETTEXTLENGTH:
1302             return STATUSBAR_GetTextLength (infoPtr, hwnd, 0);
1303
1304         case WM_LBUTTONDBLCLK:
1305             return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
1306
1307         case WM_LBUTTONUP:
1308             return STATUSBAR_SendNotify (hwnd, NM_CLICK);
1309
1310         case WM_MOUSEMOVE:
1311             return STATUSBAR_WMMouseMove (infoPtr, hwnd, wParam, lParam);
1312
1313         case WM_NCHITTEST:
1314             return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
1315
1316         case WM_NCLBUTTONDOWN:
1317             return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
1318
1319         case WM_NCLBUTTONUP:
1320             return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
1321
1322         case WM_PAINT:
1323             return STATUSBAR_WMPaint (infoPtr, hwnd, wParam);
1324
1325         case WM_RBUTTONDBLCLK:
1326             return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
1327
1328         case WM_RBUTTONUP:
1329             return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
1330
1331         case WM_SETFONT:
1332             return STATUSBAR_WMSetFont (infoPtr, hwnd, wParam, lParam);
1333
1334         case WM_SETTEXT:
1335             return STATUSBAR_WMSetText (infoPtr, hwnd, wParam, lParam);
1336
1337         case WM_SIZE:
1338             return STATUSBAR_WMSize (infoPtr, hwnd, wParam, lParam);
1339
1340         default:
1341             if (msg >= WM_USER)
1342                 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1343                      msg, wParam, lParam);
1344             return DefWindowProcA (hwnd, msg, wParam, lParam);
1345     }
1346     return 0;
1347 }
1348
1349
1350 /***********************************************************************
1351  * STATUS_Register [Internal]
1352  *
1353  * Registers the status window class.
1354  */
1355
1356 VOID
1357 STATUS_Register (void)
1358 {
1359     WNDCLASSA wndClass;
1360
1361     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1362     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1363     wndClass.lpfnWndProc   = (WNDPROC)StatusWindowProc;
1364     wndClass.cbClsExtra    = 0;
1365     wndClass.cbWndExtra    = sizeof(STATUSWINDOWINFO *);
1366     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
1367     wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1368     wndClass.lpszClassName = STATUSCLASSNAMEA;
1369  
1370     RegisterClassA (&wndClass);
1371 }
1372
1373
1374 /***********************************************************************
1375  * STATUS_Unregister [Internal]
1376  *
1377  * Unregisters the status window class.
1378  */
1379
1380 VOID
1381 STATUS_Unregister (void)
1382 {
1383     UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);
1384 }
1385