All:

I've been attempting to bring Tony Rollo's EM_FORMATRANGE patch up to
date and got to Wine 1.1.6.  At the suggestion of Dylan Smith, I have
been using Wordpad to test the patch after adding a little test because
of poor display on the Print Preview.  However, I've run into two what
appears to be separate 'bugs'.  The first occurs when I attempt to
change the font size, I get an error "Invalid Number Format".  The
second is that I can change the displayed font one and only one time. 
I've reversed both of  Andrey Turkin's patches that were applied between
wine-1.1.5 and wine-1.1.6 but this did not resolve the error message and
the inability to change fonts and actually introduced a possible third
error where the font name is distorted where it shows a series of blocks
and some other unintelligible data in the font display field on the screen.

Any ideas on why this is happening?

Patch attached with debugging code.

James McKenzie
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);
 }


Reply via email to