Fixed several bugs and typos.
[wine] / dlls / comctl32 / header.c
1 /*
2  *  Header control
3  *
4  *  Copyright 1998 Eric Kohl
5  *
6  *  TODO:
7  *   - Imagelist support (partially).
8  *   - Callback items (under construction).
9  *   - Order list support.
10  *   - Control specific cursors (over dividers).
11  *   - Hottrack support (partially).
12  *   - Custom draw support (including Notifications).
13  *   - Drag and Drop support (including Notifications).
14  *   - Unicode support.
15  *
16  *  FIXME:
17  *   - Replace DrawText32A by DrawTextEx32A(...|DT_ENDELLIPSIS) in
18  *     HEADER_DrawItem.
19  *   - Little flaw when drawing a bitmap on the right side of the text.
20  */
21
22 #include "windows.h"
23 #include "commctrl.h"
24 #include "header.h"
25 #include "win.h"
26 #include "debug.h"
27
28
29 #define __HDM_LAYOUT_HACK__
30
31
32 #define VERT_BORDER     4
33 #define DIVIDER_WIDTH  10
34
35 #define HEADER_GetInfoPtr(wndPtr) ((HEADER_INFO *)wndPtr->wExtra[0])
36
37
38 static INT32
39 HEADER_DrawItem (WND *wndPtr, HDC32 hdc, INT32 iItem, BOOL32 bHotTrack)
40 {
41     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
42     HEADER_ITEM *phdi = &infoPtr->items[iItem];
43     RECT32 r;
44     INT32  oldBkMode;
45
46     r = phdi->rect;
47     if (r.right - r.left == 0)
48         return phdi->rect.right;
49
50     if (wndPtr->dwStyle & HDS_BUTTONS) {
51         if (phdi->bDown) {
52             DrawEdge32 (hdc, &r, BDR_RAISEDOUTER,
53                         BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST);
54             r.left += 2;
55             r.top  += 2;
56         }
57         else
58             DrawEdge32 (hdc, &r, EDGE_RAISED,
59                         BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
60     }
61     else
62         DrawEdge32 (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST);
63
64     if (phdi->fmt & HDF_OWNERDRAW) {
65         DRAWITEMSTRUCT32 dis;
66         dis.CtlType    = ODT_HEADER;
67         dis.CtlID      = wndPtr->wIDmenu;
68         dis.itemID     = iItem;
69         dis.itemAction = ODA_DRAWENTIRE;
70         dis.itemState  = phdi->bDown ? ODS_SELECTED : 0;
71         dis.hwndItem   = wndPtr->hwndSelf;
72         dis.hDC        = hdc;
73         dis.rcItem     = r;
74         dis.itemData   = phdi->lParam;
75         SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_DRAWITEM,
76                         (WPARAM32)wndPtr->wIDmenu, (LPARAM)&dis);
77     }
78     else {
79         UINT32 uTextJustify = DT_LEFT;
80
81         if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER)
82             uTextJustify = DT_CENTER;
83         else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT)
84             uTextJustify = DT_RIGHT;
85
86         if ((phdi->fmt & HDF_BITMAP) && (phdi->hbm)) {
87             BITMAP32 bmp;
88             HDC32    hdcBitmap;
89             INT32    yD, yS, cx, cy, rx, ry;
90
91             GetObject32A (phdi->hbm, sizeof(BITMAP32), (LPVOID)&bmp);
92
93             ry = r.bottom - r.top;
94             rx = r.right - r.left;
95
96             if (ry >= bmp.bmHeight) {
97                 cy = bmp.bmHeight;
98                 yD = r.top + (ry - bmp.bmHeight) / 2;
99                 yS = 0;
100             }
101             else {
102                 cy = ry;
103                 yD = r.top;
104                 yS = (bmp.bmHeight - ry) / 2;
105
106             }
107
108             if (rx >= bmp.bmWidth + 6) {
109                 cx = bmp.bmWidth;
110             }
111             else {
112                 cx = rx - 6;
113             }
114
115             hdcBitmap = CreateCompatibleDC32 (hdc);
116             SelectObject32 (hdcBitmap, phdi->hbm);
117             BitBlt32 (hdc, r.left + 3, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY);
118             DeleteDC32 (hdcBitmap);
119
120             r.left += (bmp.bmWidth + 3);
121         }
122
123
124         if ((phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) {
125             BITMAP32 bmp;
126             HDC32    hdcBitmap;
127             INT32    xD, yD, yS, cx, cy, rx, ry, tx;
128             RECT32   textRect;
129
130             GetObject32A (phdi->hbm, sizeof(BITMAP32), (LPVOID)&bmp);
131
132             textRect = r;
133             DrawText32W (hdc, phdi->pszText, lstrlen32W (phdi->pszText),
134                   &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT);
135             tx = textRect.right - textRect.left;
136             ry = r.bottom - r.top;
137             rx = r.right - r.left;
138
139             if (ry >= bmp.bmHeight) {
140                 cy = bmp.bmHeight;
141                 yD = r.top + (ry - bmp.bmHeight) / 2;
142                 yS = 0;
143             }
144             else {
145                 cy = ry;
146                 yD = r.top;
147                 yS = (bmp.bmHeight - ry) / 2;
148
149             }
150
151             if (r.left + tx + bmp.bmWidth + 9 <= r.right) {
152                 cx = bmp.bmWidth;
153                 xD = r.left + tx + 6;
154             }
155             else {
156                 if (rx >= bmp.bmWidth + 6) {
157                     cx = bmp.bmWidth;
158                     xD = r.right - bmp.bmWidth - 3;
159                     r.right = xD - 3;
160                 }
161                 else {
162                     cx = rx - 3;
163                     xD = r.left;
164                     r.right = r.left;
165                 }
166             }
167
168             hdcBitmap = CreateCompatibleDC32 (hdc);
169             SelectObject32 (hdcBitmap, phdi->hbm);
170             BitBlt32 (hdc, xD, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY);
171             DeleteDC32 (hdcBitmap);
172         }
173
174         if (phdi->fmt & HDF_IMAGE) {
175
176
177 /*          ImageList_Draw (infoPtr->himl, phdi->iImage,...); */
178         }
179
180         if ((phdi->fmt & HDF_STRING) && (phdi->pszText)) {
181             oldBkMode = SetBkMode32(hdc, TRANSPARENT);
182             r.left += 3;
183             r.right -= 3;
184             SetTextColor32 (hdc, bHotTrack ? COLOR_HIGHLIGHT : COLOR_BTNTEXT);
185             DrawText32W (hdc, phdi->pszText, lstrlen32W (phdi->pszText),
186                   &r, uTextJustify|DT_VCENTER|DT_SINGLELINE);
187             if (oldBkMode != TRANSPARENT)
188                 SetBkMode32(hdc, oldBkMode);
189         }
190     }
191     return phdi->rect.right;
192 }
193
194
195 static void 
196 HEADER_Refresh (WND *wndPtr, HDC32 hdc)
197 {
198     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
199     HFONT32 hFont, hOldFont;
200     RECT32 rect;
201     HBRUSH32 hbrBk;
202     INT32 i, x;
203
204     /* get rect for the bar, adjusted for the border */
205     GetClientRect32 (wndPtr->hwndSelf, &rect);
206
207     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
208     hOldFont = SelectObject32 (hdc, hFont);
209
210     /* draw Background */
211     hbrBk = GetSysColorBrush32(COLOR_3DFACE);
212     FillRect32(hdc, &rect, hbrBk);
213
214     x = rect.left;
215     for (i = 0; i < infoPtr->uNumItem; i++) {
216         x = HEADER_DrawItem (wndPtr, hdc, i, FALSE);
217     }
218
219     if ((x <= rect.right) && (infoPtr->uNumItem > 0)) {
220         rect.left = x;
221         if (wndPtr->dwStyle & HDS_BUTTONS)
222             DrawEdge32 (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT);
223         else
224             DrawEdge32 (hdc, &rect, EDGE_ETCHED, BF_BOTTOM);
225     }
226
227     SelectObject32 (hdc, hOldFont);
228 }
229
230
231 static void
232 HEADER_RefreshItem (WND *wndPtr, HDC32 hdc, INT32 iItem)
233 {
234     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
235     HFONT32 hFont, hOldFont;
236
237     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
238     hOldFont = SelectObject32 (hdc, hFont);
239     HEADER_DrawItem (wndPtr, hdc, iItem, FALSE);
240     SelectObject32 (hdc, hOldFont);
241 }
242
243
244 static void
245 HEADER_SetItemBounds (WND *wndPtr)
246 {
247     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
248     HEADER_ITEM *phdi;
249     RECT32 rect;
250     int i, x;
251
252     if (infoPtr->uNumItem == 0)
253         return;
254
255     GetClientRect32 (wndPtr->hwndSelf, &rect);
256
257     x = rect.left;
258     for (i = 0; i < infoPtr->uNumItem; i++) {
259         phdi = &infoPtr->items[i];
260         phdi->rect.top = rect.top;
261         phdi->rect.bottom = rect.bottom;
262         phdi->rect.left = x;
263         phdi->rect.right = phdi->rect.left + phdi->cxy;
264         x = phdi->rect.right;
265     }
266 }
267
268
269 static void
270 HEADER_ForceItemBounds (WND *wndPtr, INT32 cy)
271 {
272     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
273     HEADER_ITEM *phdi;
274     int i, x;
275
276     if (infoPtr->uNumItem == 0)
277         return;
278
279     x = 0;
280     for (i = 0; i < infoPtr->uNumItem; i++) {
281         phdi = &infoPtr->items[i];
282         phdi->rect.top = 0;
283         phdi->rect.bottom = cy;
284         phdi->rect.left = x;
285         phdi->rect.right = phdi->rect.left + phdi->cxy;
286         x = phdi->rect.right;
287     }
288 }
289
290
291 static void
292 HEADER_InternalHitTest (WND *wndPtr, LPPOINT32 lpPt, UINT32 *pFlags, INT32 *pItem)
293 {
294     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
295     RECT32 rect, rcTest;
296     INT32  iCount, width;
297     BOOL32 bNoWidth;
298
299     GetClientRect32 (wndPtr->hwndSelf, &rect);
300
301     *pFlags = 0;
302     bNoWidth = FALSE;
303     if (PtInRect32 (&rect, *lpPt))
304     {
305         if (infoPtr->uNumItem == 0) {
306             *pFlags |= HHT_NOWHERE;
307             *pItem = 1;
308             TRACE (header, "NOWHERE\n");
309             return;
310         }
311         else {
312             /* somewhere inside */
313             for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) {
314                 rect = infoPtr->items[iCount].rect;
315                 width = rect.right - rect.left;
316                 if (width == 0) {
317                     bNoWidth = TRUE;
318                     continue;
319                 }
320                 if (PtInRect32 (&rect, *lpPt)) {
321                     if (width <= 2 * DIVIDER_WIDTH) {
322                         *pFlags |= HHT_ONHEADER;
323                         *pItem = iCount;
324                         TRACE (header, "ON HEADER %d\n", iCount);
325                         return;
326                     }
327                     if (iCount > 0) {
328                         rcTest = rect;
329                         rcTest.right = rcTest.left + DIVIDER_WIDTH;
330                         if (PtInRect32 (&rcTest, *lpPt)) {
331                             if (bNoWidth) {
332                                 *pFlags |= HHT_ONDIVOPEN;
333                                 *pItem = iCount - 1;
334                                 TRACE (header, "ON DIVOPEN %d\n", *pItem);
335                                 return;
336                             }
337                             else {
338                                 *pFlags |= HHT_ONDIVIDER;
339                                 *pItem = iCount - 1;
340                                 TRACE (header, "ON DIVIDER %d\n", *pItem);
341                                 return;
342                             }
343                         }
344                     }
345                     rcTest = rect;
346                     rcTest.left = rcTest.right - DIVIDER_WIDTH;
347                     if (PtInRect32 (&rcTest, *lpPt)) {
348                         *pFlags |= HHT_ONDIVIDER;
349                         *pItem = iCount;
350                         TRACE (header, "ON DIVIDER %d\n", *pItem);
351                         return;
352                     }
353
354                     *pFlags |= HHT_ONHEADER;
355                     *pItem = iCount;
356                     TRACE (header, "ON HEADER %d\n", iCount);
357                     return;
358                 }
359             }
360
361             /* check for last divider part (on nowhere) */
362             rect = infoPtr->items[infoPtr->uNumItem-1].rect;
363             rect.left = rect.right;
364             rect.right += DIVIDER_WIDTH;
365             if (PtInRect32 (&rect, *lpPt)) {
366                 if (bNoWidth) {
367                     *pFlags |= HHT_ONDIVOPEN;
368                     *pItem = infoPtr->uNumItem - 1;
369                     TRACE (header, "ON DIVOPEN %d\n", *pItem);
370                     return;
371                 }
372                 else {
373                     *pFlags |= HHT_ONDIVIDER;
374                     *pItem = infoPtr->uNumItem-1;
375                     TRACE (header, "ON DIVIDER %d\n", *pItem);
376                     return;
377                 }
378             }
379
380             *pFlags |= HHT_NOWHERE;
381             *pItem = 1;
382             TRACE (header, "NOWHERE\n");
383             return;
384         }
385     }
386     else {
387         if (lpPt->x < rect.left) {
388            TRACE (header, "TO LEFT\n");
389            *pFlags |= HHT_TOLEFT;
390         }
391         else if (lpPt->x > rect.right) {
392             TRACE (header, "TO LEFT\n");
393             *pFlags |= HHT_TORIGHT;
394         }
395
396         if (lpPt->y < rect.top) {
397             TRACE (header, "ABOVE\n");
398             *pFlags |= HHT_ABOVE;
399         }
400         else if (lpPt->y > rect.bottom) {
401             TRACE (header, "BELOW\n");
402             *pFlags |= HHT_BELOW;
403         }
404     }
405
406     *pItem = 1;
407     TRACE (header, "flags=0x%X\n", *pFlags);
408     return;
409 }
410
411
412 static void
413 HEADER_DrawTrackLine (WND *wndPtr, HDC32 hdc, INT32 x)
414 {
415     RECT32 rect;
416     HPEN32 hOldPen;
417     INT32  oldRop;
418
419     GetClientRect32 (wndPtr->hwndSelf, &rect);
420
421     hOldPen = SelectObject32 (hdc, GetStockObject32 (BLACK_PEN));
422     oldRop = SetROP232 (hdc, R2_XORPEN);
423     MoveToEx32 (hdc, x, rect.top, NULL);
424     LineTo32 (hdc, x, rect.bottom);
425     SetROP232 (hdc, oldRop);
426     SelectObject32 (hdc, hOldPen);
427 }
428
429
430 static BOOL32
431 HEADER_SendSimpleNotify (WND *wndPtr, UINT32 code)
432 {
433     NMHDR nmhdr;
434
435     nmhdr.hwndFrom = wndPtr->hwndSelf;
436     nmhdr.idFrom   = wndPtr->wIDmenu;
437     nmhdr.code     = code;
438
439     return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
440                                    (WPARAM32)nmhdr.idFrom, (LPARAM)&nmhdr);
441 }
442
443
444 static BOOL32
445 HEADER_SendHeaderNotify (WND *wndPtr, UINT32 code, INT32 iItem)
446 {
447     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);   
448     NMHEADER32A nmhdr;
449     HDITEM32A nmitem;
450
451     nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
452     nmhdr.hdr.idFrom = wndPtr->wIDmenu;
453     nmhdr.hdr.code = code;
454     nmhdr.iItem = iItem;
455     nmhdr.iButton = 0;
456     nmhdr.pitem = &nmitem;
457     nmitem.mask = 0;
458     nmitem.cxy = infoPtr->items[iItem].cxy;
459     nmitem.hbm = infoPtr->items[iItem].hbm;
460     nmitem.pszText = NULL;
461     nmitem.cchTextMax = 0;
462 /*    nmitem.pszText = infoPtr->items[iItem].pszText; */
463 /*    nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
464     nmitem.fmt = infoPtr->items[iItem].fmt;
465     nmitem.lParam = infoPtr->items[iItem].lParam;
466     nmitem.iOrder = infoPtr->items[iItem].iOrder;
467     nmitem.iImage = infoPtr->items[iItem].iImage;
468
469     return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
470                                    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
471 }
472
473
474 static BOOL32
475 HEADER_SendClickNotify (WND *wndPtr, UINT32 code, INT32 iItem)
476 {
477     NMHEADER32A nmhdr;
478
479     nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
480     nmhdr.hdr.idFrom = wndPtr->wIDmenu;
481     nmhdr.hdr.code = code;
482     nmhdr.iItem = iItem;
483     nmhdr.iButton = 0;
484     nmhdr.pitem = NULL;
485
486     return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
487                                    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
488 }
489
490
491 static LRESULT
492 HEADER_CreateDragImage (WND *wndPtr, WPARAM32 wParam)
493 {
494     FIXME (header, "empty stub!\n");
495     return 0;
496 }
497
498
499 static LRESULT
500 HEADER_DeleteItem (WND *wndPtr, WPARAM32 wParam)
501 {
502     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
503     INT32 iItem = (INT32)wParam;
504     HDC32 hdc;
505
506     TRACE(header, "[iItem=%d]\n", iItem);
507     
508     if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
509         return FALSE;
510
511     if (infoPtr->uNumItem == 1) {
512         TRACE(header, "Simple delete!\n");
513         if (infoPtr->items[0].pszText)
514             COMCTL32_Free (infoPtr->items[0].pszText);
515         COMCTL32_Free (infoPtr->items);
516         infoPtr->items = 0;
517         infoPtr->uNumItem = 0;
518     }
519     else {
520         HEADER_ITEM *oldItems = infoPtr->items;
521         TRACE(header, "Complex delete! [iItem=%d]\n", iItem);
522
523         if (infoPtr->items[iItem].pszText)
524             COMCTL32_Free (infoPtr->items[iItem].pszText);
525
526         infoPtr->uNumItem--;
527         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
528         /* pre delete copy */
529         if (iItem > 0) {
530             memcpy (&infoPtr->items[0], &oldItems[0],
531                     iItem * sizeof(HEADER_ITEM));
532         }
533
534         /* post delete copy */
535         if (iItem < infoPtr->uNumItem) {
536             memcpy (&infoPtr->items[iItem], &oldItems[iItem+1],
537                     (infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM));
538         }
539
540         COMCTL32_Free (oldItems);
541     }
542
543     HEADER_SetItemBounds (wndPtr);
544
545     hdc = GetDC32 (wndPtr->hwndSelf);
546     HEADER_Refresh (wndPtr, hdc);
547     ReleaseDC32 (wndPtr->hwndSelf, hdc);
548     
549     return TRUE;
550 }
551
552
553 static LRESULT
554 HEADER_GetImageList (WND *wndPtr)
555 {
556     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
557
558     return (LRESULT)infoPtr->himl;
559 }
560
561
562 static LRESULT
563 HEADER_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
564 {
565     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
566     HDITEM32A   *phdi = (HDITEM32A*)lParam;
567     INT32       nItem = (INT32)wParam;
568     HEADER_ITEM *lpItem;
569
570     if (!phdi)
571         return FALSE;
572     if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
573         return FALSE;
574
575     TRACE (header, "[nItem=%d]\n", nItem);
576
577     if (phdi->mask == 0)
578         return TRUE;
579
580     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
581     if (phdi->mask & HDI_BITMAP)
582         phdi->hbm = lpItem->hbm;
583
584     if (phdi->mask & HDI_FORMAT)
585         phdi->fmt = lpItem->fmt;
586
587     if (phdi->mask & HDI_WIDTH)
588         phdi->cxy = lpItem->cxy;
589
590     if (phdi->mask & HDI_LPARAM)
591         phdi->lParam = lpItem->lParam;
592
593     if (phdi->mask & HDI_TEXT) {
594         if (lpItem->pszText != LPSTR_TEXTCALLBACK32W)
595             lstrcpynWtoA (phdi->pszText, lpItem->pszText, phdi->cchTextMax);
596         else
597             phdi->pszText = LPSTR_TEXTCALLBACK32A;
598     }
599
600     if (phdi->mask & HDI_IMAGE)
601         phdi->iImage = lpItem->iImage;
602
603     if (phdi->mask & HDI_ORDER)
604         phdi->iOrder = lpItem->iOrder;
605
606     return TRUE;
607 }
608
609
610 static LRESULT
611 HEADER_GetItem32W (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
612 {
613     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
614     HDITEM32W   *phdi = (HDITEM32W*)lParam;
615     INT32       nItem = (INT32)wParam;
616     HEADER_ITEM *lpItem;
617
618     if (!phdi)
619         return FALSE;
620     if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
621         return FALSE;
622
623     TRACE (header, "[nItem=%d]\n", nItem);
624
625     if (phdi->mask == 0)
626         return TRUE;
627
628     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
629     if (phdi->mask & HDI_BITMAP)
630         phdi->hbm = lpItem->hbm;
631
632     if (phdi->mask & HDI_FORMAT)
633         phdi->fmt = lpItem->fmt;
634
635     if (phdi->mask & HDI_WIDTH)
636         phdi->cxy = lpItem->cxy;
637
638     if (phdi->mask & HDI_LPARAM)
639         phdi->lParam = lpItem->lParam;
640
641     if (phdi->mask & HDI_TEXT) {
642         if (lpItem->pszText != LPSTR_TEXTCALLBACK32W)
643             lstrcpyn32W (phdi->pszText, lpItem->pszText, phdi->cchTextMax);
644         else
645             phdi->pszText = LPSTR_TEXTCALLBACK32W;
646     }
647
648     if (phdi->mask & HDI_IMAGE)
649         phdi->iImage = lpItem->iImage;
650
651     if (phdi->mask & HDI_ORDER)
652         phdi->iOrder = lpItem->iOrder;
653
654     return TRUE;
655 }
656
657
658 __inline__ static LRESULT
659 HEADER_GetItemCount (WND *wndPtr)
660 {
661     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
662     return infoPtr->uNumItem;
663 }
664
665
666 static LRESULT
667 HEADER_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
668 {
669     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
670     INT32 iItem = (INT32)wParam;
671     LPRECT32 lpRect = (LPRECT32)lParam;
672
673     if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
674         return FALSE;
675
676     lpRect->left   = infoPtr->items[iItem].rect.left;
677     lpRect->right  = infoPtr->items[iItem].rect.right;
678     lpRect->top    = infoPtr->items[iItem].rect.top;
679     lpRect->bottom = infoPtr->items[iItem].rect.bottom;
680
681     return TRUE;
682 }
683
684
685 /* << HEADER_GetOrderArray >> */
686
687
688 __inline__ static LRESULT
689 HEADER_GetUnicodeFormat (WND *wndPtr)
690 {
691     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
692     return infoPtr->bUnicode;
693 }
694
695
696 static LRESULT
697 HEADER_HitTest (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
698 {
699     LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam;
700
701     HEADER_InternalHitTest (wndPtr, &phti->pt, &phti->flags, &phti->iItem);
702
703     return phti->flags;
704 }
705
706
707 static LRESULT
708 HEADER_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
709 {
710     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
711     HDITEM32A   *phdi = (HDITEM32A*)lParam;
712     INT32       nItem = (INT32)wParam;
713     HEADER_ITEM *lpItem;
714     HDC32       hdc;
715     INT32       len;
716
717     if ((phdi == NULL) || (nItem < 0))
718         return -1;
719
720     if (nItem > infoPtr->uNumItem)
721         nItem = infoPtr->uNumItem;
722
723     if (infoPtr->uNumItem == 0) {
724         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
725         infoPtr->uNumItem++;
726     }
727     else {
728         HEADER_ITEM *oldItems = infoPtr->items;
729
730         infoPtr->uNumItem++;
731         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
732         /* pre insert copy */
733         if (nItem > 0) {
734             memcpy (&infoPtr->items[0], &oldItems[0],
735                     nItem * sizeof(HEADER_ITEM));
736         }
737
738         /* post insert copy */
739         if (nItem < infoPtr->uNumItem - 1) {
740             memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
741                     (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
742         }
743
744         COMCTL32_Free (oldItems);
745     }
746
747     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
748     lpItem->bDown = FALSE;
749
750     if (phdi->mask & HDI_WIDTH)
751         lpItem->cxy = phdi->cxy;
752
753     if (phdi->mask & HDI_TEXT) {
754         if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
755             len = lstrlen32A (phdi->pszText);
756             lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
757             lstrcpyAtoW (lpItem->pszText, phdi->pszText);
758         }
759         else
760             lpItem->pszText = LPSTR_TEXTCALLBACK32W;
761     }
762
763     if (phdi->mask & HDI_FORMAT)
764         lpItem->fmt = phdi->fmt;
765
766     if (lpItem->fmt == 0)
767         lpItem->fmt = HDF_LEFT;
768
769     if (phdi->mask & HDI_BITMAP)
770         lpItem->hbm = phdi->hbm;
771
772     if (phdi->mask & HDI_LPARAM)
773         lpItem->lParam = phdi->lParam;
774
775     if (phdi->mask & HDI_IMAGE)
776         lpItem->iImage = phdi->iImage;
777
778     if (phdi->mask & HDI_ORDER)
779         lpItem->iOrder = phdi->iOrder;
780
781     HEADER_SetItemBounds (wndPtr);
782
783     hdc = GetDC32 (wndPtr->hwndSelf);
784     HEADER_Refresh (wndPtr, hdc);
785     ReleaseDC32 (wndPtr->hwndSelf, hdc);
786
787     return nItem;
788 }
789
790
791 static LRESULT
792 HEADER_InsertItem32W (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
793 {
794     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
795     HDITEM32W   *phdi = (HDITEM32W*)lParam;
796     INT32       nItem = (INT32)wParam;
797     HEADER_ITEM *lpItem;
798     HDC32       hdc;
799     INT32       len;
800
801     if ((phdi == NULL) || (nItem < 0))
802         return -1;
803
804     if (nItem > infoPtr->uNumItem)
805         nItem = infoPtr->uNumItem;
806
807     if (infoPtr->uNumItem == 0) {
808         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
809         infoPtr->uNumItem++;
810     }
811     else {
812         HEADER_ITEM *oldItems = infoPtr->items;
813
814         infoPtr->uNumItem++;
815         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
816         /* pre insert copy */
817         if (nItem > 0) {
818             memcpy (&infoPtr->items[0], &oldItems[0],
819                     nItem * sizeof(HEADER_ITEM));
820         }
821
822         /* post insert copy */
823         if (nItem < infoPtr->uNumItem - 1) {
824             memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
825                     (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
826         }
827
828         COMCTL32_Free (oldItems);
829     }
830
831     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
832     lpItem->bDown = FALSE;
833
834     if (phdi->mask & HDI_WIDTH)
835         lpItem->cxy = phdi->cxy;
836
837     if (phdi->mask & HDI_TEXT) {
838         if (phdi->pszText != LPSTR_TEXTCALLBACK32W) {
839             len = lstrlen32W (phdi->pszText);
840             lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
841             lstrcpy32W (lpItem->pszText, phdi->pszText);
842         }
843         else
844             lpItem->pszText = LPSTR_TEXTCALLBACK32W;
845     }
846
847     if (phdi->mask & HDI_FORMAT)
848         lpItem->fmt = phdi->fmt;
849
850     if (lpItem->fmt == 0)
851         lpItem->fmt = HDF_LEFT;
852
853     if (phdi->mask & HDI_BITMAP)
854         lpItem->hbm = phdi->hbm;
855
856     if (phdi->mask & HDI_LPARAM)
857         lpItem->lParam = phdi->lParam;
858
859     if (phdi->mask & HDI_IMAGE)
860         lpItem->iImage = phdi->iImage;
861
862     if (phdi->mask & HDI_ORDER)
863         lpItem->iOrder = phdi->iOrder;
864
865     HEADER_SetItemBounds (wndPtr);
866
867     hdc = GetDC32 (wndPtr->hwndSelf);
868     HEADER_Refresh (wndPtr, hdc);
869     ReleaseDC32 (wndPtr->hwndSelf, hdc);
870
871     return nItem;
872 }
873
874
875 static LRESULT
876 HEADER_Layout (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
877 {
878     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
879     LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam;
880
881     lpLayout->pwpos->hwnd = wndPtr->hwndSelf;
882     lpLayout->pwpos->hwndInsertAfter = 0;
883     lpLayout->pwpos->x = lpLayout->prc->left;
884     lpLayout->pwpos->y = lpLayout->prc->top;
885     lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left;
886     if (wndPtr->dwStyle & HDS_HIDDEN)
887         lpLayout->pwpos->cy = 0;
888     else
889         lpLayout->pwpos->cy = infoPtr->nHeight;
890     lpLayout->pwpos->flags = SWP_NOZORDER;
891
892     TRACE (header, "Layout x=%d y=%d cx=%d cy=%d\n",
893            lpLayout->pwpos->x, lpLayout->pwpos->y,
894            lpLayout->pwpos->cx, lpLayout->pwpos->cy);
895
896     HEADER_ForceItemBounds (wndPtr, lpLayout->pwpos->cy);
897
898     /* hack */
899 #ifdef __HDM_LAYOUT_HACK__
900     MoveWindow32 (lpLayout->pwpos->hwnd, lpLayout->pwpos->x, lpLayout->pwpos->y,
901                   lpLayout->pwpos->cx, lpLayout->pwpos->cy, TRUE);
902 #endif
903
904     return TRUE;
905 }
906
907
908 static LRESULT
909 HEADER_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
910 {
911     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
912     HIMAGELIST himlOld;
913
914     himlOld = infoPtr->himl;
915     infoPtr->himl = (HIMAGELIST)lParam;
916
917     /* FIXME: Refresh needed??? */
918
919     return (LRESULT)himlOld;
920 }
921
922
923 static LRESULT
924 HEADER_SetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
925 {
926     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
927     HDITEM32A *phdi = (HDITEM32A*)lParam;
928     INT32 nItem = (INT32)wParam;
929     HEADER_ITEM *lpItem;
930     HDC32 hdc;
931
932     if (phdi == NULL)
933         return FALSE;
934     if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
935         return FALSE;
936
937     TRACE (header, "[nItem=%d]\n", nItem);
938
939     if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, nItem))
940         return FALSE;
941
942     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
943     if (phdi->mask & HDI_BITMAP)
944         lpItem->hbm = phdi->hbm;
945
946     if (phdi->mask & HDI_FORMAT)
947         lpItem->fmt = phdi->fmt;
948
949     if (phdi->mask & HDI_LPARAM)
950         lpItem->lParam = phdi->lParam;
951
952     if (phdi->mask & HDI_TEXT) {
953         if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
954             if (lpItem->pszText) {
955                 COMCTL32_Free (lpItem->pszText);
956                 lpItem->pszText = NULL;
957             }
958             if (phdi->pszText) {
959                 INT32 len = lstrlen32A (phdi->pszText);
960                 lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
961                 lstrcpyAtoW (lpItem->pszText, phdi->pszText);
962             }
963         }
964         else
965             lpItem->pszText = LPSTR_TEXTCALLBACK32W;
966     }
967
968     if (phdi->mask & HDI_WIDTH)
969         lpItem->cxy = phdi->cxy;
970
971     if (phdi->mask & HDI_IMAGE)
972         lpItem->iImage = phdi->iImage;
973
974     if (phdi->mask & HDI_ORDER)
975         lpItem->iOrder = phdi->iOrder;
976
977     HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, nItem);
978
979     HEADER_SetItemBounds (wndPtr);
980     hdc = GetDC32 (wndPtr->hwndSelf);
981     HEADER_Refresh (wndPtr, hdc);
982     ReleaseDC32 (wndPtr->hwndSelf, hdc);
983
984     return TRUE;
985 }
986
987
988 static LRESULT
989 HEADER_SetItem32W (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
990 {
991     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
992     HDITEM32W *phdi = (HDITEM32W*)lParam;
993     INT32 nItem = (INT32)wParam;
994     HEADER_ITEM *lpItem;
995     HDC32 hdc;
996
997     if (phdi == NULL)
998         return FALSE;
999     if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
1000         return FALSE;
1001
1002     TRACE (header, "[nItem=%d]\n", nItem);
1003
1004     if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, nItem))
1005         return FALSE;
1006
1007     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1008     if (phdi->mask & HDI_BITMAP)
1009         lpItem->hbm = phdi->hbm;
1010
1011     if (phdi->mask & HDI_FORMAT)
1012         lpItem->fmt = phdi->fmt;
1013
1014     if (phdi->mask & HDI_LPARAM)
1015         lpItem->lParam = phdi->lParam;
1016
1017     if (phdi->mask & HDI_TEXT) {
1018         if (phdi->pszText != LPSTR_TEXTCALLBACK32W) {
1019             if (lpItem->pszText) {
1020                 COMCTL32_Free (lpItem->pszText);
1021                 lpItem->pszText = NULL;
1022             }
1023             if (phdi->pszText) {
1024                 INT32 len = lstrlen32W (phdi->pszText);
1025                 lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1026                 lstrcpy32W (lpItem->pszText, phdi->pszText);
1027             }
1028         }
1029         else
1030             lpItem->pszText = LPSTR_TEXTCALLBACK32W;
1031     }
1032
1033     if (phdi->mask & HDI_WIDTH)
1034         lpItem->cxy = phdi->cxy;
1035
1036     if (phdi->mask & HDI_IMAGE)
1037         lpItem->iImage = phdi->iImage;
1038
1039     if (phdi->mask & HDI_ORDER)
1040         lpItem->iOrder = phdi->iOrder;
1041
1042     HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, nItem);
1043
1044     HEADER_SetItemBounds (wndPtr);
1045     hdc = GetDC32 (wndPtr->hwndSelf);
1046     HEADER_Refresh (wndPtr, hdc);
1047     ReleaseDC32 (wndPtr->hwndSelf, hdc);
1048
1049     return TRUE;
1050 }
1051
1052
1053 /* << HEADER_SetOrderArray >> */
1054
1055
1056 __inline__ static LRESULT
1057 HEADER_SetUnicodeFormat (WND *wndPtr, WPARAM32 wParam)
1058 {
1059     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1060     BOOL32 bTemp = infoPtr->bUnicode;
1061
1062     infoPtr->bUnicode = (BOOL32)wParam;
1063
1064     return bTemp;
1065 }
1066
1067
1068 static LRESULT
1069 HEADER_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1070 {
1071     HEADER_INFO *infoPtr;
1072     TEXTMETRIC32A tm;
1073     HFONT32 hOldFont;
1074     HDC32   hdc;
1075
1076     infoPtr = (HEADER_INFO *)COMCTL32_Alloc (sizeof(HEADER_INFO));
1077     wndPtr->wExtra[0] = (DWORD)infoPtr;
1078
1079     infoPtr->uNumItem = 0;
1080     infoPtr->nHeight = 20;
1081     infoPtr->hFont = 0;
1082     infoPtr->items = 0;
1083     infoPtr->hcurArrow = LoadCursor32A (0, IDC_ARROW32A);
1084     infoPtr->hcurDivider = LoadCursor32A (0, IDC_SIZEWE32A);
1085     infoPtr->hcurDivopen = LoadCursor32A (0, IDC_SIZENS32A);
1086     infoPtr->bPressed  = FALSE;
1087     infoPtr->bTracking = FALSE;
1088     infoPtr->iMoveItem = 0;
1089     infoPtr->himl = 0;
1090     infoPtr->iHotItem = -1;
1091     infoPtr->bUnicode = IsWindowUnicode (wndPtr->hwndSelf);
1092
1093     hdc = GetDC32 (0);
1094     hOldFont = SelectObject32 (hdc, GetStockObject32 (SYSTEM_FONT));
1095     GetTextMetrics32A (hdc, &tm);
1096     infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1097     SelectObject32 (hdc, hOldFont);
1098     ReleaseDC32 (0, hdc);
1099
1100     return 0;
1101 }
1102
1103
1104 static LRESULT
1105 HEADER_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1106 {
1107     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1108     HEADER_ITEM *lpItem;
1109     INT32 nItem;
1110
1111     if (infoPtr->items) {
1112         lpItem = (HEADER_ITEM*)infoPtr->items;
1113         for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
1114             if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32W))
1115                 COMCTL32_Free (lpItem->pszText);
1116         }
1117         COMCTL32_Free (infoPtr->items);
1118     }
1119
1120     if (infoPtr->himl)
1121         ImageList_Destroy (infoPtr->himl);
1122
1123     COMCTL32_Free (infoPtr);
1124
1125     return 0;
1126 }
1127
1128
1129 static __inline__ LRESULT
1130 HEADER_GetFont (WND *wndPtr)
1131 {
1132     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1133
1134     return (LRESULT)infoPtr->hFont;
1135 }
1136
1137
1138 static LRESULT
1139 HEADER_LButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1140 {
1141     POINT32 pt;
1142     UINT32  flags;
1143     INT32   nItem;
1144
1145     pt.x = (INT32)LOWORD(lParam); 
1146     pt.y = (INT32)HIWORD(lParam);
1147     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1148
1149     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1150         HEADER_SendHeaderNotify (wndPtr, HDN_ITEMDBLCLICK32A, nItem);
1151     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1152         HEADER_SendHeaderNotify (wndPtr, HDN_DIVIDERDBLCLICK32A, nItem);
1153
1154     return 0;
1155 }
1156
1157
1158 static LRESULT
1159 HEADER_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1160 {
1161     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1162     POINT32 pt;
1163     UINT32  flags;
1164     INT32   nItem;
1165     HDC32   hdc;
1166
1167     pt.x = (INT32)LOWORD(lParam); 
1168     pt.y = (INT32)HIWORD(lParam);
1169     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1170
1171     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER)) {
1172         SetCapture32 (wndPtr->hwndSelf);
1173         infoPtr->bCaptured = TRUE;   
1174         infoPtr->bPressed  = TRUE;
1175         infoPtr->iMoveItem = nItem;
1176
1177         infoPtr->items[nItem].bDown = TRUE;
1178
1179         /* Send WM_CUSTOMDRAW */
1180         hdc = GetDC32 (wndPtr->hwndSelf);
1181         HEADER_RefreshItem (wndPtr, hdc, nItem);
1182         ReleaseDC32 (wndPtr->hwndSelf, hdc);
1183
1184         TRACE (header, "Pressed item %d!\n", nItem);
1185     } 
1186     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) {
1187         if (!(HEADER_SendHeaderNotify (wndPtr, HDN_BEGINTRACK32A, nItem))) {
1188             SetCapture32 (wndPtr->hwndSelf);
1189             infoPtr->bCaptured = TRUE;   
1190             infoPtr->bTracking = TRUE;
1191             infoPtr->iMoveItem = nItem;
1192             infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
1193             infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
1194
1195             if (!(wndPtr->dwStyle & HDS_FULLDRAG)) {
1196                 infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
1197                 hdc = GetDC32 (wndPtr->hwndSelf);
1198                 HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1199                 ReleaseDC32 (wndPtr->hwndSelf, hdc);
1200             }
1201
1202             TRACE (header, "Begin tracking item %d!\n", nItem);
1203         }
1204     }
1205
1206     return 0;
1207 }
1208
1209
1210 static LRESULT
1211 HEADER_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1212 {
1213     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1214     POINT32 pt;
1215     UINT32  flags;
1216     INT32   nItem, nWidth;
1217     HDC32   hdc;
1218
1219     pt.x = (INT32)LOWORD(lParam);
1220     pt.y = (INT32)HIWORD(lParam);
1221     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1222
1223     if (infoPtr->bPressed) {
1224         if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
1225             infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1226             hdc = GetDC32 (wndPtr->hwndSelf);
1227             HEADER_RefreshItem (wndPtr, hdc, infoPtr->iMoveItem);
1228             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1229
1230             HEADER_SendClickNotify (wndPtr, HDN_ITEMCLICK32A, infoPtr->iMoveItem);
1231         }
1232         TRACE (header, "Released item %d!\n", infoPtr->iMoveItem);
1233         infoPtr->bPressed = FALSE;
1234     }
1235     else if (infoPtr->bTracking) {
1236         TRACE (header, "End tracking item %d!\n", infoPtr->iMoveItem);
1237         infoPtr->bTracking = FALSE;
1238
1239         HEADER_SendHeaderNotify (wndPtr, HDN_ENDTRACK32A, infoPtr->iMoveItem);
1240
1241         if (!(wndPtr->dwStyle & HDS_FULLDRAG)) {
1242             hdc = GetDC32 (wndPtr->hwndSelf);
1243             HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1244             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1245             if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
1246                 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1247             else {
1248                 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1249                 if (nWidth < 0)
1250                     nWidth = 0;
1251                 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1252                 HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, infoPtr->iMoveItem);
1253             }
1254
1255             HEADER_SetItemBounds (wndPtr);
1256             hdc = GetDC32 (wndPtr->hwndSelf);
1257             HEADER_Refresh (wndPtr, hdc);
1258             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1259         }
1260     }
1261
1262     if (infoPtr->bCaptured) {
1263         infoPtr->bCaptured = FALSE;
1264         ReleaseCapture ();
1265         HEADER_SendSimpleNotify (wndPtr, NM_RELEASEDCAPTURE);
1266     }
1267
1268     return 0;
1269 }
1270
1271
1272 static LRESULT
1273 HEADER_MouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1274 {
1275     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1276     POINT32 pt;
1277     UINT32  flags;
1278     INT32   nItem, nWidth;
1279     HDC32   hdc;
1280
1281     pt.x = (INT32)LOWORD(lParam);
1282     pt.y = (INT32)HIWORD(lParam);
1283     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1284
1285     if ((wndPtr->dwStyle & HDS_BUTTONS) && (wndPtr->dwStyle & HDS_HOTTRACK)) {
1286         if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
1287             infoPtr->iHotItem = nItem;
1288         else
1289             infoPtr->iHotItem = -1;
1290         hdc = GetDC32 (wndPtr->hwndSelf);
1291         HEADER_Refresh (wndPtr, hdc);
1292         ReleaseDC32 (wndPtr->hwndSelf, hdc);
1293     }
1294
1295     if (infoPtr->bCaptured) {
1296         if (infoPtr->bPressed) {
1297             if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
1298                 infoPtr->items[infoPtr->iMoveItem].bDown = TRUE;
1299             else
1300                 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1301             hdc = GetDC32 (wndPtr->hwndSelf);
1302             HEADER_RefreshItem (wndPtr, hdc, infoPtr->iMoveItem);
1303             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1304
1305             TRACE (header, "Moving pressed item %d!\n", infoPtr->iMoveItem);
1306         }
1307         else if (infoPtr->bTracking) {
1308             if (wndPtr->dwStyle & HDS_FULLDRAG) {
1309                 if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
1310                     infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1311                 else {
1312                     nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1313                     if (nWidth < 0)
1314                         nWidth = 0;
1315                     infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1316                     HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A,
1317                                              infoPtr->iMoveItem);
1318                 }
1319                 HEADER_SetItemBounds (wndPtr);
1320                 hdc = GetDC32 (wndPtr->hwndSelf);
1321                 HEADER_Refresh (wndPtr, hdc);
1322                 ReleaseDC32 (wndPtr->hwndSelf, hdc);
1323             }
1324             else {
1325                 hdc = GetDC32 (wndPtr->hwndSelf);
1326                 HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1327                 infoPtr->xOldTrack = pt.x + infoPtr->xTrackOffset;
1328                 if (infoPtr->xOldTrack < infoPtr->items[infoPtr->iMoveItem].rect.left)
1329                     infoPtr->xOldTrack = infoPtr->items[infoPtr->iMoveItem].rect.left;
1330                 infoPtr->items[infoPtr->iMoveItem].cxy = 
1331                     infoPtr->xOldTrack - infoPtr->items[infoPtr->iMoveItem].rect.left;
1332                 HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1333                 ReleaseDC32 (wndPtr->hwndSelf, hdc);
1334             }
1335
1336             HEADER_SendHeaderNotify (wndPtr, HDN_TRACK32A, infoPtr->iMoveItem);
1337             TRACE (header, "Tracking item %d!\n", infoPtr->iMoveItem);
1338         }
1339     }
1340
1341     if ((wndPtr->dwStyle & HDS_BUTTONS) && (wndPtr->dwStyle & HDS_HOTTRACK)) {
1342         FIXME (header, "hot track support!\n");
1343     }
1344
1345     return 0;
1346 }
1347
1348
1349 static LRESULT
1350 HEADER_Paint (WND *wndPtr, WPARAM32 wParam)
1351 {
1352     HDC32 hdc;
1353     PAINTSTRUCT32 ps;
1354
1355     hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
1356     HEADER_Refresh (wndPtr, hdc);
1357     if(!wParam)
1358         EndPaint32 (wndPtr->hwndSelf, &ps);
1359     return 0;
1360 }
1361
1362
1363 static LRESULT
1364 HEADER_RButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1365 {
1366     return HEADER_SendSimpleNotify (wndPtr, NM_RCLICK);
1367 }
1368
1369
1370 static LRESULT
1371 HEADER_SetCursor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1372 {
1373     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1374     POINT32 pt;
1375     UINT32  flags;
1376     INT32   nItem;
1377
1378     TRACE (header, "code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
1379
1380     GetCursorPos32 (&pt);
1381     ScreenToClient32 (wndPtr->hwndSelf, &pt);
1382
1383     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1384
1385     if (flags == HHT_ONDIVIDER)
1386         SetCursor32 (infoPtr->hcurDivider);
1387     else if (flags == HHT_ONDIVOPEN)
1388         SetCursor32 (infoPtr->hcurDivopen);
1389     else
1390         SetCursor32 (infoPtr->hcurArrow);
1391
1392     return 0;
1393 }
1394
1395
1396 static LRESULT
1397 HEADER_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1398 {
1399     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1400     TEXTMETRIC32A tm;
1401     HFONT32 hFont, hOldFont;
1402     HDC32 hdc;
1403
1404     infoPtr->hFont = (HFONT32)wParam;
1405
1406     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
1407
1408     hdc = GetDC32 (0);
1409     hOldFont = SelectObject32 (hdc, hFont);
1410     GetTextMetrics32A (hdc, &tm);
1411     infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1412     SelectObject32 (hdc, hOldFont);
1413     ReleaseDC32 (0, hdc);
1414
1415     if (lParam) {
1416         HEADER_ForceItemBounds (wndPtr, infoPtr->nHeight);
1417         hdc = GetDC32 (wndPtr->hwndSelf);
1418         HEADER_Refresh (wndPtr, hdc);
1419         ReleaseDC32 (wndPtr->hwndSelf, hdc);
1420     }
1421
1422     return 0;
1423 }
1424
1425
1426 LRESULT WINAPI
1427 HEADER_WindowProc (HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
1428 {
1429     WND *wndPtr = WIN_FindWndPtr(hwnd);
1430
1431     switch (msg) {
1432         case HDM_CREATEDRAGIMAGE:
1433             return HEADER_CreateDragImage (wndPtr, wParam);
1434
1435         case HDM_DELETEITEM:
1436             return HEADER_DeleteItem (wndPtr, wParam);
1437
1438         case HDM_GETIMAGELIST:
1439             return HEADER_GetImageList (wndPtr);
1440
1441         case HDM_GETITEM32A:
1442             return HEADER_GetItem32A (wndPtr, wParam, lParam);
1443
1444         case HDM_GETITEM32W:
1445             return HEADER_GetItem32W (wndPtr, wParam, lParam);
1446
1447         case HDM_GETITEMCOUNT:
1448             return HEADER_GetItemCount (wndPtr);
1449
1450         case HDM_GETITEMRECT:
1451             return HEADER_GetItemRect (wndPtr, wParam, lParam);
1452
1453 /*      case HDM_GETORDERARRAY: */
1454
1455         case HDM_GETUNICODEFORMAT:
1456             return HEADER_GetUnicodeFormat (wndPtr);
1457
1458         case HDM_HITTEST:
1459             return HEADER_HitTest (wndPtr, wParam, lParam);
1460
1461         case HDM_INSERTITEM32A:
1462             return HEADER_InsertItem32A (wndPtr, wParam, lParam);
1463
1464         case HDM_INSERTITEM32W:
1465             return HEADER_InsertItem32W (wndPtr, wParam, lParam);
1466
1467         case HDM_LAYOUT:
1468             return HEADER_Layout (wndPtr, wParam, lParam);
1469
1470         case HDM_SETIMAGELIST:
1471             return HEADER_SetImageList (wndPtr, wParam, lParam);
1472
1473         case HDM_SETITEM32A:
1474             return HEADER_SetItem32A (wndPtr, wParam, lParam);
1475
1476         case HDM_SETITEM32W:
1477             return HEADER_SetItem32W (wndPtr, wParam, lParam);
1478
1479 /*      case HDM_SETORDERARRAY: */
1480
1481         case HDM_SETUNICODEFORMAT:
1482             return HEADER_SetUnicodeFormat (wndPtr, wParam);
1483
1484
1485         case WM_CREATE:
1486             return HEADER_Create (wndPtr, wParam, lParam);
1487
1488         case WM_DESTROY:
1489             return HEADER_Destroy (wndPtr, wParam, lParam);
1490
1491         case WM_ERASEBKGND:
1492             return 1;
1493
1494         case WM_GETDLGCODE:
1495             return DLGC_WANTTAB | DLGC_WANTARROWS;
1496
1497         case WM_GETFONT:
1498             return HEADER_GetFont (wndPtr);
1499
1500         case WM_LBUTTONDBLCLK:
1501             return HEADER_LButtonDblClk (wndPtr, wParam, lParam);
1502
1503         case WM_LBUTTONDOWN:
1504             return HEADER_LButtonDown (wndPtr, wParam, lParam);
1505
1506         case WM_LBUTTONUP:
1507             return HEADER_LButtonUp (wndPtr, wParam, lParam);
1508
1509         case WM_MOUSEMOVE:
1510             return HEADER_MouseMove (wndPtr, wParam, lParam);
1511
1512 /*      case WM_NOTIFYFORMAT: */
1513
1514         case WM_PAINT:
1515             return HEADER_Paint (wndPtr, wParam);
1516
1517         case WM_RBUTTONUP:
1518             return HEADER_RButtonUp (wndPtr, wParam, lParam);
1519
1520         case WM_SETCURSOR:
1521             return HEADER_SetCursor (wndPtr, wParam, lParam);
1522
1523         case WM_SETFONT:
1524             return HEADER_SetFont (wndPtr, wParam, lParam);
1525
1526         default:
1527             if (msg >= WM_USER) 
1528                 ERR (header, "unknown msg %04x wp=%04x lp=%08lx\n",
1529                      msg, wParam, lParam );
1530             return DefWindowProc32A (hwnd, msg, wParam, lParam);
1531     }
1532     return 0;
1533 }
1534
1535
1536 VOID
1537 HEADER_Register (VOID)
1538 {
1539     WNDCLASS32A wndClass;
1540
1541     if (GlobalFindAtom32A (WC_HEADER32A)) return;
1542
1543     ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
1544     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
1545     wndClass.lpfnWndProc   = (WNDPROC32)HEADER_WindowProc;
1546     wndClass.cbClsExtra    = 0;
1547     wndClass.cbWndExtra    = sizeof(HEADER_INFO *);
1548     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
1549     wndClass.lpszClassName = WC_HEADER32A;
1550  
1551     RegisterClass32A (&wndClass);
1552 }
1553
1554
1555 VOID
1556 HEADER_Unregister (VOID)
1557 {
1558     if (GlobalFindAtom32A (WC_HEADER32A))
1559         UnregisterClass32A (WC_HEADER32A, (HINSTANCE32)NULL);
1560 }
1561