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; - } - - 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) - { - /* 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; - } - } - - 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; + /* 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; } - } - 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; - } + 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)) + { + 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 ); - ME_InsertBefore(wc->pRowStart, row); - wc->nRow++; - wc->pt.y += row->member.row.nHeight; - ME_BeginRow(wc); + 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, 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( 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 = ¶->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 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;