RICHEDIT: PageUp and better scrollbar support (replaces previous PageUp patch)

Krzysztof Foltman wdev at foltman.com
Sun Mar 20 08:55:55 CST 2005


ChangeLog:
 * PageUp key support (like in the old patch +/- minor fixes)
 * Support for "normal" scroll bar functionality (line and page scrolling)

Krzysztof

-------------- next part --------------
Index: caret.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/caret.c,v
retrieving revision 1.7
diff -u -r1.7 caret.c
--- caret.c	19 Mar 2005 17:06:17 -0000	1.7
+++ caret.c	20 Mar 2005 14:52:14 -0000
@@ -112,7 +112,7 @@
       }
       CreateCaret(editor->hWnd, NULL, 0, pSizeRun->member.run.nAscent+pSizeRun->member.run.nDescent);
       SetCaretPos(run->member.run.pt.x+sz.cx,
-        para->member.para.nYPos+row->member.row.nBaseline+pSizeRun->member.run.pt.y-pSizeRun->member.run.nAscent-GetScrollPos(editor->hWnd, SB_VERT));
+        para->member.para.nYPos+row->member.row.nBaseline+pSizeRun->member.run.pt.y-pSizeRun->member.run.nAscent-ME_GetYScrollPos(editor));
     } else {
       assert(0 == "Wrapped paragraph run without a row?");
       CreateCaret(editor->hWnd, NULL, 0, 10);
@@ -532,7 +532,7 @@
   
   editor->nUDArrowX = -1;
   
-  y += GetScrollPos(editor->hWnd, SB_VERT);  
+  y += ME_GetYScrollPos(editor);
 
   tmp_cursor = editor->pCursors[0];
   is_selection = ME_IsSelection(editor);
@@ -563,7 +563,7 @@
 {
   ME_Cursor tmp_cursor;
   
-  y += GetScrollPos(editor->hWnd, SB_VERT);  
+  y += ME_GetYScrollPos(editor);
 
   tmp_cursor = editor->pCursors[0];
   if (!ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd))
@@ -697,6 +697,61 @@
   assert(pCursor->pRun->type == diRun);
 }
 
+void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
+{
+  ME_DisplayItem *pRun = pCursor->pRun;
+  ME_DisplayItem *pLast, *p;
+  int x, y, ys, yd, yp, yprev;
+  ME_Cursor tmp_curs = *pCursor;
+  
+  x = ME_GetXForArrow(editor, pCursor);
+  if (!pCursor->nOffset && editor->bCaretAtEnd)
+    pRun = ME_FindItemBack(pRun, diRun);
+  
+  p = ME_FindItemBack(pRun, diStartRowOrParagraph);
+  assert(p->type == diStartRow);
+  yp = ME_FindItemBack(p, diParagraph)->member.para.nYPos;
+  yprev = ys = y = yp + p->member.row.nYPos;
+  yd = y - editor->sizeWindow.cy;
+  pLast = p;
+  
+  do {
+    p = ME_FindItemBack(p, diStartRowOrParagraph);
+    if (!p)
+      break;
+    if (p->type == diParagraph) { /* crossing paragraphs */
+      if (p->member.para.prev_para == NULL)
+        break;
+      yp = p->member.para.prev_para->member.para.nYPos;
+      continue;
+    }
+    y = yp + p->member.row.nYPos;
+    if (y < yd)
+      break;
+    pLast = p;
+    yprev = y;
+  } while(1);
+  
+  pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd);
+  ME_UpdateSelection(editor, &tmp_curs);
+  if (yprev < editor->sizeWindow.cy)
+  {
+    ME_EnsureVisible(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diRun));
+    ME_Repaint(editor);
+  }
+  else {
+    ME_Scroll(editor, 0, ys-yprev);
+    ME_Repaint(editor);
+  }
+  assert(pCursor->pRun);
+  assert(pCursor->pRun->type == diRun);
+}
+
+/* FIXME: in the original RICHEDIT, PageDown always scrolls by the same amount 
+   of pixels, even if it makes the scroll bar position exceed its normal maximum.
+   In such a situation, clicking the scrollbar restores its position back to the
+   normal range (ie. sets it to (doclength-screenheight)). */
+
 void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_DisplayItem *pRun = pCursor->pRun;
@@ -738,8 +793,8 @@
     ME_Repaint(editor);
   }
   else {
-    ME_Repaint(editor);
     ME_Scroll(editor, 0, ys-yprev);
+    ME_Repaint(editor);
   }
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);
@@ -865,7 +920,6 @@
     {
       editor->pCursors[1] = *pTempCursor;
       return TRUE;
-/*      ME_EnsureVisible(editor, editor->pCursors[0].pRun); */
     }
   }
 
@@ -941,6 +995,11 @@
       ME_RepaintSelection(editor, &tmp_curs);
       ME_SendSelChange(editor);
       return TRUE;
+    case VK_PRIOR:
+      ME_ArrowPageUp(editor, p);
+      ME_ClearTempStyle(editor);
+      ME_SendSelChange(editor);
+      return TRUE;
     case VK_NEXT:
       ME_ArrowPageDown(editor, p);
       ME_ClearTempStyle(editor);
Index: editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.c,v
retrieving revision 1.17
diff -u -r1.17 editor.c
--- editor.c	19 Mar 2005 17:06:17 -0000	1.17
+++ editor.c	20 Mar 2005 14:52:15 -0000
@@ -564,7 +564,6 @@
   ed->pCursors[1].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun);
   ed->pCursors[1].nOffset = 0;
   ed->nLastTotalLength = ed->nTotalLength = 0;
-  ed->nScrollPos = 0;
   ed->nUDArrowX = -1;
   ed->nSequence = 0;
   ed->rgbBackColor = -1;
@@ -575,6 +574,7 @@
   ed->nUndoMode = umAddToUndo;
   ed->nParagraphs = 1;
   ed->nLastSelStart = ed->nLastSelEnd = 0;
+  ed->nScrollPosY = 0;
   for (i=0; i<HFONT_CACHE_SIZE; i++)
   {
     ed->pFontCache[i].nRefs = 0;
@@ -1131,17 +1131,41 @@
   }
   case WM_VSCROLL: 
   {
+    int nPos = editor->nScrollPosY;
     si.cbSize = sizeof(SCROLLINFO);
     si.fMask = SIF_PAGE|SIF_POS|SIF_RANGE|SIF_TRACKPOS;
     GetScrollInfo(hWnd, SB_VERT, &si);
     switch(LOWORD(wParam)) {
+    case SB_LINEUP:
+      nPos -= 24; /* FIXME follow the original */
+      if (nPos<0) nPos = 0;
+      break;
+    case SB_LINEDOWN:
+    {
+      int nEnd = editor->nTotalLength - editor->sizeWindow.cy;
+      nPos += 24; /* FIXME follow the original */
+      if (nPos>=nEnd) nPos = nEnd;
+      break;
+    }
+    case SB_PAGEUP:
+      nPos -= editor->sizeWindow.cy;
+      if (nPos<0) nPos = 0;
+      break;
+    case SB_PAGEDOWN:
+      nPos += editor->sizeWindow.cy;
+      if (nPos>=editor->nTotalLength) nPos = editor->nTotalLength-1;
+      break;
     case SB_THUMBTRACK:
-      SetScrollPos(hWnd, SB_VERT, si.nTrackPos, FALSE);
-      ScrollWindow(hWnd, 0, si.nPos-si.nTrackPos, NULL, NULL);
-      /* InvalidateRect(hWnd, NULL, TRUE); */
-      UpdateWindow(hWnd);
+    case SB_THUMBPOSITION:
+      nPos = si.nTrackPos;
       break;
     }
+    if (nPos != editor->nScrollPosY) {
+      ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+      editor->nScrollPosY = nPos;
+      SetScrollPos(hWnd, SB_VERT, nPos, FALSE);
+      UpdateWindow(hWnd);
+    }
     break;
   }
   case WM_SIZE:
Index: editor.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.h,v
retrieving revision 1.10
diff -u -r1.10 editor.h
--- editor.h	19 Mar 2005 17:06:17 -0000	1.10
+++ editor.h	20 Mar 2005 14:52:15 -0000
@@ -191,7 +191,7 @@
 void ME_UpdateRepaint(ME_TextEditor *editor);
 void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
 void ME_UpdateScrollBar(ME_TextEditor *editor);
-int ME_GetScrollPos(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);
Index: editstr.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editstr.h,v
retrieving revision 1.6
diff -u -r1.6 editstr.h
--- editstr.h	19 Mar 2005 17:06:17 -0000	1.6
+++ editstr.h	20 Mar 2005 14:52:15 -0000
@@ -231,7 +231,6 @@
   ME_Cursor *pCursors;
   int nCursors;
   SIZE sizeWindow;
-  int nScrollPos;
   int nTotalLength, nLastTotalLength;
   int nUDArrowX;
   int nSequence;
@@ -247,6 +246,7 @@
   ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
   ME_OutStream *pStream;
   BOOL bScrollX, bScrollY;
+  int nScrollPosY;
 } ME_TextEditor;
 
 typedef struct tagME_Context
Index: paint.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/paint.c,v
retrieving revision 1.7
diff -u -r1.7 paint.c
--- paint.c	19 Mar 2005 17:06:17 -0000	1.7
+++ paint.c	20 Mar 2005 14:52:15 -0000
@@ -28,7 +28,7 @@
   int yoffset;
 
   editor->nSequence++;
-  yoffset = GetScrollPos(editor->hWnd, SB_VERT);
+  yoffset = ME_GetYScrollPos(editor);
   ME_InitContext(&c, editor, hDC);
   SetBkMode(hDC, TRANSPARENT);
   ME_MoveCaret(editor);
@@ -386,9 +386,12 @@
   si.cbSize = sizeof(SCROLLINFO);
   si.fMask = SIF_POS;
   GetScrollInfo(hWnd, SB_VERT, &si);
-  si.nPos -= cy;
+  si.nPos = editor->nScrollPosY -= cy;
   SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
-  ScrollWindow(hWnd, cx, cy, NULL, NULL);
+  if (abs(cy) > editor->sizeWindow.cy)
+    InvalidateRect(editor->hWnd, NULL, TRUE);
+  else
+    ScrollWindowEx(hWnd, cx, cy, NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE);
 }
 
 void ME_UpdateScrollBar(ME_TextEditor *editor)
@@ -436,15 +439,16 @@
       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);
   }
 }
 
-int ME_GetScrollPos(ME_TextEditor *editor)
+int ME_GetYScrollPos(ME_TextEditor *editor)
 {
-  return GetScrollPos(editor->hWnd, SB_VERT);
+  return editor->nScrollPosY;
 }
 
 void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
@@ -459,14 +463,16 @@
   
   y = pPara->member.para.nYPos+pRow->member.row.nYPos;
   yheight = pRow->member.row.nHeight;
-  yold = ME_GetScrollPos(editor);
+  yold = ME_GetYScrollPos(editor);
   yrel = y - yold;
   if (yrel < 0) {
+    editor->nScrollPosY = y;
     SetScrollPos(hWnd, SB_VERT, y, TRUE);
     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);
     ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL);
     UpdateWindow(hWnd);


More information about the wine-patches mailing list