riched20: Move several of the wrapping functions to use ME_Run directly.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4039c5ad47
commit
7291506667
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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) found_black = !(run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA));
|
||||
if (found_black) num_runs++;
|
||||
}
|
||||
if (run == start) break;
|
||||
}
|
||||
|
||||
TRACE("%d runs\n", num_runs);
|
||||
|
@ -262,42 +257,37 @@ 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;
|
||||
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 );
|
||||
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_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;
|
||||
int ascent = 0, descent = 0, width = 0, shift = 0, align = 0;
|
||||
|
||||
/* Include height of para numbering label */
|
||||
if (wc->nRow == 0 && para->fmt.wNumbering)
|
||||
|
@ -306,40 +296,40 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
descent = para->para_num.style->tm.tmDescent;
|
||||
}
|
||||
|
||||
for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev)
|
||||
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 (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 (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 = p->member.run.len;
|
||||
WCHAR *text = get_text( &p->member.run, len - 1 );
|
||||
int len = run->len;
|
||||
WCHAR *text = get_text( run, len - 1 );
|
||||
|
||||
assert (len);
|
||||
if (~p->member.run.nFlags & MERF_GRAPHICS)
|
||||
while (len && *(text--) == ' ')
|
||||
len--;
|
||||
assert(len);
|
||||
if (~run->nFlags & MERF_GRAPHICS)
|
||||
while (len && *(text--) == ' ') len--;
|
||||
if (len)
|
||||
{
|
||||
if (len == p->member.run.len)
|
||||
width += p->member.run.nWidth;
|
||||
if (len == run->len)
|
||||
width += run->nWidth;
|
||||
else
|
||||
width += ME_PointFromCharContext( wc->context, &p->member.run, len, FALSE );
|
||||
width += ME_PointFromCharContext( wc->context, run, len, FALSE );
|
||||
}
|
||||
bSkippingSpaces = !len;
|
||||
} else if (!(p->member.run.nFlags & MERF_ENDPARA))
|
||||
width += p->member.run.nWidth;
|
||||
}
|
||||
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);
|
||||
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))
|
||||
{
|
||||
|
@ -354,19 +344,17 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
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 (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 );
|
||||
if (para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, last );
|
||||
|
||||
row->member.row.pt.x = row->member.row.nLMargin + shift;
|
||||
for (p = wc->pRowStart; p!=pEnd; p = p->next)
|
||||
|
||||
for (run = wc->pRowStart; run; run = run_next( run ))
|
||||
{
|
||||
if (p->type==diRun) { /* FIXME add more run types */
|
||||
p->member.run.pt.x += row->member.row.nLMargin+shift;
|
||||
}
|
||||
run->pt.x += row->member.row.nLMargin+shift;
|
||||
if (run == last) break;
|
||||
}
|
||||
|
||||
if (wc->nRow == 0 && para->fmt.wNumbering)
|
||||
|
@ -375,18 +363,19 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
para->para_num.pt.y = wc->pt.y + row->member.row.nBaseline;
|
||||
}
|
||||
|
||||
ME_InsertBefore(wc->pRowStart, row);
|
||||
ME_InsertBefore( run_get_di( wc->pRowStart ), row );
|
||||
wc->nRow++;
|
||||
wc->pt.y += row->member.row.nHeight;
|
||||
ME_BeginRow(wc);
|
||||
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<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);
|
||||
run = &ME_FindItemFwd( tp, diRun )->member.run;
|
||||
while (run)
|
||||
{
|
||||
run = ME_WrapHandleRun( &wc, run );
|
||||
if (wc.nRow && run == wc.pRowStart) wc.pt.y += linespace;
|
||||
}
|
||||
else p = p->next;
|
||||
if (wc.nRow && p == 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;
|
||||
|
|
Loading…
Reference in New Issue