[PATCH 1/5] riched20: Move several of the wrapping functions to use ME_Run directly.

Huw Davies huw at codeweavers.com
Thu Oct 8 05:10:45 CDT 2020


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/riched20/editor.h |   6 +
 dlls/riched20/run.c    |  20 ++
 dlls/riched20/wrap.c   | 441 +++++++++++++++++++----------------------
 3 files changed, 231 insertions(+), 236 deletions(-)

diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 02bff7ccebf..c42d3bc5e7c 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -76,6 +76,8 @@ ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN;
 void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN;
 void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN;
 void destroy_para(ME_TextEditor *editor, ME_DisplayItem *item) DECLSPEC_HIDDEN;
+ME_Run *run_prev( ME_Run *run ) DECLSPEC_HIDDEN;
+ME_Run *run_next( ME_Run *run ) DECLSPEC_HIDDEN;
 
 /* string.c */
 ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN;
@@ -145,6 +147,10 @@ void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from,
 void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
 void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
 void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod) DECLSPEC_HIDDEN;
+static inline ME_DisplayItem *run_get_di( ME_Run *run )
+{
+    return (ME_DisplayItem *)((ptrdiff_t)run - offsetof(ME_DisplayItem, member));
+}
 
 /* caret.c */
 void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index b5408320ca8..66925ca3434 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -27,6 +27,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 WINE_DECLARE_DEBUG_CHANNEL(richedit_check);
 WINE_DECLARE_DEBUG_CHANNEL(richedit_lists);
 
+ME_Run *run_next( ME_Run *run )
+{
+    ME_DisplayItem *item = run_get_di( run );
+
+    if (ME_NextRun( NULL, &item, FALSE ))
+        return &item->member.run;
+
+    return NULL;
+}
+
+ME_Run *run_prev( ME_Run *run )
+{
+    ME_DisplayItem *item = run_get_di( run );
+
+    if (ME_PrevRun( NULL, &item, FALSE ))
+        return &item->member.run;
+
+    return NULL;
+}
+
 /******************************************************************************
  * ME_CanJoinRuns
  *
diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
index 499ba934a06..cde46e2d7cf 100644
--- a/dlls/riched20/wrap.c
+++ b/dlls/riched20/wrap.c
@@ -44,9 +44,8 @@ typedef struct tagME_WrapContext
   POINT pt;
   BOOL bOverflown, bWordWrap;
   ME_DisplayItem *pPara;
-  ME_DisplayItem *pRowStart;
-
-  ME_DisplayItem *pLastSplittableRun;
+  ME_Run *pRowStart;
+  ME_Run *pLastSplittableRun;
 } ME_WrapContext;
 
 static BOOL get_run_glyph_buffers( ME_Run *run )
@@ -128,18 +127,16 @@ static void calc_run_extent(ME_Context *c, const ME_Paragraph *para, int startx,
  * Splits a run into two in a given place. It also updates the screen position
  * and size (extent) of the newly generated runs.
  */
-static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *item, int nVChar)
+static ME_Run *split_run_extents( ME_WrapContext *wc, ME_Run *run, int nVChar )
 {
   ME_TextEditor *editor = wc->context->editor;
-  ME_Run *run, *run2;
+  ME_Run *run2;
   ME_Paragraph *para = &wc->pPara->member.para;
-  ME_Cursor cursor = {wc->pPara, item, nVChar};
+  ME_Cursor cursor = {wc->pPara, run_get_di( run ), nVChar};
 
-  assert(item->member.run.nCharOfs != -1);
+  assert( run->nCharOfs != -1 );
   ME_CheckCharOffsets(editor);
 
-  run = &item->member.run;
-
   TRACE("Before split: %s(%d, %d)\n", debugstr_run( run ),
         run->pt.x, run->pt.y);
 
@@ -152,7 +149,7 @@ static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *ite
   shape_run( wc->context, run2 );
   calc_run_extent(wc->context, para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run);
 
-  run2->pt.x = run->pt.x+run->nWidth;
+  run2->pt.x = run->pt.x + run->nWidth;
   run2->pt.y = run->pt.y;
 
   ME_CheckCharOffsets(editor);
@@ -161,7 +158,7 @@ static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *ite
         debugstr_run( run ), run->pt.x, run->pt.y,
         debugstr_run( run2 ), run2->pt.x, run2->pt.y);
 
-  return cursor.pRun;
+  return &cursor.pRun->member.run;
 }
 
 /******************************************************************************
@@ -233,22 +230,20 @@ static void ME_BeginRow(ME_WrapContext *wc)
     wc->pt.y++;
 }
 
-static void layout_row( ME_DisplayItem *start, const ME_DisplayItem *end )
+static void layout_row( ME_Run *start, ME_Run *last )
 {
-    ME_DisplayItem *p;
+    ME_Run *run;
     int i, num_runs = 0;
     int buf[16 * 5]; /* 5 arrays - 4 of int & 1 of BYTE, alloc space for 5 of ints */
     int *vis_to_log = buf, *log_to_vis, *widths, *pos;
     BYTE *levels;
     BOOL found_black = FALSE;
 
-    for (p = end->prev; p != start->prev; p = p->prev)
+    for (run = last; run; run = run_prev( run ))
     {
-        if (p->type == diRun)
-        {
-            if (!found_black) found_black = !(p->member.run.nFlags & (MERF_WHITESPACE | MERF_ENDPARA));
-            if (found_black) num_runs++;
-        }
+        if (!found_black) found_black = !(run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA));
+        if (found_black) num_runs++;
+        if (run == start) break;
     }
 
     TRACE("%d runs\n", num_runs);
@@ -262,131 +257,125 @@ static void layout_row( ME_DisplayItem *start, const ME_DisplayItem *end )
     pos = vis_to_log + 3 * num_runs;
     levels = (BYTE*)(vis_to_log + 4 * num_runs);
 
-    for (i = 0, p = start; i < num_runs; p = p->next)
+    for (i = 0, run = start; i < num_runs; run = run_next( run ))
     {
-        if (p->type == diRun)
-        {
-            levels[i] = p->member.run.script_analysis.s.uBidiLevel;
-            widths[i] = p->member.run.nWidth;
-            TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] );
-            i++;
-        }
+        levels[i] = run->script_analysis.s.uBidiLevel;
+        widths[i] = run->nWidth;
+        TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] );
+        i++;
     }
 
     ScriptLayout( num_runs, levels, vis_to_log, log_to_vis );
 
-    pos[0] = start->member.run.para->pt.x;
+    pos[0] = run->para->pt.x;
     for (i = 1; i < num_runs; i++)
         pos[i] = pos[i - 1] + widths[ vis_to_log[ i - 1 ] ];
 
-    for (i = 0, p = start; i < num_runs; p = p->next)
+    for (i = 0, run = start; i < num_runs; run = run_next( run ))
     {
-        if (p->type == diRun)
-        {
-            p->member.run.pt.x = pos[ log_to_vis[ i ] ];
-            TRACE( "%d: x = %d\n", i, p->member.run.pt.x );
-            i++;
-        }
+        run->pt.x = pos[ log_to_vis[ i ] ];
+        TRACE( "%d: x = %d\n", i, run->pt.x );
+        i++;
     }
 
     if (vis_to_log != buf) heap_free( vis_to_log );
 }
 
-static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
+static void ME_InsertRowStart( ME_WrapContext *wc, ME_Run *last )
 {
-  ME_DisplayItem *p, *row;
-  ME_Paragraph *para = &wc->pPara->member.para;
-  BOOL bSkippingSpaces = TRUE;
-  int ascent = 0, descent = 0, width=0, shift = 0, align = 0;
+    ME_Run *run;
+    ME_DisplayItem *row;
+    ME_Paragraph *para = &wc->pPara->member.para;
+    BOOL bSkippingSpaces = TRUE;
+    int ascent = 0, descent = 0, width = 0, shift = 0, align = 0;
 
-  /* Include height of para numbering label */
-  if (wc->nRow == 0 && para->fmt.wNumbering)
-  {
-      ascent = para->para_num.style->tm.tmAscent;
-      descent = para->para_num.style->tm.tmDescent;
-  }
+    /* Include height of para numbering label */
+    if (wc->nRow == 0 && para->fmt.wNumbering)
+    {
+        ascent = para->para_num.style->tm.tmAscent;
+        descent = para->para_num.style->tm.tmDescent;
+    }
 
-  for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev)
-  {
-      /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */
-      if (p->type==diRun && ((p==wc->pRowStart) || !(p->member.run.nFlags & MERF_ENDPARA))) { /* FIXME add more run types */
-        if (p->member.run.nAscent>ascent)
-          ascent = p->member.run.nAscent;
-        if (p->member.run.nDescent>descent)
-          descent = p->member.run.nDescent;
-        if (bSkippingSpaces)
+    for (run = last; run; run = run_prev( run ))
+    {
+        /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */
+        if (run == wc->pRowStart || !(run->nFlags & MERF_ENDPARA))
         {
-          /* Exclude space characters from run width.
-           * Other whitespace or delimiters are not treated this way. */
-          int len = p->member.run.len;
-          WCHAR *text = get_text( &p->member.run, len - 1 );
-
-          assert (len);
-          if (~p->member.run.nFlags & MERF_GRAPHICS)
-            while (len && *(text--) == ' ')
-              len--;
-          if (len)
-          {
-              if (len == p->member.run.len)
-                  width += p->member.run.nWidth;
-              else
-                  width += ME_PointFromCharContext( wc->context, &p->member.run, len, FALSE );
-          }
-          bSkippingSpaces = !len;
-        } else if (!(p->member.run.nFlags & MERF_ENDPARA))
-          width += p->member.run.nWidth;
-      }
-  }
+            if (run->nAscent>ascent) ascent = run->nAscent;
+            if (run->nDescent>descent) descent = run->nDescent;
+            if (bSkippingSpaces)
+            {
+                /* Exclude space characters from run width.
+                 * Other whitespace or delimiters are not treated this way. */
+                int len = run->len;
+                WCHAR *text = get_text( run, len - 1 );
+
+                assert(len);
+                if (~run->nFlags & MERF_GRAPHICS)
+                    while (len && *(text--) == ' ') len--;
+                if (len)
+                {
+                    if (len == run->len)
+                        width += run->nWidth;
+                    else
+                        width += ME_PointFromCharContext( wc->context, run, len, FALSE );
+                }
+                bSkippingSpaces = !len;
+            }
+            else if (!(run->nFlags & MERF_ENDPARA))
+                width += run->nWidth;
+        }
+        if (run == wc->pRowStart) break;
+    }
 
-  para->nWidth = max(para->nWidth, width);
-  row = ME_MakeRow(ascent+descent, ascent, width);
-  if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
-      (para->fmt.dwMask & PFM_TABLE) && (para->fmt.wEffects & PFE_TABLE))
-  {
-    /* The text was shifted down in ME_BeginRow so move the wrap context
-     * back to where it should be. */
-    wc->pt.y--;
-    /* The height of the row is increased by the borders. */
-    row->member.row.nHeight += 2;
-  }
-  row->member.row.pt = wc->pt;
-  row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
-  row->member.row.nRMargin = wc->nRightMargin;
-  assert(para->fmt.dwMask & PFM_ALIGNMENT);
-  align = para->fmt.wAlignment;
-  if (align == PFA_CENTER)
-    shift = max((wc->nAvailWidth-width)/2, 0);
-  if (align == PFA_RIGHT)
-    shift = max(wc->nAvailWidth-width, 0);
-
-  if (para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, pEnd );
-
-  row->member.row.pt.x = row->member.row.nLMargin + shift;
-  for (p = wc->pRowStart; p!=pEnd; p = p->next)
-  {
-    if (p->type==diRun) { /* FIXME add more run types */
-      p->member.run.pt.x += row->member.row.nLMargin+shift;
+    para->nWidth = max(para->nWidth, width);
+    row = ME_MakeRow( ascent + descent, ascent, width );
+    if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
+        (para->fmt.dwMask & PFM_TABLE) && (para->fmt.wEffects & PFE_TABLE))
+    {
+        /* The text was shifted down in ME_BeginRow so move the wrap context
+         * back to where it should be. */
+        wc->pt.y--;
+        /* The height of the row is increased by the borders. */
+        row->member.row.nHeight += 2;
     }
-  }
+    row->member.row.pt = wc->pt;
+    row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
+    row->member.row.nRMargin = wc->nRightMargin;
+    assert(para->fmt.dwMask & PFM_ALIGNMENT);
+    align = para->fmt.wAlignment;
+    if (align == PFA_CENTER) shift = max((wc->nAvailWidth-width)/2, 0);
+    if (align == PFA_RIGHT) shift = max(wc->nAvailWidth-width, 0);
 
-  if (wc->nRow == 0 && para->fmt.wNumbering)
-  {
-    para->para_num.pt.x = wc->nParaNumOffset + shift;
-    para->para_num.pt.y = wc->pt.y + row->member.row.nBaseline;
-  }
+    if (para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, last );
+
+    row->member.row.pt.x = row->member.row.nLMargin + shift;
+
+    for (run = wc->pRowStart; run; run = run_next( run ))
+    {
+        run->pt.x += row->member.row.nLMargin+shift;
+        if (run == last) break;
+    }
+
+    if (wc->nRow == 0 && para->fmt.wNumbering)
+    {
+        para->para_num.pt.x = wc->nParaNumOffset + shift;
+        para->para_num.pt.y = wc->pt.y + row->member.row.nBaseline;
+    }
 
-  ME_InsertBefore(wc->pRowStart, row);
-  wc->nRow++;
-  wc->pt.y += row->member.row.nHeight;
-  ME_BeginRow(wc);
+    ME_InsertBefore( run_get_di( wc->pRowStart ), row );
+    wc->nRow++;
+    wc->pt.y += row->member.row.nHeight;
+    ME_BeginRow( wc );
 }
 
-static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p)
+static void ME_WrapEndParagraph( ME_WrapContext *wc )
 {
   ME_DisplayItem *para = wc->pPara;
   PARAFORMAT2 *pFmt = &para->member.para.fmt;
-  if (wc->pRowStart)
-    ME_InsertRowStart(wc, p);
+
+  if (wc->pRowStart) ME_InsertRowStart( wc, para->member.para.eop_run );
+
   if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
       pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
   {
@@ -394,30 +383,16 @@ static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p)
      * text down by one pixel for the border, so fix up the wrap context. */
     wc->pt.y--;
   }
-
-  /*
-  p = para->next;
-  while(p) {
-    if (p->type == diParagraph || p->type == diTextEnd)
-      return;
-    if (p->type == diRun)
-    {
-      ME_Run *run = &p->member.run;
-      TRACE("%s - (%d, %d)\n", debugstr_run(run), run->pt.x, run->pt.y);
-    }
-    p = p->next;
-  }
-  */
 }
 
-static void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p)
+static void ME_WrapSizeRun( ME_WrapContext *wc, ME_Run *run )
 {
   /* FIXME compose style (out of character and paragraph styles) here */
 
-  ME_UpdateRunFlags(wc->context->editor, &p->member.run);
+  ME_UpdateRunFlags( wc->context->editor, run );
 
-  calc_run_extent(wc->context, &wc->pPara->member.para,
-                  wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, &p->member.run);
+  calc_run_extent( wc->context, &wc->pPara->member.para,
+                   wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run );
 }
 
 
@@ -453,173 +428,169 @@ static int reverse_find_whitespace(const WCHAR *s, int start)
   return i;
 }
 
-static ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i)
+static ME_Run *ME_MaximizeSplit( ME_WrapContext *wc, ME_Run *run, int i )
 {
-  ME_DisplayItem *pp, *piter = p;
+  ME_Run *new_run, *iter = run;
   int j;
   if (!i)
     return NULL;
-  j = reverse_find_non_whitespace( get_text( &p->member.run, 0 ), i);
-  if (j>0) {
-    pp = split_run_extents(wc, piter, j);
-    wc->pt.x += piter->member.run.nWidth;
-    return pp;
+  j = reverse_find_non_whitespace( get_text( run, 0 ), i );
+  if (j > 0)
+  {
+    new_run = split_run_extents( wc, iter, j );
+    wc->pt.x += iter->nWidth;
+    return new_run;
   }
   else
   {
-    pp = piter;
+    new_run = iter;
     /* omit all spaces before split point */
-    while(piter != wc->pRowStart)
+    while (iter != wc->pRowStart)
     {
-      piter = ME_FindItemBack(piter, diRun);
-      if (piter->member.run.nFlags & MERF_WHITESPACE)
+      iter = run_prev( iter );
+      if (iter->nFlags & MERF_WHITESPACE)
       {
-        pp = piter;
+        new_run = iter;
         continue;
       }
-      if (piter->member.run.nFlags & MERF_ENDWHITE)
+      if (iter->nFlags & MERF_ENDWHITE)
       {
-        i = reverse_find_non_whitespace( get_text( &piter->member.run, 0 ),
-                                         piter->member.run.len );
-        pp = split_run_extents(wc, piter, i);
-        wc->pt = pp->member.run.pt;
-        return pp;
+        i = reverse_find_non_whitespace( get_text( iter, 0 ), iter->len );
+        new_run = split_run_extents( wc, iter, i );
+        wc->pt = new_run->pt;
+        return new_run;
       }
       /* this run is the end of spaces, so the run edge is a good point to split */
-      wc->pt = pp->member.run.pt;
+      wc->pt = new_run->pt;
       wc->bOverflown = TRUE;
-      TRACE("Split point is: %s|%s\n", debugstr_run( &piter->member.run ), debugstr_run( &pp->member.run ));
-      return pp;
+      TRACE( "Split point is: %s|%s\n", debugstr_run( iter ), debugstr_run( new_run ) );
+      return new_run;
     }
-    wc->pt = piter->member.run.pt;
-    return piter;
+    wc->pt = iter->pt;
+    return iter;
   }
 }
 
-static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, int loc)
+static ME_Run *ME_SplitByBacktracking( ME_WrapContext *wc, ME_Run *run, int loc )
 {
-  ME_DisplayItem *new_run;
+  ME_Run *new_run;
   int i, idesp, len;
-  ME_Run *run = &p->member.run;
 
   idesp = i = find_split_point( wc->context, loc, run );
   len = run->len;
-  assert(len>0);
-  assert(i<len);
-  if (i) {
+  assert( len > 0 );
+  assert( i < len );
+  if (i)
+  {
     /* don't split words */
     i = reverse_find_whitespace( get_text( run, 0 ), i );
-    new_run = ME_MaximizeSplit(wc, p, i);
+    new_run = ME_MaximizeSplit(wc, run, i);
     if (new_run) return new_run;
   }
-  TRACE("Must backtrack to split at: %s\n", debugstr_run( &p->member.run ));
+  TRACE("Must backtrack to split at: %s\n", debugstr_run( run ));
   if (wc->pLastSplittableRun)
   {
-    if (wc->pLastSplittableRun->member.run.nFlags & (MERF_GRAPHICS|MERF_TAB))
+    if (wc->pLastSplittableRun->nFlags & (MERF_GRAPHICS|MERF_TAB))
     {
-      wc->pt = wc->pLastSplittableRun->member.run.pt;
+      wc->pt = wc->pLastSplittableRun->pt;
       return wc->pLastSplittableRun;
     }
-    else if (wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE)
+    else if (wc->pLastSplittableRun->nFlags & MERF_SPLITTABLE)
     {
       /* the following two lines are just to check if we forgot to call UpdateRunFlags earlier,
          they serve no other purpose */
       ME_UpdateRunFlags(wc->context->editor, run);
-      assert((wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE));
+      assert((wc->pLastSplittableRun->nFlags & MERF_SPLITTABLE));
 
-      p = wc->pLastSplittableRun;
-      run = &p->member.run;
+      run = wc->pLastSplittableRun;
       len = run->len;
       /* don't split words */
       i = reverse_find_whitespace( get_text( run, 0 ), len );
       if (i == len)
         i = reverse_find_non_whitespace( get_text( run, 0 ), len );
-      new_run = split_run_extents(wc, p, i);
-      wc->pt = new_run->member.run.pt;
+      new_run = split_run_extents(wc, run, i);
+      wc->pt = new_run->pt;
       return new_run;
     }
     else
     {
       /* restart from the first run beginning with spaces */
-      wc->pt = wc->pLastSplittableRun->member.run.pt;
+      wc->pt = wc->pLastSplittableRun->pt;
       return wc->pLastSplittableRun;
     }
   }
-  TRACE("Backtracking failed, trying desperate: %s\n", debugstr_run( &p->member.run ));
+  TRACE("Backtracking failed, trying desperate: %s\n", debugstr_run( run ));
   /* OK, no better idea, so assume we MAY split words if we can split at all*/
   if (idesp)
-    return split_run_extents(wc, p, idesp);
+    return split_run_extents(wc, run, idesp);
   else
-  if (wc->pRowStart && p != wc->pRowStart)
+  if (wc->pRowStart && run != wc->pRowStart)
   {
     /* don't need to break current run, because it's possible to split
        before this run */
     wc->bOverflown = TRUE;
-    return p;
+    return run;
   }
   else
   {
     /* split point inside first character - no choice but split after that char */
-    if (len != 1) {
+    if (len != 1)
       /* the run is more than 1 char, so we may split */
-      return split_run_extents(wc, p, 1);
-    }
+      return split_run_extents( wc, run, 1 );
+
     /* the run is one char, can't split it */
-    return p;
+    return run;
   }
 }
 
-static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
+static ME_Run *ME_WrapHandleRun( ME_WrapContext *wc, ME_Run *run )
 {
-  ME_DisplayItem *pp;
-  ME_Run *run;
+  ME_Run *new_run;
   int len;
 
-  assert(p->type == diRun);
-  if (!wc->pRowStart)
-    wc->pRowStart = p;
-  run = &p->member.run;
+  if (!wc->pRowStart) wc->pRowStart = run;
   run->pt.x = wc->pt.x;
   run->pt.y = wc->pt.y;
-  ME_WrapSizeRun(wc, p);
+  ME_WrapSizeRun( wc, run );
   len = run->len;
 
   if (wc->bOverflown) /* just skipping final whitespaces */
   {
     /* End paragraph run can't overflow to the next line by itself. */
-    if (run->nFlags & MERF_ENDPARA)
-      return p->next;
+    if (run->nFlags & MERF_ENDPARA) return run_next( run );
 
-    if (run->nFlags & MERF_WHITESPACE) {
+    if (run->nFlags & MERF_WHITESPACE)
+    {
       wc->pt.x += run->nWidth;
       /* skip runs consisting of only whitespaces */
-      return p->next;
+      return run_next( run );
     }
 
-    if (run->nFlags & MERF_STARTWHITE) {
+    if (run->nFlags & MERF_STARTWHITE)
+    {
       /* try to split the run at the first non-white char */
       int black;
       black = find_non_whitespace( get_text( run, 0 ), run->len, 0 );
-      if (black) {
+      if (black)
+      {
+        ME_Run *new_run;
         wc->bOverflown = FALSE;
-        pp = split_run_extents(wc, p, black);
-        calc_run_extent(wc->context, &wc->pPara->member.para,
-                        wc->nRow ? wc->nLeftMargin : wc->nFirstMargin,
-                        &pp->member.run);
-        ME_InsertRowStart(wc, pp);
-        return pp;
+        new_run = split_run_extents( wc, run, black );
+        calc_run_extent( wc->context, &wc->pPara->member.para,
+                         wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run );
+        ME_InsertRowStart( wc, run );
+        return new_run;
       }
     }
     /* black run: the row goes from pRowStart to the previous run */
-    ME_InsertRowStart(wc, p);
-    return p;
+    ME_InsertRowStart( wc, run_prev( run ) );
+    return run;
   }
   /* simply end the current row and move on to next one */
   if (run->nFlags & MERF_ENDROW)
   {
-    p = p->next;
-    ME_InsertRowStart(wc, p);
-    return p;
+    ME_InsertRowStart( wc, run );
+    return run_next( run );
   }
 
   /* will current run fit? */
@@ -631,35 +602,35 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
     if (run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA)) {
       /* let the overflow logic handle it */
       wc->bOverflown = TRUE;
-      return p;
+      return run;
     }
     /* TAB: we can split before */
     if (run->nFlags & MERF_TAB) {
       wc->bOverflown = TRUE;
-      if (wc->pRowStart == p)
+      if (wc->pRowStart == run)
         /* Don't split before the start of the run, or we will get an
          * endless loop. */
-        return p->next;
+        return run_next( run );
       else
-        return p;
+        return run;
     }
     /* graphics: we can split before, if run's width is smaller than row's width */
     if ((run->nFlags & MERF_GRAPHICS) && run->nWidth <= wc->nAvailWidth) {
       wc->bOverflown = TRUE;
-      return p;
+      return run;
     }
     /* can we separate out the last spaces ? (to use overflow logic later) */
     if (run->nFlags & MERF_ENDWHITE)
     {
       /* we aren't sure if it's *really* necessary, it's a good start however */
       int black = reverse_find_non_whitespace( get_text( run, 0 ), len );
-      split_run_extents(wc, p, black);
+      split_run_extents( wc, run, black );
       /* handle both parts again */
-      return p;
+      return run;
     }
     /* determine the split point by backtracking */
-    pp = ME_SplitByBacktracking(wc, p, loc);
-    if (pp == wc->pRowStart)
+    new_run = ME_SplitByBacktracking( wc, run, loc );
+    if (new_run == wc->pRowStart)
     {
       if (run->nFlags & MERF_STARTWHITE)
       {
@@ -671,32 +642,32 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
           /* The lines will only contain spaces, and the rest of the run will
            * overflow onto the next line. */
           wc->bOverflown = TRUE;
-          return p;
+          return run;
       }
       /* Couldn't split the first run, possible because we have a large font
        * with a single character that caused an overflow.
        */
       wc->pt.x += run->nWidth;
-      return p->next;
+      return run_next( run );
     }
-    if (p != pp) /* found a suitable split point */
+    if (run != new_run) /* found a suitable split point */
     {
       wc->bOverflown = TRUE;
-      return pp;
+      return new_run;
     }
     /* we detected that it's best to split on start of this run */
     if (wc->bOverflown)
-      return pp;
+      return new_run;
     ERR("failure!\n");
     /* not found anything - writing over margins is the only option left */
   }
   if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE))
-    || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (p != wc->pRowStart)))
+    || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (run != wc->pRowStart)))
   {
-    wc->pLastSplittableRun = p;
+    wc->pLastSplittableRun = run;
   }
   wc->pt.x += run->nWidth;
-  return p->next;
+  return run_next( run );
 }
 
 static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para)
@@ -860,8 +831,9 @@ static HRESULT shape_para( ME_Context *c, ME_DisplayItem *p )
     return hr;
 }
 
-static void ME_WrapTextParagraph(ME_TextEditor *editor, ME_Context *c, ME_DisplayItem *tp) {
-  ME_DisplayItem *p;
+static void ME_WrapTextParagraph( ME_TextEditor *editor, ME_Context *c, ME_DisplayItem *tp )
+{
+  ME_Run *run;
   ME_WrapContext wc;
   int border = 0;
   int linespace = 0;
@@ -940,16 +912,13 @@ static void ME_WrapTextParagraph(ME_TextEditor *editor, ME_Context *c, ME_Displa
   linespace = ME_GetParaLineSpace(c, &tp->member.para);
 
   ME_BeginRow(&wc);
-  for (p = tp->next; p!=tp->member.para.next_para; ) {
-    assert(p->type != diStartRow);
-    if (p->type == diRun) {
-      p = ME_WrapHandleRun(&wc, p);
-    }
-    else p = p->next;
-    if (wc.nRow && p == wc.pRowStart)
-      wc.pt.y += linespace;
+  run = &ME_FindItemFwd( tp, diRun )->member.run;
+  while (run)
+  {
+    run = ME_WrapHandleRun( &wc, run );
+    if (wc.nRow && run == wc.pRowStart) wc.pt.y += linespace;
   }
-  ME_WrapEndParagraph(&wc, p);
+  ME_WrapEndParagraph( &wc );
   if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
       (pFmt->dwMask & PFM_BORDER) && (pFmt->wBorders & 8))
     wc.pt.y += border;
-- 
2.23.0




More information about the wine-devel mailing list