[Libreoffice-commits] libvisio.git: src/lib

Fridrich Štrba fridrich.strba at bluewin.ch
Fri Dec 18 08:27:08 PST 2015


 src/lib/VSD5Parser.cpp           |   66 ++++++++++++++++++++
 src/lib/VSD5Parser.h             |    1 
 src/lib/VSD6Parser.cpp           |   43 +++++++++++--
 src/lib/VSDCollector.h           |   10 ++-
 src/lib/VSDContentCollector.cpp  |  126 ++++++++++++++++++++++++++++++++++-----
 src/lib/VSDContentCollector.h    |   10 ++-
 src/lib/VSDOutputElementList.cpp |  114 +++++++++++++++++++++++++++++++++++
 src/lib/VSDOutputElementList.h   |   10 ++-
 src/lib/VSDParagraphList.cpp     |   37 +++++++----
 src/lib/VSDParagraphList.h       |    3 
 src/lib/VSDParser.cpp            |   47 ++++++++++++--
 src/lib/VSDStyles.h              |   37 ++++++++---
 src/lib/VSDStylesCollector.cpp   |   20 ++++--
 src/lib/VSDStylesCollector.h     |    8 +-
 src/lib/VSDTypes.h               |   23 +++++++
 src/lib/VSDXMLParserBase.cpp     |   33 ++++++++--
 src/lib/tokens.txt               |    3 
 17 files changed, 523 insertions(+), 68 deletions(-)

New commits:
commit 0766a97602f3dd8e68b47fd838d3897f20dc58da
Author: Fridrich Štrba <fridrich.strba at bluewin.ch>
Date:   Fri Dec 18 17:26:42 2015 +0100

    BIPU support of bullets
    
    Change-Id: If859332ac564522fdad06c081b644fba0759880b

diff --git a/src/lib/VSD5Parser.cpp b/src/lib/VSD5Parser.cpp
index be47174..1c116f6 100644
--- a/src/lib/VSD5Parser.cpp
+++ b/src/lib/VSD5Parser.cpp
@@ -218,6 +218,72 @@ void libvisio::VSD5Parser::readLine(librevenge::RVNGInputStream *input)
     m_shape.m_lineStyle.override(VSDOptionalLineStyle(strokeWidth, c, linePattern, startMarker, endMarker, lineCap, rounding));
 }
 
+void libvisio::VSD5Parser::readParaIX(librevenge::RVNGInputStream *input)
+{
+  long startPosition = input->tell();
+  unsigned charCount = readU16(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+  double indFirst = readDouble(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+  double indLeft = readDouble(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+  double indRight = readDouble(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+  double spLine = readDouble(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+  double spBefore = readDouble(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+  double spAfter = readDouble(input);
+  unsigned char align = readU8(input);
+  unsigned char bullet = readU8(input);
+  input->seek(1, librevenge::RVNG_SEEK_CUR);
+
+  long remainingData = m_header.dataLength - input->tell() + startPosition;
+  unsigned blockLength = 0;
+  VSDName bulletStr;
+
+  while (remainingData >= 2 && (blockLength = readU16(input)))
+  {
+    long blockEnd = blockLength-2 + input->tell();
+    unsigned char blockType = readU8(input);
+    unsigned char blockIdx = readU8(input);
+    if (blockType == 2 && blockIdx == 8)
+    {
+      input->seek(1, librevenge::RVNG_SEEK_CUR);
+      unsigned long numBytes = readU8(input);
+      unsigned long numBytesRead = 0;
+      const unsigned char *tmpBuffer = input->read(numBytes, numBytesRead);
+      if (tmpBuffer && numBytesRead)
+      {
+        librevenge::RVNGBinaryData tmpBulletString(tmpBuffer, numBytesRead);
+        bulletStr = VSDName(tmpBulletString, libvisio::VSD_TEXT_ANSI);
+      }
+    }
+    else if (blockType == 2 && blockIdx == 3)
+    {
+    };
+    input->seek(blockEnd, librevenge::RVNG_SEEK_SET);
+    remainingData -= blockLength;
+  }
+
+  if (m_isInStyles)
+    m_collector->collectParaIXStyle(m_header.id, m_header.level, charCount, indFirst, indLeft, indRight,
+                                    spLine, spBefore, spAfter, align, bullet, bulletStr, 0.0, 0);
+  else
+  {
+    if (m_isStencilStarted)
+    {
+      VSD_DEBUG_MSG(("Found stencil paragraph style\n"));
+    }
+
+    m_shape.m_paraStyle.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight,
+                                                      spLine, spBefore, spAfter, align, bullet,
+                                                      bulletStr, 0.0, 0));
+    m_shape.m_paraList.addParaIX(m_header.id, m_header.level, charCount, indFirst, indLeft, indRight,
+                                 spLine, spBefore, spAfter, align, bullet, bulletStr, 0.0, 0);
+  }
+}
+
 void libvisio::VSD5Parser::readCharIX(librevenge::RVNGInputStream *input)
 {
   unsigned charCount = readU16(input);
diff --git a/src/lib/VSD5Parser.h b/src/lib/VSD5Parser.h
index 08e8497..914f93d 100644
--- a/src/lib/VSD5Parser.h
+++ b/src/lib/VSD5Parser.h
@@ -43,6 +43,7 @@ protected:
   virtual void readFillAndShadow(librevenge::RVNGInputStream *input);
   virtual void readTextBlock(librevenge::RVNGInputStream *input);
   virtual void readCharIX(librevenge::RVNGInputStream *input);
+  virtual void readParaIX(librevenge::RVNGInputStream *input);
   virtual void readTextField(librevenge::RVNGInputStream *input);
 
   virtual void readShape(librevenge::RVNGInputStream *input);
diff --git a/src/lib/VSD6Parser.cpp b/src/lib/VSD6Parser.cpp
index d38454e..e8707c6 100644
--- a/src/lib/VSD6Parser.cpp
+++ b/src/lib/VSD6Parser.cpp
@@ -169,7 +169,8 @@ void libvisio::VSD6Parser::readCharIX(librevenge::RVNGInputStream *input)
 
 void libvisio::VSD6Parser::readParaIX(librevenge::RVNGInputStream *input)
 {
-  unsigned charCount = getUInt(input);
+  long startPosition = input->tell();
+  unsigned charCount = readU32(input);
   input->seek(1, librevenge::RVNG_SEEK_CUR);
   double indFirst = readDouble(input);
   input->seek(1, librevenge::RVNG_SEEK_CUR);
@@ -183,10 +184,42 @@ void libvisio::VSD6Parser::readParaIX(librevenge::RVNGInputStream *input)
   input->seek(1, librevenge::RVNG_SEEK_CUR);
   double spAfter = readDouble(input);
   unsigned char align = readU8(input);
+  unsigned char bullet = readU8(input);
+  input->seek(4, librevenge::RVNG_SEEK_CUR);
+  unsigned flags = readU32(input);
+  input->seek(5, librevenge::RVNG_SEEK_CUR);
+
+  long remainingData = m_header.dataLength - input->tell() + startPosition;
+  unsigned blockLength = 0;
+  VSDName bulletStr;
+
+  while (remainingData >= 4 && (blockLength = readU32(input)))
+  {
+    long blockEnd = blockLength-4 + input->tell();
+    unsigned char blockType = readU8(input);
+    unsigned char blockIdx = readU8(input);
+    if (blockType == 2 && blockIdx == 8)
+    {
+      input->seek(1, librevenge::RVNG_SEEK_CUR);
+      unsigned long numBytes = readU8(input);
+      unsigned long numBytesRead = 0;
+      const unsigned char *tmpBuffer = input->read(numBytes, numBytesRead);
+      if (tmpBuffer && numBytesRead)
+      {
+        librevenge::RVNGBinaryData tmpBulletString(tmpBuffer, numBytesRead);
+        bulletStr = VSDName(tmpBulletString, libvisio::VSD_TEXT_ANSI);
+      }
+    }
+    else if (blockType == 2 && blockIdx == 3)
+    {
+    };
+    input->seek(blockEnd, librevenge::RVNG_SEEK_SET);
+    remainingData -= blockLength;
+  }
 
   if (m_isInStyles)
     m_collector->collectParaIXStyle(m_header.id, m_header.level, charCount, indFirst, indLeft, indRight,
-                                    spLine, spBefore, spAfter, align, (unsigned)0);
+                                    spLine, spBefore, spAfter, align, bullet, bulletStr, 0.0, flags);
   else
   {
     if (m_isStencilStarted)
@@ -195,13 +228,13 @@ void libvisio::VSD6Parser::readParaIX(librevenge::RVNGInputStream *input)
     }
 
     m_shape.m_paraStyle.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight,
-                                                      spLine, spBefore, spAfter, align, (unsigned)0));
+                                                      spLine, spBefore, spAfter, align, bullet,
+                                                      bulletStr, 0.0, flags));
     m_shape.m_paraList.addParaIX(m_header.id, m_header.level, charCount, indFirst, indLeft, indRight,
-                                 spLine, spBefore, spAfter, align, (unsigned)0);
+                                 spLine, spBefore, spAfter, align, bullet, bulletStr, 0.0, flags);
   }
 }
 
-
 void libvisio::VSD6Parser::readFillAndShadow(librevenge::RVNGInputStream *input)
 {
   unsigned char colourFGIndex = readU8(input);
diff --git a/src/lib/VSDCollector.h b/src/lib/VSDCollector.h
index fd4adeb..56f6b82 100644
--- a/src/lib/VSDCollector.h
+++ b/src/lib/VSDCollector.h
@@ -89,10 +89,13 @@ public:
   virtual void collectParaIX(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                              const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                              const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-                             const boost::optional<unsigned> &flags) = 0;
+                             const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                             const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags) = 0;
   virtual void collectDefaultParaStyle(unsigned charCount, const boost::optional<double> &indFirst, const boost::optional<double> &indLeft,
                                        const boost::optional<double> &indRight, const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
-                                       const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align, const boost::optional<unsigned> &flags) = 0;
+                                       const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                                       const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                                       const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags) = 0;
   virtual void collectTextBlock(unsigned level, const boost::optional<double> &leftMargin, const boost::optional<double> &rightMargin,
                                 const boost::optional<double> &topMargin, const boost::optional<double> &bottomMargin,
                                 const boost::optional<unsigned char> &verticalAlign, const boost::optional<bool> &isBgFilled,
@@ -128,7 +131,8 @@ public:
   virtual void collectParaIXStyle(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                                   const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                                   const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-                                  const boost::optional<unsigned> &flags) = 0;
+                                  const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                                  const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags) = 0;
   virtual void collectTextBlockStyle(unsigned level, const boost::optional<double> &leftMargin, const boost::optional<double> &rightMargin,
                                      const boost::optional<double> &topMargin, const boost::optional<double> &bottomMargin,
                                      const boost::optional<unsigned char> &verticalAlign, const boost::optional<bool> &isBgFilled,
diff --git a/src/lib/VSDContentCollector.cpp b/src/lib/VSDContentCollector.cpp
index c736f0e..5b2ecb4 100644
--- a/src/lib/VSDContentCollector.cpp
+++ b/src/lib/VSDContentCollector.cpp
@@ -462,6 +462,8 @@ void libvisio::VSDContentCollector::_flushText()
   const unsigned char *pTextBuffer = m_textStream.getDataBuffer();
   const unsigned long nTextBufferLength = m_textStream.size();
 
+  VSDBullet currentBullet;
+
   for (std::vector<VSDParaStyle>::iterator paraIt = m_paraFormats.begin();
        paraIt != m_paraFormats.end() && charIndex < m_charFormats.size(); ++paraIt)
   {
@@ -545,7 +547,30 @@ void libvisio::VSDContentCollector::_flushText()
         paraProps.insert("style:tab-stops", tmpTabSet);
     }
 
-    m_shapeOutputText->addOpenParagraph(paraProps);
+    VSDBullet bullet;
+    _bulletFromParaFormat(bullet, *paraIt);
+
+    if (bullet != currentBullet)
+    {
+      if (!!currentBullet)
+      {
+        m_shapeOutputText->addCloseUnorderedListLevel();
+      }
+
+      currentBullet = bullet;
+      if (!!bullet)
+      {
+        librevenge::RVNGPropertyList bulletList;
+        _listLevelFromBullet(bulletList, bullet);
+        m_shapeOutputText->addOpenUnorderedListLevel(bulletList);
+      }
+
+    }
+
+    if (!currentBullet)
+      m_shapeOutputText->addOpenParagraph(paraProps);
+    else
+      m_shapeOutputText->addOpenListElement(paraProps);
 
     // Find char format that overlaps
     while (charIndex < m_charFormats.size() && paraCharCount)
@@ -684,10 +709,16 @@ void libvisio::VSDContentCollector::_flushText()
 
       charIndex++;
     }
-    m_shapeOutputText->addCloseParagraph();
+    if (!currentBullet)
+      m_shapeOutputText->addCloseParagraph();
+    else
+      m_shapeOutputText->addCloseListElement();
     tabIndex++;
   }
 
+  if (!!currentBullet)
+    m_shapeOutputText->addCloseUnorderedListLevel();
+
   m_shapeOutputText->addEndTextObject();
   m_textStream.clear();
 }
@@ -2144,21 +2175,28 @@ void libvisio::VSDContentCollector::collectText(unsigned level, const librevenge
 }
 
 void libvisio::VSDContentCollector::collectParaIX(unsigned /* id */ , unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
-                                                  const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
-                                                  const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align, const boost::optional<unsigned> &flags)
+                                                  const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
+                                                  const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                                                  const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                                                  const boost::optional<double> &textPosAfterBullet,  const boost::optional<unsigned> &flags)
 {
   _handleLevelChange(level);
   VSDParaStyle format(m_defaultParaStyle);
-  format.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align, flags));
+  format.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align,
+                                       bullet, bulletStr, textPosAfterBullet, flags));
   format.charCount = charCount;
   m_paraFormats.push_back(format);
 }
 
 void libvisio::VSDContentCollector::collectDefaultParaStyle(unsigned charCount, const boost::optional<double> &indFirst,
-                                                            const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
-                                                            const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align, const boost::optional<unsigned> &flags)
+                                                            const boost::optional<double> &indLeft, const boost::optional<double> &indRight,
+                                                            const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
+                                                            const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                                                            const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                                                            const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags)
 {
-  m_defaultParaStyle.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align, flags));
+  m_defaultParaStyle.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align,
+                                                   bullet, bulletStr, textPosAfterBullet, flags));
 }
 
 void libvisio::VSDContentCollector::collectCharIX(unsigned /* id */ , unsigned level, unsigned charCount,
@@ -2276,11 +2314,15 @@ void libvisio::VSDContentCollector::collectFillStyle(unsigned level, const boost
 }
 
 void libvisio::VSDContentCollector::collectParaIXStyle(unsigned /* id */, unsigned /* level */, unsigned charCount,
-                                                       const boost::optional<double> &indFirst, const boost::optional<double> &indLeft, const boost::optional<double> &indRight,
-                                                       const boost::optional<double> &spLine, const boost::optional<double> &spBefore, const boost::optional<double> &spAfter,
-                                                       const boost::optional<unsigned char> &align, const boost::optional<unsigned> &flags)
-{
-  VSDOptionalParaStyle paraStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align, flags);
+                                                       const boost::optional<double> &indFirst, const boost::optional<double> &indLeft,
+                                                       const boost::optional<double> &indRight, const boost::optional<double> &spLine,
+                                                       const boost::optional<double> &spBefore, const boost::optional<double> &spAfter,
+                                                       const boost::optional<unsigned char> &align, const boost::optional<unsigned char> &bullet,
+                                                       const boost::optional<VSDName> &bulletStr, const boost::optional<double> &textPosAfterBullet,
+                                                       const boost::optional<unsigned> &flags)
+{
+  VSDOptionalParaStyle paraStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align,
+                                 bullet, bulletStr, textPosAfterBullet, flags);
   m_styles.addParaStyle(m_currentStyleSheet, paraStyle);
 }
 
@@ -3251,4 +3293,62 @@ void libvisio::VSDContentCollector::_appendVisibleAndPrintable(librevenge::RVNGP
     propList.insert("draw:display", "screen");
 }
 
+void libvisio::VSDContentCollector::_bulletFromParaFormat(libvisio::VSDBullet &bullet, const libvisio::VSDParaStyle &paraStyle)
+{
+  bullet.m_textPosAfterBullet = paraStyle.textPosAfterBullet;
+  if (!paraStyle.bullet)
+  {
+    bullet.m_bulletStr.clear();
+    bullet.m_textPosAfterBullet = 0.0;
+  }
+  else
+  {
+    VSDName name = paraStyle.bulletStr;
+    if (name.m_data.empty())
+      bullet.m_bulletStr.clear();
+    else
+      _convertDataToString(bullet.m_bulletStr, name.m_data, name.m_format);
+    if (bullet.m_bulletStr.empty())
+    {
+      switch (paraStyle.bullet)
+      {
+      case 1: // U+2022
+        appendUCS4(bullet.m_bulletStr, 0x2022);
+        break;
+      case 2: // U+25CB
+        appendUCS4(bullet.m_bulletStr, 0x25cb);
+        break;
+      case 3: // U+25A0
+        appendUCS4(bullet.m_bulletStr, 0x25a0);
+        break;
+      case 4: // U+25A1
+        appendUCS4(bullet.m_bulletStr, 0x25a1);
+        break;
+      case 5: // U+2756
+        appendUCS4(bullet.m_bulletStr, 0x2756);
+        break;
+      case 6: // U+27A2
+        appendUCS4(bullet.m_bulletStr, 0x27a2);
+        break;
+      case 7: // U+2714
+        appendUCS4(bullet.m_bulletStr, 0x2714);
+        break;
+      default:
+        appendUCS4(bullet.m_bulletStr, 0x2022);
+        break;
+      }
+    }
+  }
+}
+
+void libvisio::VSDContentCollector::_listLevelFromBullet(librevenge::RVNGPropertyList &propList, const libvisio::VSDBullet &bullet)
+{
+  if (!bullet)
+    return;
+  propList.insert("librevenge:level", 1);
+  propList.insert("text:bullet-char", bullet.m_bulletStr);
+  propList.insert("fo:font-size", 1.0, librevenge::RVNG_PERCENT);
+  propList.insert("text:min-label-width", bullet.m_textPosAfterBullet);
+}
+
 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
diff --git a/src/lib/VSDContentCollector.h b/src/lib/VSDContentCollector.h
index 503cead..6cc8da1 100644
--- a/src/lib/VSDContentCollector.h
+++ b/src/lib/VSDContentCollector.h
@@ -109,10 +109,13 @@ public:
   void collectParaIX(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                      const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                      const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                     const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr, const boost::optional<double> &textPosAfterBullet,
                      const boost::optional<unsigned> &flags);
   void collectDefaultParaStyle(unsigned charCount, const boost::optional<double> &indFirst, const boost::optional<double> &indLeft,
                                const boost::optional<double> &indRight, const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
-                               const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align, const boost::optional<unsigned> &flags);
+                               const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                               const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                               const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags);
   void collectTextBlock(unsigned level, const boost::optional<double> &leftMargin, const boost::optional<double> &rightMargin,
                         const boost::optional<double> &topMargin, const boost::optional<double> &bottomMargin,
                         const boost::optional<unsigned char> &verticalAlign, const boost::optional<bool> &isBgFilled,
@@ -148,7 +151,8 @@ public:
   void collectParaIXStyle(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                           const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                           const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-                          const boost::optional<unsigned> &flags);
+                          const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                          const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags);
   void collectTextBlockStyle(unsigned level, const boost::optional<double> &leftMargin, const boost::optional<double> &rightMargin,
                              const boost::optional<double> &topMargin, const boost::optional<double> &bottomMargin,
                              const boost::optional<unsigned char> &verticalAlign, const boost::optional<bool> &isBgFilled,
@@ -217,6 +221,8 @@ private:
   void _outputQuadraticBezierSegment(const std::vector<std::pair<double, double> > &points);
   void _outputLinearBezierSegment(const std::vector<std::pair<double, double> > &points);
   void _appendVisibleAndPrintable(librevenge::RVNGPropertyList &propList);
+  void _bulletFromParaFormat(VSDBullet &bullet, const VSDParaStyle &paraStyle);
+  void _listLevelFromBullet(librevenge::RVNGPropertyList &propList, const VSDBullet &bullet);
 
   bool m_isPageStarted;
   double m_pageWidth;
diff --git a/src/lib/VSDOutputElementList.cpp b/src/lib/VSDOutputElementList.cpp
index 9c6df59..73ddef4 100644
--- a/src/lib/VSDOutputElementList.cpp
+++ b/src/lib/VSDOutputElementList.cpp
@@ -277,6 +277,62 @@ public:
   }
 };
 
+class VSDOpenListElementOutputElement : public VSDOutputElement
+{
+public:
+  VSDOpenListElementOutputElement(const librevenge::RVNGPropertyList &propList);
+  virtual ~VSDOpenListElementOutputElement() {}
+  virtual void draw(librevenge::RVNGDrawingInterface *painter);
+  virtual VSDOutputElement *clone()
+  {
+    return new VSDOpenListElementOutputElement(m_propList);
+  }
+private:
+  librevenge::RVNGPropertyList m_propList;
+};
+
+
+class VSDCloseListElementOutputElement : public VSDOutputElement
+{
+public:
+  VSDCloseListElementOutputElement();
+  virtual ~VSDCloseListElementOutputElement() {}
+  virtual void draw(librevenge::RVNGDrawingInterface *painter);
+  virtual VSDOutputElement *clone()
+  {
+    return new VSDCloseListElementOutputElement();
+  }
+};
+
+
+class VSDOpenUnorderedListLevelOutputElement : public VSDOutputElement
+{
+public:
+  VSDOpenUnorderedListLevelOutputElement(const librevenge::RVNGPropertyList &propList);
+  virtual ~VSDOpenUnorderedListLevelOutputElement() {}
+  virtual void draw(librevenge::RVNGDrawingInterface *painter);
+  virtual VSDOutputElement *clone()
+  {
+    return new VSDOpenUnorderedListLevelOutputElement(m_propList);
+  }
+private:
+  librevenge::RVNGPropertyList m_propList;
+};
+
+
+class VSDCloseUnorderedListLevelOutputElement : public VSDOutputElement
+{
+public:
+  VSDCloseUnorderedListLevelOutputElement();
+  virtual ~VSDCloseUnorderedListLevelOutputElement() {}
+  virtual void draw(librevenge::RVNGDrawingInterface *painter);
+  virtual VSDOutputElement *clone()
+  {
+    return new VSDCloseUnorderedListLevelOutputElement();
+  }
+};
+
+
 } // namespace libvisio
 
 libvisio::VSDStyleOutputElement::VSDStyleOutputElement(const librevenge::RVNGPropertyList &propList) :
@@ -393,6 +449,44 @@ void libvisio::VSDEndTextObjectOutputElement::draw(librevenge::RVNGDrawingInterf
 }
 
 
+libvisio::VSDOpenListElementOutputElement::VSDOpenListElementOutputElement(const librevenge::RVNGPropertyList &propList) :
+  m_propList(propList) {}
+
+void libvisio::VSDOpenListElementOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
+{
+  if (painter)
+    painter->openListElement(m_propList);
+}
+
+
+libvisio::VSDCloseListElementOutputElement::VSDCloseListElementOutputElement() {}
+
+void libvisio::VSDCloseListElementOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
+{
+  if (painter)
+    painter->closeListElement();
+}
+
+
+libvisio::VSDOpenUnorderedListLevelOutputElement::VSDOpenUnorderedListLevelOutputElement(const librevenge::RVNGPropertyList &propList) :
+  m_propList(propList) {}
+
+void libvisio::VSDOpenUnorderedListLevelOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
+{
+  if (painter)
+    painter->openUnorderedListLevel(m_propList);
+}
+
+
+libvisio::VSDCloseUnorderedListLevelOutputElement::VSDCloseUnorderedListLevelOutputElement() {}
+
+void libvisio::VSDCloseUnorderedListLevelOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
+{
+  if (painter)
+    painter->closeUnorderedListLevel();
+}
+
+
 libvisio::VSDOutputElementList::VSDOutputElementList()
   : m_elements()
 {
@@ -498,4 +592,24 @@ void libvisio::VSDOutputElementList::addEndLayer()
   m_elements.push_back(new VSDEndLayerOutputElement());
 }
 
+void libvisio::VSDOutputElementList::addOpenListElement(const librevenge::RVNGPropertyList &propList)
+{
+  m_elements.push_back(new VSDOpenListElementOutputElement(propList));
+}
+
+void libvisio::VSDOutputElementList::addOpenUnorderedListLevel(const librevenge::RVNGPropertyList &propList)
+{
+  m_elements.push_back(new VSDOpenUnorderedListLevelOutputElement(propList));
+}
+
+void libvisio::VSDOutputElementList::addCloseListElement()
+{
+  m_elements.push_back(new VSDCloseListElementOutputElement());
+}
+
+void libvisio::VSDOutputElementList::addCloseUnorderedListLevel()
+{
+  m_elements.push_back(new VSDCloseUnorderedListLevelOutputElement());
+}
+
 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
diff --git a/src/lib/VSDOutputElementList.h b/src/lib/VSDOutputElementList.h
index 4d9eed5..c77bada 100644
--- a/src/lib/VSDOutputElementList.h
+++ b/src/lib/VSDOutputElementList.h
@@ -33,12 +33,16 @@ public:
   void addPath(const librevenge::RVNGPropertyList &propList);
   void addGraphicObject(const librevenge::RVNGPropertyList &propList);
   void addStartTextObject(const librevenge::RVNGPropertyList &propList);
+  void addEndTextObject();
+  void addOpenUnorderedListLevel(const librevenge::RVNGPropertyList &propList);
+  void addCloseUnorderedListLevel();
+  void addOpenListElement(const librevenge::RVNGPropertyList &propList);
+  void addCloseListElement();
   void addOpenParagraph(const librevenge::RVNGPropertyList &propList);
+  void addCloseParagraph();
   void addOpenSpan(const librevenge::RVNGPropertyList &propList);
-  void addInsertText(const librevenge::RVNGString &text);
   void addCloseSpan();
-  void addCloseParagraph();
-  void addEndTextObject();
+  void addInsertText(const librevenge::RVNGString &text);
   void addStartLayer(const librevenge::RVNGPropertyList &propList);
   void addEndLayer();
   bool empty() const
diff --git a/src/lib/VSDParagraphList.cpp b/src/lib/VSDParagraphList.cpp
index 9a58695..27c66f0 100644
--- a/src/lib/VSDParagraphList.cpp
+++ b/src/lib/VSDParagraphList.cpp
@@ -30,10 +30,14 @@ class VSDParaIX : public VSDParagraphListElement
 {
 public:
   VSDParaIX(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
-            const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
-            const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-            const boost::optional<unsigned> &flags) : VSDParagraphListElement(id, level),
-    m_style(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align, flags) {}
+            const boost::optional<double> &indLeft, const boost::optional<double> &indRight,
+            const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
+            const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+            const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+            const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags) :
+    VSDParagraphListElement(id, level),
+    m_style(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter,
+            align, bullet, bulletStr, textPosAfterBullet, flags) {}
   ~VSDParaIX() {}
   void handle(VSDCollector *collector) const;
   VSDParagraphListElement *clone();
@@ -54,13 +58,15 @@ public:
 void libvisio::VSDParaIX::handle(VSDCollector *collector) const
 {
   collector->collectParaIX(m_id, m_level, m_style.charCount, m_style.indFirst, m_style.indLeft, m_style.indRight,
-                           m_style.spLine, m_style.spBefore, m_style.spAfter, m_style.align, m_style.flags);
+                           m_style.spLine, m_style.spBefore, m_style.spAfter, m_style.align, m_style.bullet,
+                           m_style.bulletStr, m_style.textPosAfterBullet, m_style.flags);
 }
 
 libvisio::VSDParagraphListElement *libvisio::VSDParaIX::clone()
 {
   return new VSDParaIX(m_id, m_level, m_style.charCount, m_style.indFirst, m_style.indLeft, m_style.indRight,
-                       m_style.spLine, m_style.spBefore, m_style.spAfter, m_style.align, m_style.flags);
+                       m_style.spLine, m_style.spBefore, m_style.spAfter, m_style.align, m_style.bullet,
+                       m_style.bulletStr, m_style.textPosAfterBullet, m_style.flags);
 }
 
 
@@ -95,9 +101,11 @@ libvisio::VSDParagraphList::~VSDParagraphList()
 }
 
 void libvisio::VSDParagraphList::addParaIX(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
-                                           const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
-                                           const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-                                           const boost::optional<unsigned> &flags)
+                                           const boost::optional<double> &indLeft, const boost::optional<double> &indRight,
+                                           const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
+                                           const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                                           const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                                           const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags)
 {
   VSDParaIX *tmpElement = dynamic_cast<VSDParaIX *>(m_elements[id]);
   if (!tmpElement)
@@ -110,16 +118,19 @@ void libvisio::VSDParagraphList::addParaIX(unsigned id, unsigned level, unsigned
       m_elements.erase(iter);
     }
 
-    m_elements[id] = new VSDParaIX(id, level, charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align, flags);
+    m_elements[id] = new VSDParaIX(id, level, charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter,
+                                   align, bullet, bulletStr, textPosAfterBullet, flags);
   }
   else
-    tmpElement->m_style.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter, align, flags));
+    tmpElement->m_style.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight, spLine, spBefore, spAfter,
+                                                      align, bullet, bulletStr, textPosAfterBullet, flags));
 }
 
 void libvisio::VSDParagraphList::addParaIX(unsigned id, unsigned level, const VSDOptionalParaStyle &style)
 {
-  addParaIX(id, level, style.charCount, style.indFirst, style.indLeft, style.indRight, style.spLine,
-            style.spBefore, style.spAfter, style.align, style.flags);
+  addParaIX(id, level, style.charCount, style.indFirst, style.indLeft, style.indRight,
+            style.spLine, style.spBefore, style.spAfter, style.align,
+            style.bullet, style.bulletStr, style.textPosAfterBullet, style.flags);
 }
 
 unsigned libvisio::VSDParagraphList::getCharCount(unsigned id) const
diff --git a/src/lib/VSDParagraphList.h b/src/lib/VSDParagraphList.h
index ca11ca5..72ff37f 100644
--- a/src/lib/VSDParagraphList.h
+++ b/src/lib/VSDParagraphList.h
@@ -30,7 +30,8 @@ public:
   void addParaIX(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                  const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                  const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-                 const boost::optional<unsigned> &flags);
+                 const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                 const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags);
   void addParaIX(unsigned id, unsigned level, const VSDOptionalParaStyle &style);
   unsigned getCharCount(unsigned id) const;
   void setCharCount(unsigned id, unsigned charCount);
diff --git a/src/lib/VSDParser.cpp b/src/lib/VSDParser.cpp
index 47e58b4..bdf4abe 100644
--- a/src/lib/VSDParser.cpp
+++ b/src/lib/VSDParser.cpp
@@ -682,7 +682,8 @@ void libvisio::VSDParser::_flushShape()
 
   m_collector->collectDefaultParaStyle(m_shape.m_paraStyle.charCount, m_shape.m_paraStyle.indFirst, m_shape.m_paraStyle.indLeft,
                                        m_shape.m_paraStyle.indRight, m_shape.m_paraStyle.spLine, m_shape.m_paraStyle.spBefore,
-                                       m_shape.m_paraStyle.spAfter, m_shape.m_paraStyle.align, m_shape.m_paraStyle.flags);
+                                       m_shape.m_paraStyle.spAfter, m_shape.m_paraStyle.align, m_shape.m_paraStyle.bullet,
+                                       m_shape.m_paraStyle.bulletStr, m_shape.m_paraStyle.textPosAfterBullet, m_shape.m_paraStyle.flags);
 
   m_shape.m_paraList.handle(m_collector);
 }
@@ -1902,6 +1903,7 @@ void libvisio::VSDParser::readCharIX(librevenge::RVNGInputStream *input)
 
 void libvisio::VSDParser::readParaIX(librevenge::RVNGInputStream *input)
 {
+  long startPosition = input->tell();
   unsigned charCount = readU32(input);
   input->seek(1, librevenge::RVNG_SEEK_CUR);
   double indFirst = readDouble(input);
@@ -1916,12 +1918,43 @@ void libvisio::VSDParser::readParaIX(librevenge::RVNGInputStream *input)
   input->seek(1, librevenge::RVNG_SEEK_CUR);
   double spAfter = readDouble(input);
   unsigned char align = readU8(input);
-  input->seek(26, librevenge::RVNG_SEEK_CUR);
+  unsigned char bullet = readU8(input);
+  input->seek(17, librevenge::RVNG_SEEK_CUR);
+  double textPosAfterBullet = readDouble(input);
   unsigned flags = readU32(input);
+  input->seek(34, librevenge::RVNG_SEEK_CUR);
+  long remainingData = m_header.dataLength - input->tell() + startPosition;
+  unsigned blockLength = 0;
+  VSDName bulletStr;
+
+  while (remainingData >= 4 && (blockLength = readU32(input)))
+  {
+    long blockEnd = blockLength-4 + input->tell();
+    unsigned char blockType = readU8(input);
+    unsigned char blockIdx = readU8(input);
+    if (blockType == 2 && blockIdx == 8)
+    {
+      input->seek(1, librevenge::RVNG_SEEK_CUR);
+      unsigned long numBytes = 2*readU8(input);
+      unsigned long numBytesRead = 0;
+      const unsigned char *tmpBuffer = input->read(numBytes, numBytesRead);
+      if (tmpBuffer && numBytesRead)
+      {
+        librevenge::RVNGBinaryData tmpBulletString(tmpBuffer, numBytesRead);
+        bulletStr = VSDName(tmpBulletString, libvisio::VSD_TEXT_UTF16);
+      }
+    }
+    else if (blockType == 2 && blockIdx == 3)
+    {
+    };
+    input->seek(blockEnd, librevenge::RVNG_SEEK_SET);
+    remainingData -= blockLength;
+  }
+
 
   if (m_isInStyles)
     m_collector->collectParaIXStyle(m_header.id, m_header.level, charCount, indFirst, indLeft, indRight,
-                                    spLine, spBefore, spAfter, align, flags);
+                                    spLine, spBefore, spAfter, align, bullet, bulletStr, textPosAfterBullet, flags);
   else
   {
     if (m_isStencilStarted)
@@ -1930,9 +1963,11 @@ void libvisio::VSDParser::readParaIX(librevenge::RVNGInputStream *input)
     }
 
     m_shape.m_paraStyle.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight,
-                                                      spLine, spBefore, spAfter, align, flags));
-    m_shape.m_paraList.addParaIX(m_header.id, m_header.level, charCount, indFirst, indLeft, indRight,
-                                 spLine, spBefore, spAfter, align, flags);
+                                                      spLine, spBefore, spAfter, align, bullet,
+                                                      bulletStr, textPosAfterBullet, flags));
+    m_shape.m_paraList.addParaIX(m_header.id, m_header.level, charCount, indFirst,
+                                 indLeft, indRight, spLine, spBefore, spAfter, align,
+                                 bullet, bulletStr, textPosAfterBullet, flags);
   }
 }
 
diff --git a/src/lib/VSDStyles.h b/src/lib/VSDStyles.h
index 456577a..a4245ac 100644
--- a/src/lib/VSDStyles.h
+++ b/src/lib/VSDStyles.h
@@ -320,14 +320,18 @@ struct VSDCharStyle
 struct VSDOptionalParaStyle
 {
   VSDOptionalParaStyle() :
-    charCount(0), indFirst(), indLeft(), indRight(), spLine(), spBefore(), spAfter(), align(), flags() {}
+    charCount(0), indFirst(), indLeft(), indRight(), spLine(), spBefore(), spAfter(), align(), bullet(),
+    bulletStr(), textPosAfterBullet(0.0), flags() {}
   VSDOptionalParaStyle(unsigned cc, const boost::optional<double> &ifst, const boost::optional<double> &il,
                        const boost::optional<double> &ir, const boost::optional<double> &sl, const boost::optional<double> &sb,
-                       const boost::optional<double> &sa, const boost::optional<unsigned char> &a, const boost::optional<unsigned> &f) :
-    charCount(cc), indFirst(ifst), indLeft(il), indRight(ir), spLine(sl), spBefore(sb), spAfter(sa), align(a), flags(f) {}
+                       const boost::optional<double> &sa, const boost::optional<unsigned char> &a, const boost::optional<unsigned char> &b,
+                       const boost::optional<VSDName> &bs, const boost::optional<double> &tpab, const boost::optional<unsigned> &f) :
+    charCount(cc), indFirst(ifst), indLeft(il), indRight(ir), spLine(sl), spBefore(sb), spAfter(sa), align(a), bullet(b),
+    bulletStr(bs), textPosAfterBullet(tpab), flags(f) {}
   VSDOptionalParaStyle(const VSDOptionalParaStyle &style) :
     charCount(style.charCount), indFirst(style.indFirst), indLeft(style.indLeft), indRight(style.indRight), spLine(style.spLine),
-    spBefore(style.spBefore), spAfter(style.spAfter), align(style.align), flags(style.flags) {}
+    spBefore(style.spBefore), spAfter(style.spAfter), align(style.align), bullet(style.bullet), bulletStr(style.bulletStr),
+    textPosAfterBullet(style.textPosAfterBullet), flags(style.flags) {}
   ~VSDOptionalParaStyle() {}
   void override(const VSDOptionalParaStyle &style)
   {
@@ -338,6 +342,9 @@ struct VSDOptionalParaStyle
     ASSIGN_OPTIONAL(style.spBefore, spBefore);
     ASSIGN_OPTIONAL(style.spAfter, spAfter);
     ASSIGN_OPTIONAL(style.align, align);
+    ASSIGN_OPTIONAL(style.bullet, bullet);
+    ASSIGN_OPTIONAL(style.bulletStr, bulletStr);
+    ASSIGN_OPTIONAL(style.textPosAfterBullet, textPosAfterBullet);
     ASSIGN_OPTIONAL(style.flags, flags);
   }
 
@@ -349,19 +356,25 @@ struct VSDOptionalParaStyle
   boost::optional<double> spBefore;
   boost::optional<double> spAfter;
   boost::optional<unsigned char> align;
+  boost::optional<unsigned char> bullet;
+  boost::optional<VSDName> bulletStr;
+  boost::optional<double> textPosAfterBullet;
   boost::optional<unsigned> flags;
 };
 
 struct VSDParaStyle
 {
   VSDParaStyle() :
-    charCount(0), indFirst(0.0), indLeft(0.0), indRight(0.0), spLine(-1.2), spBefore(0.0), spAfter(0.0), align(1), flags(0) {}
+    charCount(0), indFirst(0.0), indLeft(0.0), indRight(0.0), spLine(-1.2), spBefore(0.0), spAfter(0.0), align(1),
+    bullet(0), bulletStr(), textPosAfterBullet(0.0), flags(0) {}
   VSDParaStyle(unsigned cc, double ifst, double il, double ir, double sl, double sb,
-               double sa, unsigned char a, unsigned f) :
-    charCount(cc), indFirst(ifst), indLeft(il), indRight(ir), spLine(sl), spBefore(sb), spAfter(sa), align(a), flags(f) {}
+               double sa, unsigned char a, unsigned b, const VSDName &bs, double tpab, unsigned f) :
+    charCount(cc), indFirst(ifst), indLeft(il), indRight(ir), spLine(sl), spBefore(sb), spAfter(sa), align(a),
+    bullet(b), bulletStr(bs), textPosAfterBullet(tpab), flags(f) {}
   VSDParaStyle(const VSDParaStyle &style) :
-    charCount(style.charCount), indFirst(style.indFirst), indLeft(style.indLeft), indRight(style.indRight), spLine(style.spLine),
-    spBefore(style.spBefore), spAfter(style.spAfter), align(style.align), flags(style.flags) {}
+    charCount(style.charCount), indFirst(style.indFirst), indLeft(style.indLeft), indRight(style.indRight),
+    spLine(style.spLine), spBefore(style.spBefore), spAfter(style.spAfter), align(style.align),
+    bullet(style.bullet), bulletStr(style.bulletStr), textPosAfterBullet(style.textPosAfterBullet), flags(style.flags) {}
   ~VSDParaStyle() {}
   void override(const VSDOptionalParaStyle &style)
   {
@@ -372,6 +385,9 @@ struct VSDParaStyle
     ASSIGN_OPTIONAL(style.spBefore, spBefore);
     ASSIGN_OPTIONAL(style.spAfter, spAfter);
     ASSIGN_OPTIONAL(style.align, align);
+    ASSIGN_OPTIONAL(style.bullet, bullet);
+    ASSIGN_OPTIONAL(style.bulletStr, bulletStr);
+    ASSIGN_OPTIONAL(style.textPosAfterBullet, textPosAfterBullet);
     ASSIGN_OPTIONAL(style.flags, flags);
   }
 
@@ -383,6 +399,9 @@ struct VSDParaStyle
   double spBefore;
   double spAfter;
   unsigned char align;
+  unsigned char bullet;
+  VSDName bulletStr;
+  double textPosAfterBullet;
   unsigned flags;
 };
 
diff --git a/src/lib/VSDStylesCollector.cpp b/src/lib/VSDStylesCollector.cpp
index 5df617a..bb7333e 100644
--- a/src/lib/VSDStylesCollector.cpp
+++ b/src/lib/VSDStylesCollector.cpp
@@ -270,17 +270,22 @@ void libvisio::VSDStylesCollector::collectText(unsigned level, const librevenge:
 }
 
 void libvisio::VSDStylesCollector::collectParaIX(unsigned /* id */, unsigned level, unsigned /* charCount */,
-                                                 const boost::optional<double> & /* indFirst */, const boost::optional<double> & /* indLeft */, const boost::optional<double> & /* indRight */,
-                                                 const boost::optional<double> & /* spLine */, const boost::optional<double> & /* spBefore */, const boost::optional<double> & /* spAfter */,
-                                                 const boost::optional<unsigned char> & /* align */, const boost::optional<unsigned> & /* flags */)
+                                                 const boost::optional<double> & /* indFirst */, const boost::optional<double> & /* indLeft */,
+                                                 const boost::optional<double> & /* indRight */, const boost::optional<double> & /* spLine */,
+                                                 const boost::optional<double> & /* spBefore */, const boost::optional<double> & /* spAfter */,
+                                                 const boost::optional<unsigned char> & /* align */, const boost::optional<unsigned char> & /* bullet */,
+                                                 const boost::optional<VSDName> & /* bulletStr */, const boost::optional<double> & /* textPosAfterBullet */,
+                                                 const boost::optional<unsigned> & /* flags */)
 {
   _handleLevelChange(level);
 }
 
 void libvisio::VSDStylesCollector::collectDefaultParaStyle(unsigned /* charCount */, const boost::optional<double> & /* indFirst */,
-                                                           const boost::optional<double> & /* indLeft */, const boost::optional<double> & /* indRight */, const boost::optional<double> & /* spLine */,
-                                                           const boost::optional<double> & /* spBefore */, const boost::optional<double> & /* spAfter */,
-                                                           const boost::optional<unsigned char> & /* align */, const boost::optional<unsigned> & /* flags */)
+                                                           const boost::optional<double> & /* indLeft */, const boost::optional<double> & /* indRight */,
+                                                           const boost::optional<double> & /* spLine */, const boost::optional<double> & /* spBefore */,
+                                                           const boost::optional<double> & /* spAfter */, const boost::optional<unsigned char> & /* align */,
+                                                           const boost::optional<unsigned char> & /* bullet */, const boost::optional<VSDName> & /* bulletStr */,
+                                                           const boost::optional<double> & /* textPosAfterBullet */, const boost::optional<unsigned> & /* flags */)
 {
 }
 
@@ -373,7 +378,8 @@ void libvisio::VSDStylesCollector::collectParaIXStyle(unsigned /* id */, unsigne
                                                       const boost::optional<double> & /* indLeft */, const boost::optional<double> & /* indRight */,
                                                       const boost::optional<double> & /* spLine */, const boost::optional<double> & /* spBefore */,
                                                       const boost::optional<double> & /* spAfter */, const boost::optional<unsigned char> & /* align */,
-                                                      const boost::optional<unsigned> & /* flags */)
+                                                      const boost::optional<unsigned char> & /* bullet */, const boost::optional<VSDName> & /* bulletStr */,
+                                                      const boost::optional<double> & /* textPosAfterBullet */, const boost::optional<unsigned> & /* flags */)
 {
   _handleLevelChange(level);
 }
diff --git a/src/lib/VSDStylesCollector.h b/src/lib/VSDStylesCollector.h
index 7457e2a..1e8048a 100644
--- a/src/lib/VSDStylesCollector.h
+++ b/src/lib/VSDStylesCollector.h
@@ -99,10 +99,13 @@ public:
   void collectParaIX(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                      const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                      const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                     const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr, const boost::optional<double> &textPosAfterBullet,
                      const boost::optional<unsigned> &flags);
   void collectDefaultParaStyle(unsigned charCount, const boost::optional<double> &indFirst, const boost::optional<double> &indLeft,
                                const boost::optional<double> &indRight, const boost::optional<double> &spLine, const boost::optional<double> &spBefore,
-                               const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align, const boost::optional<unsigned> &flags);
+                               const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
+                               const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                               const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags);
   void collectTextBlock(unsigned level, const boost::optional<double> &leftMargin, const boost::optional<double> &rightMargin,
                         const boost::optional<double> &topMargin, const boost::optional<double> &bottomMargin,
                         const boost::optional<unsigned char> &verticalAlign, const boost::optional<bool> &isBgFilled,
@@ -141,7 +144,8 @@ public:
   void collectParaIXStyle(unsigned id, unsigned level, unsigned charCount, const boost::optional<double> &indFirst,
                           const boost::optional<double> &indLeft, const boost::optional<double> &indRight, const boost::optional<double> &spLine,
                           const boost::optional<double> &spBefore, const boost::optional<double> &spAfter, const boost::optional<unsigned char> &align,
-                          const boost::optional<unsigned> &flags);
+                          const boost::optional<unsigned char> &bullet, const boost::optional<VSDName> &bulletStr,
+                          const boost::optional<double> &textPosAfterBullet, const boost::optional<unsigned> &flags);
   void collectTextBlockStyle(unsigned level, const boost::optional<double> &leftMargin, const boost::optional<double> &rightMargin,
                              const boost::optional<double> &topMargin, const boost::optional<double> &bottomMargin,
                              const boost::optional<unsigned char> &verticalAlign, const boost::optional<bool> &isBgFilled,
diff --git a/src/lib/VSDTypes.h b/src/lib/VSDTypes.h
index 3a4fce4..ef74271 100644
--- a/src/lib/VSDTypes.h
+++ b/src/lib/VSDTypes.h
@@ -230,6 +230,29 @@ struct VSDTabSet
     m_numChars(tabSet.m_numChars), m_tabStops(tabSet.m_tabStops) {}
 };
 
+struct VSDBullet
+{
+  librevenge::RVNGString m_bulletStr;
+  double m_textPosAfterBullet;
+  VSDBullet() : m_bulletStr(), m_textPosAfterBullet(0.0) {}
+  VSDBullet(const VSDBullet &bullet) :
+    m_bulletStr(bullet.m_bulletStr),
+    m_textPosAfterBullet(bullet.m_textPosAfterBullet) {}
+  inline bool operator==(const VSDBullet &bullet) const
+  {
+    return ((m_bulletStr == bullet.m_bulletStr) &&
+            (m_textPosAfterBullet == bullet.m_textPosAfterBullet));
+  }
+  inline bool operator!=(const VSDBullet &bullet) const
+  {
+    return !operator==(bullet);
+  }
+  inline bool operator!() const
+  {
+    return (m_bulletStr.empty() && m_textPosAfterBullet == 0.0);
+  }
+};
+
 } // namespace libvisio
 
 #endif /* VSDTYPES_H */
diff --git a/src/lib/VSDXMLParserBase.cpp b/src/lib/VSDXMLParserBase.cpp
index a8a7b68..ad7300d 100644
--- a/src/lib/VSDXMLParserBase.cpp
+++ b/src/lib/VSDXMLParserBase.cpp
@@ -1417,6 +1417,9 @@ void libvisio::VSDXMLParserBase::readParaIX(xmlTextReaderPtr reader)
   boost::optional<double> spBefore;
   boost::optional<double> spAfter;
   boost::optional<unsigned char> align;
+  boost::optional<unsigned char> bullet;
+  boost::optional<VSDName> bulletStr;
+  boost::optional<double> textPosAfterBullet;
   boost::optional<unsigned> flags;
 
   do
@@ -1463,6 +1466,24 @@ void libvisio::VSDXMLParserBase::readParaIX(xmlTextReaderPtr reader)
       if (XML_READER_TYPE_ELEMENT == tokenType)
         readUnsignedData(flags, reader);
       break;
+    case XML_BULLET:
+      if (XML_READER_TYPE_ELEMENT == tokenType)
+        readByteData(bullet, reader);
+      break;
+    case XML_BULLETSTR:
+      if (XML_READER_TYPE_ELEMENT == tokenType)
+      {
+        const shared_ptr<xmlChar> stringValue(readStringData(reader), xmlFree);
+        if (stringValue && !xmlStrEqual(stringValue.get(), BAD_CAST("Themed")))
+        {
+          bulletStr = VSDName(librevenge::RVNGBinaryData(stringValue.get(), xmlStrlen(stringValue.get())), VSD_TEXT_UTF8);
+        }
+      }
+      break;
+    case XML_TEXTPOSAFTERBULLET:
+      if (XML_READER_TYPE_ELEMENT == tokenType)
+        readDoubleData(textPosAfterBullet, reader);
+      break;
     default:
       break;
     }
@@ -1471,15 +1492,18 @@ void libvisio::VSDXMLParserBase::readParaIX(xmlTextReaderPtr reader)
 
   if (m_isInStyles)
     m_collector->collectParaIXStyle(ix, level, charCount, indFirst, indLeft, indRight,
-                                    spLine, spBefore, spAfter, align, flags);
+                                    spLine, spBefore, spAfter, align, bullet, bulletStr,
+                                    textPosAfterBullet, flags);
   else
   {
     if (!ix || m_shape.m_paraList.empty()) // paragraph style 0 is the default paragraph style
       m_shape.m_paraStyle.override(VSDOptionalParaStyle(charCount, indFirst, indLeft, indRight,
-                                                        spLine, spBefore, spAfter, align, flags));
+                                                        spLine, spBefore, spAfter, align, bullet,
+                                                        bulletStr, textPosAfterBullet, flags));
 
     m_shape.m_paraList.addParaIX(ix, level, charCount, indFirst, indLeft, indRight,
-                                 spLine, spBefore, spAfter, align, flags);
+                                 spLine, spBefore, spAfter, align, bullet, bulletStr,
+                                 textPosAfterBullet, flags);
   }
 }
 
@@ -1764,7 +1788,8 @@ void libvisio::VSDXMLParserBase::_flushShape()
 
   m_collector->collectDefaultParaStyle(m_shape.m_paraStyle.charCount, m_shape.m_paraStyle.indFirst, m_shape.m_paraStyle.indLeft,
                                        m_shape.m_paraStyle.indRight, m_shape.m_paraStyle.spLine, m_shape.m_paraStyle.spBefore,
-                                       m_shape.m_paraStyle.spAfter, m_shape.m_paraStyle.align, m_shape.m_paraStyle.flags);
+                                       m_shape.m_paraStyle.spAfter, m_shape.m_paraStyle.align, m_shape.m_paraStyle.bullet,
+                                       m_shape.m_paraStyle.bulletStr, m_shape.m_paraStyle.textPosAfterBullet, m_shape.m_paraStyle.flags);
 
   m_shape.m_paraList.handle(m_collector);
 
diff --git a/src/lib/tokens.txt b/src/lib/tokens.txt
index 590944a..caeb9eb 100644
--- a/src/lib/tokens.txt
+++ b/src/lib/tokens.txt
@@ -56,6 +56,8 @@ BeginArrow
 BeginX
 BeginY
 BottomMargin
+Bullet
+BulletStr
 C
 Case
 Cell
@@ -205,6 +207,7 @@ TextBkgnd
 TextBkgndTrans
 TextBlock
 TextDirection
+TextPosAfterBullet
 TextXForm
 TopMargin
 tp


More information about the Libreoffice-commits mailing list