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