c31dcf298f7b6511084a0857bb7c26a79ff44a2d
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / scrollbar.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Scrollbars
5 * FILE: subsys/win32k/ntuser/scrollbar.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
7 * Jason Filby (jasonfilby@yahoo.com)
8 */
9
10 #include <win32k.h>
11 DBG_DEFAULT_CHANNEL(UserScrollbar);
12
13 #define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */
14
15 /* What to do after SetScrollInfo() */
16 #define SA_SSI_HIDE 0x0001
17 #define SA_SSI_SHOW 0x0002
18 #define SA_SSI_REFRESH 0x0004
19 #define SA_SSI_REPAINT_ARROWS 0x0008
20
21 #define SBRG_SCROLLBAR 0 /* The scrollbar itself */
22 #define SBRG_TOPRIGHTBTN 1 /* The top or right button */
23 #define SBRG_PAGEUPRIGHT 2 /* The page up or page right region */
24 #define SBRG_SCROLLBOX 3 /* The scroll box */
25 #define SBRG_PAGEDOWNLEFT 4 /* The page down or page left region */
26 #define SBRG_BOTTOMLEFTBTN 5 /* The bottom or left button */
27
28 #define CHANGERGSTATE(item, status) \
29 if(Info->rgstate[(item)] != (status)) \
30 Chg = TRUE; \
31 Info->rgstate[(item)] = (status);
32
33 /* FUNCTIONS *****************************************************************/
34
35 /* Ported from WINE20020904 */
36 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
37 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
38 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
39 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
40 */
41 BOOL FASTCALL
42 IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect)
43 {
44 BOOL vertical;
45 RECTL ClientRect = Wnd->rcClient;
46 RECTL WindowRect = Wnd->rcWindow;
47
48 switch (nBar)
49 {
50 case SB_HORZ:
51 lprect->left = ClientRect.left - WindowRect.left;
52 lprect->top = ClientRect.bottom - WindowRect.top;
53 lprect->right = ClientRect.right - WindowRect.left;
54 lprect->bottom = lprect->top + UserGetSystemMetrics (SM_CYHSCROLL);
55 vertical = FALSE;
56 break;
57
58 case SB_VERT:
59 if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR)
60 {
61 lprect->right = ClientRect.left - WindowRect.left;
62 lprect->left = lprect->right - UserGetSystemMetrics(SM_CXVSCROLL);
63 }
64 else
65 {
66 lprect->left = ClientRect.right - WindowRect.left;
67 lprect->right = lprect->left + UserGetSystemMetrics(SM_CXVSCROLL);
68 }
69 lprect->top = ClientRect.top - WindowRect.top;
70 lprect->bottom = ClientRect.bottom - WindowRect.top;
71 vertical = TRUE;
72 break;
73
74 case SB_CTL:
75 IntGetClientRect (Wnd, lprect);
76 vertical = ((Wnd->style & SBS_VERT) != 0);
77 break;
78
79 default:
80 return FALSE;
81 }
82
83 return vertical;
84 }
85
86 BOOL FASTCALL
87 IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi)
88 {
89 INT Thumb, ThumbBox, ThumbPos, cxy, mx;
90 RECTL ClientRect;
91
92 switch(idObject)
93 {
94 case SB_HORZ:
95 Thumb = UserGetSystemMetrics(SM_CXHSCROLL);
96 cxy = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
97 break;
98 case SB_VERT:
99 Thumb = UserGetSystemMetrics(SM_CYVSCROLL);
100 cxy = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
101 break;
102 case SB_CTL:
103 IntGetClientRect(Wnd, &ClientRect);
104 if(Wnd->style & SBS_VERT)
105 {
106 Thumb = UserGetSystemMetrics(SM_CYVSCROLL);
107 cxy = ClientRect.bottom - ClientRect.top;
108 }
109 else
110 {
111 Thumb = UserGetSystemMetrics(SM_CXHSCROLL);
112 cxy = ClientRect.right - ClientRect.left;
113 }
114 break;
115 default:
116 return FALSE;
117 }
118
119 ThumbPos = Thumb;
120 /* Calculate Thumb */
121 if(cxy <= (2 * Thumb))
122 {
123 Thumb = cxy / 2;
124 psbi->xyThumbTop = 0;
125 psbi->xyThumbBottom = 0;
126 ThumbPos = Thumb;
127 }
128 else
129 {
130 ThumbBox = psi->nPage ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB);
131 cxy -= (2 * Thumb);
132 if(cxy >= ThumbBox)
133 {
134 if(psi->nPage)
135 {
136 ThumbBox = max(EngMulDiv(cxy, psi->nPage, psi->nMax - psi->nMin + 1), ThumbBox);
137 }
138
139 if(cxy > ThumbBox)
140 {
141 mx = psi->nMax - max(psi->nPage - 1, 0);
142 if(psi->nMin < mx)
143 ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, psi->nPos - psi->nMin, mx - psi->nMin);
144 else
145 ThumbPos = Thumb + ThumbBox;
146 }
147
148 psbi->xyThumbTop = ThumbPos;
149 psbi->xyThumbBottom = ThumbPos + ThumbBox;
150 }
151 else
152 {
153 psbi->xyThumbTop = 0;
154 psbi->xyThumbBottom = 0;
155 }
156 }
157 psbi->dxyLineButton = Thumb;
158
159 return TRUE;
160 }
161
162 static VOID FASTCALL
163 IntUpdateSBInfo(PWND Window, int wBar)
164 {
165 PSCROLLBARINFO sbi;
166 LPSCROLLINFO psi;
167
168 ASSERT(Window);
169 ASSERT(Window->pSBInfo);
170 ASSERT(Window->pSBInfoex);
171
172 sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
173 psi = IntGetScrollInfoFromWindow(Window, wBar);
174 IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
175 IntCalculateThumb(Window, wBar, sbi, psi);
176 }
177
178 static BOOL FASTCALL
179 co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi)
180 {
181 UINT Mask;
182 LPSCROLLINFO psi;
183
184 ASSERT_REFS_CO(Window);
185
186 if(!SBID_IS_VALID(nBar))
187 {
188 EngSetLastError(ERROR_INVALID_PARAMETER);
189 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar);
190 return FALSE;
191 }
192
193 if (!Window->pSBInfo) return FALSE;
194
195 psi = IntGetScrollInfoFromWindow(Window, nBar);
196
197 if (lpsi->fMask == SIF_ALL)
198 {
199 Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
200 }
201 else
202 {
203 Mask = lpsi->fMask;
204 }
205
206 if (0 != (Mask & SIF_PAGE))
207 {
208 lpsi->nPage = psi->nPage;
209 }
210
211 if (0 != (Mask & SIF_POS))
212 {
213 lpsi->nPos = psi->nPos;
214 }
215
216 if (0 != (Mask & SIF_RANGE))
217 {
218 lpsi->nMin = psi->nMin;
219 lpsi->nMax = psi->nMax;
220 }
221
222 if (0 != (Mask & SIF_TRACKPOS))
223 {
224 lpsi->nTrackPos = psi->nTrackPos;
225 }
226
227 return TRUE;
228 }
229
230 BOOL FASTCALL
231 NEWco_IntGetScrollInfo(
232 PWND pWnd,
233 INT nBar,
234 PSBDATA pSBData,
235 LPSCROLLINFO lpsi)
236 {
237 UINT Mask;
238 PSBTRACK pSBTrack = pWnd->head.pti->pSBTrack;
239
240 if (!SBID_IS_VALID(nBar))
241 {
242 EngSetLastError(ERROR_INVALID_PARAMETER);
243 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar);
244 return FALSE;
245 }
246
247 if (!pWnd->pSBInfo || !pSBTrack) return FALSE;
248
249 Mask = lpsi->fMask;
250
251 if (0 != (Mask & SIF_PAGE))
252 {
253 lpsi->nPage = pSBData->page;
254 }
255
256 if (0 != (Mask & SIF_POS))
257 {
258 lpsi->nPos = pSBData->pos;
259 }
260
261 if (0 != (Mask & SIF_RANGE))
262 {
263 lpsi->nMin = pSBData->posMin;
264 lpsi->nMax = pSBData->posMax;
265 }
266
267 if (0 != (Mask & SIF_TRACKPOS))
268 {
269 if ( pSBTrack &&
270 pSBTrack->nBar == nBar &&
271 pSBTrack->spwndTrack == pWnd )
272 lpsi->nTrackPos = pSBTrack->posNew;
273 else
274 lpsi->nTrackPos = pSBData->pos;
275 }
276 return (Mask & SIF_ALL) !=0;
277 }
278
279 static DWORD FASTCALL
280 co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
281 {
282 /*
283 * Update the scrollbar state and set action flags according to
284 * what has to be done graphics wise.
285 */
286
287 LPSCROLLINFO Info;
288 PSCROLLBARINFO psbi;
289 UINT new_flags;
290 INT action = 0;
291 BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */
292
293 ASSERT_REFS_CO(Window);
294
295 if(!SBID_IS_VALID(nBar))
296 {
297 EngSetLastError(ERROR_INVALID_PARAMETER);
298 ERR("Trying to set scrollinfo for unknown scrollbar type %d", nBar);
299 return FALSE;
300 }
301
302 if(!co_IntCreateScrollBars(Window))
303 {
304 return FALSE;
305 }
306
307 if (lpsi->cbSize != sizeof(SCROLLINFO) &&
308 lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos)))
309 {
310 EngSetLastError(ERROR_INVALID_PARAMETER);
311 return 0;
312 }
313 if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL))
314 {
315 EngSetLastError(ERROR_INVALID_PARAMETER);
316 return 0;
317 }
318
319 psbi = IntGetScrollbarInfoFromWindow(Window, nBar);
320 Info = IntGetScrollInfoFromWindow(Window, nBar);
321
322 /* Set the page size */
323 if (lpsi->fMask & SIF_PAGE)
324 {
325 if (Info->nPage != lpsi->nPage)
326 {
327 Info->nPage = lpsi->nPage;
328 bChangeParams = TRUE;
329 }
330 }
331
332 /* Set the scroll pos */
333 if (lpsi->fMask & SIF_POS)
334 {
335 if (Info->nPos != lpsi->nPos)
336 {
337 Info->nPos = lpsi->nPos;
338 bChangeParams = TRUE;
339 }
340 }
341
342 /* Set the scroll range */
343 if (lpsi->fMask & SIF_RANGE)
344 {
345 /* Invalid range -> range is set to (0,0) */
346 if ((lpsi->nMin > lpsi->nMax) ||
347 ((UINT)(lpsi->nMax - lpsi->nMin) >= 0x80000000))
348 {
349 Info->nMin = 0;
350 Info->nMax = 0;
351 bChangeParams = TRUE;
352 }
353 else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax)
354 {
355 Info->nMin = lpsi->nMin;
356 Info->nMax = lpsi->nMax;
357 bChangeParams = TRUE;
358 }
359 }
360
361 /* Make sure the page size is valid */
362 if (Info->nPage < 0)
363 Info->nPage = 0;
364 else if ((Info->nMax - Info->nMin + 1UL) < Info->nPage)
365 {
366 Info->nPage = Info->nMax - Info->nMin + 1;
367 }
368
369 /* Make sure the pos is inside the range */
370 if (Info->nPos < Info->nMin)
371 {
372 Info->nPos = Info->nMin;
373 }
374 else if (Info->nPos > (Info->nMax - max((int)Info->nPage - 1, 0)))
375 {
376 Info->nPos = Info->nMax - max(Info->nPage - 1, 0);
377 }
378
379 /*
380 * Don't change the scrollbar state if SetScrollInfo is just called
381 * with SIF_DISABLENOSCROLL
382 */
383 if (!(lpsi->fMask & SIF_ALL))
384 {
385 goto done; //return Info->nPos;
386 }
387
388 /* Check if the scrollbar should be hidden or disabled */
389 if (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
390 {
391 new_flags = Window->pSBInfo->WSBflags;
392 if (Info->nMin >= (int)(Info->nMax - max(Info->nPage - 1, 0)))
393 {
394 /* Hide or disable scroll-bar */
395 if (lpsi->fMask & SIF_DISABLENOSCROLL)
396 {
397 new_flags = ESB_DISABLE_BOTH;
398 bChangeParams = TRUE;
399 }
400 else if ((nBar != SB_CTL) && bChangeParams)
401 {
402 action = SA_SSI_HIDE;
403 }
404 }
405 else /* Show and enable scroll-bar only if no page only changed. */
406 if (lpsi->fMask != SIF_PAGE)
407 {
408 new_flags = ESB_ENABLE_BOTH;
409 if ((nBar != SB_CTL) && bChangeParams)
410 {
411 action |= SA_SSI_SHOW;
412 }
413 }
414
415 if (Window->pSBInfo->WSBflags != new_flags) /* Check arrow flags */
416 {
417 Window->pSBInfo->WSBflags = new_flags;
418 action |= SA_SSI_REPAINT_ARROWS;
419 }
420 }
421
422 done:
423 if ( action & SA_SSI_HIDE )
424 {
425 co_UserShowScrollBar(Window, nBar, FALSE, FALSE);
426 }
427 else
428 {
429 if ( action & SA_SSI_SHOW )
430 if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) )
431 return Info->nPos; /* SetWindowPos() already did the painting */
432 if (bRedraw)
433 { // FIXME: Arrows and interior.
434 RECTL UpdateRect = psbi->rcScrollBar;
435 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
436 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left;
437 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top;
438 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
439 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
440 } // FIXME: Arrows
441 else if( action & SA_SSI_REPAINT_ARROWS )
442 {
443 RECTL UpdateRect = psbi->rcScrollBar;
444 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
445 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left;
446 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top;
447 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
448 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
449 }
450 }
451 /* Return current position */
452 return Info->nPos;
453 }
454
455 BOOL FASTCALL
456 co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
457 {
458 INT Bar;
459 PSCROLLBARINFO sbi;
460 LPSCROLLINFO psi;
461 ASSERT_REFS_CO(Window);
462
463 Bar = SBOBJ_TO_SBID(idObject);
464
465 if(!SBID_IS_VALID(Bar))
466 {
467 EngSetLastError(ERROR_INVALID_PARAMETER);
468 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar);
469 return FALSE;
470 }
471
472 if(!co_IntCreateScrollBars(Window))
473 {
474 return FALSE;
475 }
476
477 sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
478 psi = IntGetScrollInfoFromWindow(Window, Bar);
479
480 IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
481 IntCalculateThumb(Window, Bar, sbi, psi);
482
483 RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
484
485 return TRUE;
486 }
487
488 BOOL FASTCALL
489 co_IntCreateScrollBars(PWND Window)
490 {
491 PSCROLLBARINFO psbi;
492 LPSCROLLINFO psi;
493 ULONG Size, s;
494 INT i;
495
496 ASSERT_REFS_CO(Window);
497
498 if (Window->pSBInfo && Window->pSBInfoex)
499 {
500 /* No need to create it anymore */
501 return TRUE;
502 }
503
504 /* Allocate memory for all scrollbars (HORZ, VERT, CONTROL) */
505 Size = 3 * (sizeof(SBINFOEX));
506 if(!(Window->pSBInfoex = ExAllocatePoolWithTag(PagedPool, Size, TAG_SBARINFO)))
507 {
508 ERR("Unable to allocate memory for scrollbar information for window 0x%x\n", Window->head.h);
509 return FALSE;
510 }
511
512 RtlZeroMemory(Window->pSBInfoex, Size);
513
514 if(!(Window->pSBInfo = DesktopHeapAlloc( Window->head.rpdesk, sizeof(SBINFO))))
515 {
516 ERR("Unable to allocate memory for scrollbar information for window 0x%x\n", Window->head.h);
517 return FALSE;
518 }
519
520 RtlZeroMemory(Window->pSBInfo, sizeof(SBINFO));
521 Window->pSBInfo->Vert.posMax = 100;
522 Window->pSBInfo->Horz.posMax = 100;
523
524 co_WinPosGetNonClientSize(Window,
525 &Window->rcWindow,
526 &Window->rcClient);
527
528 for(s = SB_HORZ; s <= SB_VERT; s++)
529 {
530 psbi = IntGetScrollbarInfoFromWindow(Window, s);
531 psbi->cbSize = sizeof(SCROLLBARINFO);
532 for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
533 psbi->rgstate[i] = 0;
534
535 psi = IntGetScrollInfoFromWindow(Window, s);
536 psi->cbSize = sizeof(LPSCROLLINFO);
537 psi->nMax = 100;
538
539 IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar));
540 IntCalculateThumb(Window, s, psbi, psi);
541 }
542
543 return TRUE;
544 }
545
546 BOOL FASTCALL
547 IntDestroyScrollBars(PWND Window)
548 {
549 if (Window->pSBInfo && Window->pSBInfoex)
550 {
551 DesktopHeapFree(Window->head.rpdesk, Window->pSBInfo);
552 Window->pSBInfo = NULL;
553 ExFreePool(Window->pSBInfoex);
554 Window->pSBInfoex = NULL;
555 return TRUE;
556 }
557 return FALSE;
558 }
559
560 BOOL APIENTRY
561 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows)
562 {
563 BOOL Chg = FALSE;
564 switch(wArrows)
565 {
566 case ESB_DISABLE_BOTH:
567 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
568 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
569 break;
570 case ESB_DISABLE_RTDN:
571 if(Horz)
572 {
573 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
574 }
575 else
576 {
577 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
578 }
579 break;
580 case ESB_DISABLE_LTUP:
581 if(Horz)
582 {
583 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
584 }
585 else
586 {
587 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
588 }
589 break;
590 case ESB_ENABLE_BOTH:
591 CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0);
592 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0);
593 break;
594 }
595 return Chg;
596 }
597
598 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
599 DWORD FASTCALL
600 co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
601 {
602 ULONG old_style, set_bits = 0, clear_bits = 0;
603
604 ASSERT_REFS_CO(Wnd);
605
606 switch(nBar)
607 {
608 case SB_CTL:
609 {
610 if (Wnd->pSBInfo) IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o!
611
612 co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE);
613 return TRUE;
614 }
615 case SB_BOTH:
616 case SB_HORZ:
617 if (fShowH) set_bits |= WS_HSCROLL;
618 else clear_bits |= WS_HSCROLL;
619 if( nBar == SB_HORZ ) break;
620 /* Fall through */
621 case SB_VERT:
622 if (fShowV) set_bits |= WS_VSCROLL;
623 else clear_bits |= WS_VSCROLL;
624 break;
625 default:
626 EngSetLastError(ERROR_INVALID_PARAMETER);
627 return FALSE;
628 }
629
630
631 old_style = Wnd->style;
632 Wnd->style = (Wnd->style | set_bits) & ~clear_bits;
633
634 if (fShowH || fShowV)
635 {
636 if (!Wnd->pSBInfo) co_IntCreateScrollBars(Wnd);
637 }
638
639 if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits)
640 {
641 ///// Is this needed? Was tested w/o!
642 if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
643 if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
644 /////
645 /* Frame has been changed, let the window redraw itself */
646 co_WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
647 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING);
648 return TRUE;
649 }
650 return FALSE;
651 }
652
653 ////
654
655 BOOL
656 APIENTRY
657 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
658 {
659 NTSTATUS Status;
660 SCROLLBARINFO sbi;
661 PWND Window;
662 BOOL Ret;
663 DECLARE_RETURN(BOOL);
664 USER_REFERENCE_ENTRY Ref;
665
666 TRACE("Enter NtUserGetScrollBarInfo\n");
667 UserEnterExclusive();
668
669 Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO));
670 if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO)))
671 {
672 SetLastNtError(Status);
673 RETURN(FALSE);
674 }
675
676 if(!(Window = UserGetWindowObject(hWnd)))
677 {
678 RETURN(FALSE);
679 }
680
681 UserRefObjectCo(Window, &Ref);
682 Ret = co_IntGetScrollBarInfo(Window, idObject, &sbi);
683 UserDerefObjectCo(Window);
684
685 Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO));
686 if(!NT_SUCCESS(Status))
687 {
688 SetLastNtError(Status);
689 Ret = FALSE;
690 }
691
692 RETURN( Ret);
693
694 CLEANUP:
695 TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_);
696 UserLeave();
697 END_CLEANUP;
698
699 }
700
701 BOOL
702 APIENTRY
703 NtUserSBGetParms(
704 HWND hWnd,
705 int fnBar,
706 PSBDATA pSBData,
707 LPSCROLLINFO lpsi)
708 {
709 NTSTATUS Status;
710 PWND Window;
711 SCROLLINFO psi;
712 DWORD sz;
713 BOOL Ret;
714 DECLARE_RETURN(BOOL);
715 USER_REFERENCE_ENTRY Ref;
716
717 TRACE("Enter NtUserGetScrollInfo\n");
718 UserEnterExclusive();
719
720 Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT));
721 if(!NT_SUCCESS(Status) ||
722 !((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos))))
723 {
724 SetLastNtError(Status);
725 RETURN(FALSE);
726 }
727 sz = psi.cbSize;
728 Status = MmCopyFromCaller(&psi, lpsi, sz);
729 if (!NT_SUCCESS(Status))
730 {
731 SetLastNtError(Status);
732 RETURN(FALSE);
733 }
734
735 if(!(Window = UserGetWindowObject(hWnd)))
736 {
737 RETURN(FALSE);
738 }
739
740 UserRefObjectCo(Window, &Ref);
741 Ret = co_IntGetScrollInfo(Window, fnBar, &psi);
742 UserDerefObjectCo(Window);
743
744 Status = MmCopyToCaller(lpsi, &psi, sz);
745 if(!NT_SUCCESS(Status))
746 {
747 SetLastNtError(Status);
748 RETURN( FALSE);
749 }
750
751 RETURN( Ret);
752
753 CLEANUP:
754 TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_);
755 UserLeave();
756 END_CLEANUP;
757 }
758
759 BOOL
760 APIENTRY
761 NtUserEnableScrollBar(
762 HWND hWnd,
763 UINT wSBflags,
764 UINT wArrows)
765 {
766 UINT OrigArrows;
767 PWND Window = NULL;
768 PSCROLLBARINFO InfoV = NULL, InfoH = NULL;
769 BOOL Chg = FALSE;
770 DECLARE_RETURN(BOOL);
771 USER_REFERENCE_ENTRY Ref;
772
773 TRACE("Enter NtUserEnableScrollBar\n");
774 UserEnterExclusive();
775
776 if (!(Window = UserGetWindowObject(hWnd)))
777 {
778 RETURN(FALSE);
779 }
780 UserRefObjectCo(Window, &Ref);
781
782 if (!co_IntCreateScrollBars(Window))
783 {
784 RETURN( FALSE);
785 }
786
787 OrigArrows = Window->pSBInfo->WSBflags;
788 Window->pSBInfo->WSBflags = wArrows;
789
790 if (wSBflags == SB_CTL)
791 {
792 if ((wArrows == ESB_DISABLE_BOTH || wArrows == ESB_ENABLE_BOTH))
793 IntEnableWindow(hWnd, (wArrows == ESB_ENABLE_BOTH));
794
795 RETURN(TRUE);
796 }
797
798 if(wSBflags != SB_BOTH && !SBID_IS_VALID(wSBflags))
799 {
800 EngSetLastError(ERROR_INVALID_PARAMETER);
801 ERR("Trying to set scrollinfo for unknown scrollbar type %d", wSBflags);
802 RETURN(FALSE);
803 }
804
805 switch(wSBflags)
806 {
807 case SB_BOTH:
808 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
809 /* Fall through */
810 case SB_HORZ:
811 InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ);
812 break;
813 case SB_VERT:
814 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
815 break;
816 default:
817 RETURN(FALSE);
818 }
819
820 if(InfoV)
821 Chg = IntEnableScrollBar(FALSE, InfoV, wArrows);
822
823 if(InfoH)
824 Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg);
825
826 ERR("FIXME: EnableScrollBar wSBflags %d wArrows %d Chg %d\n",wSBflags,wArrows, Chg);
827 // Done in user32:
828 // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
829
830 if (OrigArrows == wArrows) RETURN( FALSE);
831 RETURN( TRUE);
832
833 CLEANUP:
834 if (Window)
835 UserDerefObjectCo(Window);
836
837 TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_);
838 UserLeave();
839 END_CLEANUP;
840 }
841
842 DWORD
843 APIENTRY
844 NtUserSetScrollInfo(
845 HWND hWnd,
846 int fnBar,
847 LPCSCROLLINFO lpsi,
848 BOOL bRedraw)
849 {
850 PWND Window = NULL;
851 NTSTATUS Status;
852 SCROLLINFO ScrollInfo;
853 DECLARE_RETURN(DWORD);
854 USER_REFERENCE_ENTRY Ref;
855
856 TRACE("Enter NtUserSetScrollInfo\n");
857 UserEnterExclusive();
858
859 if(!(Window = UserGetWindowObject(hWnd)))
860 {
861 RETURN( 0);
862 }
863 UserRefObjectCo(Window, &Ref);
864
865 Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos));
866 if(!NT_SUCCESS(Status))
867 {
868 SetLastNtError(Status);
869 RETURN( 0);
870 }
871
872 RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw));
873
874 CLEANUP:
875 if (Window)
876 UserDerefObjectCo(Window);
877
878 TRACE("Leave NtUserSetScrollInfo, ret=%i\n",_ret_);
879 UserLeave();
880 END_CLEANUP;
881
882 }
883
884 DWORD APIENTRY
885 NtUserShowScrollBar(HWND hWnd, int nBar, DWORD bShow)
886 {
887 PWND Window;
888 DECLARE_RETURN(DWORD);
889 DWORD ret;
890 USER_REFERENCE_ENTRY Ref;
891
892 TRACE("Enter NtUserShowScrollBar\n");
893 UserEnterExclusive();
894
895 if (!(Window = UserGetWindowObject(hWnd)))
896 {
897 RETURN(0);
898 }
899
900 UserRefObjectCo(Window, &Ref);
901 ret = co_UserShowScrollBar(Window, nBar, (nBar == SB_VERT) ? 0 : bShow,
902 (nBar == SB_HORZ) ? 0 : bShow);
903 UserDerefObjectCo(Window);
904
905 RETURN(ret);
906
907 CLEANUP:
908 TRACE("Leave NtUserShowScrollBar, ret%i\n",_ret_);
909 UserLeave();
910 END_CLEANUP;
911
912 }
913
914
915 //// Ugly NtUser API ////
916
917 BOOL
918 APIENTRY
919 NtUserSetScrollBarInfo(
920 HWND hWnd,
921 LONG idObject,
922 SETSCROLLBARINFO *info)
923 {
924 PWND Window = NULL;
925 SETSCROLLBARINFO Safeinfo;
926 PSCROLLBARINFO sbi;
927 LPSCROLLINFO psi;
928 NTSTATUS Status;
929 LONG Obj;
930 DECLARE_RETURN(BOOL);
931 USER_REFERENCE_ENTRY Ref;
932
933 TRACE("Enter NtUserSetScrollBarInfo\n");
934 UserEnterExclusive();
935
936 if(!(Window = UserGetWindowObject(hWnd)))
937 {
938 RETURN( FALSE);
939 }
940 UserRefObjectCo(Window, &Ref);
941
942 Obj = SBOBJ_TO_SBID(idObject);
943 if(!SBID_IS_VALID(Obj))
944 {
945 EngSetLastError(ERROR_INVALID_PARAMETER);
946 ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj);
947 RETURN( FALSE);
948 }
949
950 if(!co_IntCreateScrollBars(Window))
951 {
952 RETURN(FALSE);
953 }
954
955 Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO));
956 if(!NT_SUCCESS(Status))
957 {
958 SetLastNtError(Status);
959 RETURN(FALSE);
960 }
961
962 sbi = IntGetScrollbarInfoFromWindow(Window, Obj);
963 psi = IntGetScrollInfoFromWindow(Window, Obj);
964
965 psi->nTrackPos = Safeinfo.nTrackPos;
966 sbi->reserved = Safeinfo.reserved;
967 RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate));
968
969 RETURN(TRUE);
970
971 CLEANUP:
972 if (Window)
973 UserDerefObjectCo(Window);
974
975 TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_);
976 UserLeave();
977 END_CLEANUP;
978 }
979
980 /* EOF */