richedit: Scrollinfo stored as 16-bit values externally. (Bug 19396)

Dylan Smith dylan.ah.smith at gmail.com
Tue Jul 21 18:51:37 CDT 2009


The application Blitzin2 was sending WM_VSCROLL messages to the richedit
control directly, when normally this message is supposed to be a
notification sent after the scrollinfo is set.  Native richedit controls
always use the 16-bit value passed to this message to set the scroll
position for SB_THUMBPOSITION, rather than trying to find a 32-bit value
through GetScrollInfo like I had previously done.

This brought up the question of how text with height greater than the
16-bit limit is handled.  I ran some tests, and found that nMax is
capped at the maximum 16-bit value 0xffff, and nPos is scaled into this
range.  This patch implements this behaviour, but keeps the precision
for the internal value, since it can be obtained through EM_POSFROMCHAR,
and is used for drawing the text.

EM_GETSCROLLPOS also uses this 16-bit value, and it must be derived from
an internal value since calling SetScrollInfo just before sending this
message didn't affect the returned value.
---
 dlls/riched20/editor.c |   31 +++++++++++++------------------
 dlls/riched20/paint.c  |   20 ++++++++++++++++++--
 2 files changed, 31 insertions(+), 20 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index c3cd187..cf317b7 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -3587,6 +3587,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     POINT *point = (POINT *)lParam;
     point->x = editor->horz_si.nPos;
     point->y = editor->vert_si.nPos;
+    /* 16-bit scaled value is returned as stored in scrollinfo */
+    if (editor->horz_si.nMax > 0xffff)
+      point->x = MulDiv(point->x, 0xffff, editor->horz_si.nMax);
+    if (editor->vert_si.nMax > 0xffff)
+      point->y = MulDiv(point->y, 0xffff, editor->vert_si.nMax);
     return 1;
   }
   case EM_GETTEXTRANGE:
@@ -4012,15 +4017,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       case SB_THUMBTRACK:
       case SB_THUMBPOSITION:
       {
-        SCROLLINFO sbi;
-        sbi.cbSize = sizeof(sbi);
-        sbi.fMask = SIF_TRACKPOS;
-        /* Try to get 32-bit track position value. */
-        if (!GetScrollInfo(editor->hWnd, SB_HORZ, &sbi))
-          /* GetScrollInfo failed, settle for 16-bit value in wParam. */
-          sbi.nTrackPos = HIWORD(wParam);
-
-        ME_HScrollAbs(editor, sbi.nTrackPos);
+        WORD pos = HIWORD(wParam);
+        if (editor->horz_si.nMax > 0xffff)
+          pos = MulDiv(pos, editor->horz_si.nMax, 0xffff);
+        ME_HScrollAbs(editor, pos);
         break;
       }
     }
@@ -4064,15 +4064,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       case SB_THUMBTRACK:
       case SB_THUMBPOSITION:
       {
-        SCROLLINFO sbi;
-        sbi.cbSize = sizeof(sbi);
-        sbi.fMask = SIF_TRACKPOS;
-        /* Try to get 32-bit track position value. */
-        if (!GetScrollInfo(editor->hWnd, SB_VERT, &sbi))
-          /* GetScrollInfo failed, settle for 16-bit value in wParam. */
-          sbi.nTrackPos = HIWORD(wParam);
-
-        ME_VScrollAbs(editor, sbi.nTrackPos);
+        WORD pos = HIWORD(wParam);
+        if (editor->vert_si.nMax > 0xffff)
+          pos = MulDiv(pos, editor->vert_si.nMax, 0xffff);
+        ME_VScrollAbs(editor, pos);
         break;
       }
     }
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 4b5fed1..a5be178 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -1036,17 +1036,21 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
   if (editor->horz_si.nPos != x) {
     x = min(x, editor->horz_si.nMax);
     x = max(x, editor->horz_si.nMin);
-    ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, x, TRUE);
     scrollX = editor->horz_si.nPos - x;
     editor->horz_si.nPos = x;
+    if (editor->horz_si.nMax > 0xFFFF) /* scale to 16-bit value */
+      x = MulDiv(x, 0xFFFF, editor->horz_si.nMax);
+    ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, x, TRUE);
   }
 
   if (editor->vert_si.nPos != y) {
     y = min(y, editor->vert_si.nMax - (int)editor->vert_si.nPage);
     y = max(y, editor->vert_si.nMin);
-    ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, y, TRUE);
     scrollY = editor->vert_si.nPos - y;
     editor->vert_si.nPos = y;
+    if (editor->vert_si.nMax > 0xFFFF) /* scale to 16-bit value */
+      y = MulDiv(y, 0xFFFF, editor->vert_si.nMax);
+    ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, y, TRUE);
   }
 
   if (abs(scrollX) > editor->sizeWindow.cx ||
@@ -1170,6 +1174,12 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
     if ((bScrollBarWillBeVisible || bScrollBarWasVisible) &&
         editor->styleFlags & WS_HSCROLL)
     {
+      if (si.nMax > 0xFFFF)
+      {
+        /* Native scales the scrollbar info to 16-bit external values. */
+        si.nPos = MulDiv(si.nPos, 0xFFFF, si.nMax);
+        si.nMax = 0xFFFF;
+      }
       if (editor->hWnd) {
         SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
       } else {
@@ -1219,6 +1229,12 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
     if ((bScrollBarWillBeVisible || bScrollBarWasVisible) &&
         editor->styleFlags & WS_VSCROLL)
     {
+      if (si.nMax > 0xFFFF)
+      {
+        /* Native scales the scrollbar info to 16-bit external values. */
+        si.nPos = MulDiv(si.nPos, 0xFFFF, si.nMax);
+        si.nMax = 0xFFFF;
+      }
       if (editor->hWnd) {
         SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
       } else {


More information about the wine-patches mailing list