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