42d08749e31bcabae813c4e1aca2a53a0650306f
[reactos.git] / subsys / win32k / ntuser / scrollbar.c
1 /* $Id$
2  *
3  * COPYRIGHT:        See COPYING in the top level directory
4  * PROJECT:          ReactOS kernel
5  * PURPOSE:          Scrollbars
6  * FILE:             subsys/win32k/ntuser/scrollbar.c
7  * PROGRAMER:        Jason Filby (jasonfilby@yahoo.com)
8  * REVISION HISTORY:
9  *       16-11-2002  Jason Filby  Created
10  */
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <win32k/win32k.h>
15 #include <include/object.h>
16 #include <include/window.h>
17 #include <include/class.h>
18 #include <include/error.h>
19 #include <include/winsta.h>
20 #include <include/winpos.h>
21 #include <include/rect.h>
22
23 //#define NDEBUG
24 #include <debug.h>
25
26 #define SCROLL_MIN_RECT  4               /* Minimum size of the rectangle between the arrows */
27 #define SCROLL_ARROW_THUMB_OVERLAP 0     /* Overlap between arrows and thumb */
28
29 /* FUNCTIONS *****************************************************************/
30
31 /* Ported from WINE20020904 */
32 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
33  * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
34  * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
35  * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
36  */
37 static BOOL
38 SCROLL_GetScrollBarRect (PWINDOW_OBJECT Window, INT nBar, PRECT lprect)
39 {
40   SCROLLBARINFO info;
41   INT pixels, thumbSize, arrowSize;
42   BOOL vertical;
43   RECT ClientRect = Window->ClientRect;
44   RECT WindowRect = Window->WindowRect;
45   ULONG Style;
46
47   switch (nBar)
48     {
49     case SB_HORZ:
50       lprect->left = ClientRect.left - WindowRect.left;
51       lprect->top = ClientRect.bottom - WindowRect.top;
52       lprect->right = ClientRect.right - WindowRect.left;
53       lprect->bottom = lprect->top + NtUserGetSystemMetrics (SM_CYHSCROLL);
54       if (Window->Style & WS_BORDER)
55         {
56           lprect->left--;
57           lprect->right++;
58         }
59       else if (Window->Style & WS_VSCROLL)
60         lprect->right++;
61       vertical = FALSE;
62       break;
63
64     case SB_VERT:
65       lprect->left = ClientRect.right - WindowRect.left;
66       lprect->top = ClientRect.top - WindowRect.top;
67       lprect->right = lprect->left + NtUserGetSystemMetrics (SM_CXVSCROLL);
68       lprect->bottom = ClientRect.bottom - WindowRect.top;
69       if (Window->Style & WS_BORDER)
70         {
71           lprect->top--;
72           lprect->bottom++;
73         }
74       else if (Window->Style & WS_HSCROLL)
75         lprect->bottom++;
76       vertical = TRUE;
77       break;
78
79     case SB_CTL:
80       W32kGetClientRect (Window, lprect);
81       vertical = ((Window->Style & SBS_VERT) != 0);
82       break;
83
84     default:
85       W32kReleaseWindowObject(Window);
86       return FALSE;
87     }
88
89   if (vertical)
90     pixels = lprect->bottom - lprect->top;
91   else
92     pixels = lprect->right - lprect->left;
93
94   info.cbSize = sizeof(SCROLLBARINFO);
95   SCROLL_GetScrollBarInfo (Window, nBar, &info);
96
97   if (pixels <= 2 * NtUserGetSystemMetrics (SM_CXVSCROLL) + SCROLL_MIN_RECT)
98     {
99       info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
100     }
101   else
102     {
103       arrowSize = NtUserGetSystemMetrics (SM_CXVSCROLL);
104       pixels -= (2 * (NtUserGetSystemMetrics (SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
105
106       /* Temporary initialization - to be removed once proper code is in */
107       info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
108
109 /*        if (info->Page)
110         {
111             thumbSize = MulDiv(pixels,info->Page,(info->MaxVal-info->MinVal+1));
112             if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
113         }
114         else *thumbSize = NtUserGetSystemMetrics(SM_CXVSCROLL); */
115 /*
116         if (((pixels -= *thumbSize ) < 0) ||
117             ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
118         { */
119       /* Rectangle too small or scrollbar disabled -> no thumb */
120 /*            *thumbPos = *thumbSize = 0;
121         }
122         else
123         { */
124 /*            INT max = info->MaxVal - max( info->Page-1, 0 );
125             if (info->MinVal >= max)
126                 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
127             else
128                 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
129                   + MulDiv(pixels, (info->CurVal-info->MinVal),(max - info->MinVal));
130         } */
131   }
132
133   return vertical;
134 }
135
136 DWORD SCROLL_CreateScrollBar(PWINDOW_OBJECT Window, LONG idObject)
137 {
138   PSCROLLBARINFO psbi;
139   LRESULT Result;
140   INT i;
141
142   Result = WinPosGetNonClientSize(Window->Self,
143                                   &Window->WindowRect,
144                                   &Window->ClientRect);
145
146   psbi = ExAllocatePool(NonPagedPool, sizeof(SCROLLBARINFO));
147
148   for (i=0; i<CCHILDREN_SCROLLBAR+1; i++)
149     psbi->rgstate[i] = 0;
150
151   switch(idObject)
152   {
153     case SB_HORZ:
154       Window->pHScroll = psbi;
155       break;
156     case SB_VERT:
157       Window->pVScroll = psbi;
158       break;
159     case SB_CTL:
160       Window->wExtra = psbi;
161       break;
162     default:
163       return FALSE;
164   }
165
166   SCROLL_GetScrollBarRect (Window, idObject, &(psbi->rcScrollBar));
167
168   return 0;
169 }
170
171 DWORD SCROLL_GetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
172 {
173   switch(idObject)
174   {
175     case SB_HORZ:
176       memcpy(psbi, Window->pHScroll, psbi->cbSize);
177       break;
178     case SB_VERT:
179       memcpy(psbi, Window->pVScroll, psbi->cbSize);
180       break;
181     case SB_CTL:
182       memcpy(psbi, Window->wExtra, psbi->cbSize);
183       break;
184     default:
185       W32kReleaseWindowObject(Window);
186       return FALSE;
187   }
188
189   return TRUE;
190 }
191
192 DWORD
193 STDCALL
194 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
195 {
196   PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
197
198   if (!Window) return FALSE;
199
200   SCROLL_GetScrollBarInfo(Window, idObject, psbi);
201
202   W32kReleaseWindowObject(Window);
203
204   return TRUE;
205 }
206
207 DWORD
208 STDCALL
209 NtUserEnableScrollBar(
210   DWORD Unknown0,
211   DWORD Unknown1,
212   DWORD Unknown2)
213 {
214   return 0;
215 }
216
217 DWORD
218 STDCALL
219 NtUserScrollDC(
220   DWORD Unknown0,
221   DWORD Unknown1,
222   DWORD Unknown2,
223   DWORD Unknown3,
224   DWORD Unknown4,
225   DWORD Unknown5,
226   DWORD Unknown6)
227
228 {
229   UNIMPLEMENTED
230
231   return 0;
232 }
233
234 DWORD
235 STDCALL
236 NtUserSetScrollInfo(
237   DWORD Unknown0,
238   DWORD Unknown1,
239   DWORD Unknown2,
240   DWORD Unknown3)
241 {
242   UNIMPLEMENTED
243
244   return 0;
245 }
246
247 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
248 DWORD
249 STDCALL
250 NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
251 {
252   BOOL fShowV = (wBar == SB_VERT) ? 0 : bShow;
253   BOOL fShowH = (wBar == SB_HORZ) ? 0 : bShow;
254   PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
255
256   switch (wBar)
257     {
258     case SB_CTL:
259       NtUserShowWindow (hWnd, fShowH ? SW_SHOW : SW_HIDE);
260       return TRUE;
261
262     case SB_BOTH:
263     case SB_HORZ:
264       if (fShowH)
265         {
266           fShowH = !(Window->Style & WS_HSCROLL);
267           Window->Style |= WS_HSCROLL;
268         }
269       else                      /* hide it */
270         {
271           fShowH = (Window->Style & WS_HSCROLL);
272           Window->Style &= ~WS_HSCROLL;
273         }
274       if (wBar == SB_HORZ)
275         {
276           fShowV = FALSE;
277           break;
278         }
279       /* fall through */
280
281     case SB_VERT:
282       if (fShowV)
283         {
284           fShowV = !(Window->Style & WS_VSCROLL);
285           Window->Style |= WS_VSCROLL;
286         }
287       else                      /* hide it */
288         {
289           fShowV = (Window->Style & WS_VSCROLL);
290           Window->Style &= ~WS_VSCROLL;
291         }
292       if (wBar == SB_VERT)
293         fShowH = FALSE;
294       break;
295
296     default:
297       return FALSE;             /* Nothing to do! */
298     }
299
300   if (fShowH || fShowV)         /* frame has been changed, let the window redraw itself */
301   {
302     NtUserSetWindowPos (hWnd, 0, 0, 0, 0, 0,
303                         SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
304     return TRUE;
305   }
306   return FALSE;                 /* no frame changes */
307 }
308
309 /* EOF */