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