[PATCH 6/8] riched20: Implement list of marked paragraphs.

Sergio Gómez Del Real sdelreal at codeweavers.com
Thu Nov 29 07:30:27 CST 2018


---
 dlls/riched20/editor.c  |  1 +
 dlls/riched20/editor.h  |  2 ++
 dlls/riched20/editstr.h |  2 ++
 dlls/riched20/para.c    | 76 +++++++++++++++++++++++++++++++++++++++++
 dlls/riched20/wrap.c    | 60 ++++++++++++++++++++++++--------
 5 files changed, 127 insertions(+), 14 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 9ecba6f824..bf4c8ea0c2 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -3035,6 +3035,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
   ed->bEmulateVersion10 = bEmulateVersion10;
   ed->styleFlags = 0;
   ed->exStyleFlags = 0;
+  ed->first_marked_para = NULL;
   ITextHost_TxGetPropertyBits(texthost,
                               (TXTBIT_RICHTEXT|TXTBIT_MULTILINE|
                                TXTBIT_READONLY|TXTBIT_USEPASSWORD|
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 3b4dc542a9..2da7365a6e 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -205,6 +205,8 @@ void para_num_clear( struct para_num *pn ) DECLSPEC_HIDDEN;
 int get_total_width(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN;
 ME_DisplayItem *get_di_from_para(ME_Paragraph *para) DECLSPEC_HIDDEN;
+void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN;
+void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN;
 
 /* paint.c */
 void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 206ce85287..2cd16c93c8 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -219,6 +219,7 @@ typedef struct tagME_Paragraph
   struct para_num para_num;
   ME_Run *eop_run; /* ptr to the end-of-para run */
   struct tagME_DisplayItem *prev_para, *next_para;
+  struct tagME_DisplayItem *prev_marked, *next_marked;
 } ME_Paragraph;
 
 typedef struct tagME_Cell /* v4.1 */
@@ -432,6 +433,7 @@ typedef struct tagME_TextEditor
   int imeStartIndex;
   DWORD selofs; /* The size of the selection bar on the left side of control */
   ME_SelectionType nSelectionType;
+  ME_DisplayItem *first_marked_para;
 
   /* Track previous notified selection */
   CHARRANGE notified_cr;
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index ae2227e235..aaa2bda06a 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -26,6 +26,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para)
 {
     para->member.para.nFlags |= MEPF_REWRAP;
+    add_marked_para(editor, para);
 }
 
 ME_DisplayItem *get_di_from_para(ME_Paragraph *para)
@@ -39,6 +40,8 @@ static ME_DisplayItem *make_para(ME_TextEditor *editor)
 
     ME_SetDefaultParaFormat(editor, &item->member.para.fmt);
     item->member.para.nFlags = MEPF_REWRAP;
+    item->member.para.next_marked = item->member.para.prev_marked = NULL;
+
     return item;
 }
 
@@ -53,6 +56,7 @@ void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item)
     }
     ME_DestroyString(item->member.para.text);
     para_num_clear( &item->member.para.para_num );
+    remove_marked_para(editor, item);
     ME_DestroyDisplayItem(item);
 }
 
@@ -74,6 +78,77 @@ int get_total_width(ME_TextEditor *editor)
     return total_width;
 }
 
+void remove_marked_para(ME_TextEditor *editor, ME_DisplayItem *di)
+{
+    ME_DisplayItem *head = editor->first_marked_para;
+
+    assert(di->type == diParagraph);
+    if (!di->member.para.next_marked && !di->member.para.prev_marked)
+    {
+        if (di == head)
+            editor->first_marked_para = NULL;
+    }
+    else if (di->member.para.next_marked && di->member.para.prev_marked)
+    {
+        di->member.para.prev_marked->member.para.next_marked = di->member.para.next_marked;
+        di->member.para.next_marked->member.para.prev_marked = di->member.para.prev_marked;
+        di->member.para.prev_marked = di->member.para.next_marked = NULL;
+    }
+    else if (di->member.para.next_marked)
+    {
+        assert(di == editor->first_marked_para);
+        editor->first_marked_para = di->member.para.next_marked;
+        di->member.para.next_marked->member.para.prev_marked = NULL;
+        di->member.para.next_marked = NULL;
+    }
+    else
+    {
+        di->member.para.prev_marked->member.para.next_marked = NULL;
+        di->member.para.prev_marked = NULL;
+    }
+}
+
+void add_marked_para(ME_TextEditor *editor, ME_DisplayItem *di)
+{
+    ME_DisplayItem *iter = editor->first_marked_para;
+
+    if (!iter)
+    {
+        editor->first_marked_para = di;
+        return;
+    }
+    while (iter)
+    {
+        if (iter == di)
+            return;
+        else if (di->member.para.nCharOfs < iter->member.para.nCharOfs)
+        {
+            if (iter == editor->first_marked_para)
+                editor->first_marked_para = di;
+            di->member.para.next_marked = iter;
+            iter->member.para.prev_marked = di;
+            break;
+        }
+        else if (di->member.para.nCharOfs >= iter->member.para.nCharOfs)
+        {
+            if (!iter->member.para.next_marked ||
+                (iter->member.para.next_marked &&
+                 di->member.para.nCharOfs < iter->member.para.next_marked->member.para.nCharOfs))
+            {
+                if (iter->member.para.next_marked)
+                {
+                    di->member.para.next_marked = iter->member.para.next_marked;
+                    iter->member.para.next_marked->member.para.prev_marked = di;
+                }
+                di->member.para.prev_marked = iter;
+                iter->member.para.next_marked = di;
+                break;
+            }
+        }
+        iter = iter->member.para.next_marked;
+    }
+}
+
 void ME_MakeFirstParagraph(ME_TextEditor *editor)
 {
   ME_Context c;
@@ -146,6 +221,7 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
 
   text->pLast->member.para.nCharOfs = editor->bEmulateVersion10 ? 2 : 1;
 
+  add_marked_para(editor, para);
   ME_DestroyContext(&c);
 }
 
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
index e1ec692004..c2e3f62162 100644
--- a/dlls/riched20/wrap.c
+++ b/dlls/riched20/wrap.c
@@ -1098,29 +1098,61 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
 {
   ME_DisplayItem *item;
   ME_Context c;
-  int totalWidth = 0;
+  int totalWidth = editor->nTotalWidth, diff = 0, prev_width;
   ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL;
+  ME_Paragraph *para;
+
+  if (!editor->first_marked_para)
+    return FALSE;
 
   ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
-  c.pt.x = 0;
-  item = editor->pBuffer->pFirst->next;
-  while(item != editor->pBuffer->pLast) {
-    BOOL bRedraw = FALSE;
 
+  item = editor->first_marked_para;
+  c.pt = item->member.para.pt;
+  while (item != editor->pBuffer->pLast)
+  {
     assert(item->type == diParagraph);
-    if ((item->member.para.nFlags & MEPF_REWRAP)
-     || (item->member.para.pt.y != c.pt.y))
-      bRedraw = TRUE;
-    item->member.para.pt = c.pt;
 
+    prev_width = item->member.para.nWidth;
     ME_WrapTextParagraph(&c, item);
+    if (prev_width == totalWidth && item->member.para.nWidth < totalWidth)
+      totalWidth = get_total_width(editor);
+    else
+      totalWidth = max(totalWidth, item->member.para.nWidth);
 
-    if (bRedraw)
-      ME_MarkRepaintEnd(item, &repaint_start, &repaint_end);
-
+    if (!item->member.para.nCharOfs)
+      ME_MarkRepaintEnd(item->member.para.prev_para, &repaint_start, &repaint_end);
+    ME_MarkRepaintEnd(item, &repaint_start, &repaint_end);
     adjust_para_y(item, &c, repaint_start, repaint_end);
-    totalWidth = max(totalWidth, item->member.para.nWidth);
-    item = item->member.para.next_para;
+
+    if (item->member.para.next_para)
+    {
+      diff = c.pt.y - item->member.para.next_para->member.para.pt.y;
+      if (diff)
+      {
+        para = &item->member.para;
+        while (para->next_para && para != &item->member.para.next_marked->member.para &&
+               para != &editor->pBuffer->pLast->member.para)
+        {
+          ME_MarkRepaintEnd(para->next_para, &repaint_start, &repaint_end);
+          para->next_para->member.para.pt.y = c.pt.y;
+          adjust_para_y(para->next_para, &c, repaint_start, repaint_end);
+          para = &para->next_para->member.para;
+        }
+      }
+    }
+    if (item->member.para.next_marked)
+    {
+      ME_DisplayItem *rem = item;
+      item = item->member.para.next_marked;
+      remove_marked_para(editor, rem);
+    }
+    else
+    {
+      remove_marked_para(editor, item);
+      item = editor->pBuffer->pLast;
+    }
+    c.pt.y = item->member.para.pt.y;
   }
   editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
   editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
-- 
2.17.1




More information about the wine-devel mailing list