Changes to richedit to use target device DPI vice screen DPI. Changes coordinated with Dylan Smith <dylan.ah.smith at gmail.com>

James McKenzie jjmckenzie51 at earthlink.net
Sat Feb 20 19:43:04 CST 2010


---
 dlls/riched20/caret.c   |    2 +-
 dlls/riched20/context.c |   18 ++-
 dlls/riched20/editor.h  |   13 ++-
 dlls/riched20/paint.c   |  356 ++++++++++++++++++++++++++++------------------
 dlls/riched20/para.c    |    2 +-
 dlls/riched20/richole.c |   80 +++++------
 dlls/riched20/run.c     |   30 ++--
 dlls/riched20/style.c   |   29 +++--
 dlls/riched20/wrap.c    |  344 +++++++++++++++++++++++-----------------------
 9 files changed, 487 insertions(+), 387 deletions(-)

diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index abcc73e..76b48cd 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -210,7 +210,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
   row = ME_FindItemBack(run, diStartRowOrParagraph);
   assert(row && row->type == diStartRow);
 
-  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
+  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost), NULL);
 
   if (!pCursor->nOffset)
   {
diff --git a/dlls/riched20/context.c b/dlls/riched20/context.c
index 93d5caa..6d038f6 100644
--- a/dlls/riched20/context.c
+++ b/dlls/riched20/context.c
@@ -20,10 +20,14 @@
 
 #include "editor.h"
 
-void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC)
+void ME_InitContext(ME_Context *c, ME_TextEditor *editor,
+                    HDC hDC, HDC hdcTarget)
 {
   c->nSequence = editor->nSequence++;
   c->hDC = hDC;
+  c->bClip = FALSE;
+  c->bHideSelection = editor->bHideSelection;
+  c->bWordWrap = editor->bWordWrap;
   c->editor = editor;
   c->pt.x = 0;
   c->pt.y = 0;
@@ -35,8 +39,18 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC)
   } else {
       c->dpi.cx = c->dpi.cy = 96;
   }
+  if (hdcTarget) {
+      c->hdcTarget = hdcTarget;
+      c->dpiTarget.cx = GetDeviceCaps(hdcTarget, LOGPIXELSX);
+      c->dpiTarget.cy = GetDeviceCaps(hdcTarget, LOGPIXELSY);
+  } else {
+      c->hdcTarget = hDC;
+      c->dpiTarget = c->dpi;
+  }
+  c->nZoomNumerator = c->editor->nZoomNumerator;
+  c->nZoomDenominator = c->editor->nZoomDenominator;
   if (editor->nAvailWidth)
-      c->nAvailWidth = ME_twips2pointsX(c, editor->nAvailWidth);
+      c->nAvailWidth = ME_twips2targetX(c, editor->nAvailWidth);
   else
       c->nAvailWidth = c->rcView.right - c->rcView.left;
 }
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 89c18b7..cdb5544 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -62,8 +62,8 @@ void ME_AddRefStyle(ME_Style *item);
 void ME_ReleaseStyle(ME_Style *item);
 ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor);
 ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style);
-HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s);
-void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont);
+HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s, BOOL bTarget);
+void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, BOOL bTarget, HFONT hOldFont);
 void ME_InitCharFormat2W(CHARFORMAT2W *pFmt);
 void ME_SaveTempStyle(ME_TextEditor *editor);
 void ME_ClearTempStyle(ME_TextEditor *editor);
@@ -182,10 +182,11 @@ int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how);
 ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor);
 
 /* context.c */
-void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC);
+void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC, HDC hdcTarget);
 void ME_DestroyContext(ME_Context *c);
 
 /* wrap.c */
+void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp);
 BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor);
 void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor);
 void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
@@ -216,6 +217,10 @@ void ME_InvalidateSelection(ME_TextEditor *editor);
 BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
 int  ME_twips2pointsX(ME_Context *c, int x);
 int  ME_twips2pointsY(ME_Context *c, int y);
+int  ME_target2pointsX(ME_Context *c, int x);
+int  ME_target2pointsY(ME_Context *c, int y);
+int  ME_twips2targetX(ME_Context *c, int x);
+int  ME_twips2targetY(ME_Context *c, int y);
 
 /* scroll functions in paint.c */
 
@@ -229,7 +234,7 @@ void ME_ScrollRight(ME_TextEditor *editor, int cx);
 void ME_UpdateScrollBar(ME_TextEditor *editor);
 
 /* other functions in paint.c */
-int  ME_GetParaBorderWidth(ME_TextEditor *editor, int);
+int ME_GetParaBorderWidth(ME_Context *c, int flags);
 
 /* richole.c */
 LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *);
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index b0e6c1e..e17c2bd 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2004 by Krzysztof Foltman
  * Copyright 2005 by Phil Krylov
+ * Copyright 2006 CorVu Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,52 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
 static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
 
+int ME_target2pointsX(ME_Context *c, int x)
+{
+  if (c->dpiTarget.cx == c->dpi.cx)
+    return x;
+  return (LONGLONG)x * c->dpi.cx / c->dpiTarget.cx;
+}
+
+int ME_target2pointsY(ME_Context *c, int y)
+{
+  if (c->dpiTarget.cy == c->dpi.cy)
+    return y;
+  return (LONGLONG)y * c->dpi.cy / c->dpiTarget.cy;
+}
+
+int ME_twips2targetX(ME_Context *c, int x)
+{
+  x = (LONGLONG)x * c->dpiTarget.cx / 1440;
+  if (c->nZoomNumerator != 0)
+    x = (LONGLONG)x * c->nZoomNumerator / c->nZoomDenominator;
+  return x;
+}
+
+int ME_twips2targetY(ME_Context *c, int y)
+{
+  y = (LONGLONG)y * c->dpiTarget.cy / 1440;
+  if (c->nZoomNumerator != 0)
+    y = (LONGLONG)y * c->nZoomNumerator / c->nZoomDenominator;
+  return y;
+}
+
+int ME_twips2pointsX(ME_Context *c, int x)
+{
+  x = (LONGLONG)x * c->dpi.cx / 1440;
+  if (c->nZoomNumerator != 0)
+    x = (LONGLONG)x * c->nZoomNumerator / c->nZoomDenominator;
+  return x;
+}
+
+int ME_twips2pointsY(ME_Context *c, int y)
+{
+  y = (LONGLONG)y * c->dpi.cy / 1440;
+  if (c->nZoomNumerator != 0)
+    y = (LONGLONG)y * c->nZoomNumerator / c->nZoomDenominator;
+  return y;
+}
+
 void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *rcUpdate)
 {
   ME_DisplayItem *item;
@@ -42,7 +89,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
                      rcUpdate->right, rcUpdate->bottom);
 
   editor->nSequence++;
-  ME_InitContext(&c, editor, hDC);
+  ME_InitContext(&c, editor, hDC, NULL);
   SetBkMode(hDC, TRANSPARENT);
   ME_MoveCaret(editor);
   item = editor->pBuffer->pFirst->next;
@@ -169,67 +216,51 @@ ME_RewrapRepaint(ME_TextEditor *editor)
   ME_Repaint(editor);
 }
 
-int ME_twips2pointsX(ME_Context *c, int x)
-{
-  if (c->editor->nZoomNumerator == 0)
-    return x * c->dpi.cx / 1440;
-  else
-    return x * c->dpi.cx * c->editor->nZoomNumerator / 1440 / c->editor->nZoomDenominator;
-}
-
-int ME_twips2pointsY(ME_Context *c, int y)
-{
-  if (c->editor->nZoomNumerator == 0)
-    return y * c->dpi.cy / 1440;
-  else
-    return y * c->dpi.cy * c->editor->nZoomNumerator / 1440 / c->editor->nZoomDenominator;
-}
-
 static void ME_HighlightSpace(ME_Context *c, int x, int y, LPCWSTR szText,
                               int nChars, ME_Style *s, int width,
                               int nSelFrom, int nSelTo, int ymin, int cy)
 {
-  HDC hDC = c->hDC;
   HGDIOBJ hOldFont = NULL;
   SIZE sz;
   int selWidth;
   /* Only highlight if there is a selection in the run and when
    * EM_HIDESELECTION is not being used to hide the selection. */
   if (nSelFrom >= nChars || nSelTo < 0 || nSelFrom >= nSelTo
-      || c->editor->bHideSelection)
+      || c->bHideSelection)
     return;
-  hOldFont = ME_SelectStyleFont(c, s);
+  hOldFont = ME_SelectStyleFont(c, s, TRUE);
   if (width <= 0)
   {
-    GetTextExtentPoint32W(hDC, szText, nChars, &sz);
+    GetTextExtentPoint32W(c->hdcTarget, szText, nChars, &sz);
     width = sz.cx;
   }
   if (nSelFrom < 0) nSelFrom = 0;
   if (nSelTo > nChars) nSelTo = nChars;
-  GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz);
+  GetTextExtentPoint32W(c->hdcTarget, szText, nSelFrom, &sz);
   x += sz.cx;
   if (nSelTo != nChars)
   {
-    GetTextExtentPoint32W(hDC, szText+nSelFrom, nSelTo-nSelFrom, &sz);
+    GetTextExtentPoint32W(c->hdcTarget, szText+nSelFrom, nSelTo-nSelFrom, &sz);
     selWidth = sz.cx;
   } else {
     selWidth = width - sz.cx;
   }
-  ME_UnselectStyleFont(c, s, hOldFont);
+  ME_UnselectStyleFont(c, s, TRUE, hOldFont);
 
   if (c->editor->bEmulateVersion10)
-    PatBlt(hDC, x, ymin, selWidth, cy, DSTINVERT);
+    PatBlt(c->hDC, ME_target2pointsX(c, x), ME_target2pointsY(c, ymin),
+           ME_target2pointsX(c, x), ME_target2pointsY(c, cy), DSTINVERT);
   else
   {
     RECT rect;
     HBRUSH hBrush;
-    rect.left = x;
-    rect.top = ymin;
-    rect.right = x + selWidth;
-    rect.bottom = ymin + cy;
+    rect.left = ME_target2pointsX(c, x);
+    rect.top = ME_target2pointsY(c, ymin);
+    rect.right = ME_target2pointsX(c, x + selWidth);
+    rect.bottom = ME_target2pointsY(c, ymin + cy);
     hBrush = CreateSolidBrush(ITextHost_TxGetSysColor(c->editor->texthost,
                                                       COLOR_HIGHLIGHT));
-    FillRect(hDC, &rect, hBrush);
+    FillRect(c->hDC, &rect, hBrush);
     DeleteObject(hBrush);
   }
 }
@@ -245,18 +276,20 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
   SIZE          sz;
   COLORREF      rgb;
   HPEN hPen = NULL, hOldPen = NULL;
-  BOOL bHighlightedText = (nSelFrom < nChars && nSelTo >= 0
-                           && nSelFrom < nSelTo && !c->editor->bHideSelection);
+  BOOL bHighlightedText = nSelFrom < nChars && nSelTo >= 0
+                          && nSelFrom < nSelTo && !c->bHideSelection;
   int xSelStart = x, xSelEnd = x;
-  int *lpDx = NULL;
+  int dx, *lpDx = NULL;
   /* lpDx is only needed for tabs to make sure the underline done automatically
    * by the font extends to the end of the tab. Tabs are always stored as
    * a single character run, so we can handle this case separately, since
    * otherwise lpDx would need to specify the lengths of each character. */
-  if (width && nChars == 1)
-      lpDx = &width; /* Make sure underline for tab extends across tab space */
+  if (width && nChars == 1) {
+    dx = ME_target2pointsX(c, width);
+    lpDx = &dx; /* Make sure underline for tab extends across tab space */
+  }
 
-  hOldFont = ME_SelectStyleFont(c, s);
+  hOldFont = ME_SelectStyleFont(c, s, TRUE);
   if ((s->fmt.dwMask & s->fmt.dwEffects) & CFM_OFFSET) {
     yTwipsOffset = s->fmt.yOffset;
   }
@@ -265,7 +298,7 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
     if (s->fmt.dwEffects & CFE_SUBSCRIPT) yTwipsOffset = -s->fmt.yHeight/12;
   }
   if (yTwipsOffset)
-    yOffset = ME_twips2pointsY(c, yTwipsOffset);
+    yOffset = ME_twips2targetY(c, yTwipsOffset);
 
   if ((s->fmt.dwMask & CFM_LINK) && (s->fmt.dwEffects & CFE_LINK))
     rgb = RGB(0,0,255);
@@ -275,7 +308,7 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
     rgb = s->fmt.crTextColor;
 
   /* Determine the area that is selected in the run. */
-  GetTextExtentPoint32W(hDC, szText, nChars, &sz);
+  GetTextExtentPoint32W(c->hdcTarget, szText, nChars, &sz);
   /* Treat width as an optional parameter.  We can get the width from the
    * text extent of the string if it isn't specified. */
   if (!width) width = sz.cx;
@@ -287,7 +320,7 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
     }
     else
     {
-      GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz);
+      GetTextExtentPoint32W(c->hdcTarget, szText, nSelFrom, &sz);
       xSelStart = x + sz.cx;
     }
     if (nSelTo >= nChars)
@@ -297,11 +330,15 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
     }
     else
     {
-      GetTextExtentPoint32W(hDC, szText+nSelFrom, nSelTo-nSelFrom, &sz);
+      GetTextExtentPoint32W(c->hdcTarget, szText+nSelFrom, nSelTo-nSelFrom, &sz);
       xSelEnd = xSelStart + sz.cx;
     }
   }
 
+  /* Done measuring with hdcTarget, so start drawing with hdc. */
+  ME_UnselectStyleFont(c, s, TRUE, hOldFont);
+  hOldFont = ME_SelectStyleFont(c, s, FALSE);
+
   /* Choose the pen type for underlining the text. */
   if (s->fmt.dwMask & CFM_UNDERLINETYPE)
   {
@@ -334,51 +371,59 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
   {
     COLORREF rgbBackOld;
     RECT dim;
+    int y_text = ME_target2pointsY(c, y - yOffset);
+    int y_line = 0;
     /* FIXME: should use textmetrics info for Descent info */
-    if (hPen)
-      MoveToEx(hDC, x, y - yOffset + 1, NULL);
+    if (hPen) {
+      y_line = ME_target2pointsY(c, y - yOffset + 1);
+      MoveToEx(hDC, ME_target2pointsX(c, x), y_line, NULL);
+    }
     if (xSelStart > x)
     {
-      ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nSelFrom, NULL);
+      ExtTextOutW(hDC, ME_target2pointsX(c, x), y_text,
+                  0, NULL, szText, nSelFrom, NULL);
       if (hPen)
-        LineTo(hDC, xSelStart, y - yOffset + 1);
+        LineTo(hDC, ME_target2pointsX(c, xSelStart), y_line);
     }
-    dim.top = ymin;
-    dim.bottom = ymin + cy;
-    dim.left = xSelStart;
-    dim.right = xSelEnd;
+    dim.top = ME_target2pointsY(c, ymin);
+    dim.bottom = ME_target2pointsY(c, ymin + cy);
+    dim.left = ME_target2pointsX(c, xSelStart);
+    dim.right = ME_target2pointsX(c, xSelEnd);
     SetTextColor(hDC, ITextHost_TxGetSysColor(c->editor->texthost,
                                               COLOR_HIGHLIGHTTEXT));
     rgbBackOld = SetBkColor(hDC, ITextHost_TxGetSysColor(c->editor->texthost,
                                                          COLOR_HIGHLIGHT));
-    ExtTextOutW(hDC, xSelStart, y-yOffset, ETO_OPAQUE, &dim,
-                szText+nSelFrom, nSelTo-nSelFrom, lpDx);
+    ExtTextOutW(hDC, dim.left, y_text, ETO_OPAQUE, &dim,
+                szText + nSelFrom, nSelTo - nSelFrom, lpDx);
     if (hPen)
-      LineTo(hDC, xSelEnd, y - yOffset + 1);
+      LineTo(hDC, dim.right, y_line);
     SetBkColor(hDC, rgbBackOld);
     if (xSelEnd < x + width)
     {
       SetTextColor(hDC, rgb);
-      ExtTextOutW(hDC, xSelEnd, y-yOffset, 0, NULL, szText+nSelTo,
-                  nChars-nSelTo, NULL);
+      ExtTextOutW(hDC, dim.right, y_text, 0, NULL,
+                  szText + nSelTo, nChars - nSelTo, NULL);
       if (hPen)
-        LineTo(hDC, x + width, y - yOffset + 1);
+        LineTo(hDC, ME_target2pointsX(c, x + width), y_line);
     }
   }
   else
   {
-    ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, lpDx);
+    ExtTextOutW(hDC, ME_target2pointsX(c, x), ME_target2pointsY(c, y - yOffset),
+                0, NULL, szText, nChars, lpDx);
 
     /* FIXME: should use textmetrics info for Descent info */
     if (hPen)
     {
-      MoveToEx(hDC, x, y - yOffset + 1, NULL);
-      LineTo(hDC, x + width, y - yOffset + 1);
+      int y_line = ME_target2pointsY(c, y - yOffset + 1);
+      MoveToEx(hDC, ME_target2pointsX(c, x), y_line, NULL);
+      LineTo(hDC, ME_target2pointsX(c, x + width), y_line);
     }
 
     if (bHighlightedText) /* v1.0 inverts the selection */
     {
-      PatBlt(hDC, xSelStart, ymin, xSelEnd-xSelStart, cy, DSTINVERT);
+      PatBlt(hDC, ME_target2pointsX(c, xSelStart), ME_target2pointsY(c, ymin),
+             ME_target2pointsX(c, xSelEnd-xSelStart), ME_target2pointsY(c, cy), DSTINVERT);
     }
   }
 
@@ -388,7 +433,7 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
     DeleteObject(hPen);
   }
   SetTextColor(hDC, rgbOld);
-  ME_UnselectStyleFont(c, s, hOldFont);
+  ME_UnselectStyleFont(c, s, FALSE, hOldFont);
 }
 
 static void ME_DebugWrite(HDC hDC, const POINT *pt, LPCWSTR szText) {
@@ -487,25 +532,28 @@ static const COLORREF pen_colors[16] = {
   /* Dark gray */       RGB(0x80, 0x80, 0x80),  /* Light gray */      RGB(0xc0, 0xc0, 0xc0),
 };
 
-static int ME_GetBorderPenWidth(ME_TextEditor* editor, int idx)
+static int ME_GetBorderPenWidth(ME_Context* c, int idx)
 {
   int width;
 
-  if (editor->nZoomNumerator == 0)
+  if (c->nZoomNumerator == 0)
   {
       width = border_details[idx].width_num + border_details[idx].width_den / 2;
       width /= border_details[idx].width_den;
   }
   else
   {
-      width = border_details[idx].width_num * editor->nZoomNumerator;
-      width += border_details[idx].width_den * editor->nZoomNumerator / 2;
-      width /= border_details[idx].width_den * editor->nZoomDenominator;
+      width = border_details[idx].width_num * c->nZoomNumerator;
+      width += border_details[idx].width_den * c->nZoomNumerator / 2;
+      width /= border_details[idx].width_den * c->nZoomDenominator;
   }
-  return width;
+  /* Convert from points to target resolution */
+  if (c->dpiTarget.cx == c->dpi.cx)
+    return width;
+  return (LONGLONG)width * c->dpiTarget.cx / c->dpi.cx;
 }
 
-int  ME_GetParaBorderWidth(ME_TextEditor* editor, int flags)
+int ME_GetParaBorderWidth(ME_Context* c, int flags)
 {
   int idx = (flags >> 8) & 0xF;
   int width;
@@ -515,7 +563,7 @@ int  ME_GetParaBorderWidth(ME_TextEditor* editor, int flags)
       FIXME("Unsupported border value %d\n", idx);
       return 0;
   }
-  width = ME_GetBorderPenWidth(editor, idx);
+  width = ME_GetBorderPenWidth(c, idx);
   if (border_details[idx].dble) width = width * 2 + 1;
   return width;
 }
@@ -565,28 +613,28 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
      */
     if (para->pFmt->wBorders & 0x00B0)
       FIXME("Unsupported border flags %x\n", para->pFmt->wBorders);
-    border_width = ME_GetParaBorderWidth(c->editor, para->pFmt->wBorders);
+    border_width = ME_GetParaBorderWidth(c, para->pFmt->wBorders);
     if (para->pFmt->wBorders & 4)       top_border = border_width;
     if (para->pFmt->wBorders & 8)       bottom_border = border_width;
   }
 
   if (para->pFmt->dwMask & PFM_SPACEBEFORE)
   {
-    rc.left = c->rcView.left;
-    rc.right = c->rcView.right;
-    rc.top = y;
-    bounds->top = ME_twips2pointsY(c, para->pFmt->dySpaceBefore);
-    rc.bottom = y + bounds->top + top_border;
+    bounds->top = ME_twips2targetY(c, para->pFmt->dySpaceBefore);
+    rc.left = ME_target2pointsX(c, c->rcView.left);
+    rc.right = ME_target2pointsX(c, c->rcView.right);
+    rc.top = ME_target2pointsY(c, y);
+    rc.bottom = ME_target2pointsY(c, y + bounds->top + top_border);
     FillRect(c->hDC, &rc, c->editor->hbrBackground);
   }
 
   if (para->pFmt->dwMask & PFM_SPACEAFTER)
   {
-    rc.left = c->rcView.left;
-    rc.right = c->rcView.right;
-    rc.bottom = y + para->nHeight;
-    bounds->bottom = ME_twips2pointsY(c, para->pFmt->dySpaceAfter);
-    rc.top = rc.bottom - bounds->bottom - bottom_border;
+    bounds->bottom = ME_twips2targetY(c, para->pFmt->dySpaceAfter);
+    rc.left = ME_target2pointsX(c, c->rcView.left);
+    rc.right = ME_target2pointsX(c, c->rcView.right);
+    rc.bottom = ME_target2pointsY(c, y + para->nHeight);
+    rc.top = ME_target2pointsY(c, y + para->nHeight - bounds->bottom - bottom_border);
     FillRect(c->hDC, &rc, c->editor->hbrBackground);
   }
 
@@ -604,11 +652,11 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
     else
       pencr = pen_colors[(para->pFmt->wBorders >> 12) & 0xF];
 
-    rightEdge = c->pt.x + max(c->editor->sizeWindow.cx,
+    rightEdge = c->pt.x + max(c->rcView.right - c->rcView.left,
                               c->editor->nTotalWidth);
 
-    pen_width = ME_GetBorderPenWidth(c->editor, idx);
-    pen = CreatePen(border_details[idx].pen_style, pen_width, pencr);
+    pen_width = ME_GetBorderPenWidth(c, idx);
+    pen = CreatePen(border_details[idx].pen_style, ME_target2pointsX(c, pen_width), pencr);
     oldpen = SelectObject(c->hDC, pen);
     MoveToEx(c->hDC, 0, 0, &pt);
 
@@ -619,51 +667,59 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
 
     if (para->pFmt->wBorders & 1)
     {
-      MoveToEx(c->hDC, c->pt.x, y + bounds->top, NULL);
-      LineTo(c->hDC, c->pt.x, y + para->nHeight - bounds->bottom);
+      int line_x = ME_target2pointsX(c, c->pt.x);
+      MoveToEx(c->hDC, line_x, ME_target2pointsY(c, y + bounds->top), NULL);
+      LineTo(c->hDC, line_x, ME_target2pointsY(c, y + para->nHeight - bounds->bottom));
       if (border_details[idx].dble) {
-        rc.left = c->pt.x + 1;
-        rc.right = rc.left + border_width;
-        rc.top = y + bounds->top;
-        rc.bottom = y + para->nHeight - bounds->bottom;
+        rc.left = ME_target2pointsX(c, c->pt.x + 1);
+        rc.right = rc.left + ME_target2pointsX(c, border_width);
+        rc.top = ME_target2pointsY(c, y + bounds->top);
+        rc.bottom = ME_target2pointsY(c, y + para->nHeight - bounds->bottom);
         FillRect(c->hDC, &rc, c->editor->hbrBackground);
-        MoveToEx(c->hDC, c->pt.x + pen_width + 1, y + bounds->top + DD(4), NULL);
-        LineTo(c->hDC, c->pt.x + pen_width + 1, y + para->nHeight - bounds->bottom - DD(8));
+        line_x = ME_target2pointsX(c, c->pt.x + pen_width + 1);
+        MoveToEx(c->hDC, line_x, ME_target2pointsY(c, y + bounds->top + DD(4)), NULL);
+        LineTo(c->hDC, line_x, ME_target2pointsY(c, y + para->nHeight - bounds->bottom - DD(8)));
       }
       bounds->left += border_width;
     }
     if (para->pFmt->wBorders & 2)
     {
-      MoveToEx(c->hDC, rightEdge - 1, y + bounds->top, NULL);
-      LineTo(c->hDC, rightEdge - 1, y + para->nHeight - bounds->bottom);
+      int line_x = ME_target2pointsX(c, rightEdge - 1);
+      MoveToEx(c->hDC, line_x, ME_target2pointsY(c, y + bounds->top), NULL);
+      LineTo(c->hDC, line_x, ME_target2pointsY(c, y + para->nHeight - bounds->bottom));
       if (border_details[idx].dble) {
-        rc.left = rightEdge - pen_width - 1;
-        rc.right = rc.left + pen_width;
-        rc.top = y + bounds->top;
-        rc.bottom = y + para->nHeight - bounds->bottom;
+        rc.left = ME_target2pointsX(c, rightEdge - pen_width - 1);
+        rc.right = rc.left + ME_target2pointsX(c, pen_width);
+        rc.top = ME_target2pointsY(c, y + bounds->top);
+        rc.bottom = ME_target2pointsY(c, y + para->nHeight - bounds->bottom);
         FillRect(c->hDC, &rc, c->editor->hbrBackground);
-        MoveToEx(c->hDC, rightEdge - 1 - pen_width - 1, y + bounds->top + DD(4), NULL);
-        LineTo(c->hDC, rightEdge - 1 - pen_width - 1, y + para->nHeight - bounds->bottom - DD(8));
+        line_x = ME_target2pointsX(c, rightEdge - 1 - pen_width - 1);
+        MoveToEx(c->hDC, line_x, ME_target2pointsY(c, y + bounds->top + DD(4)), NULL);
+        LineTo(c->hDC, line_x, ME_target2pointsY(c, y + para->nHeight - bounds->bottom - DD(8)));
       }
       bounds->right += border_width;
     }
     if (para->pFmt->wBorders & 4)
     {
-      MoveToEx(c->hDC, c->pt.x, y + bounds->top, NULL);
-      LineTo(c->hDC, rightEdge, y + bounds->top);
+      int line_y = ME_target2pointsY(c, y + bounds->top);
+      MoveToEx(c->hDC, ME_target2pointsX(c, c->pt.x), line_y, NULL);
+      LineTo(c->hDC, ME_target2pointsX(c, rightEdge), line_y);
       if (border_details[idx].dble) {
-        MoveToEx(c->hDC, c->pt.x + DD(1), y + bounds->top + pen_width + 1, NULL);
-        LineTo(c->hDC, rightEdge - DD(2), y + bounds->top + pen_width + 1);
+        line_y = ME_target2pointsY(c, y + bounds->top + pen_width + 1);
+        MoveToEx(c->hDC, ME_target2pointsX(c, c->pt.x + DD(1)), line_y, NULL);
+        LineTo(c->hDC, ME_target2pointsX(c, rightEdge - DD(2)), line_y);
       }
       bounds->top += border_width;
     }
     if (para->pFmt->wBorders & 8)
     {
-      MoveToEx(c->hDC, c->pt.x, y + para->nHeight - bounds->bottom - 1, NULL);
-      LineTo(c->hDC, rightEdge, y + para->nHeight - bounds->bottom - 1);
+      int line_y = ME_target2pointsY(c, y + para->nHeight - bounds->bottom - 1);
+      MoveToEx(c->hDC, ME_target2pointsX(c, c->pt.x), line_y, NULL);
+      LineTo(c->hDC, ME_target2pointsX(c, rightEdge), line_y);
       if (border_details[idx].dble) {
-        MoveToEx(c->hDC, c->pt.x + DD(1), y + para->nHeight - bounds->bottom - 1 - pen_width - 1, NULL);
-        LineTo(c->hDC, rightEdge - DD(2), y + para->nHeight - bounds->bottom - 1 - pen_width - 1);
+        line_y = ME_target2pointsY(c, y + para->nHeight - bounds->bottom - 1 - pen_width - 1);
+        MoveToEx(c->hDC, ME_target2pointsX(c, c->pt.x + DD(1)), line_y, NULL);
+        LineTo(c->hDC, ME_target2pointsX(c, rightEdge - DD(2)), line_y);
       }
       bounds->bottom += border_width;
     }
@@ -690,7 +746,6 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
       HBRUSH brush;
       COLORREF color;
       POINT oldPt;
-      int width;
       BOOL atTop = (para->pCell != para->prev_para->member.para.pCell);
       BOOL atBottom = (para->pCell != para->next_para->member.para.pCell);
       int top = c->pt.y + (atTop ? cell->pt.y : para->pt.y);
@@ -698,13 +753,15 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
                     c->pt.y + cell->pt.y + cell->nHeight :
                     top + para->nHeight + (atTop ? cell->yTextOffset : 0));
       rc.left = c->pt.x + cell->pt.x;
-      rc.right = rc.left + cell->nWidth;
+      rc.right = ME_target2pointsX(c, rc.left + cell->nWidth);
+      rc.left = ME_target2pointsX(c, rc.left);
       if (atTop) {
         /* Erase gap before text if not all borders are the same height. */
-        width = max(ME_twips2pointsY(c, cell->border.top.width), 1);
+        int width = max(ME_twips2targetY(c, cell->border.top.width), 1);
         rc.top = top + width;
         width = cell->yTextOffset - width;
-        rc.bottom = rc.top + width;
+        rc.bottom = ME_target2pointsY(c, rc.top + width);
+        rc.top = ME_target2pointsY(c, rc.top);
         if (width) {
           FillRect(c->hDC, &rc, c->editor->hbrBackground);
         }
@@ -714,8 +771,9 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
        * to be consistent with native richedit.  This is noticeable from the
        * overlap of borders of different colours. */
       if (!(para->nFlags & MEPF_ROWEND)) {
-        rc.top = top;
-        rc.bottom = bottom;
+        int width;
+        rc.top = ME_target2pointsY(c, top);
+        rc.bottom = ME_target2pointsY(c, bottom);
         if (cell->border.left.width > 0)
         {
           color = cell->border.left.colorRef;
@@ -738,16 +796,17 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
       }
 
       if (atTop) {
+        int width;
         if (cell->border.top.width > 0)
         {
           brush = CreateSolidBrush(cell->border.top.colorRef);
-          width = max(ME_twips2pointsY(c, cell->border.top.width), 1);
+          width = max(ME_twips2targetY(c, cell->border.top.width), 1);
         } else {
           brush = GetStockObject(LTGRAY_BRUSH);
           width = 1;
         }
-        rc.top = top;
-        rc.bottom = rc.top + width;
+        rc.top = ME_target2pointsY(c, top);
+        rc.bottom = ME_target2pointsY(c, top + width);
         FillRect(c->hDC, &rc, brush);
         if (cell->border.top.width > 0)
           DeleteObject(brush);
@@ -757,13 +816,13 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
        * in the last row of the table. */
       if (atBottom) {
         int oldLeft = rc.left;
-        width = max(ME_twips2pointsY(c, cell->border.bottom.width), 1);
+        int width = max(ME_twips2targetY(c, cell->border.bottom.width), 1);
         paraAfterRow = ME_GetTableRowEnd(paragraph)->member.para.next_para;
         if (paraAfterRow->member.para.nFlags & MEPF_ROWSTART) {
           ME_DisplayItem *nextEndCell;
           nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell);
           assert(nextEndCell && !nextEndCell->member.cell.next_cell);
-          rc.left = c->pt.x + nextEndCell->member.cell.pt.x;
+          rc.left = ME_target2pointsX(c, c->pt.x + nextEndCell->member.cell.pt.x);
           /* FIXME: Native draws FROM the bottom of the table rather than
            * TO the bottom of the table in this case, but just doing so here
            * will cause the next row to erase the border. */
@@ -779,7 +838,8 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
             brush = GetStockObject(LTGRAY_BRUSH);
           }
           rc.bottom = bottom;
-          rc.top = rc.bottom - width;
+          rc.top = ME_target2pointsY(c, rc.bottom - width);
+          rc.bottom = ME_target2pointsY(c, rc.bottom);
           FillRect(c->hDC, &rc, brush);
           if (cell->border.bottom.width > 0)
             DeleteObject(brush);
@@ -791,8 +851,9 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
       if (!cell->next_cell->member.cell.next_cell &&
           !(para->nFlags & MEPF_ROWSTART))
       {
-        rc.top = top;
-        rc.bottom = bottom;
+        int width;
+        rc.top = ME_target2pointsY(c, top);
+        rc.bottom = ME_target2pointsY(c, bottom);
         if (cell->border.right.width > 0) {
           color = cell->border.right.colorRef;
           width = max(ME_twips2pointsX(c, cell->border.right.width), 1);
@@ -827,23 +888,28 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
       /* Find the start relative to the text */
       firstX = c->pt.x + ME_FindItemFwd(paragraph, diRun)->member.run.pt.x;
       /* Go back by the horizontal gap, which is stored in dxOffset */
-      firstX -= ME_twips2pointsX(c, para->pFmt->dxOffset);
+      firstX -= ME_twips2targetX(c, para->pFmt->dxOffset);
       /* The left edge, stored in dxStartIndent affected just the first edge */
-      startX = firstX - ME_twips2pointsX(c, para->pFmt->dxStartIndent);
+      startX = firstX - ME_twips2targetX(c, para->pFmt->dxStartIndent);
       rowY = c->pt.y + para->pt.y;
       if (para->pFmt->dwMask & PFM_SPACEBEFORE)
-        rowY += ME_twips2pointsY(c, para->pFmt->dySpaceBefore);
+        rowY += ME_twips2targetX(c, para->pFmt->dySpaceBefore);
       nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight;
       rowBottom = rowY + nHeight;
 
+      firstX = ME_target2pointsX(c, firstX);
+      rowY = ME_target2pointsY(c, rowY);
+
       /* Draw horizontal lines */
       MoveToEx(c->hDC, firstX, rowY, &oldPt);
       i = para->pFmt->cTabCount - 1;
-      endX = startX + ME_twips2pointsX(c, para->pFmt->rgxTabs[i] & 0x00ffffff) + 1;
+      endX = startX + ME_twips2targetX(c, para->pFmt->rgxTabs[i] & 0x00ffffff) + 1;
+      endX = ME_target2pointsX(c, endX);
       LineTo(c->hDC, endX, rowY);
       pNextFmt = para->next_para->member.para.pFmt;
       /* The bottom of the row only needs to be drawn if the next row is
        * not a table. */
+      rowBottom = ME_target2pointsY(c, rowBottom);
       if (!(pNextFmt && pNextFmt->dwMask & PFM_TABLE && pNextFmt->wEffects &&
             para->nRows == 1))
       {
@@ -860,7 +926,8 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
       for (i = 0; i < para->pFmt->cTabCount; i++)
       {
         int rightBoundary = para->pFmt->rgxTabs[i] & 0x00ffffff;
-        endX = startX + ME_twips2pointsX(c, rightBoundary);
+        endX = startX + ME_twips2targetX(c, rightBoundary);
+        endX = ME_target2pointsX(c, endX);
         MoveToEx(c->hDC, endX, rowY, NULL);
         LineTo(c->hDC, endX, rowBottom);
       }
@@ -907,12 +974,13 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
   if (bounds.left || bounds.right) {
     rc.left = max(rc.left, c->pt.x + bounds.left);
     rc.right = min(rc.right, c->pt.x - bounds.right
-                             + max(c->editor->sizeWindow.cx,
+                             + max(c->rcView.right - c->rcView.left,
                                    c->editor->nTotalWidth));
   }
 
   for (p = paragraph->next; p != para->next_para; p = p->next)
   {
+    RECT rcDraw;
     switch(p->type) {
       case diParagraph:
         assert(FALSE);
@@ -925,17 +993,21 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
         } else {
           rc.bottom = y + p->member.row.nHeight;
         }
-        visible = RectVisible(c->hDC, &rc);
+        rcDraw.left = ME_target2pointsX(c, rc.left);
+        rcDraw.right = ME_target2pointsX(c, rc.right);
+        rcDraw.top = ME_target2pointsY(c, rc.top);
+        rcDraw.bottom = ME_target2pointsY(c, rc.bottom);
+        visible = RectVisible(c->hDC, &rcDraw);
         if (visible) {
-          FillRect(c->hDC, &rc, c->editor->hbrBackground);
+          FillRect(c->hDC, &rcDraw, c->editor->hbrBackground);
         }
         if (bounds.right)
         {
           /* If scrolled to the right past the end of the text, then
            * there may be space to the right of the paragraph border. */
-          RECT rcAfterBrdr = rc;
-          rcAfterBrdr.left = rc.right + bounds.right;
-          rcAfterBrdr.right = c->rcView.right;
+          RECT rcAfterBrdr = rcDraw;
+          rcAfterBrdr.left = ME_target2pointsX(c, rc.right + bounds.right);
+          rcAfterBrdr.right = ME_target2pointsX(c, c->rcView.right);
           if (RectVisible(c->hDC, &rcAfterBrdr))
             FillRect(c->hDC, &rcAfterBrdr, c->editor->hbrBackground);
         }
@@ -943,7 +1015,9 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
         {
           const WCHAR wszRowDebug[] = {'r','o','w','[','%','d',']',0};
           WCHAR buf[128];
-          POINT pt = c->pt;
+          POINT pt;
+          pt.x = ME_target2pointsX(c, c->pt.x);
+          pt.y = ME_target2pointsY(c, c->pt.y);
           wsprintfW(buf, wszRowDebug, no);
           pt.y = 12+y;
           ME_DebugWrite(c->hDC, &pt, buf);
@@ -957,10 +1031,10 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
         run = &p->member.run;
         if (visible && me_debug) {
           RECT rc;
-          rc.left = c->pt.x + run->pt.x;
-          rc.right = rc.left + run->nWidth;
-          rc.top = c->pt.y + para->pt.y + run->pt.y;
-          rc.bottom = rc.bottom + height;
+          rc.left = ME_target2pointsX(c, c->pt.x + run->pt.x);
+          rc.right = ME_target2pointsX(c, c->pt.x + run->pt.x + run->nWidth);
+          rc.top = ME_target2pointsY(c, c->pt.y + para->pt.y + run->pt.y);
+          rc.bottom = ME_target2pointsY(c, c->pt.y + para->pt.y + run->pt.y + height);
           TRACE("rc = (%d, %d, %d, %d)\n", rc.left, rc.top, rc.right, rc.bottom);
           if (run->nFlags & MERF_SKIPPED)
             DrawFocusRect(c->hDC, &rc);
@@ -976,8 +1050,8 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
           const WCHAR wszRunDebug[] = {'[','%','d',':','%','x',']',' ','%','l','s',0};
           WCHAR buf[2560];
           POINT pt;
-          pt.x = c->pt.x + run->pt.x;
-          pt.y = c->pt.y + para->pt.y + run->pt.y;
+          pt.x = ME_target2pointsX(c, c->pt.x + run->pt.x);
+          pt.y = ME_target2pointsY(c, c->pt.y + para->pt.y + run->pt.y);
           wsprintfW(buf, wszRunDebug, no, p->member.run.nFlags, p->member.run.strText->szData);
           ME_DebugWrite(c->hDC, &pt, buf);
         }
@@ -989,9 +1063,13 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
         y += height;
         rc.top = c->pt.y + para->pt.y + para->nHeight;
         rc.bottom = c->pt.y + p->member.cell.pt.y + p->member.cell.nHeight;
-        if (RectVisible(c->hDC, &rc))
+        rcDraw.left = ME_target2pointsX(c, rc.left);
+        rcDraw.right = ME_target2pointsX(c, rc.right);
+        rcDraw.top = ME_target2pointsY(c, rc.top);
+        rcDraw.bottom = ME_target2pointsY(c, rc.bottom);
+        if (RectVisible(c->hDC, &rcDraw))
         {
-          FillRect(c->hDC, &rc, c->editor->hbrBackground);
+          FillRect(c->hDC, &rcDraw, c->editor->hbrBackground);
         }
         break;
       default:
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index b6319e7..c0e3de0 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -36,7 +36,7 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
   ME_String *eol_str;
   WCHAR cr_lf[] = {'\r','\n',0};
 
-  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
+  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost), NULL);
 
   hf = GetStockObject(SYSTEM_FONT);
   assert(hf);
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index c7eb5ff..ef690c8 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -1703,11 +1703,11 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj)
     return 1;
 }
 
-static void convert_sizel(ME_Context *c, const SIZEL* szl, SIZE* sz)
+static void convert_sizel(SIZE dpi, const SIZEL* szl, SIZE* sz)
 {
   /* sizel is in .01 millimeters, sz in pixels */
-  sz->cx = MulDiv(szl->cx, c->dpi.cx, 2540);
-  sz->cy = MulDiv(szl->cy, c->dpi.cy, 2540);
+  sz->cx = MulDiv(szl->cx, dpi.cx, 2540);
+  sz->cy = MulDiv(szl->cy, dpi.cy, 2540);
 }
 
 /******************************************************************************
@@ -1728,7 +1728,7 @@ void ME_GetOLEObjectSize(ME_Context *c, ME_Run *run, SIZE *pSize)
 
   if (run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0)
   {
-    convert_sizel(c, &run->ole_obj->sizel, pSize);
+    convert_sizel(c->dpiTarget, &run->ole_obj->sizel, pSize);
     return;
   }
 
@@ -1769,11 +1769,13 @@ void ME_GetOLEObjectSize(ME_Context *c, ME_Run *run, SIZE *pSize)
     FIXME("Unsupported tymed %d\n", stgm.tymed);
     break;
   }
+  pSize->cx = MulDiv(pSize->cx, c->dpiTarget.cx, 96);
+  pSize->cy = MulDiv(pSize->cy, c->dpiTarget.cy, 96);
   IDataObject_Release(ido);
-  if (c->editor->nZoomNumerator != 0)
+  if (c->nZoomNumerator != 0)
   {
-    pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
-    pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+    pSize->cx = MulDiv(pSize->cx, c->nZoomNumerator, c->nZoomDenominator);
+    pSize->cy = MulDiv(pSize->cy, c->nZoomNumerator, c->nZoomDenominator);
   }
 }
 
@@ -1796,6 +1798,8 @@ void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run,
     FIXME("Couldn't get interface\n");
     return;
   }
+  x = ME_target2pointsX(c, x);
+  y = ME_target2pointsY(c, y);
   has_size = run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0;
   fmt.cfFormat = CF_BITMAP;
   fmt.ptd = NULL;
@@ -1819,53 +1823,45 @@ void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run,
     GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect);
     hMemDC = CreateCompatibleDC(c->hDC);
     SelectObject(hMemDC, stgm.u.hBitmap);
-    if (!has_size && c->editor->nZoomNumerator == 0)
+    if (has_size)
     {
-      sz.cx = dibsect.dsBm.bmWidth;
-      sz.cy = dibsect.dsBm.bmHeight;
-      BitBlt(c->hDC, x, y - dibsect.dsBm.bmHeight,
-             dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight,
-             hMemDC, 0, 0, SRCCOPY);
+      convert_sizel(c->dpi, &run->ole_obj->sizel, &sz);
+    } else {
+      sz.cx = MulDiv(dibsect.dsBm.bmWidth, c->dpi.cx, 96);
+      sz.cy = MulDiv(dibsect.dsBm.bmHeight, c->dpi.cy, 96);
+    }
+    if (c->nZoomNumerator != 0)
+    {
+      sz.cx = MulDiv(sz.cx, c->nZoomNumerator, c->nZoomDenominator);
+      sz.cy = MulDiv(sz.cy, c->nZoomNumerator, c->nZoomDenominator);
     }
-    else
+    if (sz.cx == dibsect.dsBm.bmWidth && sz.cy == dibsect.dsBm.bmHeight)
     {
-      if (has_size)
-      {
-        convert_sizel(c, &run->ole_obj->sizel, &sz);
-      }
-      else
-      {
-        sz.cx = MulDiv(dibsect.dsBm.bmWidth,
-                       c->editor->nZoomNumerator, c->editor->nZoomDenominator);
-        sz.cy = MulDiv(dibsect.dsBm.bmHeight,
-                       c->editor->nZoomNumerator, c->editor->nZoomDenominator);
-      }
+      BitBlt(c->hDC, x, y - sz.cy,
+             dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight,
+             hMemDC, 0, 0, SRCCOPY);
+    } else {
       StretchBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy,
-                 hMemDC, 0, 0, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, SRCCOPY);
+                 hMemDC, 0, 0, dibsect.dsBm.bmWidth,
+                 dibsect.dsBm.bmHeight, SRCCOPY);
     }
     if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap);
     break;
   case TYMED_ENHMF:
     GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh);
-    if (!has_size && c->editor->nZoomNumerator == 0)
+    if (has_size)
     {
-      sz.cy = emh.rclBounds.bottom - emh.rclBounds.top;
-      sz.cx = emh.rclBounds.right - emh.rclBounds.left;
+      convert_sizel(c->dpi, &run->ole_obj->sizel, &sz);
+    } else {
+      sz.cy = MulDiv(emh.rclBounds.bottom - emh.rclBounds.top, c->dpi.cx, 96);
+      sz.cx = MulDiv(emh.rclBounds.right - emh.rclBounds.left, c->dpi.cy, 96);
     }
-    else
+    if (c->nZoomNumerator != 0)
     {
-      if (has_size)
-      {
-        convert_sizel(c, &run->ole_obj->sizel, &sz);
-      }
-      else
-      {
-        sz.cy = MulDiv(emh.rclBounds.bottom - emh.rclBounds.top,
-                       c->editor->nZoomNumerator, c->editor->nZoomDenominator);
-        sz.cx = MulDiv(emh.rclBounds.right - emh.rclBounds.left,
-                       c->editor->nZoomNumerator, c->editor->nZoomDenominator);
-      }
+      sz.cx = MulDiv(sz.cx, c->nZoomNumerator, c->nZoomDenominator);
+      sz.cy = MulDiv(sz.cy, c->nZoomNumerator, c->nZoomDenominator);
     }
+
     {
       RECT    rc;
 
@@ -1882,7 +1878,7 @@ void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run,
     selected = FALSE;
     break;
   }
-  if (selected && !c->editor->bHideSelection)
+  if (selected && !c->bHideSelection)
     PatBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy, DSTINVERT);
   IDataObject_Release(ido);
 }
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index cd282ec..e41bf23 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -458,22 +458,22 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run)
       return 0;
     return 1;
   }
-  hOldFont = ME_SelectStyleFont(c, run->style);
-  
+  hOldFont = ME_SelectStyleFont(c, run->style, TRUE);
+
   if (c->editor->cPasswordMask)
   {
     ME_String *strMasked = ME_MakeStringR(c->editor->cPasswordMask, run->strText->nLen);
-    GetTextExtentExPointW(c->hDC, strMasked->szData, run->strText->nLen,
+    GetTextExtentExPointW(c->hdcTarget, strMasked->szData, run->strText->nLen,
       cx, &fit, NULL, &sz);
     ME_DestroyString(strMasked);
   }
   else
   {
-    GetTextExtentExPointW(c->hDC, run->strText->szData, run->strText->nLen,
+    GetTextExtentExPointW(c->hdcTarget, run->strText->szData, run->strText->nLen,
       cx, &fit, NULL, &sz);
   }
-  
-  ME_UnselectStyleFont(c, run->style, hOldFont);
+
+  ME_UnselectStyleFont(c, run->style, TRUE, hOldFont);
 
   return fit;
 }
@@ -507,7 +507,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
       return 0;
     return 1;
   }
-  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
+  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost), NULL);
   if (run->nFlags & MERF_GRAPHICS)
   {
     SIZE sz;
@@ -523,7 +523,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
   else
     strRunText = run->strText;
 
-  hOldFont = ME_SelectStyleFont(&c, run->style);
+  hOldFont = ME_SelectStyleFont(&c, run->style, FALSE);
   GetTextExtentExPointW(c.hDC, strRunText->szData, strRunText->nLen,
                         cx, &fit, NULL, &sz);
   if (fit != strRunText->nLen)
@@ -537,7 +537,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
   if (editor->cPasswordMask)
     ME_DestroyString(strRunText);
 
-  ME_UnselectStyleFont(&c, run->style, hOldFont);
+  ME_UnselectStyleFont(&c, run->style, FALSE, hOldFont);
   ME_DestroyContext(&c);
   return fit;
 }
@@ -550,10 +550,10 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
 static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
 {
   HGDIOBJ hOldFont;
-  if (c->hDC) {
-    hOldFont = ME_SelectStyleFont(c, s);
-    GetTextExtentPoint32W(c->hDC, szText, nChars, size);
-    ME_UnselectStyleFont(c, s, hOldFont);
+  if (c->hdcTarget) {
+    hOldFont = ME_SelectStyleFont(c, s, TRUE);
+    GetTextExtentPoint32W(c->hdcTarget, szText, nChars, size);
+    ME_UnselectStyleFont(c, s, TRUE, hOldFont);
   } else {
     size->cx = 0;
     size->cy = 0;
@@ -573,7 +573,7 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
   ME_String *strRunText;
   /* This could point to either the run's real text, or it's masked form in a password control */
 
-  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
+  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost), NULL);
   if (pRun->nFlags & MERF_GRAPHICS)
   {
     if (nOffset)
@@ -653,7 +653,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run
       {
         pos += lDefaultTab - (pos % lDefaultTab);
       }
-      ppos = ME_twips2pointsX(c, pos);
+      ppos = ME_twips2targetX(c, pos);
       if (ppos > startx + run->pt.x) {
         size.cx = ppos - startx - run->pt.x;
         break;
diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c
index bb2f808..7545b42 100644
--- a/dlls/riched20/style.c
+++ b/dlls/riched20/style.c
@@ -303,13 +303,16 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048])
 
 
 static void
-ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s)
+ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s, BOOL bTarget)
 {
   ZeroMemory(lf, sizeof(LOGFONTW));
   lstrcpyW(lf->lfFaceName, s->fmt.szFaceName);
 
-  lf->lfHeight = ME_twips2pointsY(c, -s->fmt.yHeight);
-  
+  if (bTarget)
+    lf->lfHeight = ME_twips2targetY(c, -s->fmt.yHeight);
+  else
+    lf->lfHeight = ME_twips2pointsY(c, -s->fmt.yHeight);
+
   lf->lfWeight = FW_NORMAL;
   if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD)
     lf->lfWeight = FW_BOLD;
@@ -362,16 +365,17 @@ static BOOL ME_IsFontEqual(const LOGFONTW *p1, const LOGFONTW *p2)
   return TRUE;
 }
 
-HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s)
+HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s, BOOL bTarget)
 {
   HFONT hOldFont;
   LOGFONTW lf;
   int i, nEmpty, nAge = 0x7FFFFFFF;
   ME_FontCacheItem *item;
+  HDC hdc = bTarget ? c->hdcTarget : c->hDC;
   assert(s);
-  
-  ME_LogFontFromStyle(c, &lf, s);
-  
+
+  ME_LogFontFromStyle(c, &lf, s, bTarget);
+
   for (i=0; i<HFONT_CACHE_SIZE; i++)
     c->editor->pFontCache[i].nAge++;
   for (i=0, nEmpty=-1, nAge=0; i<HFONT_CACHE_SIZE; i++)
@@ -410,18 +414,19 @@ HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s)
     item->nRefs = 1;
     item->lfSpecs = lf;
   }
-  hOldFont = SelectObject(c->hDC, s->hFont);
+  hOldFont = SelectObject(hdc, s->hFont);
   /* should be cached too, maybe ? */
-  GetTextMetricsW(c->hDC, &s->tm);
+  GetTextMetricsW(hdc, &s->tm);
   return hOldFont;
 }
 
-void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont)
+void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, BOOL bTarget, HFONT hOldFont)
 {
   int i;
-  
+  HDC hdc = bTarget ? c->hdcTarget : c->hDC;
+
   assert(s);
-  SelectObject(c->hDC, hOldFont);
+  SelectObject(hdc, hOldFont);
   for (i=0; i<HFONT_CACHE_SIZE; i++)
   {
     ME_FontCacheItem *pItem = &c->editor->pFontCache[i];
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
index f567d40..94fd642 100644
--- a/dlls/riched20/wrap.c
+++ b/dlls/riched20/wrap.c
@@ -51,7 +51,7 @@ static void ME_BeginRow(ME_WrapContext *wc)
   wc->pRowStart = NULL;
   wc->bOverflown = FALSE;
   wc->pLastSplittableRun = NULL;
-  wc->bWordWrap = wc->context->editor->bWordWrap;
+  wc->bWordWrap = wc->context->bWordWrap;
   if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) {
     wc->nAvailWidth = 0;
     wc->bWordWrap = FALSE;
@@ -72,7 +72,7 @@ static void ME_BeginRow(ME_WrapContext *wc)
       int rowIndent = ME_GetTableRowEnd(para)->member.para.pFmt->dxStartIndent;
       width -= rowIndent;
     }
-    cell->nWidth = max(ME_twips2pointsX(wc->context, width), 0);
+    cell->nWidth = max(ME_twips2targetX(wc->context, width), 0);
 
     wc->nAvailWidth = cell->nWidth
         - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin;
@@ -468,20 +468,21 @@ static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para)
   case 0:       sp = ls; break;
   case 1:       sp = (3 * ls) / 2; break;
   case 2:       sp = 2 * ls; break;
-  case 3:       sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); if (sp < ls) sp = ls; break;
-  case 4:       sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); break;
+  case 3:       sp = ME_twips2targetY(c, para->pFmt->dyLineSpacing); if (sp < ls) sp = ls; break;
+  case 4:       sp = ME_twips2targetY(c, para->pFmt->dyLineSpacing); break;
   case 5:       sp = para->pFmt->dyLineSpacing / 20; break;
   default: FIXME("Unsupported spacing rule value %d\n", para->pFmt->bLineSpacingRule);
   }
-  if (c->editor->nZoomNumerator == 0)
+  if (c->nZoomNumerator == 0)
     return sp;
   else
-    return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator;
+    return sp * c->nZoomNumerator / c->nZoomDenominator;
 }
 
 static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp);
 
-static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
+void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp)
+{
   ME_DisplayItem *p;
   ME_WrapContext wc;
   int border = 0;
@@ -489,72 +490,180 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
   PARAFORMAT2 *pFmt;
 
   assert(tp->type == diParagraph);
-  if (!(tp->member.para.nFlags & MEPF_REWRAP)) {
-    return;
-  }
-  ME_PrepareParagraphForWrapping(c, tp);
-  pFmt = tp->member.para.pFmt;
-
-  wc.context = c;
-  wc.pPara = tp;
-/*   wc.para_style = tp->member.para.style; */
-  wc.style = NULL;
-  if (tp->member.para.nFlags & MEPF_ROWEND) {
-    wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0;
-  } else {
-    int dxStartIndent = pFmt->dxStartIndent;
-    if (tp->member.para.pCell) {
-      dxStartIndent += ME_GetTableRowEnd(tp)->member.para.pFmt->dxOffset;
+  if (tp->member.para.nFlags & MEPF_REWRAP)
+  {
+    ME_PrepareParagraphForWrapping(c, tp);
+    pFmt = tp->member.para.pFmt;
+
+    wc.context = c;
+    wc.pPara = tp;
+    /* wc.para_style = tp->member.para.style; */
+    wc.style = NULL;
+    if (tp->member.para.nFlags & MEPF_ROWEND) {
+      wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0;
+    } else {
+      int dxStartIndent = pFmt->dxStartIndent;
+      if (tp->member.para.pCell) {
+        dxStartIndent += ME_GetTableRowEnd(tp)->member.para.pFmt->dxOffset;
+      }
+      wc.nFirstMargin = ME_twips2targetX(c, dxStartIndent);
+      wc.nLeftMargin = wc.nFirstMargin + ME_twips2targetX(c, pFmt->dxOffset);
+      wc.nRightMargin = ME_twips2targetX(c, pFmt->dxRightIndent);
+    }
+    if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
+        pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
+    {
+      wc.nFirstMargin += ME_twips2targetX(c, pFmt->dxOffset * 2);
+    }
+    wc.nRow = 0;
+    wc.pt.y = 0;
+    if (pFmt->dwMask & PFM_SPACEBEFORE)
+      wc.pt.y += ME_twips2targetY(c, pFmt->dySpaceBefore);
+    if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
+        pFmt->dwMask & PFM_BORDER)
+    {
+      border = ME_GetParaBorderWidth(c, tp->member.para.pFmt->wBorders);
+      if (pFmt->wBorders & 1) {
+        wc.nFirstMargin += border;
+        wc.nLeftMargin += border;
+      }
+      if (pFmt->wBorders & 2)
+        wc.nRightMargin -= border;
+      if (pFmt->wBorders & 4)
+        wc.pt.y += border;
+    }
+
+    linespace = ME_GetParaLineSpace(c, &tp->member.para);
+
+    ME_BeginRow(&wc);
+    for (p = tp->next; p!=tp->member.para.next_para; ) {
+      assert(p->type != diStartRow);
+      if (p->type == diRun) {
+        p = ME_WrapHandleRun(&wc, p);
+      }
+      else p = p->next;
+      if (wc.nRow && p == wc.pRowStart)
+        wc.pt.y += linespace;
     }
-    wc.nFirstMargin = ME_twips2pointsX(c, dxStartIndent);
-    wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, pFmt->dxOffset);
-    wc.nRightMargin = ME_twips2pointsX(c, pFmt->dxRightIndent);
+    ME_WrapEndParagraph(&wc, p);
+    if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
+        (pFmt->dwMask & PFM_BORDER) && (pFmt->wBorders & 8))
+      wc.pt.y += border;
+    if (tp->member.para.pFmt->dwMask & PFM_SPACEAFTER)
+      wc.pt.y += ME_twips2targetY(c, pFmt->dySpaceAfter);
+
+    tp->member.para.nFlags &= ~MEPF_REWRAP;
+    tp->member.para.nHeight = wc.pt.y;
+    tp->member.para.nRows = wc.nRow;
   }
-  if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
-      pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
+
+  /* Update c->pt for wrapping the next paragraph. */
+  if (tp->member.para.nFlags & MEPF_ROWSTART)
   {
-    wc.nFirstMargin += ME_twips2pointsX(c, pFmt->dxOffset * 2);
+    ME_DisplayItem *cell = ME_FindItemFwd(tp, diCell);
+    ME_DisplayItem *endRowPara;
+    int borderWidth = 0;
+    cell->member.cell.pt = c->pt;
+    /* Offset the text by the largest top border width. */
+    while (cell->member.cell.next_cell) {
+      borderWidth = max(borderWidth, cell->member.cell.border.top.width);
+      cell = cell->member.cell.next_cell;
+    }
+    endRowPara = ME_FindItemFwd(cell, diParagraph);
+    assert(endRowPara->member.para.nFlags & MEPF_ROWEND);
+    if (borderWidth > 0)
+    {
+      borderWidth = max(ME_twips2targetY(c, borderWidth), 1);
+      while (cell) {
+        cell->member.cell.yTextOffset = borderWidth;
+        cell = cell->member.cell.prev_cell;
+      }
+      c->pt.y += borderWidth;
+    }
+    if (endRowPara->member.para.pFmt->dxStartIndent > 0)
+    {
+      int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent;
+      cell = ME_FindItemFwd(tp, diCell);
+      cell->member.cell.pt.x += ME_twips2targetX(c, dxStartIndent);
+      c->pt.x = cell->member.cell.pt.x;
+    }
   }
-  wc.nRow = 0;
-  wc.pt.y = 0;
-  if (pFmt->dwMask & PFM_SPACEBEFORE)
-    wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceBefore);
-  if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
-      pFmt->dwMask & PFM_BORDER)
+  else if (tp->member.para.nFlags & MEPF_ROWEND)
   {
-    border = ME_GetParaBorderWidth(c->editor, tp->member.para.pFmt->wBorders);
-    if (pFmt->wBorders & 1) {
-      wc.nFirstMargin += border;
-      wc.nLeftMargin += border;
-    }
-    if (pFmt->wBorders & 2)
-      wc.nRightMargin -= border;
-    if (pFmt->wBorders & 4)
-      wc.pt.y += border;
+    /* Set all the cells to the height of the largest cell */
+    ME_DisplayItem *startRowPara;
+    int prevHeight, nHeight, bottomBorder = 0;
+    ME_DisplayItem *cell = ME_FindItemBack(tp, diCell);
+    tp->member.para.nWidth = cell->member.cell.pt.x + cell->member.cell.nWidth;
+    if (!(tp->member.para.next_para->member.para.nFlags & MEPF_ROWSTART))
+    {
+      /* Last row, the bottom border is added to the height. */
+      cell = cell->member.cell.prev_cell;
+      while (cell)
+      {
+        bottomBorder = max(bottomBorder, cell->member.cell.border.bottom.width);
+        cell = cell->member.cell.prev_cell;
+      }
+      bottomBorder = ME_twips2targetY(c, bottomBorder);
+      cell = ME_FindItemBack(tp, diCell);
+    }
+    prevHeight = cell->member.cell.nHeight;
+    nHeight = cell->member.cell.prev_cell->member.cell.nHeight + bottomBorder;
+    cell->member.cell.nHeight = nHeight;
+    tp->member.para.nHeight = nHeight;
+    cell = cell->member.cell.prev_cell;
+    cell->member.cell.nHeight = nHeight;
+    while (cell->member.cell.prev_cell)
+    {
+      cell = cell->member.cell.prev_cell;
+      cell->member.cell.nHeight = nHeight;
+    }
+    /* Also set the height of the start row paragraph */
+    startRowPara = ME_FindItemBack(cell, diParagraph);
+    startRowPara->member.para.nHeight = nHeight;
+    c->pt.x = startRowPara->member.para.pt.x;
+    c->pt.y = cell->member.cell.pt.y + nHeight;
+    if (prevHeight < nHeight)
+    {
+      /* The height of the cells has grown, so invalidate the bottom of
+       * the cells. */
+      tp->member.para.nFlags |= MEPF_REPAINT;
+      cell = ME_FindItemBack(tp, diCell);
+      while (cell) {
+        ME_FindItemBack(cell, diParagraph)->member.para.nFlags |= MEPF_REPAINT;
+        cell = cell->member.cell.prev_cell;
+      }
+    }
   }
+  else if (tp->member.para.pCell &&
+           tp->member.para.pCell != tp->member.para.next_para->member.para.pCell)
+  {
+    /* The next paragraph is in the next cell in the table row. */
+    ME_Cell *cell = &tp->member.para.pCell->member.cell;
+    cell->nHeight = c->pt.y + tp->member.para.nHeight - cell->pt.y;
 
-  linespace = ME_GetParaLineSpace(c, &tp->member.para);
+    /* Propagate the largest height to the end so that it can be easily
+     * sent back to all the cells at the end of the row. */
+    if (cell->prev_cell)
+      cell->nHeight = max(cell->nHeight, cell->prev_cell->member.cell.nHeight);
 
-  ME_BeginRow(&wc);
-  for (p = tp->next; p!=tp->member.para.next_para; ) {
-    assert(p->type != diStartRow);
-    if (p->type == diRun) {
-      p = ME_WrapHandleRun(&wc, p);
+    c->pt.x = cell->pt.x + cell->nWidth;
+    c->pt.y = cell->pt.y;
+    cell->next_cell->member.cell.pt = c->pt;
+    if (!(tp->member.para.next_para->member.para.nFlags & MEPF_ROWEND))
+      c->pt.y += cell->yTextOffset;
+  }
+  else
+  {
+    if (tp->member.para.pCell) {
+      /* Next paragraph in the same cell. */
+      c->pt.x = tp->member.para.pCell->member.cell.pt.x;
+    } else {
+      /* Normal paragraph */
+      c->pt.x = 0;
     }
-    else p = p->next;
-    if (wc.nRow && p == wc.pRowStart)
-      wc.pt.y += linespace;
+    c->pt.y += tp->member.para.nHeight;
   }
-  ME_WrapEndParagraph(&wc, p);
-  if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
-      (pFmt->dwMask & PFM_BORDER) && (pFmt->wBorders & 8))
-    wc.pt.y += border;
-  if (tp->member.para.pFmt->dwMask & PFM_SPACEAFTER)
-    wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceAfter);
-
-  tp->member.para.nFlags &= ~MEPF_REWRAP;
-  tp->member.para.nHeight = wc.pt.y;
-  tp->member.para.nRows = wc.nRow;
 }
 
 
@@ -605,7 +714,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
   BOOL bModified = FALSE;
   int totalWidth = 0;
 
-  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
+  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost), NULL);
   c.pt.x = 0;
   item = editor->pBuffer->pFirst->next;
   while(item != editor->pBuffer->pLast) {
@@ -624,113 +733,6 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
 
     bModified = bModified | bRedraw;
 
-    if (item->member.para.nFlags & MEPF_ROWSTART)
-    {
-      ME_DisplayItem *cell = ME_FindItemFwd(item, diCell);
-      ME_DisplayItem *endRowPara;
-      int borderWidth = 0;
-      cell->member.cell.pt = c.pt;
-      /* Offset the text by the largest top border width. */
-      while (cell->member.cell.next_cell) {
-        borderWidth = max(borderWidth, cell->member.cell.border.top.width);
-        cell = cell->member.cell.next_cell;
-      }
-      endRowPara = ME_FindItemFwd(cell, diParagraph);
-      assert(endRowPara->member.para.nFlags & MEPF_ROWEND);
-      if (borderWidth > 0)
-      {
-        borderWidth = max(ME_twips2pointsY(&c, borderWidth), 1);
-        while (cell) {
-          cell->member.cell.yTextOffset = borderWidth;
-          cell = cell->member.cell.prev_cell;
-        }
-        c.pt.y += borderWidth;
-      }
-      if (endRowPara->member.para.pFmt->dxStartIndent > 0)
-      {
-        int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent;
-        cell = ME_FindItemFwd(item, diCell);
-        cell->member.cell.pt.x += ME_twips2pointsX(&c, dxStartIndent);
-        c.pt.x = cell->member.cell.pt.x;
-      }
-    }
-    else if (item->member.para.nFlags & MEPF_ROWEND)
-    {
-      /* Set all the cells to the height of the largest cell */
-      ME_DisplayItem *startRowPara;
-      int prevHeight, nHeight, bottomBorder = 0;
-      ME_DisplayItem *cell = ME_FindItemBack(item, diCell);
-      item->member.para.nWidth = cell->member.cell.pt.x + cell->member.cell.nWidth;
-      if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWSTART))
-      {
-        /* Last row, the bottom border is added to the height. */
-        cell = cell->member.cell.prev_cell;
-        while (cell)
-        {
-          bottomBorder = max(bottomBorder, cell->member.cell.border.bottom.width);
-          cell = cell->member.cell.prev_cell;
-        }
-        bottomBorder = ME_twips2pointsY(&c, bottomBorder);
-        cell = ME_FindItemBack(item, diCell);
-      }
-      prevHeight = cell->member.cell.nHeight;
-      nHeight = cell->member.cell.prev_cell->member.cell.nHeight + bottomBorder;
-      cell->member.cell.nHeight = nHeight;
-      item->member.para.nHeight = nHeight;
-      cell = cell->member.cell.prev_cell;
-      cell->member.cell.nHeight = nHeight;
-      while (cell->member.cell.prev_cell)
-      {
-        cell = cell->member.cell.prev_cell;
-        cell->member.cell.nHeight = nHeight;
-      }
-      /* Also set the height of the start row paragraph */
-      startRowPara = ME_FindItemBack(cell, diParagraph);
-      startRowPara->member.para.nHeight = nHeight;
-      c.pt.x = startRowPara->member.para.pt.x;
-      c.pt.y = cell->member.cell.pt.y + nHeight;
-      if (prevHeight < nHeight)
-      {
-        /* The height of the cells has grown, so invalidate the bottom of
-         * the cells. */
-        item->member.para.nFlags |= MEPF_REPAINT;
-        cell = ME_FindItemBack(item, diCell);
-        while (cell) {
-          ME_FindItemBack(cell, diParagraph)->member.para.nFlags |= MEPF_REPAINT;
-          cell = cell->member.cell.prev_cell;
-        }
-      }
-    }
-    else if (item->member.para.pCell &&
-             item->member.para.pCell != item->member.para.next_para->member.para.pCell)
-    {
-      /* The next paragraph is in the next cell in the table row. */
-      ME_Cell *cell = &item->member.para.pCell->member.cell;
-      cell->nHeight = c.pt.y + item->member.para.nHeight - cell->pt.y;
-
-      /* Propagate the largest height to the end so that it can be easily
-       * sent back to all the cells at the end of the row. */
-      if (cell->prev_cell)
-        cell->nHeight = max(cell->nHeight, cell->prev_cell->member.cell.nHeight);
-
-      c.pt.x = cell->pt.x + cell->nWidth;
-      c.pt.y = cell->pt.y;
-      cell->next_cell->member.cell.pt = c.pt;
-      if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWEND))
-        c.pt.y += cell->yTextOffset;
-    }
-    else
-    {
-      if (item->member.para.pCell) {
-        /* Next paragraph in the same cell. */
-        c.pt.x = item->member.para.pCell->member.cell.pt.x;
-      } else {
-        /* Normal paragraph */
-        c.pt.x = 0;
-      }
-      c.pt.y += item->member.para.nHeight;
-    }
-
     totalWidth = max(totalWidth, item->member.para.nWidth);
     item = item->member.para.next_para;
   }
@@ -756,7 +758,7 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
   int ofs;
   ME_DisplayItem *item;
 
-  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
+  ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost), NULL);
   rc = c.rcView;
   ofs = editor->vert_si.nPos;
 
-- 
1.6.6


--------------040309090606030900000103--



More information about the wine-patches mailing list