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