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