ANSI C fixes.
[wine] / dlls / comctl32 / trackbar.c
1 /*
2  * Trackbar control
3  *
4  * Copyright 1998, 1999 Eric Kohl <ekohl@abo.rhein-zeitung.de>
5  * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
6  *
7  *
8  * TODO:
9  *   - Some messages.
10  *   - more display code.
11  *   - handle dragging slider better
12  *   - better tic handling.
13  *   - more notifications.
14  *   
15  */
16
17 /* known bugs:
18
19    -TBM_SETRANGEMAX & TBM_SETRANGEMIN should only change the view of the
20    trackbar, not the actual amount of tics in the list.
21    -TBM_GETTIC & TBM_GETTICPOS shouldn't rely on infoPtr->tics being sorted.
22    - Make drawing code exact match of w95 drawing.
23 */
24
25
26
27 #include "winbase.h"
28 #include "commctrl.h"
29 #include "trackbar.h"
30 #include "debugtools.h"
31
32 DEFAULT_DEBUG_CHANNEL(trackbar)
33
34
35 #define TRACKBAR_GetInfoPtr(wndPtr) ((TRACKBAR_INFO *)GetWindowLongA (hwnd,0))
36
37
38 /* Used by TRACKBAR_Refresh to find out which parts of the control 
39    need to be recalculated */
40
41 #define TB_THUMBPOSCHANGED      1       
42 #define TB_THUMBSIZECHANGED     2
43 #define TB_THUMBCHANGED         (TB_THUMBPOSCHANGED | TB_THUMBPOSCHANGED)
44 #define TB_SELECTIONCHANGED     4
45 #define TB_DRAG_MODE            16     /* we're dragging the slider */
46 #define TB_DRAGPOSVALID         32     /* current Position is in dragPos */
47 #define TB_SHOW_TOOLTIP         64     /* tooltip-style enabled and tooltip on */
48
49 /* helper defines for TRACKBAR_DrawTic */
50 #define TIC_LEFTEDGE            0x20
51 #define TIC_RIGHTEDGE           0x40
52 #define TIC_EDGE                (TIC_LEFTEDGE | TIC_RIGHTEDGE)
53 #define TIC_SELECTIONMARKMAX    0x80
54 #define TIC_SELECTIONMARKMIN    0x100
55 #define TIC_SELECTIONMARK       (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
56
57 static BOOL TRACKBAR_SendNotify (HWND hwnd, UINT code);
58
59 void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
60 {
61     int i,tic,nrTics;
62
63     if (infoPtr->uTicFreq && infoPtr->nRangeMax >= infoPtr->nRangeMin) 
64         nrTics=(infoPtr->nRangeMax - infoPtr->nRangeMin)/infoPtr->uTicFreq;
65     else {
66         nrTics=0;
67         COMCTL32_Free (infoPtr->tics);
68         infoPtr->tics=NULL;
69         infoPtr->uNumTics=0;
70         return;
71     }
72
73     if (nrTics!=infoPtr->uNumTics) {
74         infoPtr->tics=COMCTL32_ReAlloc (infoPtr->tics, 
75                                         (nrTics+1)*sizeof (DWORD));
76         infoPtr->uNumTics=nrTics;
77     }
78     infoPtr->uNumTics=nrTics;
79     tic=infoPtr->nRangeMin+infoPtr->uTicFreq;
80     for (i=0; i<nrTics; i++,tic+=infoPtr->uTicFreq)
81         infoPtr->tics[i]=tic;
82 }
83
84
85 /* converts from physical (mouse) position to logical position 
86    (in range of trackbar) */
87
88 static inline DOUBLE
89 TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO *infoPtr, int place, 
90                                  int vertical) 
91 {
92     double range,width,pos;
93
94     range=infoPtr->nRangeMax - infoPtr->nRangeMin;
95     if (vertical) {
96         width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
97         pos=(range*(place - infoPtr->rcChannel.top)) / width;
98     } else {
99         width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
100         pos=(range*(place - infoPtr->rcChannel.left)) / width;
101     }
102         
103     if (pos > infoPtr->nRangeMax)
104         pos = infoPtr->nRangeMax;
105     else if (pos < infoPtr->nRangeMin)
106         pos = infoPtr->nRangeMin;
107
108     TRACE("%.2f\n",pos);
109     return pos;
110 }
111
112
113 static VOID
114 TRACKBAR_CalcChannel (HWND hwnd, TRACKBAR_INFO *infoPtr)
115 {
116     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
117     INT cyChannel;
118     RECT lpRect,*channel = & infoPtr->rcChannel;
119
120     GetClientRect (hwnd, &lpRect);
121
122     if (dwStyle & TBS_ENABLESELRANGE)
123         cyChannel = MAX(infoPtr->uThumbLen - 8, 4);
124     else
125         cyChannel = 4;
126
127     if (dwStyle & TBS_VERT) {
128         channel->top    = lpRect.top + 8;
129         channel->bottom = lpRect.bottom - 8;
130
131         if (dwStyle & TBS_BOTH) {
132             channel->left  = (lpRect.right - cyChannel) / 2;
133             channel->right = (lpRect.right + cyChannel) / 2;
134         }
135         else if (dwStyle & TBS_LEFT) {
136             channel->left  = lpRect.left + 10;
137             channel->right = channel->left + cyChannel;
138         }
139         else { /* TBS_RIGHT */
140             channel->right = lpRect.right - 10;
141             channel->left  = channel->right - cyChannel;
142         }
143     }
144     else {
145         channel->left = lpRect.left + 8;
146         channel->right = lpRect.right - 8;
147         if (dwStyle & TBS_BOTH) {
148             channel->top                = (lpRect.bottom - cyChannel) / 2;
149             channel->bottom     = (lpRect.bottom + cyChannel) / 2;
150         }
151         else if (dwStyle & TBS_TOP) {
152             channel->top    = lpRect.top + 10;
153             channel->bottom = channel->top + cyChannel;
154         }
155         else { /* TBS_BOTTOM */
156             channel->bottom = lpRect.bottom - 10;
157             channel->top    = channel->bottom - cyChannel;
158         }
159     }
160 }
161
162 static VOID
163 TRACKBAR_CalcThumb (HWND hwnd, TRACKBAR_INFO *infoPtr)
164 {
165     RECT *thumb;
166     int range, width;
167         
168     thumb=&infoPtr->rcThumb;
169     range=infoPtr->nRangeMax - infoPtr->nRangeMin;
170     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT) {
171         width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
172         thumb->left  = infoPtr->rcChannel.left - 1;
173         thumb->right  = infoPtr->rcChannel.left + infoPtr->uThumbLen - 8;
174         thumb->top       = infoPtr->rcChannel.top +
175             (width*infoPtr->nPos)/range - 5;
176         thumb->bottom = thumb->top + infoPtr->uThumbLen/3;
177
178     } else {
179         width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
180         thumb->left   = infoPtr->rcChannel.left +
181             (width*infoPtr->nPos)/range - 5;
182         thumb->right  = thumb->left + infoPtr->uThumbLen/3;
183         thumb->top        = infoPtr->rcChannel.top - 1;
184         thumb->bottom = infoPtr->rcChannel.top + infoPtr->uThumbLen - 8;
185     }
186 }
187
188 static VOID
189 TRACKBAR_CalcSelection (HWND hwnd, TRACKBAR_INFO *infoPtr)
190 {
191     RECT *selection;
192     int range, width;
193
194     selection= & infoPtr->rcSelection;
195     range=infoPtr->nRangeMax - infoPtr->nRangeMin;
196     width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
197
198     if (range <= 0) 
199         SetRectEmpty (selection);
200     else 
201         if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT) {
202             selection->left   = infoPtr->rcChannel.left +
203                 (width*infoPtr->nSelMin)/range;
204             selection->right  = infoPtr->rcChannel.left +
205                 (width*infoPtr->nSelMax)/range;
206             selection->top    = infoPtr->rcChannel.top + 2;
207             selection->bottom = infoPtr->rcChannel.bottom - 2;
208         } else {
209             selection->top    = infoPtr->rcChannel.top +
210                 (width*infoPtr->nSelMin)/range;
211             selection->bottom = infoPtr->rcChannel.top +
212                 (width*infoPtr->nSelMax)/range;
213             selection->left   = infoPtr->rcChannel.left + 2;
214             selection->right  = infoPtr->rcChannel.right - 2;
215         }
216 }
217
218 /* Trackbar drawing code. I like my spaghetti done milanese.  */
219
220 /* ticPos is in tic-units, not in pixels */
221
222 static VOID
223 TRACKBAR_DrawHorizTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, 
224                        int flags, COLORREF clrTic)
225 {
226     RECT rcChannel=infoPtr->rcChannel;
227     int x,y,width,range,side;
228
229     range=infoPtr->nRangeMax - infoPtr->nRangeMin;
230     width=rcChannel.right - rcChannel.left;
231
232     if (flags & TBS_TOP) {
233         y=rcChannel.top-2;
234         side=-1;
235     } else {
236         y=rcChannel.bottom+2;
237         side=1;
238     }
239
240     if (flags & TIC_SELECTIONMARK) {
241         if (flags & TIC_SELECTIONMARKMIN) 
242             x=rcChannel.left + (width*ticPos)/range - 1;
243         else 
244             x=rcChannel.left + (width*ticPos)/range + 1;
245
246         SetPixel (hdc, x,y+6*side, clrTic);
247         SetPixel (hdc, x,y+7*side, clrTic);
248         return;
249     }
250
251     if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax)) {
252         x=rcChannel.left + (width*ticPos)/range;
253         SetPixel (hdc, x,y+5*side, clrTic);
254         SetPixel (hdc, x,y+6*side, clrTic);
255         SetPixel (hdc, x,y+7*side, clrTic);
256     }
257
258     if (flags & TIC_EDGE) {
259         if (flags & TIC_LEFTEDGE)
260             x=rcChannel.left;
261         else 
262             x=rcChannel.right;
263
264         SetPixel (hdc, x,y+5*side, clrTic);
265         SetPixel (hdc, x,y+6*side, clrTic);
266         SetPixel (hdc, x,y+7*side, clrTic);
267         SetPixel (hdc, x,y+8*side, clrTic);
268     }
269
270 }
271
272 static VOID
273 TRACKBAR_DrawVertTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, 
274                       int flags, COLORREF clrTic)
275 {
276     RECT rcChannel=infoPtr->rcChannel;
277     int x,y,width,range,side;
278
279     range=infoPtr->nRangeMax - infoPtr->nRangeMin;
280     width=rcChannel.bottom - rcChannel.top;
281
282     if (flags & TBS_TOP) {
283         x=rcChannel.right-2;
284         side=-1;
285     } else {
286         x=rcChannel.left+2;
287         side=1;
288     }
289
290
291     if (flags & TIC_SELECTIONMARK) {
292         if (flags & TIC_SELECTIONMARKMIN) 
293             y=rcChannel.top + (width*ticPos)/range - 1;
294         else 
295             y=rcChannel.top + (width*ticPos)/range + 1;
296
297         SetPixel (hdc, x+6*side, y, clrTic);
298         SetPixel (hdc, x+7*side, y, clrTic);
299         return;
300     }
301
302     if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax)) {
303         y=rcChannel.top + (width*ticPos)/range;
304         SetPixel (hdc, x+5*side, y, clrTic);
305         SetPixel (hdc, x+6*side, y, clrTic);
306         SetPixel (hdc, x+7*side, y, clrTic);
307     }
308
309     if (flags & TIC_EDGE) {
310         if (flags & TIC_LEFTEDGE)
311             y=rcChannel.top;
312         else 
313             y=rcChannel.bottom;
314
315         SetPixel (hdc, x+5*side, y, clrTic);
316         SetPixel (hdc, x+6*side, y, clrTic);
317         SetPixel (hdc, x+7*side, y, clrTic);
318         SetPixel (hdc, x+8*side, y, clrTic);
319     }
320
321 }
322
323
324 static VOID
325 TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, 
326                    int flags, COLORREF clrTic)
327 {
328
329     if (flags & TBS_VERT) {
330         if ((flags & TBS_TOP) || (flags & TBS_BOTH)) 
331             TRACKBAR_DrawVertTic (infoPtr, hdc, ticPos, 
332                                   flags | TBS_TOP , clrTic);
333         if (!(flags & TBS_TOP) || (flags & TBS_BOTH)) 
334             TRACKBAR_DrawVertTic (infoPtr, hdc, ticPos, flags, clrTic);
335         return;
336     }
337
338     if ((flags & TBS_TOP) || (flags & TBS_BOTH)) 
339         TRACKBAR_DrawHorizTic (infoPtr, hdc, ticPos, flags | TBS_TOP , clrTic);
340
341     if (!(flags & TBS_TOP) || (flags & TBS_BOTH)) 
342         TRACKBAR_DrawHorizTic (infoPtr, hdc, ticPos, flags, clrTic);
343
344 }
345
346
347 static VOID
348 TRACKBAR_Refresh (HWND hwnd, HDC hdc)
349 {
350     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
351     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
352     RECT rcClient, rcChannel, rcSelection;
353     HBRUSH hBrush = CreateSolidBrush (infoPtr->clrBk);
354     int i;
355
356     GetClientRect (hwnd, &rcClient);
357     hBrush = CreateSolidBrush (infoPtr->clrBk);
358     FillRect (hdc, &rcClient, hBrush);
359     DeleteObject (hBrush);
360
361     if (infoPtr->flags & TB_DRAGPOSVALID)  {
362         infoPtr->nPos=infoPtr->dragPos;
363         infoPtr->flags |= TB_THUMBPOSCHANGED;
364     }
365         
366     if (infoPtr->flags & TB_THUMBCHANGED) {
367         TRACKBAR_CalcThumb      (hwnd, infoPtr);
368         if (infoPtr->flags & TB_THUMBSIZECHANGED) 
369             TRACKBAR_CalcChannel (hwnd, infoPtr);
370     }
371     if (infoPtr->flags & TB_SELECTIONCHANGED)
372         TRACKBAR_CalcSelection (hwnd, infoPtr);
373     infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED | 
374                          TB_DRAGPOSVALID);
375
376     /* draw channel */
377
378     rcChannel = infoPtr->rcChannel;
379     rcSelection= infoPtr->rcSelection;
380     DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
381
382     if (dwStyle & TBS_ENABLESELRANGE) {          /* fill the channel */
383         HBRUSH hbr = CreateSolidBrush (RGB(255,255,255));
384         FillRect (hdc, &rcChannel, hbr);
385         if (((dwStyle & TBS_VERT) && 
386              (rcSelection.left!=rcSelection.right)) || 
387             ((!(dwStyle & TBS_VERT)) &&         
388              (rcSelection.left!=rcSelection.right))) {
389             hbr=CreateSolidBrush (COLOR_HIGHLIGHT); 
390             FillRect (hdc, &rcSelection, hbr);
391         }
392         DeleteObject (hbr);
393     }
394
395
396     /* draw tics */
397
398     if (!(dwStyle & TBS_NOTICKS)) {
399         int ticFlags = dwStyle & 0x0f;
400         COLORREF clrTic=GetSysColor (COLOR_3DDKSHADOW);
401
402         for (i=0; i<infoPtr->uNumTics; i++) 
403             TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->tics[i], 
404                                ticFlags, clrTic);
405
406         TRACKBAR_DrawTics (infoPtr, hdc, 0, ticFlags | TIC_LEFTEDGE, clrTic);
407         TRACKBAR_DrawTics (infoPtr, hdc, 0, ticFlags | TIC_RIGHTEDGE, clrTic);
408           
409         if ((dwStyle & TBS_ENABLESELRANGE) && 
410             (rcSelection.left!=rcSelection.right)) {
411             TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->nSelMin, 
412                                ticFlags | TIC_SELECTIONMARKMIN, clrTic);
413             TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->nSelMax, 
414                                ticFlags | TIC_SELECTIONMARKMAX, clrTic);
415         }
416     }
417
418     /* draw thumb */
419
420     if (!(dwStyle & TBS_NOTHUMB)) {
421                 
422         HBRUSH hbr = CreateSolidBrush (COLOR_BACKGROUND);
423         RECT thumb = infoPtr->rcThumb;
424
425         SelectObject (hdc, hbr);
426                 
427         if (dwStyle & TBS_BOTH) {
428             FillRect (hdc, &thumb, hbr);
429             DrawEdge (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
430         } else {
431
432             POINT points[6];
433
434             /* first, fill the thumb */
435             /* FIXME: revamp. check for TBS_VERT */
436
437             SetPolyFillMode (hdc,WINDING);
438             points[0].x=thumb.left;
439             points[0].y=thumb.top;
440             points[1].x=thumb.right - 1;
441             points[1].y=thumb.top;
442             points[2].x=thumb.right - 1;
443             points[2].y=thumb.bottom -2;
444             points[3].x=(thumb.right + thumb.left-1)/2;
445             points[3].y=thumb.bottom+4;
446             points[4].x=thumb.left;
447             points[4].y=thumb.bottom -2;
448             points[5].x=points[0].x;
449             points[5].y=points[0].y;
450             Polygon (hdc, points, 6);
451
452             if (dwStyle & TBS_VERT) {
453                 /*   draw edge  */
454             } else {
455                 RECT triangle;  /* for correct shadows of thumb */
456                 DrawEdge (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
457
458                 /* draw notch */
459
460                 triangle.right = thumb.right+5;
461                 triangle.left  = points[3].x+5;
462                 triangle.top   = thumb.bottom +5;
463                 triangle.bottom= thumb.bottom +1;
464                 DrawEdge (hdc, &triangle, EDGE_SUNKEN, 
465                           BF_DIAGONAL | BF_TOP | BF_RIGHT);
466                 triangle.left  = thumb.left+6;
467                 triangle.right = points[3].x+6;
468                 DrawEdge (hdc, &triangle, EDGE_RAISED, 
469                           BF_DIAGONAL | BF_TOP | BF_LEFT);
470             }
471         }
472         DeleteObject (hbr);
473     }
474
475     if (infoPtr->bFocus)
476         DrawFocusRect (hdc, &rcClient);
477 }
478
479
480 static VOID
481 TRACKBAR_AlignBuddies (HWND hwnd, TRACKBAR_INFO *infoPtr)
482 {
483     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
484     HWND hwndParent = GetParent (hwnd);
485     RECT rcSelf, rcBuddy;
486     INT x, y;
487
488     GetWindowRect (hwnd, &rcSelf);
489     MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2);
490
491     /* align buddy left or above */
492     if (infoPtr->hwndBuddyLA) {
493         GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy);
494         MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
495
496         if (dwStyle & TBS_VERT) {
497             x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
498                 (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
499             y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top);
500         }
501         else {
502             x = rcSelf.left - (rcBuddy.right - rcBuddy.left);
503             y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
504                 (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
505         }
506
507         SetWindowPos (infoPtr->hwndBuddyLA, 0, x, y, 0, 0,
508                       SWP_NOZORDER | SWP_NOSIZE);
509     }
510
511
512     /* align buddy right or below */
513     if (infoPtr->hwndBuddyRB) {
514         GetWindowRect (infoPtr->hwndBuddyRB, &rcBuddy);
515         MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
516
517         if (dwStyle & TBS_VERT) {
518             x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
519                 (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
520             y = rcSelf.bottom;
521         }
522         else {
523             x = rcSelf.right;
524             y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
525                 (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
526         }
527         SetWindowPos (infoPtr->hwndBuddyRB, 0, x, y, 0, 0,
528                       SWP_NOZORDER | SWP_NOSIZE);
529     }
530 }
531
532
533 static LRESULT
534 TRACKBAR_ClearSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
535 {
536     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
537
538     infoPtr->nSelMin = 0;
539     infoPtr->nSelMax = 0;
540     infoPtr->flags |= TB_SELECTIONCHANGED;
541
542     if ((BOOL)wParam) 
543         InvalidateRect (hwnd, NULL, FALSE);
544
545     return 0;
546 }
547
548
549 static LRESULT
550 TRACKBAR_ClearTics (HWND hwnd, WPARAM wParam, LPARAM lParam)
551 {
552     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
553
554     if (infoPtr->tics) {
555         COMCTL32_Free (infoPtr->tics);
556         infoPtr->tics = NULL;
557         infoPtr->uNumTics = 0;
558     }
559
560     if (wParam) 
561         InvalidateRect (hwnd, NULL, FALSE);
562
563     return 0;
564 }
565
566
567 static LRESULT
568 TRACKBAR_GetBuddy (HWND hwnd, WPARAM wParam, LPARAM lParam)
569 {
570     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
571
572     if (wParam)  /* buddy is left or above */
573         return (LRESULT)infoPtr->hwndBuddyLA;
574
575     /* buddy is right or below */
576     return (LRESULT) infoPtr->hwndBuddyRB;
577 }
578
579
580 static LRESULT
581 TRACKBAR_GetChannelRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
582 {
583     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
584     LPRECT lprc = (LPRECT)lParam;
585
586     if (lprc == NULL)
587         return 0;
588
589     lprc->left   = infoPtr->rcChannel.left;
590     lprc->right  = infoPtr->rcChannel.right;
591     lprc->bottom = infoPtr->rcChannel.bottom;
592     lprc->top    = infoPtr->rcChannel.top;
593
594     return 0;
595 }
596
597
598 static LRESULT
599 TRACKBAR_GetLineSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
600 {
601     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
602
603     return infoPtr->nLineSize;
604 }
605
606
607 static LRESULT
608 TRACKBAR_GetNumTics (HWND hwnd, WPARAM wParam, LPARAM lParam)
609 {
610     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
611
612     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_NOTICKS)
613         return 0;
614
615     return infoPtr->uNumTics+2;
616 }
617
618
619 static LRESULT
620 TRACKBAR_GetPageSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
621 {
622     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
623
624     return infoPtr->nPageSize;
625 }
626
627
628 static LRESULT
629 TRACKBAR_GetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
630 {
631     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
632
633     return infoPtr->nPos;
634 }
635
636
637 static LRESULT
638 TRACKBAR_GetRangeMax (HWND hwnd, WPARAM wParam, LPARAM lParam)
639 {
640     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
641
642     return infoPtr->nRangeMax;
643 }
644
645
646 static LRESULT
647 TRACKBAR_GetRangeMin (HWND hwnd, WPARAM wParam, LPARAM lParam)
648 {
649     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
650
651     return infoPtr->nRangeMin;
652 }
653
654
655 static LRESULT
656 TRACKBAR_GetSelEnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
657 {
658     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
659
660     return infoPtr->nSelMax;
661 }
662
663
664 static LRESULT
665 TRACKBAR_GetSelStart (HWND hwnd, WPARAM wParam, LPARAM lParam)
666 {
667     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
668
669     return infoPtr->nSelMin;
670 }
671
672
673 static LRESULT
674 TRACKBAR_GetThumbLength (HWND hwnd, WPARAM wParam, LPARAM lParam)
675 {
676     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
677
678     return infoPtr->uThumbLen;
679 }
680
681 static LRESULT
682 TRACKBAR_GetPTics (HWND hwnd)
683 {
684     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
685     
686     return (LRESULT) infoPtr->tics;
687 }
688
689 static LRESULT
690 TRACKBAR_GetThumbRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
691 {
692     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
693     LPRECT lprc = (LPRECT)lParam;
694     
695     if (lprc == NULL)
696         return 0; 
697    
698     lprc->left   = infoPtr->rcThumb.left;
699     lprc->right  = infoPtr->rcThumb.right;
700     lprc->bottom = infoPtr->rcThumb.bottom;
701     lprc->top    = infoPtr->rcThumb.top;
702    
703     return 0;
704 }  
705
706
707 static LRESULT
708 TRACKBAR_GetTic (HWND hwnd, WPARAM wParam, LPARAM lParam)
709 {
710     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
711     INT iTic;
712
713     iTic=(INT) wParam;
714     if ((iTic<0) || (iTic>infoPtr->uNumTics)) 
715         return -1;
716
717     return (LRESULT) infoPtr->tics[iTic];
718
719 }
720
721
722 static LRESULT
723 TRACKBAR_GetTicPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
724 {
725     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
726     INT iTic, range, width, pos;
727  
728
729     iTic=(INT ) wParam;
730     if ((iTic<0) || (iTic>infoPtr->uNumTics)) 
731         return -1;
732
733     range=infoPtr->nRangeMax - infoPtr->nRangeMin;
734     width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
735     pos=infoPtr->rcChannel.left + (width * infoPtr->tics[iTic]) / range;
736
737
738     return (LRESULT) pos;
739 }
740
741
742 static LRESULT
743 TRACKBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
744 {
745     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
746
747     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS)
748         return (LRESULT)infoPtr->hwndToolTip;
749     return 0;
750 }
751
752
753 /*      case TBM_GETUNICODEFORMAT: */
754
755
756 static LRESULT
757 TRACKBAR_SetBuddy (HWND hwnd, WPARAM wParam, LPARAM lParam)
758 {
759     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
760     HWND hwndTemp;
761
762     if (wParam) {
763         /* buddy is left or above */
764         hwndTemp = infoPtr->hwndBuddyLA;
765         infoPtr->hwndBuddyLA = (HWND)lParam;
766
767         FIXME("move buddy!\n");
768     }
769     else {
770         /* buddy is right or below */
771         hwndTemp = infoPtr->hwndBuddyRB;
772         infoPtr->hwndBuddyRB = (HWND)lParam;
773
774         FIXME("move buddy!\n");
775     }
776
777     TRACKBAR_AlignBuddies (hwnd, infoPtr);
778
779     return (LRESULT)hwndTemp;
780 }
781
782
783 static LRESULT
784 TRACKBAR_SetLineSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
785 {
786     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
787     INT nTemp = infoPtr->nLineSize;
788
789     infoPtr->nLineSize = (INT)lParam;
790
791     return nTemp;
792 }
793
794
795 static LRESULT
796 TRACKBAR_SetPageSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
797 {
798     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
799     INT nTemp = infoPtr->nPageSize;
800
801     infoPtr->nPageSize = (INT)lParam;
802
803     return nTemp;
804 }
805
806
807 static LRESULT
808 TRACKBAR_SetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
809 {
810     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
811
812     infoPtr->nPos = (INT)LOWORD(lParam);
813
814     if (infoPtr->nPos < infoPtr->nRangeMin)
815         infoPtr->nPos = infoPtr->nRangeMin;
816
817     if (infoPtr->nPos > infoPtr->nRangeMax)
818         infoPtr->nPos = infoPtr->nRangeMax;
819     infoPtr->flags |= TB_THUMBPOSCHANGED;
820
821     if (wParam) 
822         InvalidateRect (hwnd, NULL, FALSE);
823
824     return 0;
825 }
826
827
828 static LRESULT
829 TRACKBAR_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
830 {
831     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
832     infoPtr->nRangeMin = (INT)LOWORD(lParam);
833     infoPtr->nRangeMax = (INT)HIWORD(lParam);
834
835     if (infoPtr->nPos < infoPtr->nRangeMin) {
836         infoPtr->nPos = infoPtr->nRangeMin;
837         infoPtr->flags |=TB_THUMBPOSCHANGED;
838     }
839
840     if (infoPtr->nPos > infoPtr->nRangeMax) {
841         infoPtr->nPos = infoPtr->nRangeMax;
842         infoPtr->flags |=TB_THUMBPOSCHANGED;
843     }
844
845     infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
846     if (infoPtr->nPageSize == 0)
847         infoPtr->nPageSize = 1;
848     TRACKBAR_RecalculateTics (infoPtr);
849
850     if (wParam)
851         InvalidateRect (hwnd, NULL, FALSE);
852
853     return 0;
854 }
855
856
857 static LRESULT
858 TRACKBAR_SetRangeMax (HWND hwnd, WPARAM wParam, LPARAM lParam)
859 {
860     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
861
862     infoPtr->nRangeMax = (INT)lParam;
863     if (infoPtr->nPos > infoPtr->nRangeMax) {
864         infoPtr->nPos = infoPtr->nRangeMax;
865         infoPtr->flags |=TB_THUMBPOSCHANGED;
866     }
867
868     infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
869     if (infoPtr->nPageSize == 0)
870         infoPtr->nPageSize = 1;
871     TRACKBAR_RecalculateTics (infoPtr);
872
873     if (wParam) 
874         InvalidateRect (hwnd, NULL, FALSE);
875
876     return 0;
877 }
878
879
880 static LRESULT
881 TRACKBAR_SetRangeMin (HWND hwnd, WPARAM wParam, LPARAM lParam)
882 {
883     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
884
885     infoPtr->nRangeMin = (INT)lParam;
886     if (infoPtr->nPos < infoPtr->nRangeMin) {
887         infoPtr->nPos = infoPtr->nRangeMin;
888         infoPtr->flags |=TB_THUMBPOSCHANGED;
889     }
890
891     infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
892     if (infoPtr->nPageSize == 0)
893         infoPtr->nPageSize = 1;
894     TRACKBAR_RecalculateTics (infoPtr);
895
896     if (wParam)
897         InvalidateRect (hwnd, NULL, FALSE);
898
899     return 0;
900 }
901
902
903 static LRESULT
904 TRACKBAR_SetTicFreq (HWND hwnd, WPARAM wParam)
905 {
906     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
907         
908     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_AUTOTICKS)
909         infoPtr->uTicFreq=(UINT) wParam; 
910         
911     TRACKBAR_RecalculateTics (infoPtr);
912
913     InvalidateRect (hwnd, NULL, FALSE);
914
915     return 0;
916 }   
917
918
919 static LRESULT
920 TRACKBAR_SetSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
921 {
922     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
923
924     infoPtr->nSelMin = (INT)LOWORD(lParam);
925     infoPtr->nSelMax = (INT)HIWORD(lParam);
926     infoPtr->flags |=TB_SELECTIONCHANGED;
927
928     if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
929         return 0;
930
931     if (infoPtr->nSelMin < infoPtr->nRangeMin)
932         infoPtr->nSelMin = infoPtr->nRangeMin;
933     if (infoPtr->nSelMax > infoPtr->nRangeMax)
934         infoPtr->nSelMax = infoPtr->nRangeMax;
935
936     if (wParam) 
937         InvalidateRect (hwnd, NULL, FALSE);
938
939
940     return 0;
941 }
942
943
944 static LRESULT
945 TRACKBAR_SetSelEnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
946 {
947     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
948
949     if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
950         return 0;
951
952     infoPtr->nSelMax = (INT)lParam;
953     infoPtr->flags |= TB_SELECTIONCHANGED;
954         
955     if (infoPtr->nSelMax > infoPtr->nRangeMax)
956         infoPtr->nSelMax = infoPtr->nRangeMax;
957
958     if (wParam) 
959         InvalidateRect (hwnd, NULL, FALSE);
960
961     return 0;
962 }
963
964
965 static LRESULT
966 TRACKBAR_SetSelStart (HWND hwnd, WPARAM wParam, LPARAM lParam)
967 {
968     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
969
970     if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
971         return 0;
972
973     infoPtr->nSelMin = (INT)lParam;
974     infoPtr->flags  |=TB_SELECTIONCHANGED;
975
976     if (infoPtr->nSelMin < infoPtr->nRangeMin)
977         infoPtr->nSelMin = infoPtr->nRangeMin;
978
979     if (wParam) 
980         InvalidateRect (hwnd, NULL, FALSE);
981
982     return 0;
983 }
984
985
986 static LRESULT
987 TRACKBAR_SetThumbLength (HWND hwnd, WPARAM wParam, LPARAM lParam)
988 {
989     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
990
991     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_FIXEDLENGTH)
992         infoPtr->uThumbLen = (UINT)wParam;
993
994     infoPtr->flags |= TB_THUMBSIZECHANGED;
995
996     InvalidateRect (hwnd, NULL, FALSE);
997
998     return 0;
999 }
1000
1001
1002 static LRESULT
1003 TRACKBAR_SetTic (HWND hwnd, WPARAM wParam, LPARAM lParam)
1004 {
1005     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1006     INT nPos = (INT)lParam;
1007
1008     if ((nPos < infoPtr->nRangeMin) || (nPos> infoPtr->nRangeMax))
1009         return FALSE;
1010
1011     infoPtr->uNumTics++;
1012     infoPtr->tics=COMCTL32_ReAlloc( infoPtr->tics,
1013                                     (infoPtr->uNumTics)*sizeof (DWORD));
1014     infoPtr->tics[infoPtr->uNumTics-1]=nPos;
1015
1016     InvalidateRect (hwnd, NULL, FALSE);
1017
1018     return TRUE;
1019 }
1020
1021
1022 static LRESULT
1023 TRACKBAR_SetTipSide (HWND hwnd, WPARAM wParam, LPARAM lParam)
1024 {
1025     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1026     INT fTemp = infoPtr->fLocation;
1027
1028     infoPtr->fLocation = (INT)wParam;
1029         
1030     return fTemp;
1031 }
1032
1033
1034 static LRESULT
1035 TRACKBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
1036 {
1037     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1038
1039     infoPtr->hwndToolTip = (HWND)wParam;
1040
1041     return 0;
1042 }
1043
1044
1045 /*      case TBM_SETUNICODEFORMAT: */
1046
1047
1048 static LRESULT
1049 TRACKBAR_InitializeThumb (HWND hwnd)
1050 {
1051     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1052
1053     infoPtr->uThumbLen = 23;   /* initial thumb length */
1054
1055     TRACKBAR_CalcChannel (hwnd,infoPtr);
1056     TRACKBAR_CalcThumb (hwnd, infoPtr);
1057     infoPtr->flags &= ~TB_SELECTIONCHANGED;
1058
1059     return 0;
1060 }
1061
1062
1063 static LRESULT
1064 TRACKBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1065 {
1066     TRACKBAR_INFO *infoPtr;
1067
1068     infoPtr = (TRACKBAR_INFO *)COMCTL32_Alloc (sizeof(TRACKBAR_INFO));
1069     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1070
1071     /* set default values */
1072     infoPtr->nRangeMin = 0;
1073     infoPtr->nRangeMax = 100;
1074     infoPtr->nLineSize = 1;
1075     infoPtr->nPageSize = 20;
1076     infoPtr->nSelMin   = 0;
1077     infoPtr->nSelMax   = 0;
1078     infoPtr->nPos      = 0;
1079
1080     infoPtr->uNumTics  = 0;    /* start and end tic are not included in count*/
1081     infoPtr->uTicFreq  = 1;
1082     infoPtr->tics          = NULL;
1083     infoPtr->clrBk         = GetSysColor (COLOR_BACKGROUND);
1084     infoPtr->hwndNotify = GetParent (hwnd);
1085
1086     TRACKBAR_InitializeThumb (hwnd);
1087
1088     /* Create tooltip control */
1089     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS) {
1090         TTTOOLINFOA ti;
1091
1092         infoPtr->hwndToolTip =
1093             CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
1094                              CW_USEDEFAULT, CW_USEDEFAULT,
1095                              CW_USEDEFAULT, CW_USEDEFAULT,
1096                              hwnd, 0, 0, 0);
1097
1098         /* Send NM_TOOLTIPSCREATED notification */
1099         if (infoPtr->hwndToolTip) {
1100             NMTOOLTIPSCREATED nmttc;
1101
1102             nmttc.hdr.hwndFrom = hwnd;
1103             nmttc.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1104             nmttc.hdr.code = NM_TOOLTIPSCREATED;
1105             nmttc.hwndToolTips = infoPtr->hwndToolTip;
1106
1107             SendMessageA (GetParent (hwnd), WM_NOTIFY,
1108                           (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
1109         }
1110
1111         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1112         ti.cbSize   = sizeof(TTTOOLINFOA);
1113         ti.uFlags   = TTF_IDISHWND | TTF_TRACK;
1114         ti.hwnd     = hwnd;
1115         ti.uId      = 0;
1116         ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK */
1117         SetRectEmpty (&ti.rect);
1118
1119         SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
1120     }
1121
1122     return 0;
1123 }
1124
1125
1126 static LRESULT
1127 TRACKBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1128 {
1129     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1130
1131     /* delete tooltip control */
1132     if (infoPtr->hwndToolTip)
1133         DestroyWindow (infoPtr->hwndToolTip);
1134
1135     COMCTL32_Free (infoPtr);
1136     return 0;
1137 }
1138
1139
1140 static LRESULT
1141 TRACKBAR_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
1142 {
1143     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1144
1145     TRACE("\n");
1146
1147     infoPtr->bFocus = FALSE;
1148     infoPtr->flags &= ~TB_DRAG_MODE;
1149
1150     InvalidateRect (hwnd, NULL, FALSE);
1151
1152     return 0;
1153 }
1154
1155
1156 static LRESULT
1157 TRACKBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1158 {
1159     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1160     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1161     int clickPlace,prevPos,vertical;
1162     DOUBLE clickPos;
1163
1164     SetFocus (hwnd);
1165
1166     vertical = dwStyle & TBS_VERT;
1167     if (vertical)
1168         clickPlace=(INT)HIWORD(lParam);
1169     else
1170         clickPlace=(INT)LOWORD(lParam);
1171
1172     if ((vertical && 
1173          (clickPlace>infoPtr->rcThumb.top) && 
1174          (clickPlace<infoPtr->rcThumb.bottom))   ||
1175         (!vertical && 
1176          (clickPlace>infoPtr->rcThumb.left) && 
1177          (clickPlace<infoPtr->rcThumb.right))) {
1178         infoPtr->flags |= TB_DRAG_MODE;
1179         if (dwStyle & TBS_TOOLTIPS) {  /* enable tooltip */
1180             TTTOOLINFOA ti;
1181             POINT pt;
1182
1183             GetCursorPos (&pt);
1184             SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION, 0,
1185                           (LPARAM)MAKELPARAM(pt.x, pt.y));
1186
1187             ti.cbSize   = sizeof(TTTOOLINFOA);
1188             ti.uId      = 0;
1189             ti.hwnd     = (UINT)hwnd;
1190
1191             infoPtr->flags |= TB_SHOW_TOOLTIP;
1192             SetCapture (hwnd);
1193             SendMessageA (infoPtr->hwndToolTip, TTM_TRACKACTIVATE, 
1194                           (WPARAM)TRUE, (LPARAM)&ti);
1195         }
1196         return 0;
1197     }
1198
1199     clickPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace, vertical);
1200     prevPos = infoPtr->nPos;
1201
1202     if (clickPos > prevPos) {  /* similar to VK_NEXT */
1203         infoPtr->nPos += infoPtr->nPageSize;
1204         if (infoPtr->nPos > infoPtr->nRangeMax)
1205             infoPtr->nPos = infoPtr->nRangeMax;
1206         TRACKBAR_SendNotify (hwnd, TB_PAGEUP);  
1207     } else {
1208         infoPtr->nPos -= infoPtr->nPageSize;  /* similar to VK_PRIOR */
1209         if (infoPtr->nPos < infoPtr->nRangeMin)
1210             infoPtr->nPos = infoPtr->nRangeMin;
1211         TRACKBAR_SendNotify (hwnd, TB_PAGEDOWN);
1212     }
1213         
1214     if (prevPos!=infoPtr->nPos) {
1215         infoPtr->flags |= TB_THUMBPOSCHANGED;
1216         InvalidateRect (hwnd, NULL, FALSE);
1217     }
1218         
1219     return 0;
1220 }
1221
1222
1223 static LRESULT
1224 TRACKBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1225 {
1226     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1227
1228     TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1229
1230     if (infoPtr->flags & TB_DRAG_MODE)
1231     {
1232         infoPtr->flags &= ~TB_DRAG_MODE;
1233         ReleaseCapture ();
1234     }
1235
1236     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS) {  /* disable tooltip */
1237         TTTOOLINFOA ti;
1238
1239         ti.cbSize   = sizeof(TTTOOLINFOA);
1240         ti.uId      = 0;
1241         ti.hwnd     = (UINT)hwnd;
1242
1243         infoPtr->flags &= ~TB_SHOW_TOOLTIP;
1244         SendMessageA (infoPtr->hwndToolTip, TTM_TRACKACTIVATE,
1245                       (WPARAM)FALSE, (LPARAM)&ti);
1246     }
1247     
1248     InvalidateRect (hwnd, NULL, FALSE);
1249
1250     return 0;
1251 }
1252
1253
1254 static LRESULT
1255 TRACKBAR_CaptureChanged (HWND hwnd, WPARAM wParam, LPARAM lParam)
1256 {
1257     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1258         
1259     if (infoPtr->flags & TB_DRAGPOSVALID) {
1260         infoPtr->nPos=infoPtr->dragPos;
1261         InvalidateRect (hwnd, NULL, FALSE);
1262     }
1263         
1264     infoPtr->flags &= ~ TB_DRAGPOSVALID;
1265
1266     TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1267     return 0;
1268 }
1269
1270
1271 static LRESULT
1272 TRACKBAR_Paint (HWND hwnd, WPARAM wParam)
1273 {
1274     HDC hdc;
1275     PAINTSTRUCT ps;
1276
1277     hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1278     TRACKBAR_Refresh (hwnd, hdc);
1279     if(!wParam)
1280         EndPaint (hwnd, &ps);
1281     return 0;
1282 }
1283
1284
1285 static LRESULT
1286 TRACKBAR_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
1287 {
1288     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1289
1290     TRACE("\n");
1291     infoPtr->bFocus = TRUE;
1292
1293     InvalidateRect (hwnd, NULL, FALSE);
1294
1295     return 0;
1296 }
1297
1298
1299 static LRESULT
1300 TRACKBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1301 {
1302     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1303
1304     TRACKBAR_CalcChannel (hwnd, infoPtr);
1305     TRACKBAR_AlignBuddies (hwnd, infoPtr);
1306
1307     return 0;
1308 }
1309
1310
1311 static BOOL
1312 TRACKBAR_SendNotify (HWND hwnd, UINT code)
1313 {
1314     TRACE("%x\n",code);
1315
1316     if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT) 
1317         return (BOOL) SendMessageA (GetParent (hwnd), 
1318                                     WM_VSCROLL, (WPARAM)code, (LPARAM)hwnd);
1319
1320     return (BOOL) SendMessageA (GetParent (hwnd), 
1321                                 WM_HSCROLL, (WPARAM)code, (LPARAM)hwnd);
1322 }
1323
1324
1325 static LRESULT
1326 TRACKBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1327 {
1328     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1329     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1330     SHORT clickPlace;
1331     DOUBLE dragPos;
1332     char buf[80];
1333                         
1334     TRACE("%x\n",wParam);
1335
1336     if (dwStyle & TBS_VERT)
1337         clickPlace=(SHORT)HIWORD(lParam);
1338     else
1339         clickPlace=(SHORT)LOWORD(lParam);
1340
1341     if (!(infoPtr->flags & TB_DRAG_MODE))
1342         return TRUE;
1343
1344     SetCapture (hwnd);
1345     dragPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace, 
1346                                                dwStyle & TBS_VERT);
1347     if (dragPos > ((INT)dragPos) + 0.5)
1348         infoPtr->dragPos = dragPos + 1;
1349     else
1350         infoPtr->dragPos = dragPos;
1351
1352     infoPtr->flags |= TB_DRAGPOSVALID;
1353     TRACKBAR_SendNotify (hwnd, TB_THUMBTRACK | (infoPtr->nPos>>16));
1354
1355     if (infoPtr->flags & TB_SHOW_TOOLTIP) {
1356         POINT pt;
1357         TTTOOLINFOA ti;
1358         
1359         ti.cbSize = sizeof(TTTOOLINFOA);
1360         ti.hwnd = hwnd;
1361         ti.uId = 0;
1362         ti.hinst=0;
1363         sprintf (buf,"%d",infoPtr->nPos);
1364         ti.lpszText = (LPSTR) buf;
1365         GetCursorPos (&pt);
1366                 
1367         if (dwStyle & TBS_VERT) {
1368             SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION, 
1369                           0, (LPARAM)MAKELPARAM(pt.x+5, pt.y+15));
1370         } else {
1371             SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION, 
1372                           0, (LPARAM)MAKELPARAM(pt.x+15, pt.y+5));
1373         }
1374         SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
1375                       0, (LPARAM)&ti);
1376     }
1377
1378     InvalidateRect (hwnd, NULL, FALSE);
1379     UpdateWindow (hwnd);
1380
1381     return TRUE;
1382 }
1383
1384
1385 static LRESULT
1386 TRACKBAR_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1387 {
1388     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1389     INT pos;
1390
1391     TRACE("%x\n",wParam);
1392
1393     pos=infoPtr->nPos;
1394     switch (wParam) {
1395     case VK_LEFT:
1396     case VK_UP: 
1397         if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1398         infoPtr->nPos -= infoPtr->nLineSize;
1399         if (infoPtr->nPos < infoPtr->nRangeMin) 
1400             infoPtr->nPos = infoPtr->nRangeMin;
1401         TRACKBAR_SendNotify (hwnd, TB_LINEUP);
1402         break;
1403     case VK_RIGHT:
1404     case VK_DOWN: 
1405         if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1406         infoPtr->nPos += infoPtr->nLineSize;
1407         if (infoPtr->nPos > infoPtr->nRangeMax) 
1408             infoPtr->nPos = infoPtr->nRangeMax;
1409         TRACKBAR_SendNotify (hwnd, TB_LINEDOWN);
1410         break;
1411     case VK_NEXT:
1412         if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1413         infoPtr->nPos += infoPtr->nPageSize;
1414         if (infoPtr->nPos > infoPtr->nRangeMax) 
1415             infoPtr->nPos = infoPtr->nRangeMax;
1416         TRACKBAR_SendNotify (hwnd, TB_PAGEUP);
1417         break;
1418     case VK_PRIOR:
1419         if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1420         infoPtr->nPos -= infoPtr->nPageSize;
1421         if (infoPtr->nPos < infoPtr->nRangeMin) 
1422             infoPtr->nPos = infoPtr->nRangeMin;
1423         TRACKBAR_SendNotify (hwnd, TB_PAGEDOWN);
1424         break;
1425     case VK_HOME: 
1426         if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1427         infoPtr->nPos = infoPtr->nRangeMin;
1428         TRACKBAR_SendNotify (hwnd, TB_TOP);
1429         break;
1430     case VK_END: 
1431         if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1432         infoPtr->nPos = infoPtr->nRangeMax;
1433         TRACKBAR_SendNotify (hwnd, TB_BOTTOM);
1434         break;
1435     }
1436
1437     if (pos!=infoPtr->nPos) { 
1438         infoPtr->flags |=TB_THUMBPOSCHANGED;
1439         InvalidateRect (hwnd, NULL, FALSE);
1440     }
1441
1442     return TRUE;
1443 }
1444
1445
1446 static LRESULT
1447 TRACKBAR_KeyUp (HWND hwnd, WPARAM wParam)
1448 {
1449     switch (wParam) {
1450     case VK_LEFT:
1451     case VK_UP: 
1452     case VK_RIGHT:
1453     case VK_DOWN: 
1454     case VK_NEXT:
1455     case VK_PRIOR:
1456     case VK_HOME: 
1457     case VK_END:
1458         TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1459     }
1460     return TRUE;
1461 }
1462
1463
1464 LRESULT WINAPI
1465 TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1466 {
1467     switch (uMsg)
1468     {
1469     case TBM_CLEARSEL:
1470         return TRACKBAR_ClearSel (hwnd, wParam, lParam);
1471
1472     case TBM_CLEARTICS:
1473         return TRACKBAR_ClearTics (hwnd, wParam, lParam);
1474
1475     case TBM_GETBUDDY:
1476         return TRACKBAR_GetBuddy (hwnd, wParam, lParam);
1477
1478     case TBM_GETCHANNELRECT:
1479         return TRACKBAR_GetChannelRect (hwnd, wParam, lParam);
1480
1481     case TBM_GETLINESIZE:
1482         return TRACKBAR_GetLineSize (hwnd, wParam, lParam);
1483
1484     case TBM_GETNUMTICS:
1485         return TRACKBAR_GetNumTics (hwnd, wParam, lParam);
1486
1487     case TBM_GETPAGESIZE:
1488         return TRACKBAR_GetPageSize (hwnd, wParam, lParam);
1489
1490     case TBM_GETPOS:
1491         return TRACKBAR_GetPos (hwnd, wParam, lParam);
1492
1493     case TBM_GETPTICS:
1494         return TRACKBAR_GetPTics (hwnd);
1495
1496     case TBM_GETRANGEMAX:
1497         return TRACKBAR_GetRangeMax (hwnd, wParam, lParam);
1498
1499     case TBM_GETRANGEMIN:
1500         return TRACKBAR_GetRangeMin (hwnd, wParam, lParam);
1501
1502     case TBM_GETSELEND:
1503         return TRACKBAR_GetSelEnd (hwnd, wParam, lParam);
1504
1505     case TBM_GETSELSTART:
1506         return TRACKBAR_GetSelStart (hwnd, wParam, lParam);
1507
1508     case TBM_GETTHUMBLENGTH:
1509         return TRACKBAR_GetThumbLength (hwnd, wParam, lParam);
1510
1511     case TBM_GETTHUMBRECT:
1512         return TRACKBAR_GetThumbRect (hwnd, wParam, lParam);
1513
1514     case TBM_GETTIC:
1515         return TRACKBAR_GetTic (hwnd, wParam, lParam);
1516  
1517     case TBM_GETTICPOS:
1518         return TRACKBAR_GetTicPos (hwnd, wParam, lParam);
1519  
1520     case TBM_GETTOOLTIPS:
1521         return TRACKBAR_GetToolTips (hwnd, wParam, lParam);
1522
1523 /*      case TBM_GETUNICODEFORMAT: */
1524
1525     case TBM_SETBUDDY:
1526         return TRACKBAR_SetBuddy (hwnd, wParam, lParam);
1527
1528     case TBM_SETLINESIZE:
1529         return TRACKBAR_SetLineSize (hwnd, wParam, lParam);
1530
1531     case TBM_SETPAGESIZE:
1532         return TRACKBAR_SetPageSize (hwnd, wParam, lParam);
1533
1534     case TBM_SETPOS:
1535         return TRACKBAR_SetPos (hwnd, wParam, lParam);
1536
1537     case TBM_SETRANGE:
1538         return TRACKBAR_SetRange (hwnd, wParam, lParam);
1539
1540     case TBM_SETRANGEMAX:
1541         return TRACKBAR_SetRangeMax (hwnd, wParam, lParam);
1542
1543     case TBM_SETRANGEMIN:
1544         return TRACKBAR_SetRangeMin (hwnd, wParam, lParam);
1545
1546     case TBM_SETSEL:
1547         return TRACKBAR_SetSel (hwnd, wParam, lParam);
1548
1549     case TBM_SETSELEND:
1550         return TRACKBAR_SetSelEnd (hwnd, wParam, lParam);
1551
1552     case TBM_SETSELSTART:
1553         return TRACKBAR_SetSelStart (hwnd, wParam, lParam);
1554
1555     case TBM_SETTHUMBLENGTH:
1556         return TRACKBAR_SetThumbLength (hwnd, wParam, lParam);
1557
1558     case TBM_SETTIC:
1559         return TRACKBAR_SetTic (hwnd, wParam, lParam);
1560
1561     case TBM_SETTICFREQ:
1562         return TRACKBAR_SetTicFreq (hwnd, wParam);
1563
1564     case TBM_SETTIPSIDE:
1565         return TRACKBAR_SetTipSide (hwnd, wParam, lParam);
1566
1567     case TBM_SETTOOLTIPS:
1568         return TRACKBAR_SetToolTips (hwnd, wParam, lParam);
1569
1570 /*      case TBM_SETUNICODEFORMAT: */
1571
1572
1573     case WM_CAPTURECHANGED:
1574         return TRACKBAR_CaptureChanged (hwnd, wParam, lParam);
1575
1576     case WM_CREATE:
1577         return TRACKBAR_Create (hwnd, wParam, lParam);
1578
1579     case WM_DESTROY:
1580         return TRACKBAR_Destroy (hwnd, wParam, lParam);
1581
1582 /*      case WM_ENABLE: */
1583
1584 /*      case WM_ERASEBKGND: */
1585 /*          return 0; */
1586
1587     case WM_GETDLGCODE:
1588         return DLGC_WANTARROWS;
1589
1590     case WM_KEYDOWN:
1591         return TRACKBAR_KeyDown (hwnd, wParam, lParam);
1592         
1593     case WM_KEYUP:
1594         return TRACKBAR_KeyUp (hwnd, wParam);
1595
1596     case WM_KILLFOCUS:
1597         return TRACKBAR_KillFocus (hwnd, wParam, lParam);
1598
1599     case WM_LBUTTONDOWN:
1600         return TRACKBAR_LButtonDown (hwnd, wParam, lParam);
1601
1602     case WM_LBUTTONUP:
1603         return TRACKBAR_LButtonUp (hwnd, wParam, lParam);
1604
1605     case WM_MOUSEMOVE:
1606         return TRACKBAR_MouseMove (hwnd, wParam, lParam);
1607
1608     case WM_PAINT:
1609         return TRACKBAR_Paint (hwnd, wParam);
1610
1611     case WM_SETFOCUS:
1612         return TRACKBAR_SetFocus (hwnd, wParam, lParam);
1613
1614     case WM_SIZE:
1615         return TRACKBAR_Size (hwnd, wParam, lParam);
1616
1617     case WM_WININICHANGE:
1618         return TRACKBAR_InitializeThumb (hwnd);
1619
1620     default:
1621         if (uMsg >= WM_USER)
1622             ERR("unknown msg %04x wp=%08x lp=%08lx\n",
1623                  uMsg, wParam, lParam);
1624         return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1625     }
1626     return 0;
1627 }
1628
1629
1630 VOID
1631 TRACKBAR_Register (void)
1632 {
1633     WNDCLASSA wndClass;
1634
1635     if (GlobalFindAtomA (TRACKBAR_CLASSA)) return;
1636
1637     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1638     wndClass.style         = CS_GLOBALCLASS;
1639     wndClass.lpfnWndProc   = (WNDPROC)TRACKBAR_WindowProc;
1640     wndClass.cbClsExtra    = 0;
1641     wndClass.cbWndExtra    = sizeof(TRACKBAR_INFO *);
1642     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
1643     wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1644     wndClass.lpszClassName = TRACKBAR_CLASSA;
1645  
1646     RegisterClassA (&wndClass);
1647 }
1648
1649
1650 VOID
1651 TRACKBAR_Unregister (void)
1652 {
1653     if (GlobalFindAtomA (TRACKBAR_CLASSA))
1654         UnregisterClassA (TRACKBAR_CLASSA, (HINSTANCE)NULL);
1655 }
1656