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