Apply to Wine Source version 1.1.3 depatched to 046122 level
Major changes to table/cell handling
--- dlls/riched20/context.c.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/context.c	2008-03-16 17:35:34.000000000 -0700
@@ -24,6 +24,22 @@
 {
   c->nSequence = editor->nSequence++;  
   c->hDC = hDC;
+  c->hdcMeasure = hDC;
+  c->fr.hdc = hDC;
+  c->fr.hdcTarget = hDC;
+  c->fr.rc.left = 0;
+  c->fr.rc.top = ME_GetYScrollPos(editor);
+  c->fr.rc.right = editor->sizeWindow.cx;
+  c->fr.rc.bottom = editor->sizeWindow.cy + ME_GetYScrollPos(editor);
+  c->fr.rcPage = c->fr.rc;
+  c->fr.chrg.cpMin = 0;
+  c->fr.chrg.cpMax = -1;
+  c->bClip = FALSE;
+  c->bHideSelection = FALSE;
+  c->dDraw.cx = GetDeviceCaps(hDC, LOGPIXELSX);
+  c->dDraw.cy = GetDeviceCaps(hDC, LOGPIXELSY);
+  c->dTarget = c->dDraw;
+  c->mRender = 0;
   c->editor = editor;
   c->pt.x = 0;
   c->pt.y = 0;
--- dlls/riched20/editor.c.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/editor.c	2008-03-16 18:20:21.000000000 -0700
@@ -40,7 +40,7 @@
   + EM_FINDTEXTEX (only FR_DOWN flag implemented)
   - EM_FINDWORDBREAK
   - EM_FMTLINES
-  - EM_FORMATRANGE
+  + EM_FORMATRANGE
   + EM_GETAUTOURLDETECT 2.0
   - EM_GETBIDIOPTIONS 3.0
   - EM_GETCHARFORMAT (partly done)
@@ -198,7 +198,7 @@
  * - horizontal scrolling (not even started)
  * - hysteresis during wrapping (related to scrollbars appearing/disappearing)
  * - find/replace
- * - how to implement EM_FORMATRANGE and EM_DISPLAYBAND ? (Mission Impossible)
+ * - how to implement EM_DISPLAYBAND ? (Mission Impossible)
  * - italic caret with italic fonts
  * - IME
  * - most notifications aren't sent at all (the most important ones are)
@@ -2411,7 +2411,6 @@
   "EM_EXLINEFROMCHAR",
   "EM_EXSETSEL",
   "EM_FINDTEXT",
-  "EM_FORMATRANGE",
   "EM_GETCHARFORMAT",
   "EM_GETEVENTMASK",
   "EM_GETOLEINTERFACE",
@@ -2512,7 +2511,6 @@
   UNSUPPORTED_MSG(EM_DISPLAYBAND)
   UNSUPPORTED_MSG(EM_FINDWORDBREAK)
   UNSUPPORTED_MSG(EM_FMTLINES)
-  UNSUPPORTED_MSG(EM_FORMATRANGE)
   UNSUPPORTED_MSG(EM_GETBIDIOPTIONS)
   UNSUPPORTED_MSG(EM_GETEDITSTYLE)
   UNSUPPORTED_MSG(EM_GETIMECOMPMODE)
@@ -3497,6 +3495,8 @@
     }
     return (wParam >= 0x40000) ? 0 : MAKELONG( pt.x, pt.y );
   }
+  case EM_FORMATRANGE:
+    return ME_FormatContent(editor, (FORMATRANGE *) lParam, (BOOL) wParam);
   case WM_CREATE:
   {
     SCROLLINFO si;
--- dlls/riched20/editor.h.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/editor.h	2008-03-16 18:22:03.000000000 -0700
@@ -75,6 +75,9 @@
 void ME_CopyToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from);
 void ME_CopyCharFormat(CHARFORMAT2W *pDest, const CHARFORMAT2W *pSrc); /* only works with 2W structs */
 void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt); /* ditto */
+ME_Style *ME_MapStyle(ME_StyleMap *m, ME_Style *s);
+ME_StyleMap *ME_MakeStyleMap(void);
+void ME_FreeStyleMap(ME_StyleMap *m);

 /* list.c */
 void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat);
@@ -88,6 +91,7 @@
 void ME_DestroyDisplayItem(ME_DisplayItem *item);
 void ME_DumpDocument(ME_TextBuffer *buffer);
 const char *ME_GetDITypeName(ME_DIType type);
+void ME_DuplicateText(ME_DisplayItem *pFirst, ME_DisplayItem *pLast, ME_DisplayItem **ppNew, ME_DisplayItem **ppNewLast);
 
 /* string.c */
 int ME_GetOptimalBuffer(int nLen);
@@ -150,6 +154,8 @@
                                      ME_Style *style, const WCHAR *str, int len, int flags);
 void ME_CheckCharOffsets(ME_TextEditor *editor);
 void ME_PropagateCharOffset(ME_DisplayItem *p, int shift);
+/*void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize, ME_Di
+mension *pd); */
 int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run);
 /* this one accounts for 1/2 char tolerance */
 int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run);
@@ -211,6 +217,7 @@
 void ME_DestroyContext(ME_Context *c, HWND release);
 
 /* wrap.c */
+void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD beginofs);
 BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor);
 void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor);
 void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
@@ -235,6 +242,7 @@
 void ME_SetDefaultParaFormat(PARAFORMAT2 *pFmt);
 
 /* paint.c */
+LPARAM ME_FormatContent(ME_TextEditor *editor, FORMATRANGE *pfr, BOOL bNoOutput);
 void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *rcUpdate);
 void ME_Repaint(ME_TextEditor *editor);
 void ME_RewrapRepaint(ME_TextEditor *editor);
--- dlls/riched20/editstr.h.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/editstr.h	2008-03-16 18:09:19.000000000 -0700
@@ -377,10 +377,36 @@
   /* Cache previously set vertical scrollbar info */
   SCROLLINFO vert_si;
 } ME_TextEditor;
+
+typedef struct tagME_Dimension
+{
+	unsigned cx;
+	unsigned cy;
+} ME_Dimension;
+
+typedef struct tagME_StyleMapping
+{
+  ME_Style *from;
+  ME_Style *to;
+  struct tagME_StyleMapping *next;
+} ME_StyleMapping;
+
+typedef struct tagME_StyleMap
+{
+  ME_StyleMapping *first;
+} ME_StyleMap;
+
 
 typedef struct tagME_Context
 {
   HDC hDC;
+  HDC hdcMeasure;
+  FORMATRANGE fr;
+  BOOL	bClip;
+  BOOL	bHideSelection;
+  ME_Dimension dDraw;
+  ME_Dimension dTarget;
+  ME_StyleMap *mRender;
   POINT pt;
   POINT ptRowOffset;
   RECT rcView;
--- dlls/riched20/list.c.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/list.c	2008-03-16 17:35:34.000000000 -0700
@@ -2,6 +2,7 @@
  * RichEdit - Basic operations on double linked lists.
  *
  * Copyright 2004 by Krzysztof Foltman
+ * 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
@@ -128,6 +129,114 @@
   FREE_OBJ(item);
 }

+static ME_DisplayItem *ME_DuplicateDisplayItem(ME_DisplayItem *item,
+                                               ME_DisplayItem *prev,
+                                               ME_StyleMap *m)
+{
+  ME_DisplayItem *mdi = ALLOC_OBJ(ME_DisplayItem);
+
+  *mdi = *item;
+  mdi->prev = prev;
+  mdi->next = 0;
+  if (prev)
+    prev->next = mdi;
+
+  if (item->type == diParagraph || item->type == diUndoSplitParagraph)
+  {
+    mdi->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
+    *mdi->member.para.pFmt = *item->member.para.pFmt;
+    mdi->member.para.next_para = 0;
+  }
+
+  if (item->type == diRun || item->type == diUndoInsertRun)
+  {
+    /* We need to copy the style and text, in the case of styles
+     * we need to reduce duplication which we can do with a style
+     * map.
+     */
+    mdi->member.run.style = ME_MapStyle(m, mdi->member.run.style);
+    mdi->member.run.strText = ME_StrDup(item->member.run.strText);
+
+    /*if (mdi->member.run.pCell)
+    {
+      /* Find the right ME_TableCell to link to by walking both the
+       * old and new list backwards.
+       *
+      ME_DisplayItem *from, *to;
+      ME_TableCell *target = mdi->member.run.pCell;
+
+      mdi->member.run.pCell = 0;
+      for (from = item, to = mdi;
+           !mdi->member.run.pCell && from && to;
+           from = from->prev, to = to->prev)
+      {
+        ME_TableCell *tt, *tf;
+
+	if (from->type != diParagraph && from->type != diUndoSplitParagraph)
+	    continue;
+
+        for (tf = from->member.para.pCells, tt = from->member.para.pCells;
+             tf && tt;
+             tf = tf->next, tt = tt->next)
+        {
+          if (tf == target)
+          {
+            mdi->member.run.pCell = tt;
+            break;
+          }
+        }
+      }
+    }*/
+  }
+
+  if (item->type == diUndoSetCharFormat)
+  {
+    /* Just map the style back */
+    mdi->member.ustyle = ME_MapStyle(m, mdi->member.ustyle);
+  }
+  if (item->type == diTextEnd  || item->type == diParagraph)
+  {
+    /* Make sure the last top level paragraph is linked up */
+    ME_DisplayItem *from, *to;
+
+    mdi->member.para.prev_para = 0;
+
+    for (from = item, to = mdi;
+         from && to;
+         from = from->prev, to = to->prev)
+    {
+      if ((from->type == diParagraph || from->type == diUndoSplitParagraph) &&
+          from->member.para.next_para == item)
+      {
+        to->member.para.next_para = mdi;
+        mdi->member.para.prev_para = to;
+        break;
+      }
+    }
+  }
+  return mdi;
+}
+
+/* ME_DuplicateText makes a duplicate of all ME_DisplayItem structures starting
+ * with pFirst and ending with pLast.
+ */
+void ME_DuplicateText(ME_DisplayItem *pFirst, ME_DisplayItem *pLast, ME_DisplayItem 
+                      **ppNew, ME_DisplayItem **ppNewLast)
+{
+  ME_DisplayItem *pNow;
+  ME_StyleMap *m = ME_MakeStyleMap();
+
+  pNow = ME_DuplicateDisplayItem(pFirst, NULL, m);
+  *ppNew = pNow;
+  while (pFirst != pLast)
+  {
+    pFirst = pFirst->next;
+    pNow = ME_DuplicateDisplayItem(pFirst, pNow, m);
+    *ppNewLast = pNow;
+  }
+  ME_FreeStyleMap(m);
+}
+
 ME_DisplayItem *ME_MakeDI(ME_DIType type) {
   ME_DisplayItem *item = ALLOC_OBJ(ME_DisplayItem);
   ZeroMemory(item, sizeof(ME_DisplayItem));
--- dlls/riched20/paint.c.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/paint.c	2008-03-16 17:35:34.000000000 -0700
@@ -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
@@ -22,6 +23,189 @@
 #include "editor.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
+WINE_DECLARE_DEBUG_CHANNEL(richedit_paint);
+
+static int transform_x(ME_Context *c, int x)
+{
+        if (c->dTarget.cx == c->dDraw.cx)
+                return x;
+        return MulDiv(x, c->dDraw.cx, c->dTarget.cx);
+}
+
+static int transform_y(ME_Context *c, int y)
+{
+        if (c->dTarget.cy == c->dDraw.cy)
+                return y;
+        return MulDiv(y, c->dDraw.cy, c->dTarget.cy);
+}
+
+/*
+ * Support EM_FORMATRANGE.
+ *
+ * *** Notes on tables ***
+ *
+ * The CHARRANGE structure passed in the FORMATRANGE structure is not
+ * sufficient to deal with tables, where we would need information on the
+ * start position for text in each column of the table.
+ *
+ * Testing on Windows NT shows that the Microsoft Rich Edit control gives
+ * pathological results when there are tables in the document - both in edit
+ * mode and for EM_FORMATRANGE. The Microsoft Rich Edit control uses the
+ * table solely as a hint to where the paragraph should start. The table
+ * does not expand to fit its text. Long paragraphs wrap when you hit the
+ * right page margin and continue at the left page margin.
+ *
+ * If the paragraph ends outside its cell, the paragraph in the next cell
+ * continues at the X position immediately after the next cell boundary after
+ * the position of the last character in the paragraph. This may not be the
+ * cell associated with the paragraph, and may be the right hand table
+ * boundary (so that the paragraph commences after the right hand edge of the
+ * table). If the paragraph ends after the right hand table boundary, then the
+ * next paragraph begins on the next row of output at the X position for the
+ * second cell in the table.
+ *
+ * While all this wrapping is going on, the table borders will be positioned
+ * as if there were only one line of text in each cell of the table and the
+ * text fits neatly within the cells.
+ *
+ * This behaviour is sufficiently useless that it is probably not worth trying
+ * to duplicate, and given that CHARRANGE is insufficient to deal with tables,
+ * there seems little point in attempting to make our implementation of
+ * EM_FORMATRANGE do something sensible for tables. A lot of effort would be
+ * involved in doing so, and we would be doing something Microsoft has not
+ * done.
+ */
+
+LPARAM ME_FormatContent(ME_TextEditor *editor, FORMATRANGE *pfr, BOOL bDraw)
+{
+  ME_Context c;
+  int   iBGMode;
+  ME_DisplayItem *pFirst;
+  ME_DisplayItem *pLast;
+  ME_DisplayItem *pNow;
+  ME_DisplayItem *pIntra;
+  int   local_pt_y;
+  int   cyRow;
+  int   cyOffset = -1;
+  int   iEndOffset = -1;
+
+  if (!pfr)
+    return 0;
+
+  ME_InitContext(&c, editor, pfr->hdcTarget);
+  c.fr = *pfr;
+  c.bHideSelection = TRUE;
+  c.bClip = TRUE;
+
+  c.rcView.left = MulDiv(c.fr.rc.left, c.dTarget.cx, 1440);
+  c.rcView.right = MulDiv(c.fr.rc.right, c.dTarget.cx, 1440);
+  c.rcView.top = MulDiv(c.fr.rc.top, c.dTarget.cy, 1440);
+  c.rcView.bottom = MulDiv(c.fr.rc.bottom, c.dTarget.cy, 1440);
+
+  c.pt.x = 0;
+  c.pt.y = 0;
+
+  /* Get a copy of all the text in the control so we can perform calculations
+   * without interfering with the values cached for the on-screen data.
+   */
+
+  ME_DuplicateText(editor->pBuffer->pFirst, editor->pBuffer->pLast, &pFirst, &pLast);
+
+  /* Now perform wrapping on the resulting data, and find the vertical offset of
+   * the row at the start of the character range, and the character offset of the
+   * first non-printable character.
+   */
+
+  for (pNow = pFirst->next; pNow != pLast; pNow = pNow->member.para.next_para)
+  {
+    pNow->member.para.pt.y = c.pt.y;
+    pNow->member.para.nFlags |= MEPF_REWRAP;
+    ME_WrapTextParagraph(&c, pNow, editor->selofs); 
+    if (iEndOffset == -1)
+    {
+      int iParaOfs = pNow->member.para.nCharOfs;
+
+      local_pt_y = c.pt.y;
+      cyRow = 0;
+
+      for (pIntra = pNow; pIntra != pNow->member.para.next_para; pIntra = pIntra->next)
+      {
+        if (pIntra->type == diStartRow)
+        {
+              local_pt_y += cyRow;
+          cyRow = pIntra->member.row.nHeight;
+        }
+        else if (pIntra->type == diRun)
+        {
+          int iRunOfs = iParaOfs + pIntra->member.run.nCharOfs;
+          int iRunEndOfs = iRunOfs + ME_VPosToPos(pIntra->member.run.strText,
+                                                  pIntra->member.run.strText ?
+                                                    pIntra->member.run.strText->nLen : 1);
+          if (cyOffset == -1 && iRunEndOfs > c.fr.chrg.cpMin)
+            cyOffset = local_pt_y;
+          if (cyOffset != -1 && iEndOffset == -1)
+          {
+            if (local_pt_y > cyOffset &&
+                local_pt_y + cyRow > c.rcView.bottom - c.rcView.top + cyOffset)
+            {
+              iEndOffset = iRunOfs;
+              break;
+            }
+            if (c.fr.chrg.cpMax >= 0 &&
+                iRunEndOfs > c.fr.chrg.cpMax)
+            {
+              int iBottom = local_pt_y + cyRow - cyOffset + c.rcView.top;;
+
+              if (c.rcView.bottom > iBottom)
+                        c.rcView.bottom = iBottom;
+              iEndOffset = iRunOfs;
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    c.pt.y += pNow->member.para.nHeight;
+  }
+
+  if (iEndOffset == -1)
+    iEndOffset = ME_CharOfsFromRunOfs(editor, ME_FindItemBack(pLast, diRun), 0);
+
+  /* Then draw the data */
+  /* FIXME - transformation of non-text runs is not done yet */
+  
+  if (bDraw)
+  {
+    c.mRender = ME_MakeStyleMap();
+    iBGMode = SetBkMode(c.hDC, TRANSPARENT);
+    c.dDraw.cx = GetDeviceCaps(c.fr.hdc, LOGPIXELSX);
+    c.dDraw.cy = GetDeviceCaps(c.fr.hdc, LOGPIXELSY);
+    c.hDC = c.fr.hdc;
+    c.hdcMeasure = c.fr.hdcTarget;
+    c.pt.x = 0;
+    c.pt.y = c.rcView.top - cyOffset;
+
+    for (pNow = pFirst->next; pNow != pLast; pNow = pNow->member.para.next_para)
+    {
+      if (c.pt.y + pNow->member.para.nHeight > c.rcView.top &&
+          c.pt.y < c.rcView.bottom)
+        ME_DrawParagraph(&c, pNow);
+      c.pt.y += pNow->member.para.nHeight;
+    }
+    SetBkMode(c.hDC, iBGMode);
+    ME_FreeStyleMap(c.mRender);
+  }
+
+  while (pFirst)
+  {
+    pNow = pFirst;
+    pFirst = pFirst->next;
+    ME_DestroyDisplayItem(pNow);
+  }
+
+  return iEndOffset;
+}
 
 void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *rcUpdate) {
   ME_DisplayItem *item;
@@ -258,10 +442,12 @@
 }
 
 static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText,
-                                 int nChars, ME_Style *s, int width,
+                                 int nChars, ME_Style *sIn, int width,
                                  int nSelFrom, int nSelTo, int ymin, int cy)
 {
+  ME_Style *s = (c->mRender ? ME_MapStyle(c->mRender, sIn) : sIn);
   HDC hDC = c->hDC;
+  HDC hdcTarget = c->hdcMeasure;
   HGDIOBJ hOldFont;
   COLORREF rgbOld;
   int yOffset = 0, yTwipsOffset = 0;
@@ -289,6 +475,8 @@
   }
   if (yTwipsOffset)
     yOffset = ME_twips2pointsY(c, yTwipsOffset);
+  TRACE_(richedit_paint)("%d is the current value of y, %d is the current value of yoffset\n", y, yOffset);
+  TRACE_(richedit_paint)("%d is the value of transformed y\n",transform_y(c,y-yOffset));
 
   if ((s->fmt.dwMask & CFM_LINK) && (s->fmt.dwEffects & CFE_LINK))
     rgb = RGB(0,0,255);
@@ -362,9 +550,25 @@
       MoveToEx(hDC, x, y - yOffset + 1, NULL);
     if (xSelStart > x)
     {
-      ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nSelFrom, NULL);
-      if (hPen)
-        LineTo(hDC, xSelStart, y - yOffset + 1);
+      if (hDC != hdcTarget && nChars > 1 ) 
+      {
+        /*if it is not then glyphs were used and now we calculate positions for them */        
+        ExtTextOutW(hDC, transform_x(c, x), transform_y(c, y - yOffset),
+                    0, NULL, szText, nSelFrom, NULL);
+      }
+      else if (hDC != hdcTarget && nChars==1) /*Target is not current window and 
+                                               character is a tab */
+      {
+        width = transform_x(c,width);
+        ExtTextOutW(hDC, transform_x(c,x), transform_y(c,y-yOffset),
+                   0, NULL, szText, nSelFrom, NULL);
+      }
+      else  /*Target is current window */
+      {
+        ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nSelFrom, NULL);
+        if (hPen)
+          LineTo(hDC, xSelStart, y - yOffset + 1);
+      }
     }
     dim.top = ymin;
     dim.bottom = ymin + cy;
@@ -372,8 +576,26 @@
     dim.right = xSelEnd;
     SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
     rgbBackOld = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
-    ExtTextOutW(hDC, xSelStart, y-yOffset, ETO_OPAQUE, &dim,
-                szText+nSelFrom, nSelTo-nSelFrom, lpDx);
+    if (hDC != hdcTarget && nChars > 1 )
+    /*if it is not then glyphs were used and now we calculate positions for them */
+    {
+      HFONT holdFont = ME_SelectStyleFont(c, sIn);
+      ExtTextOutW(hDC, transform_x(c, xSelStart), transform_y(c, y - yOffset),
+                  ETO_OPAQUE, &dim, szText+nSelFrom, nSelTo-nSelFrom, lpDx);
+      ME_UnselectStyleFont(c, sIn, holdFont);
+    }
+    else if (hDC != hdcTarget && nChars==1) /*Target is not current window and 
+                                             character is a tab */
+    {
+      width = transform_x(c,width);
+      ExtTextOutW(hDC, transform_x(c,xSelStart), transform_y(c,y-yOffset),
+                  ETO_OPAQUE, &dim, szText+nSelFrom, nSelTo-nSelFrom, lpDx);
+    }
+    else  /*Target is current window */
+    {
+      ExtTextOutW(hDC, xSelStart, y-yOffset, ETO_OPAQUE, &dim,
+                  szText+nSelFrom, nSelTo-nSelFrom, lpDx);
+    }			
     if (hPen)
       LineTo(hDC, xSelEnd, y - yOffset + 1);
     SetBkColor(hDC, rgbBackOld);
@@ -386,9 +608,17 @@
         LineTo(hDC, x + width, y - yOffset + 1);
     }
   }
-  else
+  else  /* Version 1.0 code */
   {
-    ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, lpDx);
+    if (hDC != hdcTarget && nChars > 1 )
+    /*if it is not then glyphs were used and now we calculate positions for them */
+    {
+      ExtTextOutW(hDC, transform_x(c,x), transform_y(c,y-yOffset), 0, NULL, szText, nChars, lpDx);
+    }
+    else  /*Target is current window */
+    {
+      ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, lpDx);
+    }

     /* FIXME: should use textmetrics info for Descent info */
     if (hPen)
@@ -398,9 +628,19 @@
     }
 
     if (bHighlightedText) /* v1.0 inverts the selection */
     {
-      PatBlt(hDC, xSelStart, ymin, xSelEnd-xSelStart, cy, DSTINVERT);
+      if (hDC != hdcTarget)
+      {
+        TRACE_(richedit_paint)("Working with 1.0 emulation code and Transform Code\n");
+      /*if it is not then glyphs were used and now we calculate positions for them */
+        PatBlt(hDC, transform_x(c,xSelStart), transform_y(c,ymin), xSelEnd-xSelStart, cy, DSTINVERT);
+      }  
+      else 
+      {
+        TRACE_(richedit_paint)("Working with 1.0 empulating code without Transform Code\n");
+        PatBlt(hDC, xSelStart, ymin, xSelEnd-xSelStart, cy, DSTINVERT);
+      }  
     }
   }
 
   if (hPen)
@@ -410,6 +650,9 @@
   }
   SetTextColor(hDC, rgbOld);
   ME_UnselectStyleFont(c, s, hOldFont);
+  /*Clean up and exit */
+  if (c->mRender)
+    ME_ReleaseStyle(s);
 }
 
 static void ME_DebugWrite(HDC hDC, const POINT *pt, LPCWSTR szText) {
@@ -460,8 +703,10 @@
     return;
   }
 
+/* Add check for text and graphics to hide/unhide them */
   if (run->nFlags & MERF_GRAPHICS)
-    ME_DrawOLE(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo));
+/*    ME_DrawOLE(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo));*/
+    ME_DrawOLE(c,x,y,run,para, !c->editor->bHideSelection && !c->bHideSelection && (runofs >= nSelFrom) && (runofs < nSelTo));
   else
   {
     if (c->editor->cPasswordMask)
@@ -914,7 +1159,8 @@
   ME_DisplayItem *p;
   ME_Run *run;
   ME_Paragraph *para = NULL;
-  RECT rc, bounds;
+/* Add additional variable for EM_FONTRANGE support*/
+  RECT rc, rcParaDraw, bounds;
   int y = c->pt.y;
   int height = 0, baseline = 0, no=0;
   BOOL visible = FALSE;
@@ -978,10 +1224,15 @@
         assert(para);
         run = &p->member.run;
         if (visible && me_debug) {
+/* use transform to create margins
           rc.left = c->rcView.left+run->pt.x;
           rc.right = c->rcView.left+run->pt.x+run->nWidth;
           rc.top = c->pt.y+run->pt.y;
-          rc.bottom = c->pt.y+run->pt.y+height;
+          rc.bottom = c->pt.y+run->pt.y+height; */
+          rc.left = transform_x(c, c->rcView.left+run->pt.x);
+          rc.right = transform_x(c, c->rcView.left+run->pt.x+run->nWidth);
+          rc.top = transform_y(c, c->pt.y+run->pt.y);
+          rc.bottom = transform_y(c, c->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);
@@ -989,15 +1240,20 @@
             FrameRect(c->hDC, &rc, GetSysColorBrush(COLOR_GRAYTEXT));
         }
         if (visible)
-          ME_DrawRun(c, run->pt.x, c->pt.y+run->pt.y+baseline, p, &paragraph->member.para);
+/* Correct call to ME_DrawRun for EM_FONTRANGE support
+           ME_DrawRun(c, run->pt.x, c->pt.y+run->pt.y+baseline, p, &paragraph->member.para); */
+           ME_DrawRun(c, c->rcView.left+run->pt.x, c->pt.y+run->pt.y+baseline, p, &paragraph->member.para);
         if (me_debug)
         {
           /* I'm using %ls, hope wsprintfW is not going to use wrong (4-byte) WCHAR version */
           const WCHAR wszRunDebug[] = {'[','%','d',':','%','x',']',' ','%','l','s',0};
           WCHAR buf[2560];
           POINT pt;
+/* use transform call to create location on window
           pt.x = run->pt.x;
-          pt.y = c->pt.y + run->pt.y;
+          pt.y = c->pt.y + run->pt.y; */
+          pt.x = transform_x(c, run->pt.x);
+          pt.y = transform_y(c, c->pt.y + run->pt.y);
           wsprintfW(buf, wszRunDebug, no, p->member.run.nFlags, p->member.run.strText->szData);
           ME_DebugWrite(c->hDC, &pt, buf);
         }
--- dlls/riched20/style.c.orig	2008-03-07 07:24:24.000000000 -0700
+++ dlls/riched20/style.c	2008-03-16 17:35:34.000000000 -0700
@@ -378,43 +378,50 @@
   
   ME_LogFontFromStyle(c, &lf, s);
   
-  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++)
+  if (c->editor)
   {
-    item = &c->editor->pFontCache[i];
-    if (!item->nRefs)
-    {
-      if (item->nAge > nAge)
-        nEmpty = i, nAge = item->nAge;
-    }
+    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++)
+	{
+      item = &c->editor->pFontCache[i];
+      if (!item->nRefs)
+      {
+        if (item->nAge > nAge)
+          nEmpty = i, nAge = item->nAge;
+      }
     if (item->hFont && ME_IsFontEqual(&item->lfSpecs, &lf))
       break;
-  }
-  if (i < HFONT_CACHE_SIZE) /* found */
-  {
-    item = &c->editor->pFontCache[i];
-    TRACE_(richedit_style)("font reused %d\n", i);
+    }
+    if (i < HFONT_CACHE_SIZE) /* found */
+    {
+      item = &c->editor->pFontCache[i];
+      TRACE_(richedit_style)("font reused %d\n", i);
 
-    s->hFont = item->hFont;
-    item->nRefs++;
+      s->hFont = item->hFont;
+      item->nRefs++;
+    }
+    else
+    {
+      item = &c->editor->pFontCache[nEmpty]; /* this legal even when nEmpty == -1, as we don't dereference it */
+
+      assert(nEmpty != -1); /* otherwise we leak cache entries or get too many fonts at once*/
+      if (item->hFont) {
+        TRACE_(richedit_style)("font deleted %d\n", nEmpty);
+        DeleteObject(item->hFont);
+        item->hFont = NULL;
+      }
+      s->hFont = CreateFontIndirectW(&lf);
+      assert(s->hFont);
+      TRACE_(richedit_style)("font created %d\n", nEmpty);
+      item->hFont = s->hFont;
+      item->nRefs = 1;
+      item->lfSpecs = lf;
+	}  
   }
-  else
+  else if (!s->hFont)
   {
-    item = &c->editor->pFontCache[nEmpty]; /* this legal even when nEmpty == -1, as we don't dereference it */
-
-    assert(nEmpty != -1); /* otherwise we leak cache entries or get too many fonts at once*/
-    if (item->hFont) {
-      TRACE_(richedit_style)("font deleted %d\n", nEmpty);
-      DeleteObject(item->hFont);
-      item->hFont = NULL;
-    }
     s->hFont = CreateFontIndirectW(&lf);
-    assert(s->hFont);
-    TRACE_(richedit_style)("font created %d\n", nEmpty);
-    item->hFont = s->hFont;
-    item->nRefs = 1;
-    item->lfSpecs = lf;
   }
   hOldFont = SelectObject(c->hDC, s->hFont);
   /* should be cached too, maybe ? */
@@ -429,6 +436,8 @@
   assert(c->hDC);
   assert(s);
   SelectObject(c->hDC, hOldFont);
+  if (!c->editor)
+    return;
   for (i=0; i<HFONT_CACHE_SIZE; i++)
   {
     ME_FontCacheItem *pItem = &c->editor->pFontCache[i];
@@ -473,6 +482,50 @@
     ME_DestroyStyle(s);
 }
 
+ME_Style *ME_MapStyle(ME_StyleMap *m, ME_Style *s)
+{
+  ME_StyleMapping **tail;
+
+  if (!s)
+    return s;
+
+  for (tail = &m->first; *tail; tail = &(*tail)->next)
+  {
+    if ((*tail)->from == s)
+    {
+      ME_AddRefStyle((*tail)->to);
+      return (*tail)->to;
+    }
+  }
+  *tail = ALLOC_OBJ(ME_StyleMapping);
+  (*tail)->from = s;
+  (*tail)->to = ME_MakeStyle(&s->fmt);
+  ME_AddRefStyle((*tail)->to);
+  (*tail)->next = 0;
+  return (*tail)->to;
+}
+
+ME_StyleMap *ME_MakeStyleMap(void)
+{
+  ME_StyleMap *sm = ALLOC_OBJ(ME_StyleMap);
+
+  sm->first = 0;
+  return sm;
+}
+
+void ME_FreeStyleMap(ME_StyleMap *m)
+{
+  while (m->first)
+  {
+    ME_StyleMapping *p = m->first;
+
+    m->first = p->next;
+    ME_ReleaseStyle(p->to);
+    FREE_OBJ(p);
+  }
+  FREE_OBJ(m);
+}
+
 ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) {
   if (ME_IsSelection(editor))
   {
--- dlls/riched20/wrap.c.orig	2009-08-29 07:01:05.000000000 -0700
+++ dlls/riched20/wrap.c	2009-08-29 07:01:57.000000000 -0700
@@ -453,7 +453,7 @@
 
 static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp);
 
-static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD beginofs) {
+void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD beginofs) {
   ME_DisplayItem *p;
   ME_WrapContext wc;
   int border = 0;
--- dlls/riched20/tests/editor.c.orig	2008-03-16 19:51:07.000000000 -0700
+++ dlls/riched20/tests/editor.c	2008-03-16 19:51:54.000000000 -0700
@@ -4389,27 +4389,19 @@
   fr.chrg.cpMax = 20;

   r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) NULL);
-  todo_wine {
     ok(r == 31, "EM_FORMATRANGE expect %d, got %d\n", 31, r);
-  }

   r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) &fr);
-  todo_wine {
     ok(r == 20 || r == 9, "EM_FORMATRANGE expect 20 or 9, got %d\n", r);
-  }

   fr.chrg.cpMin = 0;
   fr.chrg.cpMax = 10;

   r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) &fr);
-  todo_wine {
     ok(r == 10, "EM_FORMATRANGE expect %d, got %d\n", 10, r);
-  }

   r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) NULL);
-  todo_wine {
     ok(r == 31, "EM_FORMATRANGE expect %d, got %d\n", 31, r);
-  }

   DestroyWindow(hwndRichEdit);
 }
