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