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