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