Fixes for FreeBSD.
[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             DrawText32A(hdc, phdi->pszText, lstrlen32A(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             DrawText32A(hdc, phdi->pszText, lstrlen32A(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_TEXTCALLBACK32A)
595             lstrcpyn32A (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_GetItemCount (WND *wndPtr)
612 {
613     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
614
615     return (infoPtr->uNumItem);
616 }
617
618
619 static LRESULT
620 HEADER_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
621 {
622     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
623     INT32 iItem = (INT32)wParam;
624     LPRECT32 lpRect = (LPRECT32)lParam;
625
626     if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
627         return FALSE;
628
629     lpRect->left   = infoPtr->items[iItem].rect.left;
630     lpRect->right  = infoPtr->items[iItem].rect.right;
631     lpRect->top    = infoPtr->items[iItem].rect.top;
632     lpRect->bottom = infoPtr->items[iItem].rect.bottom;
633
634     return TRUE;
635 }
636
637
638 static LRESULT
639 HEADER_HitTest (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
640 {
641     LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam;
642
643     HEADER_InternalHitTest (wndPtr, &phti->pt, &phti->flags, &phti->iItem);
644
645     return phti->flags;
646 }
647
648
649 static LRESULT
650 HEADER_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
651 {
652     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
653     HDITEM32A   *phdi = (HDITEM32A*)lParam;
654     INT32       nItem = (INT32)wParam;
655     HEADER_ITEM *lpItem;
656     HDC32       hdc;
657     INT32       len;
658
659     if ((phdi == NULL) || (nItem < 0))
660         return -1;
661
662     if (nItem > infoPtr->uNumItem)
663         nItem = infoPtr->uNumItem;
664
665     if (infoPtr->uNumItem == 0) {
666         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
667         infoPtr->uNumItem++;
668     }
669     else {
670         HEADER_ITEM *oldItems = infoPtr->items;
671
672         infoPtr->uNumItem++;
673         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
674         /* pre insert copy */
675         if (nItem > 0) {
676             memcpy (&infoPtr->items[0], &oldItems[0],
677                     nItem * sizeof(HEADER_ITEM));
678         }
679
680         /* post insert copy */
681         if (nItem < infoPtr->uNumItem - 1) {
682             memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
683                     (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
684         }
685
686         COMCTL32_Free (oldItems);
687     }
688
689     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
690     lpItem->bDown = FALSE;
691
692     if (phdi->mask & HDI_WIDTH)
693         lpItem->cxy = phdi->cxy;
694
695     if (phdi->mask & HDI_TEXT) {
696         if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
697             len = lstrlen32A (phdi->pszText);
698             lpItem->pszText = COMCTL32_Alloc (len+1);
699             lstrcpy32A (lpItem->pszText, phdi->pszText);
700         }
701         else
702             lpItem->pszText = LPSTR_TEXTCALLBACK32A;
703     }
704
705     if (phdi->mask & HDI_FORMAT)
706         lpItem->fmt = phdi->fmt;
707
708     if (lpItem->fmt == 0)
709         lpItem->fmt = HDF_LEFT;
710
711     if (phdi->mask & HDI_BITMAP)
712         lpItem->hbm = phdi->hbm;
713
714     if (phdi->mask & HDI_LPARAM)
715         lpItem->lParam = phdi->lParam;
716
717     if (phdi->mask & HDI_IMAGE)
718         lpItem->iImage = phdi->iImage;
719
720     if (phdi->mask & HDI_ORDER)
721         lpItem->iOrder = phdi->iOrder;
722
723     HEADER_SetItemBounds (wndPtr);
724
725     hdc = GetDC32 (wndPtr->hwndSelf);
726     HEADER_Refresh (wndPtr, hdc);
727     ReleaseDC32 (wndPtr->hwndSelf, hdc);
728
729     return nItem;
730 }
731
732
733 static LRESULT
734 HEADER_Layout (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
735 {
736     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
737     LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam;
738
739     lpLayout->pwpos->hwnd = wndPtr->hwndSelf;
740     lpLayout->pwpos->hwndInsertAfter = 0;
741     lpLayout->pwpos->x = lpLayout->prc->left;
742     lpLayout->pwpos->y = lpLayout->prc->top;
743     lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left;
744     if (wndPtr->dwStyle & HDS_HIDDEN)
745         lpLayout->pwpos->cy = 0;
746     else
747         lpLayout->pwpos->cy = infoPtr->nHeight;
748     lpLayout->pwpos->flags = SWP_NOZORDER;
749
750     TRACE (header, "Layout x=%d y=%d cx=%d cy=%d\n",
751            lpLayout->pwpos->x, lpLayout->pwpos->y,
752            lpLayout->pwpos->cx, lpLayout->pwpos->cy);
753
754     HEADER_ForceItemBounds (wndPtr, lpLayout->pwpos->cy);
755
756     /* hack */
757 #ifdef __HDM_LAYOUT_HACK__
758     MoveWindow32 (lpLayout->pwpos->hwnd, lpLayout->pwpos->x, lpLayout->pwpos->y,
759                   lpLayout->pwpos->cx, lpLayout->pwpos->cy, TRUE);
760 #endif
761
762     return TRUE;
763 }
764
765
766 static LRESULT
767 HEADER_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
768 {
769     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
770     HIMAGELIST himlOld;
771
772     himlOld = infoPtr->himl;
773     infoPtr->himl = (HIMAGELIST)lParam;
774
775     /* FIXME: Refresh needed??? */
776
777     return (LRESULT)himlOld;
778 }
779
780
781 static LRESULT
782 HEADER_SetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
783 {
784     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
785     HDITEM32A *phdi = (HDITEM32A*)lParam;
786     INT32 nItem = (INT32)wParam;
787     HEADER_ITEM *lpItem;
788     HDC32 hdc;
789
790     if (phdi == NULL)
791         return FALSE;
792     if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
793         return FALSE;
794
795     TRACE (header, "[nItem=%d]\n", nItem);
796
797     if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, nItem))
798         return FALSE;
799
800     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
801     if (phdi->mask & HDI_BITMAP)
802         lpItem->hbm = phdi->hbm;
803
804     if (phdi->mask & HDI_FORMAT)
805         lpItem->fmt = phdi->fmt;
806
807     if (phdi->mask & HDI_LPARAM)
808         lpItem->lParam = phdi->lParam;
809
810     if (phdi->mask & HDI_TEXT) {
811         if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
812             INT32 len = lstrlen32A (phdi->pszText);
813             if (lpItem->pszText)
814                 COMCTL32_Free (lpItem->pszText);
815             lpItem->pszText = COMCTL32_Alloc (len+1);
816             lstrcpy32A (lpItem->pszText, phdi->pszText);
817         }
818         else
819             lpItem->pszText = LPSTR_TEXTCALLBACK32A;
820     }
821
822     if (phdi->mask & HDI_WIDTH)
823         lpItem->cxy = phdi->cxy;
824
825     if (phdi->mask & HDI_IMAGE)
826         lpItem->iImage = phdi->iImage;
827
828     if (phdi->mask & HDI_ORDER)
829         lpItem->iOrder = phdi->iOrder;
830
831     HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, nItem);
832
833     HEADER_SetItemBounds (wndPtr);
834     hdc = GetDC32 (wndPtr->hwndSelf);
835     HEADER_Refresh (wndPtr, hdc);
836     ReleaseDC32 (wndPtr->hwndSelf, hdc);
837
838     return TRUE;
839 }
840
841
842 static LRESULT
843 HEADER_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
844 {
845     HEADER_INFO *infoPtr;
846     TEXTMETRIC32A tm;
847     HFONT32 hOldFont;
848     HDC32   hdc;
849
850     infoPtr = (HEADER_INFO *)COMCTL32_Alloc (sizeof(HEADER_INFO));
851     wndPtr->wExtra[0] = (DWORD)infoPtr;
852
853     infoPtr->uNumItem = 0;
854     infoPtr->nHeight = 20;
855     infoPtr->hFont = 0;
856     infoPtr->items = 0;
857     infoPtr->hcurArrow = LoadCursor32A (0, IDC_ARROW32A);
858     infoPtr->hcurDivider = LoadCursor32A (0, IDC_SIZEWE32A);
859     infoPtr->hcurDivopen = LoadCursor32A (0, IDC_SIZENS32A);
860     infoPtr->bPressed  = FALSE;
861     infoPtr->bTracking = FALSE;
862     infoPtr->iMoveItem = 0;
863     infoPtr->himl = 0;
864     infoPtr->iHotItem = -1;
865
866     hdc = GetDC32 (0);
867     hOldFont = SelectObject32 (hdc, GetStockObject32 (SYSTEM_FONT));
868     GetTextMetrics32A (hdc, &tm);
869     infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
870     SelectObject32 (hdc, hOldFont);
871     ReleaseDC32 (0, hdc);
872
873     return 0;
874 }
875
876
877 static LRESULT
878 HEADER_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
879 {
880     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
881     HEADER_ITEM *lpItem;
882     INT32 nItem;
883
884     if (infoPtr->items) {
885         lpItem = (HEADER_ITEM*)infoPtr->items;
886         for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
887             if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
888                 COMCTL32_Free (lpItem->pszText);
889         }
890         COMCTL32_Free (infoPtr->items);
891     }
892
893     if (infoPtr->himl)
894         ImageList_Destroy (infoPtr->himl);
895
896     COMCTL32_Free (infoPtr);
897
898     return 0;
899 }
900
901
902 static __inline__ LRESULT
903 HEADER_GetFont (WND *wndPtr)
904 {
905     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
906
907     return (LRESULT)infoPtr->hFont;
908 }
909
910
911 static LRESULT
912 HEADER_LButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
913 {
914     POINT32 pt;
915     UINT32  flags;
916     INT32   nItem;
917
918     pt.x = (INT32)LOWORD(lParam); 
919     pt.y = (INT32)HIWORD(lParam);
920     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
921
922     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
923         HEADER_SendHeaderNotify (wndPtr, HDN_ITEMDBLCLICK32A, nItem);
924     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
925         HEADER_SendHeaderNotify (wndPtr, HDN_DIVIDERDBLCLICK32A, nItem);
926
927     return 0;
928 }
929
930
931 static LRESULT
932 HEADER_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
933 {
934     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
935     POINT32 pt;
936     UINT32  flags;
937     INT32   nItem;
938     HDC32   hdc;
939
940     pt.x = (INT32)LOWORD(lParam); 
941     pt.y = (INT32)HIWORD(lParam);
942     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
943
944     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER)) {
945         SetCapture32 (wndPtr->hwndSelf);
946         infoPtr->bCaptured = TRUE;   
947         infoPtr->bPressed  = TRUE;
948         infoPtr->iMoveItem = nItem;
949
950         infoPtr->items[nItem].bDown = TRUE;
951
952         /* Send WM_CUSTOMDRAW */
953         hdc = GetDC32 (wndPtr->hwndSelf);
954         HEADER_RefreshItem (wndPtr, hdc, nItem);
955         ReleaseDC32 (wndPtr->hwndSelf, hdc);
956
957         TRACE (header, "Pressed item %d!\n", nItem);
958     } 
959     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) {
960         if (!(HEADER_SendHeaderNotify (wndPtr, HDN_BEGINTRACK32A, nItem))) {
961             SetCapture32 (wndPtr->hwndSelf);
962             infoPtr->bCaptured = TRUE;   
963             infoPtr->bTracking = TRUE;
964             infoPtr->iMoveItem = nItem;
965             infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
966             infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
967
968             if (!(wndPtr->dwStyle & HDS_FULLDRAG)) {
969                 infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
970                 hdc = GetDC32 (wndPtr->hwndSelf);
971                 HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
972                 ReleaseDC32 (wndPtr->hwndSelf, hdc);
973             }
974
975             TRACE (header, "Begin tracking item %d!\n", nItem);
976         }
977     }
978
979     return 0;
980 }
981
982
983 static LRESULT
984 HEADER_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
985 {
986     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
987     POINT32 pt;
988     UINT32  flags;
989     INT32   nItem, nWidth;
990     HDC32   hdc;
991
992     pt.x = (INT32)LOWORD(lParam);
993     pt.y = (INT32)HIWORD(lParam);
994     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
995
996     if (infoPtr->bPressed) {
997         if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
998             infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
999             hdc = GetDC32 (wndPtr->hwndSelf);
1000             HEADER_RefreshItem (wndPtr, hdc, infoPtr->iMoveItem);
1001             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1002
1003             HEADER_SendClickNotify (wndPtr, HDN_ITEMCLICK32A, infoPtr->iMoveItem);
1004         }
1005         TRACE (header, "Released item %d!\n", infoPtr->iMoveItem);
1006         infoPtr->bPressed = FALSE;
1007     }
1008     else if (infoPtr->bTracking) {
1009         TRACE (header, "End tracking item %d!\n", infoPtr->iMoveItem);
1010         infoPtr->bTracking = FALSE;
1011
1012         HEADER_SendHeaderNotify (wndPtr, HDN_ENDTRACK32A, infoPtr->iMoveItem);
1013
1014         if (!(wndPtr->dwStyle & HDS_FULLDRAG)) {
1015             hdc = GetDC32 (wndPtr->hwndSelf);
1016             HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1017             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1018             if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
1019                 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1020             else {
1021                 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1022                 if (nWidth < 0)
1023                     nWidth = 0;
1024                 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1025                 HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, infoPtr->iMoveItem);
1026             }
1027
1028             HEADER_SetItemBounds (wndPtr);
1029             hdc = GetDC32 (wndPtr->hwndSelf);
1030             HEADER_Refresh (wndPtr, hdc);
1031             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1032         }
1033     }
1034
1035     if (infoPtr->bCaptured) {
1036         infoPtr->bCaptured = FALSE;
1037         ReleaseCapture ();
1038         HEADER_SendSimpleNotify (wndPtr, NM_RELEASEDCAPTURE);
1039     }
1040
1041     return 0;
1042 }
1043
1044
1045 static LRESULT
1046 HEADER_MouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1047 {
1048     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1049     POINT32 pt;
1050     UINT32  flags;
1051     INT32   nItem, nWidth;
1052     HDC32   hdc;
1053
1054     pt.x = (INT32)LOWORD(lParam);
1055     pt.y = (INT32)HIWORD(lParam);
1056     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1057
1058     if ((wndPtr->dwStyle & HDS_BUTTONS) && (wndPtr->dwStyle & HDS_HOTTRACK)) {
1059         if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
1060             infoPtr->iHotItem = nItem;
1061         else
1062             infoPtr->iHotItem = -1;
1063         hdc = GetDC32 (wndPtr->hwndSelf);
1064         HEADER_Refresh (wndPtr, hdc);
1065         ReleaseDC32 (wndPtr->hwndSelf, hdc);
1066     }
1067
1068     if (infoPtr->bCaptured) {
1069         if (infoPtr->bPressed) {
1070             if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
1071                 infoPtr->items[infoPtr->iMoveItem].bDown = TRUE;
1072             else
1073                 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1074             hdc = GetDC32 (wndPtr->hwndSelf);
1075             HEADER_RefreshItem (wndPtr, hdc, infoPtr->iMoveItem);
1076             ReleaseDC32 (wndPtr->hwndSelf, hdc);
1077
1078             TRACE (header, "Moving pressed item %d!\n", infoPtr->iMoveItem);
1079         }
1080         else if (infoPtr->bTracking) {
1081             if (wndPtr->dwStyle & HDS_FULLDRAG) {
1082                 if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
1083                     infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1084                 else {
1085                     nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1086                     if (nWidth < 0)
1087                         nWidth = 0;
1088                     infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1089                     HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A,
1090                                              infoPtr->iMoveItem);
1091                 }
1092                 HEADER_SetItemBounds (wndPtr);
1093                 hdc = GetDC32 (wndPtr->hwndSelf);
1094                 HEADER_Refresh (wndPtr, hdc);
1095                 ReleaseDC32 (wndPtr->hwndSelf, hdc);
1096             }
1097             else {
1098                 hdc = GetDC32 (wndPtr->hwndSelf);
1099                 HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1100                 infoPtr->xOldTrack = pt.x + infoPtr->xTrackOffset;
1101                 if (infoPtr->xOldTrack < infoPtr->items[infoPtr->iMoveItem].rect.left)
1102                     infoPtr->xOldTrack = infoPtr->items[infoPtr->iMoveItem].rect.left;
1103                 infoPtr->items[infoPtr->iMoveItem].cxy = 
1104                     infoPtr->xOldTrack - infoPtr->items[infoPtr->iMoveItem].rect.left;
1105                 HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
1106                 ReleaseDC32 (wndPtr->hwndSelf, hdc);
1107             }
1108
1109             HEADER_SendHeaderNotify (wndPtr, HDN_TRACK32A, infoPtr->iMoveItem);
1110             TRACE (header, "Tracking item %d!\n", infoPtr->iMoveItem);
1111         }
1112     }
1113
1114     if ((wndPtr->dwStyle & HDS_BUTTONS) && (wndPtr->dwStyle & HDS_HOTTRACK)) {
1115         FIXME (header, "hot track support!\n");
1116     }
1117
1118     return 0;
1119 }
1120
1121
1122 static LRESULT
1123 HEADER_Paint (WND *wndPtr, WPARAM32 wParam)
1124 {
1125     HDC32 hdc;
1126     PAINTSTRUCT32 ps;
1127
1128     hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
1129     HEADER_Refresh (wndPtr, hdc);
1130     if(!wParam)
1131         EndPaint32 (wndPtr->hwndSelf, &ps);
1132     return 0;
1133 }
1134
1135
1136 static LRESULT
1137 HEADER_RButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1138 {
1139     return HEADER_SendSimpleNotify (wndPtr, NM_RCLICK);
1140 }
1141
1142
1143 static LRESULT
1144 HEADER_SetCursor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1145 {
1146     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1147     POINT32 pt;
1148     UINT32  flags;
1149     INT32   nItem;
1150
1151     TRACE (header, "code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
1152
1153     GetCursorPos32 (&pt);
1154     ScreenToClient32 (wndPtr->hwndSelf, &pt);
1155
1156     HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
1157
1158     if (flags == HHT_ONDIVIDER)
1159         SetCursor32 (infoPtr->hcurDivider);
1160     else if (flags == HHT_ONDIVOPEN)
1161         SetCursor32 (infoPtr->hcurDivopen);
1162     else
1163         SetCursor32 (infoPtr->hcurArrow);
1164
1165     return 0;
1166 }
1167
1168
1169 static LRESULT
1170 HEADER_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1171 {
1172     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
1173     TEXTMETRIC32A tm;
1174     HFONT32 hFont, hOldFont;
1175     HDC32 hdc;
1176
1177     infoPtr->hFont = (HFONT32)wParam;
1178
1179     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
1180
1181     hdc = GetDC32 (0);
1182     hOldFont = SelectObject32 (hdc, hFont);
1183     GetTextMetrics32A (hdc, &tm);
1184     infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1185     SelectObject32 (hdc, hOldFont);
1186     ReleaseDC32 (0, hdc);
1187
1188     if (lParam) {
1189         HEADER_ForceItemBounds (wndPtr, infoPtr->nHeight);
1190         hdc = GetDC32 (wndPtr->hwndSelf);
1191         HEADER_Refresh (wndPtr, hdc);
1192         ReleaseDC32 (wndPtr->hwndSelf, hdc);
1193     }
1194
1195     return 0;
1196 }
1197
1198
1199 LRESULT WINAPI
1200 HEADER_WindowProc (HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
1201 {
1202     WND *wndPtr = WIN_FindWndPtr(hwnd);
1203
1204     switch (msg) {
1205         case HDM_CREATEDRAGIMAGE:
1206             return HEADER_CreateDragImage (wndPtr, wParam);
1207
1208         case HDM_DELETEITEM:
1209             return HEADER_DeleteItem (wndPtr, wParam);
1210
1211         case HDM_GETIMAGELIST:
1212             return HEADER_GetImageList (wndPtr);
1213
1214         case HDM_GETITEM32A:
1215             return HEADER_GetItem32A (wndPtr, wParam, lParam);
1216
1217 //      case HDM_GETITEM32W:
1218
1219         case HDM_GETITEMCOUNT:
1220             return HEADER_GetItemCount (wndPtr);
1221
1222         case HDM_GETITEMRECT:
1223             return HEADER_GetItemRect (wndPtr, wParam, lParam);
1224
1225 //      case HDM_GETORDERARRAY:
1226 //      case HDM_GETUNICODEFORMAT:
1227
1228         case HDM_HITTEST:
1229             return HEADER_HitTest (wndPtr, wParam, lParam);
1230
1231         case HDM_INSERTITEM32A:
1232             return HEADER_InsertItem32A (wndPtr, wParam, lParam);
1233
1234 //      case HDM_INSERTITEM32W:
1235
1236         case HDM_LAYOUT:
1237             return HEADER_Layout (wndPtr, wParam, lParam);
1238
1239         case HDM_SETIMAGELIST:
1240             return HEADER_SetImageList (wndPtr, wParam, lParam);
1241
1242         case HDM_SETITEM32A:
1243             return HEADER_SetItem32A (wndPtr, wParam, lParam);
1244
1245 //      case HDM_SETITEM32W:
1246 //      case HDM_SETORDERARRAY:
1247 //      case HDM_SETUNICODEFORMAT:
1248
1249
1250         case WM_CREATE:
1251             return HEADER_Create (wndPtr, wParam, lParam);
1252
1253         case WM_DESTROY:
1254             return HEADER_Destroy (wndPtr, wParam, lParam);
1255
1256         case WM_ERASEBKGND:
1257             return 1;
1258
1259         case WM_GETDLGCODE:
1260             return DLGC_WANTTAB | DLGC_WANTARROWS;
1261
1262         case WM_GETFONT:
1263             return HEADER_GetFont (wndPtr);
1264
1265         case WM_LBUTTONDBLCLK:
1266             return HEADER_LButtonDblClk (wndPtr, wParam, lParam);
1267
1268         case WM_LBUTTONDOWN:
1269             return HEADER_LButtonDown (wndPtr, wParam, lParam);
1270
1271         case WM_LBUTTONUP:
1272             return HEADER_LButtonUp (wndPtr, wParam, lParam);
1273
1274         case WM_MOUSEMOVE:
1275             return HEADER_MouseMove (wndPtr, wParam, lParam);
1276
1277         case WM_PAINT:
1278             return HEADER_Paint (wndPtr, wParam);
1279
1280         case WM_RBUTTONUP:
1281             return HEADER_RButtonUp (wndPtr, wParam, lParam);
1282
1283         case WM_SETCURSOR:
1284             return HEADER_SetCursor (wndPtr, wParam, lParam);
1285
1286         case WM_SETFONT:
1287             return HEADER_SetFont (wndPtr, wParam, lParam);
1288
1289         default:
1290             if (msg >= WM_USER) 
1291                 ERR (header, "unknown msg %04x wp=%04x lp=%08lx\n",
1292                      msg, wParam, lParam );
1293             return DefWindowProc32A (hwnd, msg, wParam, lParam);
1294     }
1295     return 0;
1296 }
1297
1298
1299 void HEADER_Register( void )
1300 {
1301     WNDCLASS32A wndClass;
1302
1303     if (GlobalFindAtom32A (WC_HEADER32A)) return;
1304
1305     ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
1306     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
1307     wndClass.lpfnWndProc   = (WNDPROC32)HEADER_WindowProc;
1308     wndClass.cbClsExtra    = 0;
1309     wndClass.cbWndExtra    = sizeof(HEADER_INFO *);
1310     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
1311     wndClass.lpszClassName = WC_HEADER32A;
1312  
1313     RegisterClass32A (&wndClass);
1314 }
1315