Dylan Smith : richedit: Fix implementation of handling Page Up/Down keys.

Alexandre Julliard julliard at winehq.org
Fri Jan 16 07:41:52 CST 2009


Module: wine
Branch: master
Commit: 77a94bed984bcb19bb1b7b563537c72c63353a9b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=77a94bed984bcb19bb1b7b563537c72c63353a9b

Author: Dylan Smith <dylan.ah.smith at gmail.com>
Date:   Thu Jan 15 11:03:49 2009 -0500

richedit: Fix implementation of handling Page Up/Down keys.

---

 dlls/riched20/caret.c |  195 +++++++++++++++++++++++--------------------------
 1 files changed, 91 insertions(+), 104 deletions(-)

diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 3df8566..74c32a3 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -1338,132 +1338,119 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
   assert(pCursor->pRun->type == diRun);
 }
 
-static BOOL ME_UpdateSelection(ME_TextEditor *editor, const ME_Cursor *pTempCursor)
+static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
-  ME_Cursor old_anchor = editor->pCursors[1];
+  ME_DisplayItem *p = ME_FindItemFwd(editor->pBuffer->pFirst, diStartRow);
 
-  if (GetKeyState(VK_SHIFT)>=0) /* cancelling selection */
-  {
-    /* any selection was present ? if so, it's no more, repaint ! */
-    editor->pCursors[1] = editor->pCursors[0];
-    if (memcmp(pTempCursor, &old_anchor, sizeof(ME_Cursor))) {
-      return TRUE;
-    }
-    return FALSE;
-  }
-  else
+  if (editor->vert_si.nPos < p->member.row.nHeight)
   {
-    if (!memcmp(pTempCursor, &editor->pCursors[1], sizeof(ME_Cursor))) /* starting selection */
-    {
-      editor->pCursors[1] = *pTempCursor;
-      return TRUE;
-    }
-  }
-
-  ME_Repaint(editor);
-  return TRUE;
-}
+    pCursor->pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
+    pCursor->nOffset = 0;
+    editor->bCaretAtEnd = FALSE;
+    /* Native clears seems to clear this x value on page up at the top
+     * of the text, but not on page down at the end of the text.
+     * Doesn't make sense, but we try to be bug for bug compatible. */
+    editor->nUDArrowX = -1;
+  } else {
+    ME_DisplayItem *pRun = pCursor->pRun;
+    ME_DisplayItem *pLast;
+    int x, y, ys, yd, yp, yprev;
+    int yOldScrollPos = editor->vert_si.nPos;
 
-static 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);
 
-  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.pt.y;
+    yprev = ys = y = yp + p->member.row.pt.y;
 
-  p = ME_FindItemBack(pRun, diStartRowOrParagraph);
-  assert(p->type == diStartRow);
-  yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y;
-  yprev = ys = y = yp + p->member.row.pt.y;
-  yd = y - editor->sizeWindow.cy;
-  pLast = p;
+    ME_ScrollUp(editor, editor->sizeWindow.cy);
+    /* Only move the cursor by the amount scrolled. */
+    yd = y + editor->vert_si.nPos - yOldScrollPos;
+    pLast = p;
 
-  do {
-    p = ME_FindItemBack(p, diStartRowOrParagraph);
-    if (!p)
-      break;
-    if (p->type == diParagraph) { /* crossing paragraphs */
-      if (p->member.para.prev_para == NULL)
+    do {
+      p = ME_FindItemBack(p, diStartRowOrParagraph);
+      if (!p)
         break;
-      yp = p->member.para.prev_para->member.para.pt.y;
-      continue;
-    }
-    y = yp + p->member.row.pt.y;
-    if (y < yd)
-      break;
-    pLast = p;
-    yprev = y;
-  } while(1);
+      if (p->type == diParagraph) { /* crossing paragraphs */
+        if (p->member.para.prev_para == NULL)
+          break;
+        yp = p->member.para.prev_para->member.para.pt.y;
+        continue;
+      }
+      y = yp + p->member.row.pt.y;
+      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_Cursor startCursor = {ME_FindItemFwd(editor->pBuffer->pFirst, diRun), 0};
-    ME_EnsureVisible(editor, &startCursor);
-    ME_Repaint(editor);
-  }
-  else
-  {
-    ME_ScrollUp(editor, ys-yprev);
+    pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset,
+                                    &editor->bCaretAtEnd);
   }
   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)). */
-
 static void ME_ArrowPageDown(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;
+  ME_DisplayItem *pLast;
+  int x, y;
+
+  /* Find y position of the last row */
+  pLast = editor->pBuffer->pLast;
+  y = pLast->member.para.prev_para->member.para.pt.y
+      + ME_FindItemBack(pLast, diStartRow)->member.row.pt.y;
 
   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.pt.y;
-  yprev = ys = y = yp + p->member.row.pt.y;
-  yd = y + editor->sizeWindow.cy;
-  pLast = p;
+  if (editor->vert_si.nPos >= y - editor->sizeWindow.cy)
+  {
+    pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
+    pCursor->nOffset = 0;
+    editor->bCaretAtEnd = FALSE;
+  } else {
+    ME_DisplayItem *pRun = pCursor->pRun;
+    ME_DisplayItem *p;
+    int ys, yd, yp, yprev;
+    int yOldScrollPos = editor->vert_si.nPos;
 
-  do {
-    p = ME_FindItemFwd(p, diStartRowOrParagraph);
-    if (!p)
-      break;
-    if (p->type == diParagraph) {
-      yp = p->member.para.pt.y;
-      continue;
-    }
-    y = yp + p->member.row.pt.y;
-    if (y >= yd)
-      break;
+    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.pt.y;
+    yprev = ys = y = yp + p->member.row.pt.y;
+
+    /* For native richedit controls:
+     * v1.0 - v3.1 can only scroll down as far as the scrollbar lets us
+     * v4.1 can scroll past this position here. */
+    ME_ScrollDown(editor, editor->sizeWindow.cy);
+    /* Only move the cursor by the amount scrolled. */
+    yd = y + editor->vert_si.nPos - yOldScrollPos;
     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->nTotalLength-editor->sizeWindow.cy)
-  {
-    ME_Cursor endCursor = {ME_FindItemBack(editor->pBuffer->pLast, diRun), 0};
-    ME_EnsureVisible(editor, &endCursor);
-    ME_Repaint(editor);
-  }
-  else
-  {
-    ME_ScrollUp(editor,ys-yprev);
+    do {
+      p = ME_FindItemFwd(p, diStartRowOrParagraph);
+      if (!p)
+        break;
+      if (p->type == diParagraph) {
+        yp = p->member.para.pt.y;
+        continue;
+      }
+      y = yp + p->member.row.pt.y;
+      if (y >= yd)
+        break;
+      pLast = p;
+      yprev = y;
+    } while(1);
+
+    pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset,
+                                    &editor->bCaretAtEnd);
   }
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);




More information about the wine-cvs mailing list