Huw Davies : riched20: Add support for displaying bulleted lists.
Alexandre Julliard
julliard at winehq.org
Fri Oct 7 14:46:47 CDT 2016
Module: wine
Branch: master
Commit: 8a428d52a7e1d2b3851cfe782169c5ed1d55545a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=8a428d52a7e1d2b3851cfe782169c5ed1d55545a
Author: Huw Davies <huw at codeweavers.com>
Date: Fri Oct 7 10:49:35 2016 +0100
riched20: Add support for displaying bulleted lists.
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 24c856b..7d46692 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 fb88f71..eb4d9f5 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 15b944c..d321446 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 8e51772..7c17513 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 0174252..3c62da2 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 4c73c5d..e3a70f0 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)
More information about the wine-cvs
mailing list