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