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