8341ee184e90821ef8cfb0b75db778e128381ebf
[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_CO(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_CO(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
394 if (bRedraw)
395 {
396 RECT UpdateRect = psbi->rcScrollBar;
397 UpdateRect.left -= Window->ClientRect.left - Window->WindowRect.left;
398 UpdateRect.right -= Window->ClientRect.left - Window->WindowRect.left;
399 UpdateRect.top -= Window->ClientRect.top - Window->WindowRect.top;
400 UpdateRect.bottom -= Window->ClientRect.top - Window->WindowRect.top;
401 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
402 }
403
404 /* Return current position */
405 return Info->nPos;
406 }
407
408 BOOL FASTCALL
409 co_IntGetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
410 {
411 INT Bar;
412 PSCROLLBARINFO sbi;
413 LPSCROLLINFO psi;
414
415 ASSERT_REFS_CO(Window);
416
417 Bar = SBOBJ_TO_SBID(idObject);
418
419 if(!SBID_IS_VALID(Bar))
420 {
421 SetLastWin32Error(ERROR_INVALID_PARAMETER);
422 DPRINT1("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar);
423 return FALSE;
424 }
425
426 if(!co_IntCreateScrollBars(Window))
427 {
428 return FALSE;
429 }
430
431 sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
432 psi = IntGetScrollInfoFromWindow(Window, Bar);
433
434 IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
435 IntCalculateThumb(Window, Bar, sbi, psi);
436
437 RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
438
439 return TRUE;
440 }
441
442 BOOL FASTCALL
443 co_IntCreateScrollBars(PWINDOW_OBJECT Window)
444 {
445 PSCROLLBARINFO psbi;
446 LPSCROLLINFO psi;
447 LRESULT Result;
448 ULONG Size, s;
449 INT i;
450
451 ASSERT_REFS_CO(Window);
452
453 if(Window->Scroll)
454 {
455 /* no need to create it anymore */
456 return TRUE;
457 }
458
459 /* allocate memory for all scrollbars (HORZ, VERT, CONTROL) */
460 Size = 3 * (sizeof(WINDOW_SCROLLINFO));
461 if(!(Window->Scroll = ExAllocatePoolWithTag(PagedPool, Size, TAG_SBARINFO)))
462 {
463 DPRINT1("Unable to allocate memory for scrollbar information for window 0x%x\n", Window->hSelf);
464 return FALSE;
465 }
466
467 RtlZeroMemory(Window->Scroll, Size);
468
469 Result = co_WinPosGetNonClientSize(Window->hSelf,
470 &Window->WindowRect,
471 &Window->ClientRect);
472
473 for(s = SB_HORZ; s <= SB_VERT; s++)
474 {
475 psbi = IntGetScrollbarInfoFromWindow(Window, s);
476 psbi->cbSize = sizeof(SCROLLBARINFO);
477 for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
478 psbi->rgstate[i] = 0;
479
480 psi = IntGetScrollInfoFromWindow(Window, s);
481 psi->cbSize = sizeof(LPSCROLLINFO);
482 psi->nMax = 100;
483
484 IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar));
485 IntCalculateThumb(Window, s, psbi, psi);
486 }
487
488 return TRUE;
489 }
490
491 BOOL FASTCALL
492 IntDestroyScrollBars(PWINDOW_OBJECT Window)
493 {
494 if(Window->Scroll)
495 {
496 ExFreePool(Window->Scroll);
497 Window->Scroll = NULL;
498 return TRUE;
499 }
500 return FALSE;
501 }
502
503 BOOL STDCALL
504 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows)
505 {
506 BOOL Chg = FALSE;
507 switch(wArrows)
508 {
509 case ESB_DISABLE_BOTH:
510 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
511 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
512 break;
513 case ESB_DISABLE_RTDN:
514 if(Horz)
515 {
516 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
517 }
518 else
519 {
520 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
521 }
522 break;
523 case ESB_DISABLE_LTUP:
524 if(Horz)
525 {
526 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
527 }
528 else
529 {
530 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
531 }
532 break;
533 case ESB_ENABLE_BOTH:
534 CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0);
535 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0);
536 break;
537 }
538 return Chg;
539 }
540
541
542 BOOL
543 STDCALL
544 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
545 {
546 NTSTATUS Status;
547 SCROLLBARINFO sbi;
548 PWINDOW_OBJECT Window;
549 BOOL Ret;
550 DECLARE_RETURN(BOOL);
551
552 DPRINT("Enter NtUserGetScrollBarInfo\n");
553 UserEnterExclusive();
554
555 Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO));
556 if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO)))
557 {
558 SetLastNtError(Status);
559 RETURN(FALSE);
560 }
561
562 if(!(Window = UserGetWindowObject(hWnd)))
563 {
564 RETURN(FALSE);
565 }
566
567 UserRefObjectCo(Window);
568 Ret = co_IntGetScrollBarInfo(Window, idObject, &sbi);
569 UserDerefObjectCo(Window);
570
571 Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO));
572 if(!NT_SUCCESS(Status))
573 {
574 SetLastNtError(Status);
575 Ret = FALSE;
576 }
577
578 RETURN( Ret);
579
580 CLEANUP:
581 DPRINT("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_);
582 UserLeave();
583 END_CLEANUP;
584
585 }
586
587
588 BOOL
589 STDCALL
590 NtUserGetScrollInfo(HWND hWnd, int fnBar, LPSCROLLINFO lpsi)
591 {
592 NTSTATUS Status;
593 PWINDOW_OBJECT Window;
594 SCROLLINFO psi;
595 DWORD sz;
596 BOOL Ret;
597 DECLARE_RETURN(BOOL);
598
599 DPRINT("Enter NtUserGetScrollInfo\n");
600 UserEnterShared();
601
602 Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT));
603 if(!NT_SUCCESS(Status) ||
604 !((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos))))
605 {
606 SetLastNtError(Status);
607 RETURN(FALSE);
608 }
609 sz = psi.cbSize;
610 Status = MmCopyFromCaller(&psi, lpsi, sz);
611 if (!NT_SUCCESS(Status))
612 {
613 SetLastNtError(Status);
614 RETURN(FALSE);
615 }
616
617 if(!(Window = UserGetWindowObject(hWnd)))
618 {
619 RETURN(FALSE);
620 }
621
622 UserRefObjectCo(Window);
623 Ret = co_IntGetScrollInfo(Window, fnBar, &psi);
624 UserDerefObjectCo(Window);
625
626 Status = MmCopyToCaller(lpsi, &psi, sz);
627 if(!NT_SUCCESS(Status))
628 {
629 SetLastNtError(Status);
630 RETURN( FALSE);
631 }
632
633 RETURN( Ret);
634
635 CLEANUP:
636 DPRINT("Leave NtUserGetScrollInfo, ret=%i\n",_ret_);
637 UserLeave();
638 END_CLEANUP;
639 }
640
641
642 BOOL
643 STDCALL
644 NtUserEnableScrollBar(
645 HWND hWnd,
646 UINT wSBflags,
647 UINT wArrows)
648 {
649 PWINDOW_OBJECT Window = NULL;
650 PSCROLLBARINFO InfoV = NULL, InfoH = NULL;
651 BOOL Chg = FALSE;
652 DECLARE_RETURN(BOOL);
653
654 DPRINT("Enter NtUserEnableScrollBar\n");
655 UserEnterExclusive();
656
657 if(!(Window = UserGetWindowObject(hWnd)))
658 {
659 RETURN(FALSE);
660 }
661 UserRefObjectCo(Window);
662
663 if(wSBflags == SB_CTL)
664 {
665 /* FIXME Enable or Disable SB Ctrl*/
666 DPRINT1("Enable Scrollbar SB_CTL\n");
667 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_CTL);
668 Chg = IntEnableScrollBar(FALSE, InfoV ,wArrows);
669 /* Chg? Scrollbar is Refresh in user32/controls/scrollbar.c. */
670
671 RETURN(TRUE);
672 }
673
674 if(wSBflags != SB_BOTH && !SBID_IS_VALID(wSBflags))
675 {
676 SetLastWin32Error(ERROR_INVALID_PARAMETER);
677 DPRINT1("Trying to set scrollinfo for unknown scrollbar type %d", wSBflags);
678 RETURN(FALSE);
679 }
680
681 if(!co_IntCreateScrollBars(Window))
682 {
683 RETURN( FALSE);
684 }
685
686 switch(wSBflags)
687 {
688 case SB_BOTH:
689 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
690 /* fall through */
691 case SB_HORZ:
692 InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ);
693 break;
694 case SB_VERT:
695 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
696 break;
697 default:
698 RETURN(FALSE);
699 }
700
701 if(InfoV)
702 Chg = IntEnableScrollBar(FALSE, InfoV, wArrows);
703
704 if(InfoH)
705 Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg);
706
707 //if(Chg && (Window->Style & WS_VISIBLE))
708 /* FIXME - repaint scrollbars */
709
710 RETURN( TRUE);
711
712 CLEANUP:
713 if (Window)
714 UserDerefObjectCo(Window);
715
716 DPRINT("Leave NtUserEnableScrollBar, ret=%i\n",_ret_);
717 UserLeave();
718 END_CLEANUP;
719 }
720
721 BOOL
722 STDCALL
723 NtUserSetScrollBarInfo(
724 HWND hWnd,
725 LONG idObject,
726 SETSCROLLBARINFO *info)
727 {
728 PWINDOW_OBJECT Window = NULL;
729 SETSCROLLBARINFO Safeinfo;
730 PSCROLLBARINFO sbi;
731 LPSCROLLINFO psi;
732 NTSTATUS Status;
733 LONG Obj;
734 DECLARE_RETURN(BOOL);
735
736 DPRINT("Enter NtUserSetScrollBarInfo\n");
737 UserEnterExclusive();
738
739 if(!(Window = UserGetWindowObject(hWnd)))
740 {
741 RETURN( FALSE);
742 }
743 UserRefObjectCo(Window);
744
745 Obj = SBOBJ_TO_SBID(idObject);
746 if(!SBID_IS_VALID(Obj))
747 {
748 SetLastWin32Error(ERROR_INVALID_PARAMETER);
749 DPRINT1("Trying to set scrollinfo for unknown scrollbar type %d", Obj);
750 RETURN( FALSE);
751 }
752
753 if(!co_IntCreateScrollBars(Window))
754 {
755 RETURN(FALSE);
756 }
757
758 Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO));
759 if(!NT_SUCCESS(Status))
760 {
761 SetLastNtError(Status);
762 RETURN(FALSE);
763 }
764
765 sbi = IntGetScrollbarInfoFromWindow(Window, Obj);
766 psi = IntGetScrollInfoFromWindow(Window, Obj);
767
768 psi->nTrackPos = Safeinfo.nTrackPos;
769 sbi->reserved = Safeinfo.reserved;
770 RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate));
771
772 RETURN(TRUE);
773
774 CLEANUP:
775 if (Window)
776 UserDerefObjectCo(Window);
777
778 DPRINT("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_);
779 UserLeave();
780 END_CLEANUP;
781 }
782
783 DWORD
784 STDCALL
785 NtUserSetScrollInfo(
786 HWND hWnd,
787 int fnBar,
788 LPCSCROLLINFO lpsi,
789 BOOL bRedraw)
790 {
791 PWINDOW_OBJECT Window = NULL;
792 NTSTATUS Status;
793 SCROLLINFO ScrollInfo;
794 DECLARE_RETURN(DWORD);
795
796 DPRINT("Enter NtUserSetScrollInfo\n");
797 UserEnterExclusive();
798
799 if(!(Window = UserGetWindowObject(hWnd)))
800 {
801 RETURN( 0);
802 }
803 UserRefObjectCo(Window);
804
805 Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos));
806 if(!NT_SUCCESS(Status))
807 {
808 SetLastNtError(Status);
809 RETURN( 0);
810 }
811
812 RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw));
813
814 CLEANUP:
815 if (Window)
816 UserDerefObjectCo(Window);
817
818 DPRINT("Leave NtUserSetScrollInfo, ret=%i\n",_ret_);
819 UserLeave();
820 END_CLEANUP;
821
822 }
823
824 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
825 DWORD FASTCALL
826 co_UserShowScrollBar(PWINDOW_OBJECT Window, int wBar, DWORD bShow)
827 {
828 DWORD Style, OldStyle;
829
830 ASSERT_REFS_CO(Window);
831
832 switch(wBar)
833 {
834 case SB_HORZ:
835 Style = WS_HSCROLL;
836 break;
837 case SB_VERT:
838 Style = WS_VSCROLL;
839 break;
840 case SB_BOTH:
841 Style = WS_HSCROLL | WS_VSCROLL;
842 break;
843 case SB_CTL:
844 Style = 0;
845 break;
846 default:
847 SetLastWin32Error(ERROR_INVALID_PARAMETER);
848 return( FALSE);
849 }
850
851 if(!co_IntCreateScrollBars(Window))
852 {
853 return( FALSE);
854 }
855
856 if (wBar == SB_CTL)
857 {
858 IntUpdateSBInfo(Window, SB_CTL);
859
860 co_WinPosShowWindow(Window, bShow ? SW_SHOW : SW_HIDE);
861 return( TRUE);
862 }
863
864 OldStyle = Window->Style;
865 if(bShow)
866 Window->Style |= Style;
867 else
868 Window->Style &= ~Style;
869
870 if(Window->Style != OldStyle)
871 {
872 if(Window->Style & WS_HSCROLL)
873 IntUpdateSBInfo(Window, SB_HORZ);
874 if(Window->Style & WS_VSCROLL)
875 IntUpdateSBInfo(Window, SB_VERT);
876
877 if(Window->Style & WS_VISIBLE)
878 {
879 /* Frame has been changed, let the window redraw itself */
880 co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
881 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING);
882 }
883 }
884
885 return( TRUE);
886 }
887
888
889 DWORD STDCALL
890 NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
891 {
892 PWINDOW_OBJECT Window;
893 DECLARE_RETURN(DWORD);
894 DWORD ret;
895
896 DPRINT("Enter NtUserShowScrollBar\n");
897 UserEnterExclusive();
898
899 if (!(Window = UserGetWindowObject(hWnd)))
900 {
901 RETURN(0);
902 }
903
904 UserRefObjectCo(Window);
905 ret = co_UserShowScrollBar(Window, wBar, bShow);
906 UserDerefObjectCo(Window);
907
908 RETURN(ret);
909
910 CLEANUP:
911 DPRINT("Leave NtUserShowScrollBar, ret%i\n",_ret_);
912 UserLeave();
913 END_CLEANUP;
914
915 }
916 /* EOF */