[8/9] richedit: Use ME_Cursor instead of offsets for ME_SetCharFormat.

Dylan Smith dylan.ah.smith at gmail.com
Wed Aug 12 08:06:13 CDT 2009


The test that succeeded from this change was as a result of allowing the
end of the character format change be specified using NULL as the rest
of the text.  Before, the end paragraph run at the end of the text was
not being set for this case, when all the text was supposed to have its
character format changed.
---
 dlls/riched20/editor.c       |   12 ++++--
 dlls/riched20/editor.h       |    2 +-
 dlls/riched20/para.c         |   17 +++++---
 dlls/riched20/run.c          |   86 +++++++++++++++++++++++++++---------------
 dlls/riched20/tests/editor.c |    2 +-
 dlls/riched20/undo.c         |    5 ++-
 6 files changed, 80 insertions(+), 44 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 6eab00c..b866a13 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -3319,7 +3319,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       if (editor->mode & TM_PLAINTEXT)
         ME_SetDefaultCharFormat(editor, p);
       else {
-        ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), p);
+        ME_Cursor start;
+        ME_SetCursorToStart(editor, &start);
+        ME_SetCharFormat(editor, &start, NULL, p);
         editor->nModifyStep = 1;
       }
     } else if (editor->mode & TM_PLAINTEXT) {
@@ -3449,6 +3451,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     CHARFORMAT2W fmt;
     HDC hDC;
     BOOL bRepaint = LOWORD(lParam);
+    ME_Cursor start;
 
     if (!wParam)
       wParam = (WPARAM)GetStockObject(SYSTEM_FONT); 
@@ -3456,7 +3459,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     hDC = ITextHost_TxGetDC(editor->texthost);
     ME_CharFormatFromLogFont(hDC, &lf, &fmt); 
     ITextHost_TxReleaseDC(editor->texthost, hDC);
-    ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), &fmt);
+    ME_SetCursorToStart(editor, &start);
+    ME_SetCharFormat(editor, &start, NULL, &fmt);
     ME_SetDefaultCharFormat(editor, &fmt);
 
     ME_CommitUndo(editor);
@@ -4859,7 +4863,7 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_m
         link.cbSize = sizeof(link);
         link.dwMask = CFM_LINK;
         link.dwEffects = 0;
-        ME_SetCharFormat(editor, beforeURL[0], beforeURL[1] - beforeURL[0], &link);
+        ME_SetCharFormat(editor, &from, &to, &link);
         modified = TRUE;
       }
     }
@@ -4878,7 +4882,7 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_m
         link.cbSize = sizeof(link);
         link.dwMask = CFM_LINK;
         link.dwEffects = CFE_LINK;
-        ME_SetCharFormat(editor, inURL[0], inURL[1] - inURL[0], &link);
+        ME_SetCharFormat(editor, &from, &to, &link);
         modified = TRUE;
       }
     }
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 88bb4db..07fabdb 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -147,7 +147,7 @@ void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCurso
 void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppPara, ME_DisplayItem **ppRun, int *pOfs);
 int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, const ME_DisplayItem *pRun, int nOfs);
 void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift);
-void ME_SetCharFormat(ME_TextEditor *editor, int nFrom, int nLen, CHARFORMAT2W *pFmt);
+void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt);
 void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt);
 void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
                       const ME_Cursor *to, CHARFORMAT2W *pFmt);
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index 94ef7ae..b6319e7 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -335,6 +335,8 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
   int i, shift;
   ME_UndoItem *undo = NULL;
   int end_len;
+  CHARFORMAT2W fmt;
+  ME_Cursor startCur, endCur;
 
   assert(tp->type == diParagraph);
   assert(tp->member.para.next_para);
@@ -351,12 +353,15 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
 
   end_len = pRun->member.run.strText->nLen;
 
-  {
-    /* null char format operation to store the original char format for the ENDPARA run */
-    CHARFORMAT2W fmt;
-    ME_InitCharFormat2W(&fmt);
-    ME_SetCharFormat(editor, pNext->member.para.nCharOfs - end_len, end_len, &fmt);
-  }
+  /* null char format operation to store the original char format for the ENDPARA run */
+  ME_InitCharFormat2W(&fmt);
+  endCur.pPara = pNext;
+  endCur.pRun = ME_FindItemFwd(pNext, diRun);
+  endCur.nOffset = 0;
+  startCur = endCur;
+  ME_PrevRun(&startCur.pPara, &startCur.pRun);
+  ME_SetCharFormat(editor, &startCur, &endCur, &fmt);
+
   undo = ME_AddUndoItem(editor, diUndoSplitParagraph, pNext);
   if (undo)
   {
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index 18b19f4..7b790eb 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -726,15 +726,13 @@ void ME_CalcRunExtent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Ru
 
 /******************************************************************************
  * ME_SetSelectionCharFormat
- * 
+ *
  * Applies a style change, either to a current selection, or to insert cursor
  * (ie. the style next typed characters will use).
- */     
+ */
 void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
 {
-  int nFrom, nTo;
-  ME_GetSelectionOfs(editor, &nFrom, &nTo);
-  if (nFrom == nTo)
+  if (!ME_IsSelection(editor))
   {
     ME_Style *s;
     if (!editor->pBuffer->pCharStyle)
@@ -742,57 +740,83 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
     s = ME_ApplyStyle(editor->pBuffer->pCharStyle, pFmt);
     ME_ReleaseStyle(editor->pBuffer->pCharStyle);
     editor->pBuffer->pCharStyle = s;
+  } else {
+    ME_Cursor *from, *to;
+    ME_GetSelection(editor, &from, &to);
+    ME_SetCharFormat(editor, from, to, pFmt);
   }
-  else
-    ME_SetCharFormat(editor, nFrom, nTo-nFrom, pFmt);
 }
 
 /******************************************************************************
  * ME_SetCharFormat
- * 
+ *
  * Applies a style change to the specified part of the text
- */     
-void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt)
+ *
+ * The start and end cursors specify the part of the text.  These cursors will
+ * be updated to stay valid, but this function may invalidate other
+ * non-selection cursors. The end cursor may be NULL to specify all the text
+ * following the start cursor.
+ *
+ * If no text is selected, then nothing is done.
+ */
+void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt)
 {
-  ME_Cursor tmp, tmp2;
   ME_DisplayItem *para;
+  ME_DisplayItem *run;
+  ME_DisplayItem *end_run = NULL;
 
-  ME_CursorFromCharOfs(editor, nOfs, &tmp);
-  if (tmp.nOffset)
-    tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
+  if (end && start->pRun == end->pRun && start->nOffset == end->nOffset)
+    return;
 
-  ME_CursorFromCharOfs(editor, nOfs+nChars, &tmp2);
-  if (tmp2.nOffset)
-    tmp2.pRun = ME_SplitRunSimple(editor, tmp2.pRun, tmp2.nOffset);
+  if (start->nOffset)
+  {
+    /* SplitRunSimple may or may not update the cursors, depending on whether they
+     * are selection cursors, but we need to make sure they are valid. */
+    ME_DisplayItem *split_run = start->pRun;
+    int split_offset = start->nOffset;
+    start->pRun = ME_SplitRunSimple(editor, split_run, split_offset);
+    start->nOffset = 0;
+    if (end && end->pRun == split_run)
+    {
+      end->pRun = start->pRun;
+      end->nOffset -= split_offset;
+    }
+  }
+
+  if (end && end->nOffset)
+  {
+    end_run = end->pRun = ME_SplitRunSimple(editor, end->pRun, end->nOffset);
+    end->nOffset = 0;
+  }
 
-  para = tmp.pPara;
+  run = start->pRun;
+  para = start->pPara;
   para->member.para.nFlags |= MEPF_REWRAP;
 
-  while(tmp.pRun != tmp2.pRun)
+  while(run != end_run)
   {
     ME_UndoItem *undo = NULL;
-    ME_Style *new_style = ME_ApplyStyle(tmp.pRun->member.run.style, pFmt);
+    ME_Style *new_style = ME_ApplyStyle(run->member.run.style, pFmt);
     /* ME_DumpStyle(new_style); */
     undo = ME_AddUndoItem(editor, diUndoSetCharFormat, NULL);
     if (undo) {
-      undo->nStart = tmp.pRun->member.run.nCharOfs+para->member.para.nCharOfs;
-      undo->nLen = tmp.pRun->member.run.strText->nLen;
-      undo->di.member.ustyle = tmp.pRun->member.run.style;
+      undo->nStart = run->member.run.nCharOfs+para->member.para.nCharOfs;
+      undo->nLen = run->member.run.strText->nLen;
+      undo->di.member.ustyle = run->member.run.style;
       /* we'd have to addref undo...ustyle and release tmp...style
          but they'd cancel each other out so we can do nothing instead */
     }
     else
-      ME_ReleaseStyle(tmp.pRun->member.run.style);
-    tmp.pRun->member.run.style = new_style;
-    tmp.pRun = ME_FindItemFwd(tmp.pRun, diRunOrParagraph);
-    if (tmp.pRun->type == diParagraph)
+      ME_ReleaseStyle(run->member.run.style);
+    run->member.run.style = new_style;
+    run = ME_FindItemFwd(run, diRunOrParagraph);
+    if (run && run->type == diParagraph)
     {
-      para = tmp.pRun;
-      tmp.pRun = ME_FindItemFwd(tmp.pRun, diRun);
-      if (tmp.pRun != tmp2.pRun)
+      para = run;
+      run = ME_FindItemFwd(run, diRun);
+      if (run != end_run)
         para->member.para.nFlags |= MEPF_REWRAP;
     }
-    assert(tmp.pRun);
   }
 }
 
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 914f25b..ce164b3 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -743,7 +743,7 @@ static void test_EM_SETCHARFORMAT(void)
              (LPARAM) &cf2);
   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
   rc = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0);
-  todo_wine ok(rc == TRUE, "Should not be able to undo here.\n");
+  ok(rc == TRUE, "Should not be able to undo here.\n");
   SendMessage(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0);
 
   cf2.cbSize = sizeof(CHARFORMAT2);
diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c
index c2f7125..84285b8 100644
--- a/dlls/riched20/undo.c
+++ b/dlls/riched20/undo.c
@@ -298,7 +298,10 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
   }
   case diUndoSetCharFormat:
   {
-    ME_SetCharFormat(editor, pUItem->nStart, pUItem->nLen, &pItem->member.ustyle->fmt);
+    ME_Cursor start, end;
+    ME_CursorFromCharOfs(editor, pUItem->nStart, &start);
+    ME_CursorFromCharOfs(editor, pUItem->nStart + pUItem->nLen, &end);
+    ME_SetCharFormat(editor, &start, &end, &pItem->member.ustyle->fmt);
     break;
   }
   case diUndoInsertRun:


More information about the wine-patches mailing list