[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    RFC:  EM_FORMATRANGE Patch for Wine-1.1.33
From:       James McKenzie <jjmckenzie51 () earthlink ! net>
Date:       2009-11-29 18:36:55
Message-ID: 4B12BF47.8000807 () earthlink ! net
[Download RAW message or body]

All:

Time to beat on this patch again and make it better.  I've also attached
it to bug 6254.

Please make comments constructive.  I would like to get assistance where
to break this down so that it will be 'easier to swallow' pieces as this
is one huge patch that AJ has rejected before.

James McKenzie


["0001-EM_FORMATRANGE-Patch-for-Wine-1.1.33.patch" (application/text)]

From 26ffed03d9bfa361f4a7c8cfae3b9ae729cf1abf Mon Sep 17 00:00:00 2001
From: James McKenzie <jamesmckenzie@Macintosh-5.local>
Date: Sun, 29 Nov 2009 11:28:15 -0700
Subject: EM_FORMATRANGE Patch for Wine-1.1.33

This fixes the EM_FORMATRANGE errors encountered by several programs and is a
proposed solution to Bug 6254.
---
 dlls/riched20/context.c      |   16 +++
 dlls/riched20/editor.c       |    8 +-
 dlls/riched20/editor.h       |    8 ++
 dlls/riched20/editstr.h      |   26 ++++
 dlls/riched20/list.c         |  109 +++++++++++++++++
 dlls/riched20/paint.c        |  274 ++++++++++++++++++++++++++++++++++++++++--
 dlls/riched20/style.c        |  113 +++++++++++++-----
 dlls/riched20/tests/editor.c |   10 --
 dlls/riched20/wrap.c         |    2 +-
 9 files changed, 509 insertions(+), 57 deletions(-)

diff --git a/dlls/riched20/context.c b/dlls/riched20/context.c
index 93d5caa..5af3afd 100644
--- a/dlls/riched20/context.c
+++ b/dlls/riched20/context.c
@@ -24,6 +24,22 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC)
 {
   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 = editor->vert_si.nPos;
+  c->fr.rc.right = editor->sizeWindow.cx;
+  c->fr.rc.bottom = editor->sizeWindow.cy + editor->vert_si.nPos;
+  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;
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 4bc901e..a3a694f 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -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)
@@ -201,7 +201,7 @@
  * - calculate heights of pictures (half-done)
  * - 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)
@@ -2878,7 +2878,6 @@ static const char * const richedit_messages[] = {
   "EM_EXLINEFROMCHAR",
   "EM_EXSETSEL",
   "EM_FINDTEXT",
-  "EM_FORMATRANGE",
   "EM_GETCHARFORMAT",
   "EM_GETEVENTMASK",
   "EM_GETOLEINTERFACE",
@@ -3010,7 +3009,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, \
WPARAM wParam,  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)
@@ -3899,6 +3897,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, \
WPARAM wParam,  }
     return (wParam >= 0x40000) ? 0 : MAKELONG( pt.x, pt.y );
   }
+  case EM_FORMATRANGE:
+    return ME_FormatContent(editor, (FORMATRANGE *) lParam, (BOOL) wParam);
   case WM_CREATE:
   {
     INT max;
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 8a5304b..e6e9f4c 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -73,6 +73,9 @@ CHARFORMAT2W *ME_ToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from);
 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);
@@ -86,6 +89,7 @@ ME_DisplayItem *ME_MakeDI(ME_DIType type);
 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 */
 ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars);
@@ -130,6 +134,8 @@ ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, \
                ME_Cursor *cursor,
                                      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);
@@ -186,6 +192,7 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC \
hDC);  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);
@@ -207,6 +214,7 @@ void ME_MarkAllForWrapping(ME_TextEditor *editor);
 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);
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 9b8d645..4653312 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -385,9 +385,35 @@ typedef struct tagME_TextEditor
   BOOL bMouseCaptured;
 } 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;
diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c
index bb91bc4..636bd17 100644
--- a/dlls/riched20/list.c
+++ b/dlls/riched20/list.c
@@ -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
@@ -159,6 +160,114 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) {
   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));
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 52127d7..75e4887 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
@@ -22,9 +23,191 @@
 #include "editor.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
+WINE_DECLARE_DEBUG_CHANNEL(richedit_paint);
 
 static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph);
 
+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);
+    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 + (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_GetTextLength(editor);
+
+  /* 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;
@@ -235,10 +418,12 @@ static void ME_HighlightSpace(ME_Context *c, int x, int y, \
LPCWSTR szText,  }
 
 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;
@@ -266,6 +451,8 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, \
LPCWSTR szText,  }
   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);
@@ -339,9 +526,25 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, \
LPCWSTR szText,  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;
@@ -351,8 +554,24 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, \
LPCWSTR szText,  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);
+    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, xSelStart), transform_y(c, y - yOffset),
+                  ETO_OPAQUE, &dim, szText+nSelFrom, nSelTo-nSelFrom, lpDx);
+    }
+    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);
@@ -365,9 +584,17 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, \
LPCWSTR szText,  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)
@@ -378,7 +605,17 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, \
LPCWSTR szText,  
     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);
+      }
     }
   }
 
@@ -389,6 +626,9 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, \
LPCWSTR szText,  }
   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) {
@@ -438,8 +678,10 @@ static void ME_DrawRun(ME_Context *c, int x, int y, \
ME_DisplayItem *rundi, ME_Pa  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)
@@ -980,10 +1222,15 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem \
*paragraph)  run = &p->member.run;
         if (visible && me_debug) {
           RECT rc;
+/* use transform to create margins
           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.bottom = rc.bottom + height; */
+          rc.left = transform_x(c, c->pt.x + run->pt.x);
+          rc.right = transform_x(c, c->pt.x + run->pt.x + run->nWidth);
+          rc.top = transform_y(c, c->pt.y + para->pt.y + run->pt.y);
+          rc.bottom = transform_y(c, c->pt.y + para->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);
@@ -999,8 +1246,11 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem \
                *paragraph)
           const WCHAR wszRunDebug[] = {'[','%','d',':','%','x',']',' \
','%','l','s',0};  WCHAR buf[2560];
           POINT pt;
+/* use transform call to create location on window
           pt.x = c->pt.x + run->pt.x;
-          pt.y = c->pt.y + para->pt.y + run->pt.y;
+          pt.y = c->pt.y + para->pt.y + run->pt.y; */
+          pt.x = transform_x(c, c->pt.x + run->pt.x);
+          pt.y = transform_y(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);
         }
diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c
index bb2f808..38bf466 100644
--- a/dlls/riched20/style.c
+++ b/dlls/riched20/style.c
@@ -372,43 +372,50 @@ HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s)
   
   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 ? */
@@ -422,6 +429,8 @@ void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT \
hOldFont)  
   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];
@@ -467,6 +476,50 @@ void ME_ReleaseStyle(ME_Style *s)
     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))
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 70c100a..8fdc2c8 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -4870,9 +4870,7 @@ static void test_EM_FORMATRANGE(void)
     fr.rc.bottom = fr.rcPage.bottom = (stringsize.cy + 10) * tpp_y;
 
     r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, 0);
-    todo_wine {
     ok(r == len, "Expected %d, got %d\n", len, r);
-    }
 
     /* We know that the page can't hold the full string. See how many characters
      * are on the first one
@@ -4880,13 +4878,9 @@ static void test_EM_FORMATRANGE(void)
     fr.chrg.cpMin = 0;
     fr.chrg.cpMax = -1;
     r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) &fr);
-    todo_wine {
     ok(fr.rc.bottom == (stringsize.cy * tpp_y), "Expected bottom to be %d, got \
                %d\n", (stringsize.cy * tpp_y), fr.rc.bottom);
-    }
     if (fmtstrings[i].first)
-      todo_wine {
       ok(r == fmtstrings[i].first, "Expected %d, got %d\n", fmtstrings[i].first, r);
-      }
     else
       ok(r < len, "Expected < %d, got %d\n", len, r);
 
@@ -4894,18 +4888,14 @@ static void test_EM_FORMATRANGE(void)
     fr.chrg.cpMin = r;
     r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) &fr);
     if (fmtstrings[i].second)
-      todo_wine {
       ok(r == fmtstrings[i].second, "Expected %d, got %d\n", fmtstrings[i].second, \
                r);
-      }
     else
       ok (r < len, "Expected < %d, got %d\n", len, r);
 
     /* There is at least on more page, but we don't care */
 
     r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, 0);
-    todo_wine {
     ok(r == len, "Expected %d, got %d\n", len, r);
-    }
   }
 
   ReleaseDC(NULL, hdc);
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
index 00229b2..3e76439 100644
--- a/dlls/riched20/wrap.c
+++ b/dlls/riched20/wrap.c
@@ -458,7 +458,7 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, \
ME_DisplayItem *p)  
 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;
-- 
1.6.1





[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic