riched20: Rewrite of scrolling and some redrawing code [RESUBMIT]

Matt Finnicum mattfinn at gmail.com
Fri Sep 8 16:37:25 CDT 2006


Hello,
Sorry for combining this into one large patch, but most of it can't be
done separately (just centralizing the scroll code, for example,
brings about an ugly recursive loop with EnsureVisible). I've tested
this with a dozen programs that have shown bugs before, without any
issue. This fixes both the scrollbar and the accept button in the FEAR
installer, and the recently reported flickering / bad redraw issue in
Keynote. It probably fixes the bard's tale installer, too, but I
couldn't find the file to test it with.

Thanks,
--Matt Finnicum

Changelog:
riched20: Rewrite of scrolling and redrawing code
Replaces duplicated scrolling code with re-usable functions
Removes excessive boundary checking on scroll code, since that's done
in the scrollbar control anyways.
Properly separates repaint calls based on what has changed
Send EN_UPDATE and EN_CHANGE at the right places
Only call EnsureVisible on changes, not all repaints
Fixes bugs 6111, 4466, and possibly 4756
--
 dlls/riched20/caret.c   |   12 +--
 dlls/riched20/editor.c  |  178 +++++++++++-----------------------------
 dlls/riched20/editor.h  |   14 ++-
 dlls/riched20/editstr.h |    2
 dlls/riched20/paint.c   |  208 ++++++++++++++++++++++++++---------------------
 5 files changed, 181 insertions(+), 233 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 725172d..ce3abb7 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -948,9 +948,9 @@ static void ME_ArrowPageUp(ME_TextEditor
     ME_EnsureVisible(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diRun));
     ME_Repaint(editor);
   }
-  else {
-    ME_Scroll(editor, 0, ys-yprev);
-    ME_Repaint(editor);
+  else 
+  {
+    ME_ScrollUp(editor, ys-yprev);
   }
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);
@@ -1001,9 +1001,9 @@ static void ME_ArrowPageDown(ME_TextEdit
     ME_EnsureVisible(editor, ME_FindItemBack(editor->pBuffer->pLast, diRun));
     ME_Repaint(editor);
   }
-  else {
-    ME_Scroll(editor, 0, ys-yprev);
-    ME_Repaint(editor);
+  else 
+  {
+    ME_ScrollUp(editor,ys-yprev);
   }
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 4ea6cc0..e3383f2 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1135,7 +1135,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) 
   ed->nParagraphs = 1;
   ed->nLastSelStart = ed->nLastSelEnd = 0;
   ed->pLastSelStartPara = ed->pLastSelEndPara = ME_FindItemFwd(ed->pBuffer->pFirst, diParagraph);
-  ed->nScrollPosY = 0;
   ed->nZoomNumerator = ed->nZoomDenominator = 0;
   ed->bRedraw = TRUE;
   ed->bHideSelection = FALSE;
@@ -1151,11 +1150,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) 
     ed->pFontCache[i].hFont = NULL;
   }
   
-  if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
-    FIXME("WS_HSCROLL requested, but horizontal scrolling isn't implemented yet.\n");
-  ed->bScrollX = 0;  
-  ed->bScrollY = GetWindowLongW(hWnd, GWL_STYLE) & WS_VSCROLL;
-  
   ME_CheckCharOffsets(ed);
   
   if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD)
@@ -1410,7 +1404,6 @@ get_msg_name(UINT msg)
  *        RichEditANSIWndProc (RICHED20.10)
  */
 LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
-  SCROLLINFO si;
   ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0);
   
   TRACE("hWnd %p msg %04x (%s) %08x %08lx\n",
@@ -1583,9 +1576,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   case EM_SETSCROLLPOS:
   {
     POINT *point = (POINT *)lParam;
-    /* Native behavior when point->y is too large is very odd / dosn't follow MSDN.
-       This seems to be a pretty close approximation of what it does. */
-    ME_Scroll(editor, 0, -(min(point->y, (editor->nTotalLength - 1)) - editor->nScrollPosY));
+    ME_ScrollAbs(editor, point->y);
     return 0;
   }
   case EM_AUTOURLDETECT:
@@ -1599,7 +1590,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   }
   case EM_GETAUTOURLDETECT:
   {
-	return editor->AutoURLDetect_bEnable;
+    return editor->AutoURLDetect_bEnable;
   }
   case EM_EXSETSEL:
   {
@@ -1630,11 +1621,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   }
   case EM_SHOWSCROLLBAR:
   {
-    if (wParam == SB_VERT)
-      editor->bScrollY = lParam;
-    else if (wParam == SB_HORZ)
-      editor->bScrollX = lParam;
-    ME_UpdateScrollBar(editor);
+    ShowScrollBar(editor->hWnd, wParam, lParam);
     return 0;
   }
   case EM_SETTEXTEX:
@@ -1769,7 +1756,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   case EM_GETFIRSTVISIBLELINE:
   {
     ME_DisplayItem *p = editor->pBuffer->pFirst;
-    int y = editor->nScrollPosY;
+    int y = ME_GetYScrollPos(editor);
     int ypara = 0;
     int count = 0;
     int ystart, yend;
@@ -1798,22 +1785,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   }
   case EM_LINESCROLL:
   {
-    int nPos = editor->nScrollPosY, nEnd= editor->nTotalLength - editor->sizeWindow.cy;
-    nPos += 8 * lParam; /* FIXME follow the original */
-    if (nPos>=nEnd)
-      nPos = nEnd;
-    if (nPos<0)
-      nPos = 0;
-    if (nPos != editor->nScrollPosY) {
-      int dy = editor->nScrollPosY - nPos;
-      editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      if (editor->bRedraw)
-      {
-        ScrollWindow(hWnd, 0, dy, NULL, NULL);
-        UpdateWindow(hWnd);
-      }
-    }
+    ME_ScrollDown(editor, lParam * 8); /* FIXME follow the original */
     return TRUE; /* Should return false if a single line richedit control */
   }
   case WM_CLEAR:
@@ -1853,36 +1825,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   case EM_SCROLLCARET:
   {
     int top, bottom; /* row's edges relative to document top */
+    int nPos;
     ME_DisplayItem *para, *row;
-
+    
+    nPos = ME_GetYScrollPos(editor);
     row = ME_RowStart(editor->pCursors[0].pRun);
     para = ME_GetParagraph(row);
     top = para->member.para.nYPos + row->member.row.nYPos;
     bottom = top + row->member.row.nHeight;
-
-    if ((top < editor->nScrollPosY)
-        || (editor->nScrollPosY + editor->sizeWindow.cy < bottom))
-    {
-      int dy;
-      int prevScrollPosY = editor->nScrollPosY;
-
-      if (top < editor->nScrollPosY) /* caret above window */
-        editor->nScrollPosY = top;
-      else /* caret below window */
-        editor->nScrollPosY = bottom - editor->sizeWindow.cy;
-
-      if (editor->nScrollPosY < 0)
-        editor->nScrollPosY = 0;
-
-      dy = prevScrollPosY - editor->nScrollPosY;
-      SetScrollPos(hWnd, SB_VERT, editor->nScrollPosY, TRUE);
-      if (editor->bRedraw)
-      {
-        ScrollWindow(hWnd, 0, dy, NULL, NULL);
-        UpdateWindow(hWnd);
-      }
-    }
-
+    
+    if (top < nPos) /* caret above window */
+      ME_ScrollAbs(editor,  top);
+    else if (nPos + editor->sizeWindow.cy < bottom) /*below*/
+      ME_ScrollAbs(editor, bottom - editor->sizeWindow.cy);
     return 0;
   }
   case WM_SETFONT:
@@ -2066,7 +2021,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   {
       POINT *point = (POINT *)lParam;
       point->x = 0; /* FIXME side scrolling not implemented */
-      point->y = editor->nScrollPosY;
+      point->y = ME_GetYScrollPos(editor);
       return 1;
   }
   case EM_GETTEXTRANGE:
@@ -2300,13 +2255,8 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   case WM_CREATE:
     if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
     { /* Squelch the default horizontal scrollbar it would make */
-      si.cbSize = sizeof(SCROLLINFO);
-      si.fMask = SIF_POS | SIF_RANGE;
-      si.nMax = 0;
-      si.nMin = 0;
-      si.nPos = 0;
-      SetScrollInfo(hWnd, SB_HORZ, &si, FALSE);
-    }	  
+      ShowScrollBar(editor->hWnd, SB_HORZ, FALSE);
+    }
     ME_CommitUndo(editor);
     ME_WrapMarkedParagraphs(editor);
     ME_MoveCaret(editor);
@@ -2428,79 +2378,51 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
   case EM_SCROLL: /* fall through */
   case WM_VSCROLL: 
   {
-    int nEnd;
-    int nPos = editor->nScrollPosY;
-    int origNPos = nPos;
-    int lineHeight = 24;
-    si.cbSize = sizeof(SCROLLINFO);
-    si.fMask = SIF_PAGE|SIF_POS|SIF_RANGE|SIF_TRACKPOS;
-    GetScrollInfo(hWnd, SB_VERT, &si);
+    int origNPos;
+    int lineHeight;
+    
+    origNPos = ME_GetYScrollPos(editor);
+    lineHeight = 24;
+    
     if (editor && editor->pBuffer && editor->pBuffer->pDefaultStyle)
-        lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
+      lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
     if (lineHeight <= 0) lineHeight = 24;
-    switch(LOWORD(wParam)) {
-    case SB_LINEUP:
-      nPos -= lineHeight;
-      if (nPos<0) nPos = 0;
-      break;
-    case SB_LINEDOWN:
+    
+    switch(LOWORD(wParam)) 
     {
-      nEnd = editor->nTotalLength - editor->sizeWindow.cy;
-      if (nEnd < 0) nEnd = 0;
-      nPos += lineHeight;
-      if (nPos>=nEnd) nPos = nEnd;
-      break;
-    }
-    case SB_PAGEUP:
-      nPos -= editor->sizeWindow.cy;
-      if (nPos<0) nPos = 0;
-      break;
-    case SB_PAGEDOWN:
-      nEnd = editor->nTotalLength - editor->sizeWindow.cy;
-      if (nEnd < 0) nEnd = 0;
-      nPos += editor->sizeWindow.cy;
-      if (nPos>=nEnd) nPos = nEnd;
-      break;
-    case SB_THUMBTRACK:
-    case SB_THUMBPOSITION:
-      nPos = si.nTrackPos;
-      break;
-    }
-    if (nPos != editor->nScrollPosY) {
-      int dy = editor->nScrollPosY - nPos;
-      editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      if (editor->bRedraw)
-      {
-        ScrollWindow(hWnd, 0, dy, NULL, NULL);
-        UpdateWindow(hWnd);
-      }
+      case SB_LINEUP:
+        ME_ScrollUp(editor,lineHeight);
+        break;
+      case SB_LINEDOWN:
+        ME_ScrollDown(editor,lineHeight);
+        break;
+      case SB_PAGEUP:
+        ME_ScrollUp(editor,editor->sizeWindow.cy);
+        break;
+      case SB_PAGEDOWN:
+        ME_ScrollDown(editor,editor->sizeWindow.cy);
+        break;
+      case SB_THUMBTRACK:
+      case SB_THUMBPOSITION:
+        ME_ScrollAbs(editor,HIWORD(wParam));
+        break;
     }
     if (msg == EM_SCROLL)
-      return 0x00010000 | (((nPos - origNPos)/lineHeight) & 0xffff);
+      return 0x00010000 | (((ME_GetYScrollPos(editor) - origNPos)/lineHeight) & 0xffff);
     break;
   }
   case WM_MOUSEWHEEL:
   {
-    int gcWheelDelta = 0, nPos = editor->nScrollPosY, nEnd = editor->nTotalLength - editor->sizeWindow.cy; 
+    int gcWheelDelta;
     UINT pulScrollLines;
+    
     SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
-    gcWheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
+    gcWheelDelta = -GET_WHEEL_DELTA_WPARAM(wParam);
+    
     if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
-      nPos += pulScrollLines * (gcWheelDelta / WHEEL_DELTA) * 8; /* FIXME follow the original */
-    if (nPos>=nEnd)
-      nPos = nEnd;
-    if (nPos<0)
-      nPos = 0;
-    if (nPos != editor->nScrollPosY) {
-      int dy = editor->nScrollPosY - nPos;
-      editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      if (editor->bRedraw)
-      {
-        ScrollWindow(hWnd, 0, dy, NULL, NULL);
-        UpdateWindow(hWnd);
-      }
+    {
+      /* FIXME follow the original */
+      ME_ScrollDown(editor,pulScrollLines * (gcWheelDelta / WHEEL_DELTA) * 8); 
     }
     break;
   }
@@ -2933,7 +2855,7 @@ int ME_AutoURLDetect(ME_TextEditor *edit
         url.cpMin=text_pos;
         url.cpMax=car_pos-1;
         ME_SetCharFormat(editor, text_pos, (URLmax-text_pos), &link);
-        ME_Repaint(editor);
+        ME_RewrapRepaint(editor);
         break;
       }
     }
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index c5be88a..bb3be88 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -173,7 +173,6 @@ void ME_MouseMove(ME_TextEditor *editor,
 void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars);
 void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, 
                              const WCHAR *str, int len, ME_Style *style);
-void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt);
 BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl);
 
 void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC);
@@ -228,15 +227,22 @@ void ME_Repaint(ME_TextEditor *editor);
 void ME_RewrapRepaint(ME_TextEditor *editor);
 void ME_UpdateRepaint(ME_TextEditor *editor);
 void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
-void ME_UpdateScrollBar(ME_TextEditor *editor);
-int ME_GetYScrollPos(ME_TextEditor *editor);
 void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun);
 COLORREF ME_GetBackColor(ME_TextEditor *editor);
-void ME_Scroll(ME_TextEditor *editor, int cx, int cy);
 void ME_InvalidateSelection(ME_TextEditor *editor);
 void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor);
 BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
 
+/* scroll functions in paint.c */
+
+void ME_ScrollAbs(ME_TextEditor *editor, int absY);
+void ME_ScrollUp(ME_TextEditor *editor, int cy);
+void ME_ScrollDown(ME_TextEditor *editor, int cy);
+void ME_Scroll(ME_TextEditor *editor, int value, int type);
+void ME_UpdateScrollBar(ME_TextEditor *editor);
+int ME_GetYScrollPos(ME_TextEditor *editor);
+BOOL ME_GetYScrollVisible(ME_TextEditor *editor);
+
 /* richole.c */
 extern LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *);
 
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index f22717f..9859fe7 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -306,8 +306,6 @@ typedef struct tagME_TextEditor
   int nLastSelStart, nLastSelEnd;
   ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
   ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
-  BOOL bScrollX, bScrollY;
-  int nScrollPosY;
   int nZoomNumerator, nZoomDenominator;
   RECT rcFormat;
   BOOL bRedraw;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 53261ce..7f3e92a 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -96,36 +96,42 @@ void ME_PaintContent(ME_TextEditor *edit
 
 void ME_Repaint(ME_TextEditor *editor)
 {
-  ME_Cursor *pCursor = &editor->pCursors[0];
-
-  if (ME_WrapMarkedParagraphs(editor)) {
-    ME_UpdateScrollBar(editor);
-  }
-  if (editor->bRedraw)
+  if (ME_WrapMarkedParagraphs(editor))
   {
-    ME_EnsureVisible(editor, pCursor->pRun);
-    UpdateWindow(editor->hWnd);
+    ME_UpdateScrollBar(editor);
+    FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n");
   }
+  ME_SendOldNotify(editor, EN_UPDATE);
+  UpdateWindow(editor->hWnd);
 }
 
 void ME_UpdateRepaint(ME_TextEditor *editor)
 {
-/*
-  InvalidateRect(editor->hWnd, NULL, TRUE);
-  */
+  /* Should be called whenever the contents of the control have changed */
+  ME_Cursor *pCursor;
+  
+  if (ME_WrapMarkedParagraphs(editor))
+    ME_UpdateScrollBar(editor);
+  
+  /* Ensure that the cursor is visible */
+  pCursor = &editor->pCursors[0];
+  ME_EnsureVisible(editor, pCursor->pRun);
+  
   ME_SendOldNotify(editor, EN_CHANGE);
   ME_Repaint(editor);
-  ME_SendOldNotify(editor, EN_UPDATE);
   ME_SendSelChange(editor);
 }
 
-
 void
 ME_RewrapRepaint(ME_TextEditor *editor)
-{
+{ 
+  /* RewrapRepaint should be called whenever the control has changed in
+   * looks, but not content. Like resizing. */
+  
   ME_MarkAllForWrapping(editor);
   ME_WrapMarkedParagraphs(editor);
   ME_UpdateScrollBar(editor);
+  
   ME_Repaint(editor);
 }
 
@@ -375,88 +381,118 @@ void ME_DrawParagraph(ME_Context *c, ME_
   SetTextAlign(c->hDC, align);
 }
 
-void ME_Scroll(ME_TextEditor *editor, int cx, int cy)
+void ME_ScrollAbs(ME_TextEditor *editor, int absY)
+{
+  ME_Scroll(editor, absY, 1);
+}
+
+void ME_ScrollUp(ME_TextEditor *editor, int cy)
+{
+  ME_Scroll(editor, cy, 2);
+}
+
+void ME_ScrollDown(ME_TextEditor *editor, int cy)
+{ 
+  ME_Scroll(editor, cy, 3);
+}
+
+void ME_Scroll(ME_TextEditor *editor, int value, int type)
 {
   SCROLLINFO si;
-  HWND hWnd = editor->hWnd;
+  int nOrigPos, nNewPos, nActualScroll;
 
+  nOrigPos = ME_GetYScrollPos(editor);
+  
   si.cbSize = sizeof(SCROLLINFO);
   si.fMask = SIF_POS;
-  GetScrollInfo(hWnd, SB_VERT, &si);
-  si.nPos = editor->nScrollPosY -= cy;
-  SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+  
+  switch (type)
+  {
+    case 1:
+      /*Scroll absolutly*/
+      si.nPos = value;
+      break;
+    case 2:
+      /* Scroll up - towards the beginning of the document */
+      si.nPos = nOrigPos - value;
+      break;
+    case 3:
+      /* Scroll down - towards the end of the document */
+      si.nPos = nOrigPos + value;
+      break;
+    default:
+      FIXME("ME_Scroll called incorrectly\n");
+      si.nPos = 0;
+  }
+  
+  nNewPos = SetScrollInfo(editor->hWnd, SB_VERT, &si, editor->bRedraw);
+  nActualScroll = nOrigPos - nNewPos;
   if (editor->bRedraw)
   {
-    if (abs(cy) > editor->sizeWindow.cy)
+    if (abs(nActualScroll) > editor->sizeWindow.cy)
       InvalidateRect(editor->hWnd, NULL, TRUE);
     else
-      ScrollWindowEx(hWnd, cx, cy, NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE);
+      ScrollWindowEx(editor->hWnd, 0, nActualScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE);
+    ME_Repaint(editor);
   }
+  
+  ME_UpdateScrollBar(editor);
 }
 
-void ME_UpdateScrollBar(ME_TextEditor *editor)
-{
-  HWND hWnd = editor->hWnd;
+ 
+ void ME_UpdateScrollBar(ME_TextEditor *editor)
+{ 
+  /* Note that this is the only funciton that should ever call SetScrolLInfo 
+   * with SIF_PAGE or SIF_RANGE. SetScrollPos and SetScrollRange should never
+   * be used at all. */
+  
+  HWND hWnd;
   SCROLLINFO si;
-  BOOL bUpdateScrollBars;
+  BOOL bScrollBarWasVisible,bScrollBarWillBeVisible;
+  
+  if (ME_WrapMarkedParagraphs(editor))
+    FIXME("ME_UpdateScrollBar had to call ME_WrapMarkedParagraphs\n");
+  
+  hWnd = editor->hWnd;
   si.cbSize = sizeof(si);
-  si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
-  GetScrollInfo(hWnd, SB_VERT, &si);
-  bUpdateScrollBars = (editor->bScrollY)&& ((si.nMax != editor->nTotalLength) || (si.nPage != editor->sizeWindow.cy));
-	
-  if (editor->bScrollY != (si.nMax > 0))
-  { /* The scroll bar needs to be shown or hidden */
-    si.fMask = SIF_RANGE | SIF_PAGE;
-    if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
-      si.fMask |= SIF_DISABLENOSCROLL;
+  bScrollBarWasVisible = ME_GetYScrollVisible(editor);
+  bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy;
   
-    si.nMin = 0;
-    si.nPage = editor->sizeWindow.cy;
-	  
-    if (editor->bScrollY)
-      si.nMax = editor->nTotalLength;
-    else
-      si.nMax = 0;
-    
-    SetScrollInfo(hWnd, SB_VERT, &si, FALSE);
+  if (bScrollBarWasVisible != bScrollBarWillBeVisible)
+  {
+    ShowScrollBar(hWnd, SB_VERT, bScrollBarWillBeVisible);
     ME_MarkAllForWrapping(editor);
     ME_WrapMarkedParagraphs(editor);
-    
-    bUpdateScrollBars = TRUE;
-  }
-  if (bUpdateScrollBars) 
-  {
-    int nScroll = 0;
-    si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
-    if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
-      si.fMask |= SIF_DISABLENOSCROLL;
-    if (editor->bScrollY)
-    {
-      si.nMax = editor->nTotalLength;
-      si.nPage = editor->sizeWindow.cy;
-      if (si.nPos > si.nMax-si.nPage) 
-      {
-        nScroll = (si.nMax-si.nPage)-si.nPos;
-        si.nPos = si.nMax-si.nPage;
-      }
-    }
-    else 
-    {
-      si.nMax = 0;
-      si.nPage = 0;
-      si.nPos = 0;
-    }
-    TRACE("min=%d max=%d page=%d pos=%d shift=%d\n", si.nMin, si.nMax, si.nPage, si.nPos, nScroll);
-    editor->nScrollPosY = si.nPos;
-    SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
-    if (nScroll)
-      ScrollWindow(hWnd, 0, -nScroll, NULL, NULL);
   }
+  
+  si.fMask = SIF_PAGE | SIF_RANGE;
+  if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
+    si.fMask |= SIF_DISABLENOSCROLL;
+  
+  si.nMin = 0;  
+  si.nMax = editor->nTotalLength;
+  
+  si.nPage = editor->sizeWindow.cy;
+     
+  TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage);
+  SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
 }
 
 int ME_GetYScrollPos(ME_TextEditor *editor)
 {
-  return editor->nScrollPosY;
+  SCROLLINFO si;
+  si.cbSize = sizeof(si);
+  si.fMask = SIF_POS;
+  GetScrollInfo(editor->hWnd, SB_VERT, &si);
+  return si.nPos;
+}
+
+BOOL ME_GetYScrollVisible(ME_TextEditor *editor)
+{ /* Returns true if the scrollbar is visible */
+  SCROLLBARINFO sbi;
+  sbi.cbSize = sizeof(sbi);
+  GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi);
+  return ((sbi.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0);
 }
 
 void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
@@ -464,7 +500,6 @@ void ME_EnsureVisible(ME_TextEditor *edi
   ME_DisplayItem *pRow = ME_FindItemBack(pRun, diStartRow);
   ME_DisplayItem *pPara = ME_FindItemBack(pRun, diParagraph);
   int y, yrel, yheight, yold;
-  HWND hWnd = editor->hWnd;
   
   assert(pRow);
   assert(pPara);
@@ -473,24 +508,11 @@ void ME_EnsureVisible(ME_TextEditor *edi
   yheight = pRow->member.row.nHeight;
   yold = ME_GetYScrollPos(editor);
   yrel = y - yold;
-  if (yrel < 0) {
-    editor->nScrollPosY = y;
-    SetScrollPos(hWnd, SB_VERT, y, TRUE);
-    if (editor->bRedraw)
-    {
-      ScrollWindow(hWnd, 0, -yrel, NULL, NULL);
-      UpdateWindow(hWnd);
-    }
-  } else if (yrel + yheight > editor->sizeWindow.cy) {
-    int newy = y+yheight-editor->sizeWindow.cy;
-    editor->nScrollPosY = newy;
-    SetScrollPos(hWnd, SB_VERT, newy, TRUE);
-    if (editor->bRedraw)
-    {
-      ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL);
-      UpdateWindow(hWnd);
-    }
-  }
+  
+  if (y < yold)
+    ME_ScrollAbs(editor,y);
+  else if (yrel + yheight > editor->sizeWindow.cy) 
+    ME_ScrollAbs(editor,y+yheight-editor->sizeWindow.cy);
 }
 
 
-- 
1.4.2


More information about the wine-patches mailing list