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