]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/splittree.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / splittree.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        splittree.cpp
3 // Purpose:     Classes to achieve a remotely-scrolled tree in a splitter
4 //              window that can be scrolled by a scrolled window higher in the
5 //              hierarchy
6 // Author:      Julian Smart
7 // Modified by:
8 // Created:     8/7/2000
9 // RCS-ID:      $Id$
10 // Copyright:   (c) Julian Smart
11 //
12 // This program is part of the eCos host tools.
13 //
14 // This program is free software; you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 of the License, or (at your option)
17 // any later version.
18 //
19 // This program is distributed in the hope that it will be useful, but WITHOUT
20 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
22 // more details.
23 //
24 // You should have received a copy of the GNU General Public License along with
25 // this program; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27 //
28 /////////////////////////////////////////////////////////////////////////////
29
30 // ============================================================================
31 // declarations
32 // ============================================================================
33
34 // ----------------------------------------------------------------------------
35 // headers
36 // ----------------------------------------------------------------------------
37 #ifdef __GNUG__
38 #pragma implementation "splittree.h"
39 #endif
40
41 // For compilers that support precompilation, includes "wx/wx.h".
42 #include "ecpch.h"
43
44 #ifdef __WXMSW__
45 #include "wx/msw/private.h"
46 #endif
47
48 #ifdef __BORLANDC__
49 #pragma hdrstop
50 #endif
51
52 #include "wx/generic/treectlg.h"
53
54 #include "splittree.h"
55 #include <math.h>
56
57 /*
58 * wxRemotelyScrolledTreeCtrl
59 */
60
61 #if USE_GENERIC_TREECTRL
62 IMPLEMENT_CLASS(wxRemotelyScrolledTreeCtrl, wxGenericTreeCtrl)
63 #else
64 IMPLEMENT_CLASS(wxRemotelyScrolledTreeCtrl, wxTreeCtrl)
65 #endif
66
67 #if USE_GENERIC_TREECTRL
68 BEGIN_EVENT_TABLE(wxRemotelyScrolledTreeCtrl, wxGenericTreeCtrl)
69 #else
70 BEGIN_EVENT_TABLE(wxRemotelyScrolledTreeCtrl, wxTreeCtrl)
71 #endif
72 EVT_SIZE(wxRemotelyScrolledTreeCtrl::OnSize)
73 EVT_TREE_ITEM_EXPANDED(-1, wxRemotelyScrolledTreeCtrl::OnExpand)
74 EVT_TREE_ITEM_COLLAPSED(-1, wxRemotelyScrolledTreeCtrl::OnExpand)
75 EVT_SCROLLWIN(wxRemotelyScrolledTreeCtrl::OnScroll)
76 END_EVENT_TABLE()
77
78 wxRemotelyScrolledTreeCtrl::wxRemotelyScrolledTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pt,
79                                                        const wxSize& sz, long style):
80     wxTreeCtrl(parent, id, pt, sz, style
81 #if wxVERSION_NUMBER > 2301
82                & ~wxTR_ROW_LINES
83 #endif
84                )
85 {
86     m_companionWindow = NULL;
87 }
88
89 wxRemotelyScrolledTreeCtrl::~wxRemotelyScrolledTreeCtrl()
90 {
91 }
92
93 void wxRemotelyScrolledTreeCtrl::HideVScrollbar()
94 {
95 #ifdef __WXMSW__
96     if (!IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
97     {
98         ::ShowScrollBar((HWND) GetHWND(), SB_VERT, FALSE);
99     }
100     else
101 #endif
102     {
103         // Implicit in overriding SetScrollbars
104     }
105 }
106
107 // Number of pixels per user unit (0 or -1 for no scrollbar)
108 // Length of virtual canvas in user units
109 // Length of page in user units
110 void wxRemotelyScrolledTreeCtrl::SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
111                                                int noUnitsX, int noUnitsY,
112                                                int xPos, int yPos,
113                                                bool noRefresh)
114 {
115     if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
116     {
117         wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
118         // Pass TRUE for noRefresh so that it doesn't
119         // draw part of the tree as if the scroll view is
120         // at zero vertically.
121         win->wxGenericTreeCtrl::SetScrollbars(pixelsPerUnitX, pixelsPerUnitY, noUnitsX, 0, xPos, 0, /* noRefresh */ TRUE);
122         
123         ecScrolledWindow* scrolledWindow = GetScrolledWindow();
124         if (scrolledWindow)
125         {
126             scrolledWindow->SetScrollbars(0, pixelsPerUnitY, 0, noUnitsY, 0, yPos, noRefresh);
127         }
128     }
129 }
130
131 // In case we're using the generic tree control.
132 int wxRemotelyScrolledTreeCtrl::GetScrollPos(int orient) const
133 {
134     ecScrolledWindow* scrolledWindow = GetScrolledWindow();
135     
136     if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
137     {
138         wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
139         
140         if (orient == wxHORIZONTAL)
141             return win->wxGenericTreeCtrl::GetScrollPos(orient);
142         else
143         {
144             return scrolledWindow->GetScrollPos(orient);
145         }
146     }
147     return 0;
148 }
149
150
151 // In case we're using the generic tree control.
152 // Get the view start
153 void wxRemotelyScrolledTreeCtrl::GetViewStart(int *x, int *y) const
154 {
155     ecScrolledWindow* scrolledWindow = GetScrolledWindow();
156     
157     if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
158     {
159         
160         wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
161         int x1, y1, x2, y2;
162         win->wxGenericTreeCtrl::GetViewStart(& x1, & y1);
163         * x = x1; * y = y1;
164         if (!scrolledWindow)
165             return;
166         
167         scrolledWindow->GetViewStart(& x2, & y2);
168         * y = y2;
169     }
170     else
171     {
172         // x is wrong since the horizontal scrollbar is controlled by the
173         // tree control, but we probably don't need it.
174         scrolledWindow->GetViewStart(x, y);
175     }
176 }
177
178 // In case we're using the generic tree control.
179 void wxRemotelyScrolledTreeCtrl::PrepareDC(wxDC& dc)
180 {
181     if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
182     {
183         ecScrolledWindow* scrolledWindow = GetScrolledWindow();
184         
185         wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
186         
187         int startX, startY;
188         GetViewStart(& startX, & startY);
189         
190         int xppu1, yppu1, xppu2, yppu2;
191         win->wxGenericTreeCtrl::GetScrollPixelsPerUnit(& xppu1, & yppu1);
192         scrolledWindow->GetScrollPixelsPerUnit(& xppu2, & yppu2);
193         
194         dc.SetDeviceOrigin( -startX * xppu1, -startY * yppu2 );
195         // dc.SetUserScale( win->GetScaleX(), win->GetScaleY() );
196     }
197 }
198
199 // Scroll to the given line (in scroll units where each unit is
200 // the height of an item)
201 void wxRemotelyScrolledTreeCtrl::ScrollToLine(int posHoriz, int posVert)
202 {
203 #ifdef __WXMSW__
204     if (!IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
205     {
206         UINT sbCode = SB_THUMBPOSITION;
207         HWND vertScrollBar = 0;
208         MSWDefWindowProc((WXUINT) WM_VSCROLL, MAKELONG(sbCode, posVert), (WXHWND) vertScrollBar);
209     }
210     else
211 #endif
212     {
213         wxGenericTreeCtrl* win = (wxGenericTreeCtrl*) this;
214         win->Refresh();
215         /* Doesn't work yet because scrolling is ignored by Scroll
216         int xppu, yppu;
217         wxScrolledWindow* scrolledWindow = GetScrolledWindow();
218         if (scrolledWindow)
219         {
220         scrolledWindow->GetScrollPixelsPerUnit(& xppu, & yppu);
221         win->Scroll(-1, posVert*yppu);
222         }
223         */
224     }
225 }
226
227 void wxRemotelyScrolledTreeCtrl::OnSize(wxSizeEvent& event)
228 {
229     HideVScrollbar();
230     AdjustRemoteScrollbars();
231     event.Skip();
232 }
233
234 void wxRemotelyScrolledTreeCtrl::OnExpand(wxTreeEvent& event)
235 {
236     AdjustRemoteScrollbars();
237     event.Skip();
238     
239     // If we don't have this, we get some bits of lines still remaining
240     if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
241         Refresh();
242     
243     // Pass on the event
244     if (m_companionWindow)
245         m_companionWindow->GetEventHandler()->ProcessEvent(event);
246 }
247
248 // Adjust the containing wxScrolledWindow's scrollbars appropriately
249 void wxRemotelyScrolledTreeCtrl::AdjustRemoteScrollbars()
250 {
251     if (IsKindOf(CLASSINFO(wxGenericTreeCtrl)))
252     {
253         // This is for the generic tree control.
254         // It calls SetScrollbars which has been overridden
255         // to adjust the parent scrolled window vertical
256         // scrollbar.
257         ((wxGenericTreeCtrl*) this)->AdjustMyScrollbars();
258         return;
259     }
260     else
261     {
262         // This is for the wxMSW tree control
263         ecScrolledWindow* scrolledWindow = GetScrolledWindow();
264         if (scrolledWindow)
265         {
266             wxRect itemRect;
267             if (GetBoundingRect(GetRootItem(), itemRect))
268             {
269                 // Actually, the real height seems to be 1 less than reported
270                 // (e.g. 16 instead of 16)
271                 int itemHeight = itemRect.GetHeight() - 1;
272                 
273                 int w, h;
274                 GetClientSize(&w, &h);
275                 
276                 wxRect rect(0, 0, 0, 0);
277                 CalcTreeSize(rect);
278                 
279                 double f = ((double) (rect.GetHeight()) / (double) itemHeight)  ;
280                 int treeViewHeight = (int) ceil(f);
281                 
282                 int scrollPixelsPerLine = itemHeight;
283                 int scrollPos = - (itemRect.y / itemHeight);
284                 
285                 scrolledWindow->SetScrollbars(0, scrollPixelsPerLine, 0, treeViewHeight, 0, scrollPos);
286                 
287                 // Ensure that when a scrollbar becomes hidden or visible,
288                 // the contained window sizes are right.
289                 // Problem: this is called too early (?)
290                 wxSizeEvent event(scrolledWindow->GetSize(), scrolledWindow->GetId());
291                 scrolledWindow->GetEventHandler()->ProcessEvent(event);
292             }
293         }
294     }
295 }
296
297
298 // Calculate the area that contains both rectangles
299 static wxRect CombineRectangles(const wxRect& rect1, const wxRect& rect2)
300 {
301     wxRect rect;
302     
303     int right1 = rect1.GetRight();
304     int bottom1 = rect1.GetBottom();
305     int right2 = rect2.GetRight();
306     int bottom2 = rect2.GetBottom();
307     
308     wxPoint topLeft = wxPoint(wxMin(rect1.x, rect2.x), wxMin(rect1.y, rect2.y));
309     wxPoint bottomRight = wxPoint(wxMax(right1, right2), wxMax(bottom1, bottom2));
310     
311     rect.x = topLeft.x; rect.y = topLeft.y;
312     rect.SetRight(bottomRight.x);
313     rect.SetBottom(bottomRight.y);
314     
315     return rect;
316 }
317
318
319 // Calculate the tree overall size so we can set the scrollbar
320 // correctly
321
322 // static int g_count = 0;
323
324 void wxRemotelyScrolledTreeCtrl::CalcTreeSize(wxRect& rect)
325 {
326     //    g_count = 0;
327     CalcTreeSize(GetRootItem(), rect);
328 }
329
330 void wxRemotelyScrolledTreeCtrl::CalcTreeSize(const wxTreeItemId& id, wxRect& rect)
331 {
332     // More efficient implementation would be to find the last item (but how?)
333     // Q: is the bounding rect relative to the top of the virtual tree workspace
334     // or the top of the window? How would we convert?
335     wxRect itemSize;
336     if (GetBoundingRect(id, itemSize))
337     {
338         rect = CombineRectangles(rect, itemSize);
339     }
340
341     long cookie;
342     wxTreeItemId childId = GetFirstChild(id, cookie);
343     while (childId != 0)
344     {
345         CalcTreeSize(childId, rect);
346         childId = GetNextChild(childId, cookie);
347     }
348 }
349
350 // Find the scrolled window that contains this control
351 ecScrolledWindow* wxRemotelyScrolledTreeCtrl::GetScrolledWindow() const
352 {
353     wxWindow* parent = wxWindow::GetParent();
354     while (parent)
355     {
356         if (parent->IsKindOf(CLASSINFO(ecScrolledWindow)))
357             return (ecScrolledWindow*) parent;
358         parent = parent->GetParent();
359     }
360     return NULL;
361 }
362
363 void wxRemotelyScrolledTreeCtrl::OnScroll(wxScrollWinEvent& event)
364 {
365     int orient = event.GetOrientation();
366     if (orient == wxHORIZONTAL)
367     {
368         event.Skip();
369         return;
370     }
371     ecScrolledWindow* scrollWin = GetScrolledWindow();
372     if (!scrollWin)
373         return;
374     
375     int x, y;
376     scrollWin->GetViewStart(& x, & y);
377     
378     ScrollToLine(-1, y);
379 }
380
381 /*
382 * wxTreeCompanionWindow
383 *
384 * A window displaying values associated with tree control items.
385 */
386
387 IMPLEMENT_CLASS(wxTreeCompanionWindow, wxWindow)
388
389 BEGIN_EVENT_TABLE(wxTreeCompanionWindow, wxWindow)
390 EVT_PAINT(wxTreeCompanionWindow::OnPaint)
391 EVT_SCROLLWIN(wxTreeCompanionWindow::OnScroll)
392 EVT_TREE_ITEM_EXPANDED(-1, wxTreeCompanionWindow::OnExpand)
393 EVT_TREE_ITEM_COLLAPSED(-1, wxTreeCompanionWindow::OnExpand)
394 END_EVENT_TABLE()
395
396 wxTreeCompanionWindow::wxTreeCompanionWindow(wxWindow* parent, wxWindowID id,
397                                              const wxPoint& pos,
398                                              const wxSize& sz,
399                                              long style):
400 wxWindow(parent, id, pos, sz, style)
401 {
402     m_treeCtrl = NULL;
403 }
404
405 void wxTreeCompanionWindow::DrawItem(wxDC& dc, wxTreeItemId id, const wxRect& rect)
406 {
407     if (m_treeCtrl)
408     {
409         wxString text = m_treeCtrl->GetItemText(id);
410         dc.SetTextForeground(* wxBLACK);
411         dc.SetBackgroundMode(wxTRANSPARENT);
412         
413         int textW, textH;
414         dc.GetTextExtent(text, & textW, & textH);
415         
416         int x = 5;
417         int y = rect.GetY() + wxMax(0, (rect.GetHeight() - textH) / 2);
418         
419         dc.DrawText(text, x, y);
420     }
421 }
422
423 void wxTreeCompanionWindow::OnPaint(wxPaintEvent& event)
424 {
425     wxPaintDC dc(this);
426     
427     if (!m_treeCtrl)
428         return;
429     
430     wxPen pen(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
431     dc.SetPen(pen);
432     dc.SetBrush(* wxTRANSPARENT_BRUSH);
433     wxFont font(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
434     dc.SetFont(font);
435     
436     wxSize clientSize = GetClientSize();
437     wxRect itemRect;
438     int cy=0;
439     wxTreeItemId h, lastH;
440     for(h=m_treeCtrl->GetFirstVisibleItem();h;h=m_treeCtrl->GetNextVisible(h))
441     {
442         if (m_treeCtrl->GetBoundingRect(h, itemRect))
443         {
444             cy = itemRect.GetTop();
445             wxRect drawItemRect(0, cy, clientSize.x, itemRect.GetHeight());
446             
447             lastH = h;
448             
449             // Draw the actual item
450             DrawItem(dc, h, drawItemRect);
451             dc.DrawLine(0, cy, clientSize.x, cy);
452         }
453     }
454     if (lastH.IsOk() && m_treeCtrl->GetBoundingRect(lastH, itemRect))
455     {
456         cy = itemRect.GetBottom();
457         dc.DrawLine(0, cy, clientSize.x, cy);
458     }
459 }
460
461 void wxTreeCompanionWindow::OnScroll(wxScrollWinEvent& event)
462 {
463     int orient = event.GetOrientation();
464     if (orient == wxHORIZONTAL)
465     {
466         event.Skip();
467         return;
468     }
469     if (!m_treeCtrl)
470         return;
471     
472     // TODO: scroll the window physically instead of just refreshing.
473     Refresh(TRUE);
474 }
475
476 void wxTreeCompanionWindow::OnExpand(wxTreeEvent& event)
477 {
478     // TODO: something more optimized than simply refresh the whole
479     // window when the tree is expanded/collapsed. Tricky.
480     Refresh();
481 }
482
483 /*
484 * wxThinSplitterWindow
485 */
486
487 IMPLEMENT_CLASS(wxThinSplitterWindow, wxSplitterWindow)
488
489 BEGIN_EVENT_TABLE(wxThinSplitterWindow, wxSplitterWindow)
490 EVT_SIZE(wxThinSplitterWindow::OnSize)
491 // Not in older versions of wxWindows, unfortunately
492 #if 0
493 EVT_SPLITTER_DOUBLECLICKED(-1, wxThinSplitterWindow::OnDoubleClickSash)
494 #endif
495 END_EVENT_TABLE()
496
497 wxThinSplitterWindow::wxThinSplitterWindow(wxWindow* parent, wxWindowID id,
498                                            const wxPoint& pos,
499                                            const wxSize& sz,
500                                            long style):
501 wxSplitterWindow(parent, id, pos, sz, style)
502 {
503 }
504
505 void wxThinSplitterWindow::SizeWindows()
506 {
507     // The client size may have changed inbetween
508     // the sizing of the first window and the sizing of
509     // the second. So repeat SizeWindows.
510     wxSplitterWindow::SizeWindows();
511     wxSplitterWindow::SizeWindows();
512 }
513
514 // Tests for x, y over sash
515 bool wxThinSplitterWindow::SashHitTest(int x, int y, int tolerance)
516 {
517     return wxSplitterWindow::SashHitTest(x, y, 4);
518 }
519
520 void wxThinSplitterWindow::DrawSash(wxDC& dc)
521 {
522     if ( m_sashPosition == 0 || !m_windowTwo)
523         return;
524     if (GetWindowStyle() & wxSP_NOSASH)
525         return;
526     
527     int w, h;
528     GetClientSize(&w, &h);
529     
530     if ( m_splitMode == wxSPLIT_VERTICAL )
531     {
532         dc.SetPen(* m_facePen);
533         dc.SetBrush(* m_faceBrush);
534         int h1 = h-1;
535         int y1 = 0;
536         if ( (GetWindowStyleFlag() & wxSP_BORDER) != wxSP_BORDER && (GetWindowStyleFlag() & wxSP_3DBORDER) != wxSP_3DBORDER )
537             h1 += 1; // Not sure why this is necessary...
538         if ( (GetWindowStyleFlag() & wxSP_3DBORDER) == wxSP_3DBORDER)
539         {
540             y1 = 2; h1 -= 3;
541         }
542         dc.DrawRectangle(m_sashPosition, y1, m_sashSize, h1);
543     }
544     else
545     {
546         dc.SetPen(* m_facePen);
547         dc.SetBrush(* m_faceBrush);
548         int w1 = w-1;
549         int x1 = 0;
550         if ( (GetWindowStyleFlag() & wxSP_BORDER) != wxSP_BORDER && (GetWindowStyleFlag() & wxSP_3DBORDER) != wxSP_3DBORDER )
551             w1 ++;
552         if ( (GetWindowStyleFlag() & wxSP_3DBORDER) == wxSP_3DBORDER)
553         {
554             x1 = 2; w1 -= 3;
555         }
556         dc.DrawRectangle(x1, m_sashPosition, w1, m_sashSize);
557     }
558     
559     dc.SetPen(wxNullPen);
560     dc.SetBrush(wxNullBrush);
561 }
562
563 void wxThinSplitterWindow::OnSize(wxSizeEvent& event)
564 {
565     wxSplitterWindow::OnSize(event);
566 }
567
568 /*
569 * wxSplitterScrolledWindow
570 */
571
572 IMPLEMENT_CLASS(wxSplitterScrolledWindow, ecScrolledWindow)
573
574 BEGIN_EVENT_TABLE(wxSplitterScrolledWindow, ecScrolledWindow)
575 EVT_SCROLLWIN(wxSplitterScrolledWindow::OnScroll)
576 EVT_SIZE(wxSplitterScrolledWindow::OnSize)
577 END_EVENT_TABLE()
578
579 wxSplitterScrolledWindow::wxSplitterScrolledWindow(wxWindow* parent, wxWindowID id,
580                                                    const wxPoint& pos,
581                                                    const wxSize& sz,
582                                                    long style):
583   ecScrolledWindow(parent, id, pos, sz, style)
584 {
585 }
586
587 void wxSplitterScrolledWindow::OnSize(wxSizeEvent& event)
588 {
589     wxSize sz = GetClientSize();
590     if (GetChildren().First())
591     {
592         ((wxWindow*) GetChildren().First()->Data())->SetSize(0, 0, sz.x, sz.y);
593     }
594 }
595
596 void wxSplitterScrolledWindow::OnScroll(wxScrollWinEvent& event)
597 {
598     // Ensure that events being propagated back up the window hierarchy
599     // don't cause an infinite loop
600     static bool inOnScroll = FALSE;
601     if (inOnScroll)
602     {
603         event.Skip();
604         return;
605     }
606     inOnScroll = TRUE;
607     
608     int orient = event.GetOrientation();
609     
610     int nScrollInc = CalcScrollInc(event);
611     if (nScrollInc == 0)
612     {
613         inOnScroll = FALSE;
614         return;
615     }
616     
617     if (orient == wxHORIZONTAL)
618     {
619         inOnScroll = FALSE;
620         event.Skip();
621         return;
622 #if 0
623         int newPos = m_xScrollPosition + nScrollInc;
624         SetScrollPos(wxHORIZONTAL, newPos, TRUE );
625 #endif
626     }
627     else
628     {
629         int newPos = m_yScrollPosition + nScrollInc;
630         SetScrollPos(wxVERTICAL, newPos, TRUE );
631     }
632     
633     if (orient == wxHORIZONTAL)
634     {
635         m_xScrollPosition += nScrollInc;
636     }
637     else
638     {
639         m_yScrollPosition += nScrollInc;
640     }
641     
642     // Find targets in splitter window and send the event to them
643     wxNode* node = GetChildren().First();
644     while (node)
645     {
646         wxWindow* child = (wxWindow*) node->Data();
647         if (child->IsKindOf(CLASSINFO(wxSplitterWindow)))
648         {
649             wxSplitterWindow* splitter = (wxSplitterWindow*) child;
650             if (splitter->GetWindow1())
651                 splitter->GetWindow1()->ProcessEvent(event);
652             if (splitter->GetWindow2())
653                 splitter->GetWindow2()->ProcessEvent(event);
654             break;
655         }
656         node = node->Next();
657     }
658     
659 #ifdef __WXMAC__
660     m_targetWindow->MacUpdateImmediately() ;
661 #endif
662     
663     inOnScroll = FALSE;
664 }
665