Fixes for FreeBSD.
[wine] / dlls / comctl32 / status.c
1 /*
2  * Interface code to StatusWindow widget/control
3  *
4  * Copyright 1996 Bruce Milner
5  * Copyright 1998 Eric Kohl
6  */
7
8 #include "windows.h"
9 #include "commctrl.h"
10 #include "status.h"
11 #include "win.h"
12 #include "debug.h"
13
14 /*
15  * Run tests using Waite Group Windows95 API Bible Vol. 1&2
16  * The second cdrom contains executables drawstat.exe,gettext.exe,
17  * simple.exe, getparts.exe, setparts.exe, statwnd.exe
18  */
19
20 /*
21  * Fixme/Todo
22  * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
23  + 2) Tooltip support (almost done).
24  */
25
26 #define _MAX(a,b) (((a)>(b))?(a):(b))
27 #define _MIN(a,b) (((a)>(b))?(b):(a))
28
29 #define HORZ_BORDER 0
30 #define VERT_BORDER 2
31 #define HORZ_GAP    2
32
33 #define STATUSBAR_GetInfoPtr(wndPtr) ((STATUSWINDOWINFO *)wndPtr->wExtra[0])
34
35
36 static void
37 STATUSBAR_DrawSizeGrip (HDC32 hdc, LPRECT32 lpRect)
38 {
39     HPEN32 hOldPen;
40     POINT32 pt;
41     INT32 i;
42
43     pt.x = lpRect->right - 1;
44     pt.y = lpRect->bottom - 1;
45
46     hOldPen = SelectObject32 (hdc, GetSysColorPen32 (COLOR_3DFACE));
47     MoveToEx32 (hdc, pt.x - 12, pt.y, NULL);
48     LineTo32 (hdc, pt.x, pt.y);
49     LineTo32 (hdc, pt.x, pt.y - 12);
50
51     pt.x--;
52     pt.y--;
53
54     SelectObject32 (hdc, GetSysColorPen32 (COLOR_3DSHADOW));
55     for (i = 1; i < 11; i += 4) {
56         MoveToEx32 (hdc, pt.x - i, pt.y, NULL);
57         LineTo32 (hdc, pt.x, pt.y - i);
58
59         MoveToEx32 (hdc, pt.x - i-1, pt.y, NULL);
60         LineTo32 (hdc, pt.x, pt.y - i-1);
61     }
62
63     SelectObject32 (hdc, GetSysColorPen32 (COLOR_3DHIGHLIGHT));
64     for (i = 3; i < 13; i += 4) {
65         MoveToEx32 (hdc, pt.x - i, pt.y, NULL);
66         LineTo32 (hdc, pt.x, pt.y - i);
67     }
68
69     SelectObject32 (hdc, hOldPen);
70 }
71
72
73 static void 
74 STATUSBAR_DrawPart (HDC32 hdc, STATUSWINDOWPART *part)
75 {
76     RECT32 r = part->bound;
77     UINT32 border = BDR_SUNKENOUTER;
78
79     if (part->style==SBT_POPOUT)
80       border = BDR_RAISEDOUTER;
81     else if (part->style==SBT_NOBORDERS)
82       border = 0;
83
84     DrawEdge32(hdc, &r, border, BF_RECT|BF_ADJUST);
85
86     /* draw the icon */
87     if (part->hIcon) {
88         INT32 cy = r.bottom - r.top;
89
90         r.left += 2;
91         DrawIconEx32 (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
92         r.left += cy;
93     }
94
95     /* now draw text */
96     if (part->text) {
97       int oldbkmode = SetBkMode32(hdc, TRANSPARENT);
98       LPSTR p = (LPSTR)part->text;
99       UINT32 align = DT_LEFT;
100       if (*p == '\t') {
101         p++;
102         align = DT_CENTER;
103
104         if (*p == '\t') {
105           p++;
106           align = DT_RIGHT;
107         }
108       }
109       r.left += 3;
110       DrawText32A(hdc, p, lstrlen32A(p), &r, align|DT_VCENTER|DT_SINGLELINE);
111       if (oldbkmode != TRANSPARENT)
112         SetBkMode32(hdc, oldbkmode);
113     }
114 }
115
116
117 static VOID
118 STATUSBAR_RefreshPart (WND *wndPtr, STATUSWINDOWPART *part, HDC32 hdc)
119 {
120     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
121     HBRUSH32 hbrBk;
122     HFONT32  hOldFont;
123
124     if (!IsWindowVisible32(wndPtr->hwndSelf))
125         return;
126
127     if (self->clrBk != CLR_DEFAULT)
128         hbrBk = CreateSolidBrush32 (self->clrBk);
129     else
130         hbrBk = GetSysColorBrush32 (COLOR_3DFACE);
131     FillRect32(hdc, &part->bound, hbrBk);
132
133     hOldFont = SelectObject32 (hdc, self->hFont ? self->hFont : self->hDefaultFont);
134
135     if (part->style == SBT_OWNERDRAW) {
136         DRAWITEMSTRUCT32 dis;
137
138         dis.CtlID = wndPtr->wIDmenu;
139         dis.itemID = -1;
140         dis.hwndItem = wndPtr->hwndSelf;
141         dis.hDC = hdc;
142         dis.rcItem = part->bound;
143         dis.itemData = (INT32)part->text;
144         SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_DRAWITEM,
145                         (WPARAM32)wndPtr->wIDmenu, (LPARAM)&dis);
146     }
147     else
148         STATUSBAR_DrawPart (hdc, part);
149
150     SelectObject32 (hdc, hOldFont);
151
152     if (self->clrBk != CLR_DEFAULT)
153         DeleteObject32 (hbrBk);
154
155     if (wndPtr->dwStyle & SBARS_SIZEGRIP) {
156         RECT32 rect;
157
158         GetClientRect32 (wndPtr->hwndSelf, &rect);
159         STATUSBAR_DrawSizeGrip (hdc, &rect);
160     }
161 }
162
163
164 static BOOL32
165 STATUSBAR_Refresh (WND *wndPtr, HDC32 hdc)
166 {
167     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
168     int      i;
169     RECT32   rect;
170     HBRUSH32 hbrBk;
171     HFONT32  hOldFont;
172
173     if (!IsWindowVisible32(wndPtr->hwndSelf))
174         return (TRUE);
175
176     GetClientRect32 (wndPtr->hwndSelf, &rect);
177
178     if (self->clrBk != CLR_DEFAULT)
179         hbrBk = CreateSolidBrush32 (self->clrBk);
180     else
181         hbrBk = GetSysColorBrush32 (COLOR_3DFACE);
182     FillRect32(hdc, &rect, hbrBk);
183
184     hOldFont = SelectObject32 (hdc, self->hFont ? self->hFont : self->hDefaultFont);
185
186     if (self->simple) {
187         STATUSBAR_DrawPart (hdc, &self->part0);
188     }
189     else {
190         for (i = 0; i < self->numParts; i++) {
191             if (self->parts[i].style == SBT_OWNERDRAW) {
192                 DRAWITEMSTRUCT32 dis;
193
194                 dis.CtlID = wndPtr->wIDmenu;
195                 dis.itemID = -1;
196                 dis.hwndItem = wndPtr->hwndSelf;
197                 dis.hDC = hdc;
198                 dis.rcItem = self->parts[i].bound;
199                 dis.itemData = (INT32)self->parts[i].text;
200                 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_DRAWITEM,
201                                 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&dis);
202             }
203             else
204                 STATUSBAR_DrawPart (hdc, &self->parts[i]);
205         }
206     }
207
208     SelectObject32 (hdc, hOldFont);
209
210     if (self->clrBk != CLR_DEFAULT)
211         DeleteObject32 (hbrBk);
212
213     if (wndPtr->dwStyle & SBARS_SIZEGRIP)
214         STATUSBAR_DrawSizeGrip (hdc, &rect);
215
216     return TRUE;
217 }
218
219
220 static void
221 STATUSBAR_SetPartBounds (WND *wndPtr)
222 {
223     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
224     STATUSWINDOWPART *part;
225     RECT32 rect, *r;
226     int i;
227
228     /* get our window size */
229     GetClientRect32 (wndPtr->hwndSelf, &rect);
230
231     rect.top += VERT_BORDER;
232
233     /* set bounds for simple rectangle */
234     self->part0.bound = rect;
235
236     /* set bounds for non-simple rectangles */
237     for (i = 0; i < self->numParts; i++) {
238         part = &self->parts[i];
239         r = &self->parts[i].bound;
240         r->top = rect.top;
241         r->bottom = rect.bottom;
242         if (i == 0)
243             r->left = 0;
244         else
245             r->left = self->parts[i-1].bound.right + HORZ_GAP;
246         if (part->x == -1)
247             r->right = rect.right;
248         else
249             r->right = part->x;
250
251         if (self->hwndToolTip) {
252             TTTOOLINFO32A ti;
253
254             ti.cbSize = sizeof(TTTOOLINFO32A);
255             ti.hwnd = wndPtr->hwndSelf;
256             ti.uId = i;
257             ti.rect = *r;
258             SendMessage32A (self->hwndToolTip, TTM_NEWTOOLRECT32A,
259                             0, (LPARAM)&ti);
260         }
261     }
262 }
263
264
265 static VOID
266 STATUSBAR_RelayEvent (HWND32 hwndTip, HWND32 hwndMsg, UINT32 uMsg,
267                       WPARAM32 wParam, LPARAM lParam)
268 {
269     MSG32 msg;
270
271     msg.hwnd = hwndMsg;
272     msg.message = uMsg;
273     msg.wParam = wParam;
274     msg.lParam = lParam;
275     msg.time = GetMessageTime ();
276     msg.pt.x = LOWORD(GetMessagePos ());
277     msg.pt.y = HIWORD(GetMessagePos ());
278
279     SendMessage32A (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
280 }
281
282
283 __inline__ static LRESULT
284 STATUSBAR_GetBorders (LPARAM lParam)
285 {
286     LPINT32 out = (LPINT32) lParam;
287
288     out[0] = HORZ_BORDER; /* horizontal border width */
289     out[1] = VERT_BORDER; /* vertical border width */
290     out[2] = HORZ_GAP; /* width of border between rectangles */
291
292     return TRUE;
293 }
294
295
296 static LRESULT
297 STATUSBAR_GetIcon (WND *wndPtr, WPARAM32 wParam)
298 {
299     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
300     INT32 nPart;
301
302     nPart = (INT32)wParam & 0x00ff;
303     if ((nPart < -1) || (nPart >= self->numParts)) return 0;
304
305     if (nPart == -1)
306         return (self->part0.hIcon);
307     else
308         return (self->parts[nPart].hIcon);
309 }
310
311
312 static LRESULT
313 STATUSBAR_GetParts (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
314 {
315     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
316     LPINT32 parts;
317     INT32   num_parts;
318     int     i;
319
320     num_parts = (INT32) wParam;
321     parts = (LPINT32) lParam;
322     if (parts) {
323         return (self->numParts);
324         for (i = 0; i < num_parts; i++) {
325             parts[i] = self->parts[i].x;
326         }
327     }
328     return (self->numParts);
329 }
330
331
332 static LRESULT
333 STATUSBAR_GetRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
334 {
335     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
336     int part_num;
337     LPRECT32  rect;
338
339     part_num = ((INT32) wParam) & 0x00ff;
340     rect = (LPRECT32) lParam;
341     if (self->simple)
342         *rect = self->part0.bound;
343     else
344         *rect = self->parts[part_num].bound;
345     return TRUE;
346 }
347
348
349 static LRESULT
350 STATUSBAR_GetText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
351 {
352     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
353     STATUSWINDOWPART *part;
354     int part_num;
355     LRESULT result;
356     LPSTR   out_text;
357
358     part_num = ((INT32) wParam) & 0x00ff;
359     out_text = (LPSTR) lParam;
360     if (self->simple)
361         part = &self->part0;
362     else
363         part = &self->parts[part_num];
364
365     if (part->style == SBT_OWNERDRAW)
366         result = (LRESULT) part->text;
367     else {
368         result = part->text ? lstrlen32A(part->text) : 0;
369         result |= (part->style << 16);
370         if (out_text) {
371             lstrcpy32A(out_text, part->text);
372         }
373     }
374     return result;
375 }
376
377
378 //  << STATUSBAR_GetText32W >>
379
380
381 static LRESULT
382 STATUSBAR_GetTextLength32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
383 {
384     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
385     STATUSWINDOWPART *part;
386     int part_num;
387     DWORD       result;
388
389     part_num = ((INT32) wParam) & 0x00ff;
390
391     if (self->simple)
392         part = &self->part0;
393     else
394         part = &self->parts[part_num];
395
396     if (part->text)
397         result = lstrlen32A(part->text);
398     else
399         result = 0;
400
401     result |= (part->style << 16);
402     return result;
403 }
404
405
406 //  << STATUSBAR_GetTextLength32W >>
407
408
409 static LRESULT
410 STATUSBAR_GetTipText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
411 {
412     STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (wndPtr);
413
414     if (infoPtr->hwndToolTip) {
415         TTTOOLINFO32A ti;
416
417         ti.cbSize = sizeof(TTTOOLINFO32A);
418         ti.hwnd = wndPtr->hwndSelf;
419         ti.uId = LOWORD(wParam);
420         SendMessage32A (infoPtr->hwndToolTip, TTM_GETTEXT32A, 0, (LPARAM)&ti);
421
422         if (ti.lpszText)
423             lstrcpyn32A ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
424     }
425
426     return 0;
427 }
428
429
430 //  << STATUSBAR_GetTipText32W >>
431 //  << STATUSBAR_GetUnicodeFormat >>
432
433
434 __inline__ static LRESULT
435 STATUSBAR_IsSimple (WND *wndPtr)
436 {
437     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
438
439     return self->simple;
440 }
441
442
443 static LRESULT
444 STATUSBAR_SetBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
445 {
446     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
447     COLORREF oldBkColor;
448     HDC32    hdc;
449
450     oldBkColor = self->clrBk;
451     self->clrBk = (COLORREF)lParam;
452     hdc = GetDC32 (wndPtr->hwndSelf);
453     STATUSBAR_Refresh (wndPtr, hdc);
454     ReleaseDC32 (wndPtr->hwndSelf, hdc);
455
456     return oldBkColor;
457 }
458
459
460 static LRESULT
461 STATUSBAR_SetIcon (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
462 {
463     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
464     INT32 nPart = (INT32)wParam & 0x00ff;
465     HDC32 hdc; 
466
467     if ((nPart < -1) || (nPart >= self->numParts)) return FALSE;
468
469     hdc = GetDC32 (wndPtr->hwndSelf);
470     if (nPart == -1) {
471         self->part0.hIcon = (HICON32)lParam;
472         if (self->simple)
473             STATUSBAR_RefreshPart (wndPtr, &self->part0, hdc);
474     }
475     else {
476         self->parts[nPart].hIcon = (HICON32)lParam;
477         if (!(self->simple))
478             STATUSBAR_RefreshPart (wndPtr, &self->parts[nPart], hdc);
479     }
480     ReleaseDC32 (wndPtr->hwndSelf, hdc);
481
482     return TRUE;
483 }
484
485
486 static LRESULT
487 STATUSBAR_SetMinHeight (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
488 {
489     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
490
491     if (IsWindowVisible32 (wndPtr->hwndSelf)) {
492         HWND32 parent = GetParent32 (wndPtr->hwndSelf);
493         INT32  width, x, y;
494         RECT32 parent_rect;
495
496         GetClientRect32 (parent, &parent_rect);
497         self->height = (INT32)wParam + VERT_BORDER;
498         width = parent_rect.right - parent_rect.left;
499         x = parent_rect.left;
500         y = parent_rect.bottom - self->height;
501         MoveWindow32 (wndPtr->hwndSelf, parent_rect.left,
502                       parent_rect.bottom - self->height,
503                       width, self->height, TRUE);
504         STATUSBAR_SetPartBounds (wndPtr);
505     }
506
507     return TRUE;
508 }
509
510
511 static LRESULT
512 STATUSBAR_SetParts (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
513 {
514     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
515     HDC32       hdc;
516     LPINT32 parts;
517     STATUSWINDOWPART *  tmp;
518     int i;
519     int oldNumParts;
520
521     if (self->simple)
522         self->simple = FALSE;
523
524     oldNumParts = self->numParts;
525     self->numParts = (INT32) wParam;
526     parts = (LPINT32) lParam;
527     if (oldNumParts > self->numParts) {
528         for (i = self->numParts ; i < oldNumParts; i++) {
529             if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
530                 COMCTL32_Free (self->parts[i].text);
531         }
532     }
533     else if (oldNumParts < self->numParts) {
534         tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
535         for (i = 0; i < oldNumParts; i++) {
536             tmp[i] = self->parts[i];
537         }
538         if (self->parts)
539             COMCTL32_Free (self->parts);
540         self->parts = tmp;
541     }
542     
543     for (i = 0; i < self->numParts; i++) {
544         self->parts[i].x = parts[i];
545     }
546
547     if (self->hwndToolTip) {
548         INT32 nTipCount =
549             SendMessage32A (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
550
551         if (nTipCount < self->numParts) {
552             /* add tools */
553             TTTOOLINFO32A ti;
554             INT32 i;
555
556             ZeroMemory (&ti, sizeof(TTTOOLINFO32A));
557             ti.cbSize = sizeof(TTTOOLINFO32A);
558             ti.hwnd = wndPtr->hwndSelf;
559             for (i = nTipCount; i < self->numParts; i++) {
560                 TRACE (statusbar, "add tool %d\n", i);
561                 ti.uId = i;
562                 SendMessage32A (self->hwndToolTip, TTM_ADDTOOL32A,
563                                 0, (LPARAM)&ti);
564             }
565         }
566         else if (nTipCount > self->numParts) {
567             /* delete tools */
568             INT32 i;
569
570             for (i = nTipCount - 1; i >= self->numParts; i--) {
571
572                 TRACE (statusbar, "delete tool %d\n", i);
573
574             }
575         }
576     }
577
578     STATUSBAR_SetPartBounds (wndPtr);
579
580     hdc = GetDC32 (wndPtr->hwndSelf);
581     STATUSBAR_Refresh (wndPtr, hdc);
582     ReleaseDC32 (wndPtr->hwndSelf, hdc);
583
584     return TRUE;
585 }
586
587
588 static LRESULT
589 STATUSBAR_SetText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
590 {
591     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
592     STATUSWINDOWPART *part;
593     int part_num;
594     int style;
595     LPSTR text;
596     int len;
597     HDC32 hdc;
598
599     text = (LPSTR) lParam;
600     part_num = ((INT32) wParam) & 0x00ff;
601     style = ((INT32) wParam) & 0xff00;
602
603     if ((self->simple) || (self->parts==NULL) || (part_num==255))
604         part = &self->part0;
605     else
606         part = &self->parts[part_num];
607     if (!part) return FALSE;
608     part->style = style;
609     if (style == SBT_OWNERDRAW) {
610         part->text = text;
611     }
612     else {
613         /* duplicate string */
614         if (part->text)
615             COMCTL32_Free (part->text);
616         part->text = 0;
617         if (text && (len = lstrlen32A(text))) {
618             part->text = COMCTL32_Alloc (len+1);
619             lstrcpy32A(part->text, text);
620         }
621     }
622
623     hdc = GetDC32 (wndPtr->hwndSelf);
624     STATUSBAR_RefreshPart (wndPtr, part, hdc);
625     ReleaseDC32 (wndPtr->hwndSelf, hdc);
626
627     return TRUE;
628 }
629
630
631 //  << STATUSBAR_SetText32W >>
632
633
634 static LRESULT
635 STATUSBAR_SetTipText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
636 {
637     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
638     TTTOOLINFO32A ti;
639
640     TRACE (statusbar, "part %d: \"%s\"\n", (INT32)wParam, (LPSTR)lParam);
641     if (self->hwndToolTip) {
642         ti.cbSize = sizeof(TTTOOLINFO32A);
643         ti.hwnd = wndPtr->hwndSelf;
644         ti.uId = (INT32)wParam;
645         ti.hinst = 0;
646         ti.lpszText = (LPSTR)lParam;
647         SendMessage32A (self->hwndToolTip, TTM_UPDATETIPTEXT32A,
648                         0, (LPARAM)&ti);
649     }
650
651     return 0;
652 }
653
654
655 //  << STATUSBAR_SetTipText32W >>
656 //  << STATUSBAR_SetUnicodeFormat >>
657
658
659 static LRESULT
660 STATUSBAR_Simple (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
661 {
662     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
663     BOOL32 simple;
664     HDC32  hdc;
665     NMHDR  nmhdr;
666
667     simple = (BOOL32) wParam;
668     self->simple = simple;
669
670     /* send notification */
671     nmhdr.hwndFrom = wndPtr->hwndSelf;
672     nmhdr.idFrom = wndPtr->wIDmenu;
673     nmhdr.code = SBN_SIMPLEMODECHANGE;
674     SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
675                     0, (LPARAM)&nmhdr);
676
677     hdc = GetDC32 (wndPtr->hwndSelf);
678     STATUSBAR_Refresh (wndPtr, hdc);
679     ReleaseDC32 (wndPtr->hwndSelf, hdc);
680
681     return TRUE;
682 }
683
684
685 static LRESULT
686 STATUSBAR_WMCreate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
687 {
688     LPCREATESTRUCT32A lpCreate = (LPCREATESTRUCT32A) lParam;
689     NONCLIENTMETRICS32A nclm;
690     RECT32      rect;
691     int         width, len;
692     HDC32       hdc;
693     STATUSWINDOWINFO *self;
694
695     self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
696     wndPtr->wExtra[0] = (DWORD)self;
697
698     self->numParts = 1;
699     self->parts = 0;
700     self->simple = FALSE;
701     self->clrBk = CLR_DEFAULT;
702     self->hFont = 0;
703     GetClientRect32 (wndPtr->hwndSelf, &rect);
704
705     nclm.cbSize = sizeof(NONCLIENTMETRICS32A);
706     SystemParametersInfo32A (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
707     self->hDefaultFont = CreateFontIndirect32A (&nclm.lfStatusFont);
708
709     /* initialize simple case */
710     self->part0.bound = rect;
711     self->part0.text = 0;
712     self->part0.x = 0;
713     self->part0.style = 0;
714     self->part0.hIcon = 0;
715
716     /* initialize first part */
717     self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
718     self->parts[0].bound = rect;
719     self->parts[0].text = 0;
720     self->parts[0].x = -1;
721     self->parts[0].style = 0;
722     self->parts[0].hIcon = 0;
723
724     if ((len = lstrlen32A (lpCreate->lpszName))) {
725         self->parts[0].text = COMCTL32_Alloc (len + 1);
726         lstrcpy32A (self->parts[0].text, lpCreate->lpszName);
727     }
728
729     if ((hdc = GetDC32 (0))) {
730         TEXTMETRIC32A tm;
731         HFONT32 hOldFont;
732
733         hOldFont = SelectObject32 (hdc,self->hDefaultFont);
734         GetTextMetrics32A(hdc, &tm);
735         self->textHeight = tm.tmHeight;
736         SelectObject32 (hdc, hOldFont);
737         ReleaseDC32(0, hdc);
738     }
739
740     if (wndPtr->dwStyle & SBT_TOOLTIPS) {
741         self->hwndToolTip =
742             CreateWindowEx32A (0, TOOLTIPS_CLASS32A, NULL, 0,
743                                CW_USEDEFAULT32, CW_USEDEFAULT32,
744                                CW_USEDEFAULT32, CW_USEDEFAULT32,
745                                wndPtr->hwndSelf, 0,
746                                wndPtr->hInstance, NULL);
747
748         if (self->hwndToolTip) {
749             NMTOOLTIPSCREATED nmttc;
750
751             nmttc.hdr.hwndFrom = wndPtr->hwndSelf;
752             nmttc.hdr.idFrom = wndPtr->wIDmenu;
753             nmttc.hdr.code = NM_TOOLTIPSCREATED;
754             nmttc.hwndToolTips = self->hwndToolTip;
755
756             SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
757                             (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmttc);
758         }
759     }
760
761     GetClientRect32 (GetParent32 (wndPtr->hwndSelf), &rect);
762     width = rect.right - rect.left;
763     self->height = self->textHeight + 4 + VERT_BORDER;
764     MoveWindow32 (wndPtr->hwndSelf, lpCreate->x, lpCreate->y-1,
765                   width, self->height, FALSE);
766     STATUSBAR_SetPartBounds (wndPtr);
767
768     return 0;
769 }
770
771
772 static LRESULT
773 STATUSBAR_WMDestroy (WND *wndPtr)
774 {
775     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
776     int i;
777
778     for (i = 0; i < self->numParts; i++) {
779         if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
780             COMCTL32_Free (self->parts[i].text);
781     }
782     if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
783         COMCTL32_Free (self->part0.text);
784     COMCTL32_Free (self->parts);
785
786     /* delete default font */
787     if (self->hDefaultFont)
788         DeleteObject32 (self->hDefaultFont);
789
790     /* delete tool tip control */
791     if (self->hwndToolTip)
792         DestroyWindow32 (self->hwndToolTip);
793
794     COMCTL32_Free (self);
795
796     return 0;
797 }
798
799
800 static __inline__ LRESULT
801 STATUSBAR_WMGetFont (WND *wndPtr)
802 {
803     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
804
805     return self->hFont;
806 }
807
808
809 static LRESULT
810 STATUSBAR_WMGetText (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
811 {
812     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
813     INT32 len;
814
815     if (!(self->parts[0].text))
816         return 0;
817     len = lstrlen32A (self->parts[0].text);
818     if (wParam > len) {
819         lstrcpy32A ((LPSTR)lParam, self->parts[0].text);
820         return len;
821     }
822     else
823         return -1;
824 }
825
826
827 static LRESULT
828 STATUSBAR_WMGetTextLength (WND *wndPtr)
829 {
830     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
831
832     if (!(self->parts[0].text))
833         return 0;
834
835     return (lstrlen32A (self->parts[0].text));
836 }
837
838
839 __inline__ static LRESULT
840 STATUSBAR_WMMouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
841 {
842     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
843
844     if (self->hwndToolTip)
845         STATUSBAR_RelayEvent (self->hwndToolTip, wndPtr->hwndSelf,
846                               WM_MOUSEMOVE, wParam, lParam);
847     return 0;
848 }
849
850
851 static LRESULT
852 STATUSBAR_WMNCHitTest (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
853 {
854     if (wndPtr->dwStyle & SBARS_SIZEGRIP) {
855         RECT32  rect;
856         POINT32 pt;
857
858         GetClientRect32 (wndPtr->hwndSelf, &rect);
859
860         pt.x = (INT32)LOWORD(lParam);
861         pt.y = (INT32)HIWORD(lParam);
862         ScreenToClient32 (wndPtr->hwndSelf, &pt);
863
864         rect.left = rect.right - 13;
865         rect.top += 2;
866
867         if (PtInRect32 (&rect, pt))
868             return HTBOTTOMRIGHT;
869     }
870
871     return DefWindowProc32A (wndPtr->hwndSelf, WM_NCHITTEST, wParam, lParam);
872 }
873
874
875 static __inline__ LRESULT
876 STATUSBAR_WMNCLButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
877 {
878     PostMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NCLBUTTONDOWN,
879                     wParam, lParam);
880     return 0;
881 }
882
883
884 static __inline__ LRESULT
885 STATUSBAR_WMNCLButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
886 {
887     PostMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NCLBUTTONUP,
888                     wParam, lParam);
889     return 0;
890 }
891
892
893 static LRESULT
894 STATUSBAR_WMPaint (WND *wndPtr, WPARAM32 wParam)
895 {
896     HDC32 hdc;
897     PAINTSTRUCT32 ps;
898
899     hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
900     STATUSBAR_Refresh (wndPtr, hdc);
901     if (!wParam)
902         EndPaint32 (wndPtr->hwndSelf, &ps);
903
904     return 0;
905 }
906
907
908 static LRESULT
909 STATUSBAR_WMSetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
910 {
911     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
912
913     self->hFont = (HFONT32)wParam;
914     if (LOWORD(lParam) == TRUE) {
915         HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
916         STATUSBAR_Refresh (wndPtr, hdc);
917         ReleaseDC32 (wndPtr->hwndSelf, hdc);
918     }
919
920     return 0;
921 }
922
923
924 static LRESULT
925 STATUSBAR_WMSetText (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
926 {
927     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
928     STATUSWINDOWPART *part;
929     int len;
930     HDC32 hdc;
931
932     if (self->numParts == 0)
933         return FALSE;
934
935     part = &self->parts[0];
936     /* duplicate string */
937     if (part->text)
938         COMCTL32_Free (part->text);
939     part->text = 0;
940     if (lParam && (len = lstrlen32A((LPCSTR)lParam))) {
941         part->text = COMCTL32_Alloc (len+1);
942         lstrcpy32A (part->text, (LPCSTR)lParam);
943     }
944
945     hdc = GetDC32 (wndPtr->hwndSelf);
946     STATUSBAR_RefreshPart (wndPtr, part, hdc);
947     ReleaseDC32 (wndPtr->hwndSelf, hdc);
948
949     return TRUE;
950 }
951
952
953 static LRESULT
954 STATUSBAR_WMSize (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
955 {
956     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (wndPtr);
957     INT32       width, x, y, flags;
958     RECT32      parent_rect;
959     HWND32      parent;
960
961     /* Need to resize width to match parent */
962     flags = (INT32) wParam;
963
964     /* FIXME for flags =
965      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
966      */
967
968     if (flags == SIZE_RESTORED) {
969         /* width and height don't apply */
970         parent = GetParent32 (wndPtr->hwndSelf);
971         GetClientRect32 (parent, &parent_rect);
972         width = parent_rect.right - parent_rect.left;
973         x = parent_rect.left;
974         y = parent_rect.bottom - self->height;
975         MoveWindow32 (wndPtr->hwndSelf, parent_rect.left, 
976                       parent_rect.bottom - self->height,
977                       width, self->height, TRUE);
978         STATUSBAR_SetPartBounds (wndPtr);
979     }
980     return 0;
981 }
982
983
984 static LRESULT
985 STATUSBAR_SendNotify (WND *wndPtr, UINT32 code)
986 {
987     NMHDR  nmhdr;
988
989     nmhdr.hwndFrom = wndPtr->hwndSelf;
990     nmhdr.idFrom = wndPtr->wIDmenu;
991     nmhdr.code = code;
992     SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
993                     0, (LPARAM)&nmhdr);
994     return 0;
995 }
996
997
998
999 LRESULT WINAPI
1000 StatusWindowProc (HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
1001 {
1002     WND *wndPtr = WIN_FindWndPtr (hwnd);
1003
1004     switch (msg) {
1005         case SB_GETBORDERS:
1006             return STATUSBAR_GetBorders (lParam);
1007
1008         case SB_GETICON:
1009             return STATUSBAR_GetIcon (wndPtr, wParam);
1010
1011         case SB_GETPARTS:
1012             return STATUSBAR_GetParts (wndPtr, wParam, lParam);
1013
1014         case SB_GETRECT:
1015             return STATUSBAR_GetRect (wndPtr, wParam, lParam);
1016
1017         case SB_GETTEXT32A:
1018             return STATUSBAR_GetText32A (wndPtr, wParam, lParam);
1019
1020 //      case SB_GETTEXT32W:
1021
1022         case SB_GETTEXTLENGTH32A:
1023             return STATUSBAR_GetTextLength32A (wndPtr, wParam, lParam);
1024
1025 //      case SB_GETTEXTLENGHT32W:
1026
1027         case SB_GETTIPTEXT32A:
1028             return STATUSBAR_GetTipText32A (wndPtr, wParam, lParam);
1029
1030 //      case SB_GETTIPTEXT32W:
1031 //      case SB_GETUNICODEFORMAT:
1032
1033         case SB_ISSIMPLE:
1034             return STATUSBAR_IsSimple (wndPtr);
1035
1036         case SB_SETBKCOLOR:
1037             return STATUSBAR_SetBkColor (wndPtr, wParam, lParam);
1038
1039         case SB_SETICON:
1040             return STATUSBAR_SetIcon (wndPtr, wParam, lParam);
1041
1042         case SB_SETMINHEIGHT:
1043             return STATUSBAR_SetMinHeight (wndPtr, wParam, lParam);
1044
1045         case SB_SETPARTS:       
1046             return STATUSBAR_SetParts (wndPtr, wParam, lParam);
1047
1048         case SB_SETTEXT32A:
1049             return STATUSBAR_SetText32A (wndPtr, wParam, lParam);
1050
1051 //      case SB_SETTEXT32W:
1052
1053         case SB_SETTIPTEXT32A:
1054             return STATUSBAR_SetTipText32A (wndPtr, wParam, lParam);
1055
1056 //      case SB_SETTIPTEXT32W:
1057 //      case SB_SETUNICODEFORMAT:
1058
1059         case SB_SIMPLE:
1060             return STATUSBAR_Simple (wndPtr, wParam, lParam);
1061
1062
1063         case WM_CREATE:
1064             return STATUSBAR_WMCreate (wndPtr, wParam, lParam);
1065
1066         case WM_DESTROY:
1067             return STATUSBAR_WMDestroy (wndPtr);
1068
1069         case WM_GETFONT:
1070             return STATUSBAR_WMGetFont (wndPtr);
1071
1072         case WM_GETTEXT:
1073             return STATUSBAR_WMGetText (wndPtr, wParam, lParam);
1074
1075         case WM_GETTEXTLENGTH:
1076             return STATUSBAR_WMGetTextLength (wndPtr);
1077
1078         case WM_LBUTTONDBLCLK:
1079             return STATUSBAR_SendNotify (wndPtr, NM_DBLCLK);
1080
1081         case WM_LBUTTONUP:
1082             return STATUSBAR_SendNotify (wndPtr, NM_CLICK);
1083
1084         case WM_MOUSEMOVE:
1085             return STATUSBAR_WMMouseMove (wndPtr, wParam, lParam);
1086
1087         case WM_NCHITTEST:
1088             return STATUSBAR_WMNCHitTest (wndPtr, wParam, lParam);
1089
1090         case WM_NCLBUTTONDOWN:
1091             return STATUSBAR_WMNCLButtonDown (wndPtr, wParam, lParam);
1092
1093         case WM_NCLBUTTONUP:
1094             return STATUSBAR_WMNCLButtonUp (wndPtr, wParam, lParam);
1095
1096         case WM_PAINT:
1097             return STATUSBAR_WMPaint (wndPtr, wParam);
1098
1099         case WM_RBUTTONDBLCLK:
1100             return STATUSBAR_SendNotify (wndPtr, NM_RDBLCLK);
1101
1102         case WM_RBUTTONUP:
1103             return STATUSBAR_SendNotify (wndPtr, NM_RCLICK);
1104
1105         case WM_SETFONT:
1106             return STATUSBAR_WMSetFont (wndPtr, wParam, lParam);
1107
1108         case WM_SETTEXT:
1109             return STATUSBAR_WMSetText (wndPtr, wParam, lParam);
1110
1111         case WM_SIZE:
1112             return STATUSBAR_WMSize (wndPtr, wParam, lParam);
1113
1114         default:
1115             if (msg >= WM_USER)
1116                 ERR (statusbar, "unknown msg %04x wp=%04x lp=%08lx\n",
1117                      msg, wParam, lParam);
1118             return DefWindowProc32A (hwnd, msg, wParam, lParam);
1119     }
1120     return 0;
1121 }
1122
1123
1124 /***********************************************************************
1125  * STATUS_Register [Internal]
1126  *
1127  * Registers the status window class.
1128  */
1129 void STATUS_Register (void)
1130 {
1131     WNDCLASS32A wndClass;
1132
1133     if (GlobalFindAtom32A (STATUSCLASSNAME32A)) return;
1134
1135     ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
1136     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
1137     wndClass.lpfnWndProc   = (WNDPROC32)StatusWindowProc;
1138     wndClass.cbClsExtra    = 0;
1139     wndClass.cbWndExtra    = sizeof(STATUSWINDOWINFO *);
1140     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
1141     wndClass.hbrBackground = (HBRUSH32)(COLOR_3DFACE + 1);
1142     wndClass.lpszClassName = STATUSCLASSNAME32A;
1143  
1144     RegisterClass32A (&wndClass);
1145 }
1146