Phil Krylov : riched20: Speed up text insertion.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jan 10 14:13:51 CST 2006


Module: wine
Branch: refs/heads/master
Commit: d82af6f7115b326a75451cbf2de171846d838739
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=d82af6f7115b326a75451cbf2de171846d838739

Author: Phil Krylov <phil at newstar.rinet.ru>
Date:   Tue Jan 10 12:10:49 2006 +0100

riched20: Speed up text insertion.
Optimized reading large texts into RichEdit to be an O(n) order
algorythm instead of O(n^2) by removing extraneous conversions of
character offsets to run offsets.

---

 dlls/riched20/caret.c  |   12 +----------
 dlls/riched20/editor.h |    2 ++
 dlls/riched20/para.c   |   53 +++++++++++++++++++++++++++---------------------
 dlls/riched20/run.c    |   46 ++++++++++++++++++++++++++++--------------
 4 files changed, 64 insertions(+), 49 deletions(-)

diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 69c6ca1..03bfcf3 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -331,19 +331,13 @@ ME_InternalInsertTextFromCursor(ME_TextE
                                 const WCHAR *str, int len, ME_Style *style,
                                 int flags)
 {
-  ME_DisplayItem *pNewRun = NULL;
   ME_Cursor *p = &editor->pCursors[nCursor];
 
   editor->bCaretAtEnd = FALSE;
   
   assert(p->pRun->type == diRun);
   
-  ME_AddRefStyle(style);
-  
-  pNewRun = ME_MakeRun(style, ME_MakeStringN(str, len), flags); /* addrefs style */
-  ME_InsertRun(editor, ME_CharOfsFromRunOfs(editor, p->pRun, p->nOffset), pNewRun);
-  ME_DestroyDisplayItem(pNewRun);
-  ME_ReleaseStyle(style);
+  ME_InsertRunAtCursor(editor, p, style, str, len, flags);
 }
 
 
@@ -385,14 +379,10 @@ void ME_InsertTextFromCursor(ME_TextEdit
     }
     if (pos-str < len) {   /* handle EOLs */
       ME_DisplayItem *tp, *end_run;
-      ME_Paragraph *para;
       ME_Style *tmp_style;
       if (pos!=str)
         ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
       p = &editor->pCursors[nCursor];
-      tp = ME_FindItemBack(p->pRun, diParagraph);
-      para = &tp->member.para;
-      assert(tp);
       if (p->nOffset) {
         ME_SplitRunSimple(editor, p->pRun, p->nOffset);
         p = &editor->pCursors[nCursor];
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 420435f..98167c7 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -107,6 +107,8 @@ int ME_RowNumberFromCharOfs(ME_TextEdito
 ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags);
 /* note: ME_InsertRun inserts a copy of the specified run - so you need to destroy the original */
 ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem);
+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);
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index a6a548f..b2295c7 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -303,21 +303,37 @@ void ME_SetParaFormat(ME_TextEditor *edi
     para->member.para.nFlags |= MEPF_REWRAP;
 }
 
+
+void
+ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end)
+{
+  ME_Cursor *pEndCursor = &editor->pCursors[1];
+  
+  *para = ME_GetParagraph(editor->pCursors[0].pRun);
+  *para_end = ME_GetParagraph(editor->pCursors[1].pRun);
+  if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) {
+    ME_DisplayItem *tmp = *para;
+
+    *para = *para_end;
+    *para_end = tmp;
+    pEndCursor = &editor->pCursors[0];
+  }
+  
+  /* selection consists of chars from nFrom up to nTo-1 */
+  if ((*para_end)->member.para.nCharOfs > (*para)->member.para.nCharOfs) {
+    if (!pEndCursor->nOffset) {
+      *para_end = ME_GetParagraph(ME_FindItemBack(pEndCursor->pRun, diRun));
+    }
+  }
+}
+
+
 void ME_SetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
 {
-  int nFrom, nTo;
-  ME_DisplayItem *para, *para_end, *run;
-  int nOffset;
-  
-  ME_GetSelection(editor, &nFrom, &nTo);
-  if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */
-    nTo--;
-  
-  ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset);
-  para = ME_GetParagraph(run);
-  ME_RunOfsFromCharOfs(editor, nTo, &run, &nOffset);
-  para_end = ME_GetParagraph(run);
+  ME_DisplayItem *para, *para_end;
   
+  ME_GetSelectionParas(editor, &para, &para_end);
+ 
   do {
     ME_SetParaFormat(editor, para, pFmt);
     if (para == para_end)
@@ -338,19 +354,10 @@ void ME_GetParaFormat(ME_TextEditor *edi
 
 void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
 {
-  int nFrom, nTo;
-  ME_DisplayItem *para, *para_end, *run;
-  int nOffset;
+  ME_DisplayItem *para, *para_end;
   PARAFORMAT2 tmp;
   
-  ME_GetSelection(editor, &nFrom, &nTo);
-  if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */
-    nTo--;
-  
-  ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset);
-  para = ME_GetParagraph(run);
-  ME_RunOfsFromCharOfs(editor, nTo, &run, &nOffset);
-  para_end = ME_GetParagraph(run);
+  ME_GetSelectionParas(editor, &para, &para_end);
   
   ME_GetParaFormat(editor, para, pFmt);
   if (para == para_end) return;
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index 568472c..5c97941 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -293,31 +293,47 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, 
   return item;
 }
 
+
 ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem)
 {
   ME_Cursor tmp;
   ME_DisplayItem *pDI;
-  ME_UndoItem *pUI;
 
   assert(pItem->type == diRun || pItem->type == diUndoInsertRun);
 
+  ME_CursorFromCharOfs(editor, nCharOfs, &tmp);
+  pDI = ME_InsertRunAtCursor(editor, &tmp, pItem->member.run.style,
+                             pItem->member.run.strText->szData,
+                             pItem->member.run.strText->nLen,
+                             pItem->member.run.nFlags);
+  
+  return pDI;
+}
+
+ME_DisplayItem *
+ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
+                     const WCHAR *str, int len, int flags)
+{
+  ME_DisplayItem *pDI;
+  ME_UndoItem *pUI;
+  
+  if (cursor->nOffset) {
+    cursor->pRun = ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset);
+    cursor->nOffset = 0;
+  }
+  
   pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
   if (pUI) {
-    pUI->nStart = nCharOfs;
-    pUI->nLen = pItem->member.run.strText->nLen;
+    pUI->nStart = cursor->pRun->member.run.nCharOfs;
+    pUI->nLen = len;
   }
-  ME_CursorFromCharOfs(editor, nCharOfs, &tmp);
-  if (tmp.nOffset) {
-    tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
-    tmp.nOffset = 0;
-  }
-  pDI = ME_MakeRun(pItem->member.run.style, ME_StrDup(pItem->member.run.strText), pItem->member.run.nFlags);
-  pDI->member.run.nCharOfs = tmp.pRun->member.run.nCharOfs;
-  ME_InsertBefore(tmp.pRun, pDI);
-  TRACE("Shift length:%d\n", pDI->member.run.strText->nLen);
-  ME_PropagateCharOffset(tmp.pRun, pDI->member.run.strText->nLen);
-  ME_GetParagraph(tmp.pRun)->member.para.nFlags |= MEPF_REWRAP;
-
+  
+  pDI = ME_MakeRun(style, ME_MakeStringN(str, len), flags);
+  pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs;
+  ME_InsertBefore(cursor->pRun, pDI);
+  TRACE("Shift length:%d\n", len);
+  ME_PropagateCharOffset(cursor->pRun, len);
+  ME_GetParagraph(cursor->pRun)->member.para.nFlags |= MEPF_REWRAP;
   return pDI;
 }
 




More information about the wine-cvs mailing list