From 8a428d52a7e1d2b3851cfe782169c5ed1d55545a Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 7 Oct 2016 10:49:35 +0100 Subject: [PATCH] riched20: Add support for displaying bulleted lists. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/riched20/editor.h | 2 ++ dlls/riched20/editstr.h | 9 +++++++++ dlls/riched20/list.c | 1 + dlls/riched20/paint.c | 20 ++++++++++++++++++++ dlls/riched20/para.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/wrap.c | 33 +++++++++++++++++++++++++++++---- 6 files changed, 110 insertions(+), 4 deletions(-) diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 24c856b625b..7d46692582f 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -217,6 +217,8 @@ BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) D void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN; void ME_MarkAllForWrapping(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN; +void para_num_init( ME_Context *c, ME_Paragraph *para ) DECLSPEC_HIDDEN; +void para_num_clear( struct para_num *pn ) 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 fb88f71975d..eb4d9f5a44c 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -188,6 +188,14 @@ typedef struct tagME_BorderRect ME_Border right; } ME_BorderRect; +struct para_num +{ + ME_Style *style; + ME_String *text; + INT width; + POINT pt; +}; + typedef struct tagME_Paragraph { PARAFORMAT2 fmt; @@ -201,6 +209,7 @@ typedef struct tagME_Paragraph POINT pt; int nHeight, nWidth; int nRows; + struct para_num para_num; ME_Run *eop_run; /* ptr to the end-of-para run */ struct tagME_DisplayItem *prev_para, *next_para; } ME_Paragraph; diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c index 15b944c942c..d3214466845 100644 --- a/dlls/riched20/list.c +++ b/dlls/riched20/list.c @@ -164,6 +164,7 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) if (item->type==diParagraph) { ME_DestroyString(item->member.para.text); + para_num_clear( &item->member.para.para_num ); } if (item->type==diRun) diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 8e5177255e0..7c175133d0d 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -898,6 +898,25 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) } } +static void draw_para_number( ME_Context *c, ME_DisplayItem *p ) +{ + ME_Paragraph *para = &p->member.para; + HFONT old_font; + int x, y; + + if (para->fmt.wNumbering) + { + old_font = ME_SelectStyleFont( c, para->para_num.style ); + + x = c->pt.x + para->para_num.pt.x; + y = c->pt.y + para->pt.y + para->para_num.pt.y; + + ExtTextOutW( c->hDC, x, y, 0, NULL, para->para_num.text->szData, para->para_num.text->nLen, NULL ); + + ME_UnselectStyleFont( c, para->para_num.style, old_font ); + } +} + static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { int align = SetTextAlign(c->hDC, TA_BASELINE); @@ -1023,6 +1042,7 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) } ME_DrawTableBorders(c, paragraph); + draw_para_number(c, paragraph); SetTextAlign(c->hDC, align); } diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 01742527f4f..3c62da247b3 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -128,6 +128,55 @@ static void ME_UpdateTableFlags(ME_DisplayItem *para) para->member.para.fmt.wEffects &= ~PFE_TABLE; } +void para_num_init( ME_Context *c, ME_Paragraph *para ) +{ + ME_Style *style; + CHARFORMAT2W cf; + static const WCHAR bullet_font[] = {'S','y','m','b','o','l',0}; + static const WCHAR bullet_str[] = {0xb7, 0}; + static const WCHAR spaceW[] = {' ', 0}; + HFONT old_font; + SIZE sz; + + if (para->para_num.style && para->para_num.text) return; + + if (!para->para_num.style) + { + style = para->eop_run->style; + + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_FACE | CFM_CHARSET; + memcpy( cf.szFaceName, bullet_font, sizeof(bullet_font) ); + cf.bCharSet = SYMBOL_CHARSET; + style = ME_ApplyStyle( c->editor, style, &cf ); + + para->para_num.style = style; + } + + if (!para->para_num.text) + { + para->para_num.text = ME_MakeStringConst( bullet_str, 1 ); + } + + old_font = ME_SelectStyleFont( c, para->para_num.style ); + GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz ); + para->para_num.width = sz.cx; + GetTextExtentPointW( c->hDC, spaceW, 1, &sz ); + para->para_num.width += sz.cx; + ME_UnselectStyleFont( c, para->para_num.style, old_font ); +} + +void para_num_clear( struct para_num *pn ) +{ + if (pn->style) + { + ME_ReleaseStyle( pn->style ); + pn->style = NULL; + } + ME_DestroyString( pn->text ); + pn->text = NULL; +} + static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt) { PARAFORMAT2 copy; diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index 4c73c5d717e..e3a70f07d12 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -37,8 +37,10 @@ typedef struct tagME_WrapContext { ME_Style *style; ME_Context *context; - int nLeftMargin, nRightMargin, nFirstMargin; - int nAvailWidth; + int nLeftMargin, nRightMargin; + int nFirstMargin; /* Offset to first line's text, always to the text itself even if a para number is present */ + int nParaNumOffset; /* Offset to the para number */ + int nAvailWidth; /* Width avail for text to wrap into. Does not include any para number text */ int nRow; POINT pt; BOOL bOverflown, bWordWrap; @@ -303,7 +305,12 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) BOOL bSkippingSpaces = TRUE; int ascent = 0, descent = 0, width=0, shift = 0, align = 0; - /* wrap text */ + /* 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) { @@ -367,6 +374,13 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) p->member.run.pt.x += row->member.row.nLMargin+shift; } } + + 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; @@ -869,6 +883,9 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { } ME_PrepareParagraphForWrapping(c, tp); + /* Calculate paragraph numbering label */ + para_num_init( c, &tp->member.para ); + /* For now treating all non-password text as complex for better testing */ if (!c->editor->cPasswordMask /* && ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */) @@ -883,6 +900,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { wc.pPara = tp; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; + wc.nParaNumOffset = 0; if (tp->member.para.nFlags & MEPF_ROWEND) { wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0; } else { @@ -890,8 +908,15 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { if (tp->member.para.pCell) { dxStartIndent += ME_GetTableRowEnd(tp)->member.para.fmt.dxOffset; } + wc.nLeftMargin = ME_twips2pointsX(c, dxStartIndent + pFmt->dxOffset); wc.nFirstMargin = ME_twips2pointsX(c, dxStartIndent); - wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, pFmt->dxOffset); + if (pFmt->wNumbering) + { + wc.nParaNumOffset = wc.nFirstMargin; + dxStartIndent = max( ME_twips2pointsX(c, pFmt->wNumberingTab), + tp->member.para.para_num.width ); + wc.nFirstMargin += dxStartIndent; + } wc.nRightMargin = ME_twips2pointsX(c, pFmt->dxRightIndent); if (wc.nFirstMargin < 0) -- 2.11.4.GIT