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