[libmwaw] 01/01: New upstream version 0.3.10

Rene Engelhard rene at moszumanska.debian.org
Tue Jan 31 20:23:33 UTC 2017


This is an automated email from the git hooks/post-receive script.

rene pushed a commit to branch upstream
in repository libmwaw.

commit d1c23e57de361ede309d847a06f8f028fd0d6d20
Author: Rene Engelhard <rene at rene-engelhard.de>
Date:   Tue Jan 31 21:14:59 2017 +0100

    New upstream version 0.3.10
---
 CHANGES                             |   5 +
 build/win32/libmwaw.dsp             |   8 +
 build/win32/libmwaw.vcproj          |   8 +
 build/win32/libmwaw.vcxproj         |   5 +
 configure                           |  26 +-
 configure.ac                        |   2 +-
 inc/libmwaw/MWAWDocument.hxx        |   2 +-
 libmwaw.spec                        |   4 +-
 src/lib/MWAWFontConverter.cxx       |   2 +
 src/lib/MWAWHeader.cxx              |   2 +
 src/lib/MWAWOLEParser.cxx           | 479 +++++++++++++++++-----
 src/lib/MWAWOLEParser.hxx           |  58 +--
 src/lib/MWAWSpreadsheetListener.cxx |   6 +-
 src/lib/Makefile.am                 |   2 +
 src/lib/Makefile.in                 |  22 +-
 src/lib/MsWksDBParser.cxx           |   2 +-
 src/lib/MsWksDocument.cxx           |   2 +-
 src/lib/MsWksSSParser.cxx           |   2 +-
 src/lib/PowerPoint1Parser.cxx       | 767 +++++++++++++++++++++++++++++-------
 src/lib/PowerPoint1Parser.hxx       |   6 +
 src/lib/PowerPoint3OLE.cxx          | 228 +++++++++++
 src/lib/PowerPoint3OLE.hxx          |  91 +++++
 src/lib/PowerPoint3Parser.cxx       | 275 +++++++++----
 src/lib/PowerPoint3Parser.hxx       |   6 +-
 src/lib/README                      |   5 +-
 src/lib/ZWrtParser.cxx              |   2 +-
 26 files changed, 1634 insertions(+), 383 deletions(-)

diff --git a/CHANGES b/CHANGES
index 40ebd74..c00d818 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,10 @@
 CHANGES:
 
+1/23/2017:
+- add some parsers to read Mac PowerPoint v4 files and Windows PowerPoint v2,v4 files
+
+-------- version 0.3.10 (start)  -------------
+
 11/16/2016
 - add some parsers to read Mac PowerPoint v1-v3 files and Windows PowerPoint v3 files
 
diff --git a/build/win32/libmwaw.dsp b/build/win32/libmwaw.dsp
index 76555fc..957923d 100644
--- a/build/win32/libmwaw.dsp
+++ b/build/win32/libmwaw.dsp
@@ -619,6 +619,10 @@ SOURCE=..\..\src\lib\PowerPoint1Parser.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=..\..\src\lib\PowerPoint3OLE.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\src\lib\PowerPoint3Parser.cxx
 # End Source File
 # Begin Source File
@@ -1259,6 +1263,10 @@ SOURCE=..\..\src\lib\PowerPoint1Parser.hxx
 # End Source File
 # Begin Source File
 
+SOURCE=..\..\src\lib\PowerPoint3OLE.hxx
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\src\lib\PowerPoint3Parser.hxx
 # End Source File
 # Begin Source File
diff --git a/build/win32/libmwaw.vcproj b/build/win32/libmwaw.vcproj
index 9c461dd..d9edb76 100644
--- a/build/win32/libmwaw.vcproj
+++ b/build/win32/libmwaw.vcproj
@@ -704,6 +704,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\lib\PowerPoint3OLE.cxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\lib\PowerPoint3Parser.cxx"
 				>
 			</File>
@@ -1345,6 +1349,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\lib\PowerPoint3OLE.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\lib\PowerPoint3Parser.hxx"
 				>
 			</File>
diff --git a/build/win32/libmwaw.vcxproj b/build/win32/libmwaw.vcxproj
index f924662..f0057f5 100644
--- a/build/win32/libmwaw.vcxproj
+++ b/build/win32/libmwaw.vcxproj
@@ -630,6 +630,10 @@
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
+    <ClCompile Include="..\..\src\lib\PowerPoint3OLE.cxx">
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
     <ClCompile Include="..\..\src\lib\PowerPoint3Parser.cxx">
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -869,6 +873,7 @@
     <ClInclude Include="..\..\src\lib\NisusWrtText.hxx" />
     <ClInclude Include="..\..\src\lib\PixelPaintParser.hxx" />
     <ClInclude Include="..\..\src\lib\PowerPoint1Parser.hxx" />
+    <ClInclude Include="..\..\src\lib\PowerPoint3OLE.hxx" />
     <ClInclude Include="..\..\src\lib\PowerPoint3Parser.hxx" />
     <ClInclude Include="..\..\src\lib\RagTimeParser.hxx" />
     <ClInclude Include="..\..\src\lib\RagTimeSpreadsheet.hxx" />
diff --git a/configure b/configure
index 208f7e3..6f35e2e 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libmwaw 0.3.9.
+# Generated by GNU Autoconf 2.69 for libmwaw 0.3.10.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='libmwaw'
 PACKAGE_TARNAME='libmwaw'
-PACKAGE_VERSION='0.3.9'
-PACKAGE_STRING='libmwaw 0.3.9'
+PACKAGE_VERSION='0.3.10'
+PACKAGE_STRING='libmwaw 0.3.10'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1388,7 +1388,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libmwaw 0.3.9 to adapt to many kinds of systems.
+\`configure' configures libmwaw 0.3.10 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1458,7 +1458,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libmwaw 0.3.9:";;
+     short | recursive ) echo "Configuration of libmwaw 0.3.10:";;
    esac
   cat <<\_ACEOF
 
@@ -1604,7 +1604,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libmwaw configure 0.3.9
+libmwaw configure 0.3.10
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2193,7 +2193,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libmwaw $as_me 0.3.9, which was
+It was created by libmwaw $as_me 0.3.10, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3059,7 +3059,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='libmwaw'
- VERSION='0.3.9'
+ VERSION='0.3.10'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -17653,9 +17653,9 @@ MWAW_MAJOR_VERSION=0
 
 MWAW_MINOR_VERSION=3
 
-MWAW_MICRO_VERSION=9
+MWAW_MICRO_VERSION=10
 
-MWAW_VERSION=0.3.9
+MWAW_VERSION=0.3.10
 
 # AC_SUBST(LT_RELEASE, [libmwaw_version_major.libmwaw_version_minor])
 LT_CURRENT=`expr 100 '*' 0 + 3`
@@ -17663,7 +17663,7 @@ LT_CURRENT=`expr 100 '*' 0 + 3`
 LT_AGE=0
 # LT_AGE=libmwaw_version_minor
 
-LT_REVISION=9
+LT_REVISION=10
 
 
 
@@ -19554,7 +19554,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libmwaw $as_me 0.3.9, which was
+This file was extended by libmwaw $as_me 0.3.10, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -19620,7 +19620,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-libmwaw config.status 0.3.9
+libmwaw config.status 0.3.10
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index e55a8ff..ee23c24 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ AC_PREREQ([2.60])
 # ====================
 m4_define([libmwaw_version_major],[0])
 m4_define([libmwaw_version_minor],[3])
-m4_define([libmwaw_version_micro],[9])
+m4_define([libmwaw_version_micro],[10])
 m4_define([libmwaw_version],[libmwaw_version_major.libmwaw_version_minor.libmwaw_version_micro])
 
 # =============
diff --git a/inc/libmwaw/MWAWDocument.hxx b/inc/libmwaw/MWAWDocument.hxx
index b6b7bd9..7b311a8 100644
--- a/inc/libmwaw/MWAWDocument.hxx
+++ b/inc/libmwaw/MWAWDocument.hxx
@@ -190,7 +190,7 @@ public:
     /** MouseWrite: v1
      \note same enum as \a MWAW_T_RESERVED7*/
     MWAW_T_MOUSEWRITE=MWAW_T_RESERVED7,
-    /** PowerPoint: v1-v3 and pc v3
+    /** PowerPoint: v1-v4 and pc v2-v4
      \note same enum as \a MWAW_T_RESERVED8*/
     MWAW_T_POWERPOINT=MWAW_T_RESERVED8
 
diff --git a/libmwaw.spec b/libmwaw.spec
index 6a47989..100239a 100644
--- a/libmwaw.spec
+++ b/libmwaw.spec
@@ -1,5 +1,5 @@
 %define name libmwaw
-%define version 0.3.9
+%define version 0.3.10
 %define  RELEASE 1
 %define  release     %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
 
@@ -90,7 +90,7 @@ umask 022
 
 %if %{!?_without_docs:1}%{?_without_docs:0}
 %files docs
-%{_datadir}/doc/libmwaw-0.3.9/*
+%{_datadir}/doc/libmwaw-0.3.10/*
 %endif
 
 %changelog
diff --git a/src/lib/MWAWFontConverter.cxx b/src/lib/MWAWFontConverter.cxx
index 94ac0f7..613feaf 100644
--- a/src/lib/MWAWFontConverter.cxx
+++ b/src/lib/MWAWFontConverter.cxx
@@ -617,6 +617,8 @@ void KnownConversion::initMaps()
     m_cursiveMap[c] = m_mathMap[c] = m_scientificMap[c] = unicode;
     m_unknown107Map[c] = m_unknown128Map[c] = m_unknown200Map[c] = unicode;
   }
+  for (unsigned long c=0x20; c<=0xff; ++c)
+    m_windowsCP1252Map[static_cast<unsigned char>(c)]= c;
   initAMap(s_centralEuroUnicode, sizeof(s_centralEuroUnicode)/(2*sizeof(int)), m_centralEuroMap);
   initAMap(s_cyrillicUnicode, sizeof(s_cyrillicUnicode)/(2*sizeof(int)), m_cyrillicMap);
   initAMap(s_turkishUnicode, sizeof(s_turkishUnicode)/(2*sizeof(int)), m_turkishMap);
diff --git a/src/lib/MWAWHeader.cxx b/src/lib/MWAWHeader.cxx
index 0b79013..8c419f3 100644
--- a/src/lib/MWAWHeader.cxx
+++ b/src/lib/MWAWHeader.cxx
@@ -770,6 +770,8 @@ std::vector<MWAWHeader> MWAWHeader::constructHeader
         break;
       }
     }
+    if (!mainOle && input->getSubStreamByName("PP40"))
+      res.push_back(MWAWHeader(MWAWDocument::MWAW_T_POWERPOINT, 4, MWAWDocument::MWAW_K_PRESENTATION));
   }
 
   if ((val[0]==0xfe32 && val[1]==0) || (val[0]==0xfe34 && val[1]==0) ||
diff --git a/src/lib/MWAWOLEParser.cxx b/src/lib/MWAWOLEParser.cxx
index e83cfe1..e9b3141 100644
--- a/src/lib/MWAWOLEParser.cxx
+++ b/src/lib/MWAWOLEParser.cxx
@@ -31,49 +31,6 @@
 * instead of those above.
 */
 
-/*
- *  freely inspired from istorage :
- * ------------------------------------------------------------
- *      Generic OLE Zones furnished with a copy of the file header
- *
- * Compound Storage (32 bit version)
- * Storage implementation
- *
- * This file contains the compound file implementation
- * of the storage interface.
- *
- * Copyright 1999 Francis Beaudet
- * Copyright 1999 Sylvain St-Germain
- * Copyright 1999 Thuy Nguyen
- * Copyright 2005 Mike McCormack
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
- * NOTES
- *  The compound file implementation of IStorage used for create
- *  and manage substorages and streams within a storage object
- *  residing in a compound file object.
- *
- * MSDN
- *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/istorage_compound_file_implementation.asp
- * ------------------------------------------------------------
- */
-
 #include <cstdlib>
 #include <cstring>
 #include <iostream>
@@ -83,6 +40,7 @@
 
 #include <librevenge/librevenge.h>
 
+#include "MWAWFontConverter.hxx"
 #include "MWAWPosition.hxx"
 #include "MWAWOLEParser.hxx"
 #include "MWAWPictMac.hxx"
@@ -228,16 +186,45 @@ protected:
 
 /** Internal: internal method to keep ole definition */
 struct OleDef {
-  OleDef() : m_id(-1), m_subId(-1), m_dir(""), m_name("") { }
+  OleDef() : m_id(-1), m_subId(-1), m_dir(""), m_base(""), m_name("") { }
   int m_id /**main id*/, m_subId /**subsversion id */ ;
-  std::string m_dir/**the directory*/, m_name/**the base name*/;
+  std::string m_dir/**the directory*/, m_base/**the base*/, m_name/**the complete name*/;
+};
+
+/** Internal: internal state of a MWAWOLEParser */
+struct State {
+  /** constructor */
+  State(MWAWFontConverterPtr fontConverter, int fId)
+    : m_fontConverter(fontConverter), m_fontId(fId), m_metaData(), m_unknownOLEs(),
+      m_objects(), m_objectsPosition(), m_objectsId(), m_objectsType(), m_compObjIdName()
+  {
+  }
+  //! the font converter
+  MWAWFontConverterPtr m_fontConverter;
+  //! the font id used to decode string
+  int m_fontId;
+  //! the meta data
+  librevenge::RVNGPropertyList m_metaData;
+  //! list of ole which can not be parsed
+  std::vector<std::string> m_unknownOLEs;
+
+  //! list of pictures read
+  std::vector<librevenge::RVNGBinaryData> m_objects;
+  //! list of picture size ( if known)
+  std::vector<MWAWPosition> m_objectsPosition;
+  //! list of pictures id
+  std::vector<int> m_objectsId;
+  //! list of picture type
+  std::vector<std::string> m_objectsType;
+
+  //! a smart ptr used to stored the list of compobj id->name
+  shared_ptr<MWAWOLEParserInternal::CompObj> m_compObjIdName;
 };
 }
 
 // constructor/destructor
-MWAWOLEParser::MWAWOLEParser(std::string mainName)
-  : m_avoidOLE(mainName), m_unknownOLEs(),
-    m_objects(), m_objectsPosition(), m_objectsId(), m_objectsType(), m_compObjIdName()
+MWAWOLEParser::MWAWOLEParser(std::string mainName, MWAWFontConverterPtr fontConverter, int fId)
+  : m_avoidOLE(mainName), m_state(new MWAWOLEParserInternal::State(fontConverter, fId))
 {
 }
 
@@ -245,13 +232,47 @@ MWAWOLEParser::~MWAWOLEParser()
 {
 }
 
+void MWAWOLEParser::updateMetaData(librevenge::RVNGPropertyList &metaData) const
+{
+  librevenge::RVNGPropertyList::Iter i(m_state->m_metaData);
+  for (i.rewind(); i.next();) {
+    if (!metaData[i.key()])
+      metaData.insert(i.key(),i()->clone());
+  }
+}
+
+std::vector<std::string> const &MWAWOLEParser::getNotParse() const
+{
+  return m_state->m_unknownOLEs;
+}
+
+std::vector<int> const &MWAWOLEParser::getObjectsId() const
+{
+  return m_state->m_objectsId;
+}
+
+std::vector<MWAWPosition> const &MWAWOLEParser::getObjectsPosition() const
+{
+  return m_state->m_objectsPosition;
+}
+
+std::vector<librevenge::RVNGBinaryData> const &MWAWOLEParser::getObjects() const
+{
+  return m_state->m_objects;
+}
+
+std::vector<std::string> const &MWAWOLEParser::getObjectsType() const
+{
+  return m_state->m_objectsType;
+}
+
 bool MWAWOLEParser::getObject(int id, librevenge::RVNGBinaryData &obj, MWAWPosition &pos, std::string &type)  const
 {
-  for (size_t i = 0; i < m_objectsId.size(); i++) {
-    if (m_objectsId[i] != id) continue;
-    obj = m_objects[i];
-    pos = m_objectsPosition[i];
-    type = m_objectsType[i];
+  for (size_t i = 0; i < m_state->m_objectsId.size(); i++) {
+    if (m_state->m_objectsId[i] != id) continue;
+    obj = m_state->m_objects[i];
+    pos = m_state->m_objectsPosition[i];
+    type = m_state->m_objectsType[i];
     return true;
   }
   obj.clear();
@@ -261,29 +282,29 @@ bool MWAWOLEParser::getObject(int id, librevenge::RVNGBinaryData &obj, MWAWPosit
 void MWAWOLEParser::setObject(int id, librevenge::RVNGBinaryData const &obj, MWAWPosition const &pos,
                               std::string const &type)
 {
-  for (size_t i = 0; i < m_objectsId.size(); i++) {
-    if (m_objectsId[i] != id) continue;
-    m_objects[i] = obj;
-    m_objectsPosition[i] = pos;
-    m_objectsType[i] = type;
+  for (size_t i = 0; i < m_state->m_objectsId.size(); i++) {
+    if (m_state->m_objectsId[i] != id) continue;
+    m_state->m_objects[i] = obj;
+    m_state->m_objectsPosition[i] = pos;
+    m_state->m_objectsType[i] = type;
     return;
   }
-  m_objects.push_back(obj);
-  m_objectsPosition.push_back(pos);
-  m_objectsId.push_back(id);
-  m_objectsType.push_back(type);
+  m_state->m_objects.push_back(obj);
+  m_state->m_objectsPosition.push_back(pos);
+  m_state->m_objectsId.push_back(id);
+  m_state->m_objectsType.push_back(type);
 }
 
 // parsing
 bool MWAWOLEParser::parse(MWAWInputStreamPtr file)
 {
-  if (!m_compObjIdName)
-    m_compObjIdName.reset(new MWAWOLEParserInternal::CompObj);
+  if (!m_state->m_compObjIdName)
+    m_state->m_compObjIdName.reset(new MWAWOLEParserInternal::CompObj);
 
-  m_unknownOLEs.resize(0);
-  m_objects.resize(0);
-  m_objectsId.resize(0);
-  m_objectsType.resize(0);
+  m_state->m_unknownOLEs.resize(0);
+  m_state->m_objects.resize(0);
+  m_state->m_objectsId.resize(0);
+  m_state->m_objectsType.resize(0);
 
   if (!file.get()) return false;
 
@@ -319,7 +340,8 @@ bool MWAWOLEParser::parse(MWAWInputStreamPtr file)
 #endif
     MWAWOLEParserInternal::OleDef data;
     data.m_name = name;
-    data.m_dir = base;
+    data.m_dir = dir;
+    data.m_base = base;
 
     // try to retrieve the identificator stored in the directory
     //  MatOST/MatadorObject1/ -> 1, -1
@@ -379,32 +401,34 @@ bool MWAWOLEParser::parse(MWAWInputStreamPtr file)
       bool ok = true;
       MWAWPosition pictPos;
 
-      if (strncmp("Ole", dOle.m_dir.c_str(), 3) == 0 ||
-          strncmp("CompObj", dOle.m_dir.c_str(), 7) == 0)
+      if (strncmp("Ole", dOle.m_base.c_str(), 3) == 0 ||
+          strncmp("CompObj", dOle.m_base.c_str(), 7) == 0)
         ole->setReadInverted(true);
 
       try {
-        if (readMM(ole, dOle.m_dir, asciiFile));
-        else if (readObjInfo(ole, dOle.m_dir, asciiFile));
-        else if (readOle(ole, dOle.m_dir, asciiFile));
-        else if (isOlePres(ole, dOle.m_dir) &&
+        librevenge::RVNGPropertyList pList;
+        if (readMM(ole, dOle.m_base, asciiFile));
+        else if (readSummaryInformation(ole, dOle.m_base, dOle.m_dir.empty() ? m_state->m_metaData : pList, asciiFile));
+        else if (readObjInfo(ole, dOle.m_base, asciiFile));
+        else if (readOle(ole, dOle.m_base, asciiFile));
+        else if (isOlePres(ole, dOle.m_base) &&
                  readOlePres(ole, data, pictPos, asciiFile)) {
           hasData = true;
           newConfidence = 2;
         }
-        else if (isOle10Native(ole, dOle.m_dir) &&
+        else if (isOle10Native(ole, dOle.m_base) &&
                  readOle10Native(ole, data, asciiFile)) {
           hasData = true;
           // small size can be a symptom that this is a link to a
           // basic msworks data file, so we reduce confidence
           newConfidence = data.size() > 1000 ? 4 : 2;
         }
-        else if (readCompObj(ole, dOle.m_dir, asciiFile));
-        else if (readContents(ole, dOle.m_dir, data, pictPos, asciiFile)) {
+        else if (readCompObj(ole, dOle.m_base, asciiFile));
+        else if (readContents(ole, dOle.m_base, data, pictPos, asciiFile)) {
           hasData = true;
           newConfidence = 3;
         }
-        else if (readCONTENTS(ole, dOle.m_dir, data, pictPos, asciiFile)) {
+        else if (readCONTENTS(ole, dOle.m_base, data, pictPos, asciiFile)) {
           hasData = true;
           newConfidence = 3;
         }
@@ -415,7 +439,7 @@ bool MWAWOLEParser::parse(MWAWInputStreamPtr file)
         ok = false;
       }
       if (!ok) {
-        m_unknownOLEs.push_back(dOle.m_name);
+        m_state->m_unknownOLEs.push_back(dOle.m_name);
         asciiFile.reset();
         continue;
       }
@@ -460,18 +484,18 @@ bool MWAWOLEParser::parse(MWAWInputStreamPtr file)
     }
 
     if (pict.size()) {
-      m_objects.push_back(pict);
+      m_state->m_objects.push_back(pict);
       if (actualPos.naturalSize().x() <= 0 || actualPos.naturalSize().y() <= 0) {
         MWAWVec2f size = potentialSize.naturalSize();
         if (size.x() > 0 && size.y() > 0)
           actualPos.setNaturalSize(actualPos.getInvUnitScale(potentialSize.unit())*size);
       }
-      m_objectsPosition.push_back(actualPos);
-      m_objectsId.push_back(id);
+      m_state->m_objectsPosition.push_back(actualPos);
+      m_state->m_objectsId.push_back(id);
       if (isPict)
-        m_objectsType.push_back("image/pict");
+        m_state->m_objectsType.push_back("image/pict");
       else
-        m_objectsType.push_back("object/ole");
+        m_state->m_objectsType.push_back("object/ole");
     }
   }
 
@@ -626,7 +650,7 @@ bool MWAWOLEParser::readCompObj(MWAWInputStreamPtr ip, std::string const &oleNam
   f << "@@CompObj(CLSID):";
   if (clsData[1] == 0 && clsData[2] == 0xC0 && clsData[3] == 0x46000000L) {
     // normally, a referenced object
-    char const *clsName = m_compObjIdName->getCLSName(clsData[0]);
+    char const *clsName = m_state->m_compObjIdName->getCLSName(clsData[0]);
     if (clsName)
       f << "'" << clsName << "'";
     else {
@@ -691,8 +715,13 @@ bool MWAWOLEParser::readCompObj(MWAWInputStreamPtr ip, std::string const &oleNam
   long nbElt = 4;
   if (ip->seek(actPos+16,librevenge::RVNG_SEEK_SET) != 0 ||
       ip->tell() != actPos+16) {
-    if ((ip->tell()-actPos)%4)
-      return false;
+    if ((ip->tell()-actPos)%4) {
+      f.str("");
+      f << "@@CompObj(Footer):###";
+      ascii.addPos(actPos);
+      ascii.addNote(f.str().c_str());
+      return true;
+    }
     nbElt = (ip->tell()-actPos)/4;
   }
 
@@ -710,6 +739,280 @@ bool MWAWOLEParser::readCompObj(MWAWInputStreamPtr ip, std::string const &oleNam
 }
 
 //////////////////////////////////////////////////
+// summary and doc summary
+//////////////////////////////////////////////////
+bool MWAWOLEParser::readSummaryInformation(MWAWInputStreamPtr input, std::string const &oleName, librevenge::RVNGPropertyList &pList,
+    libmwaw::DebugFile &ascii) const
+{
+  if (oleName!="SummaryInformation" && oleName!="DocumentSummaryInformation") return false;
+  input->seek(0, librevenge::RVNG_SEEK_SET);
+  libmwaw::DebugStream f;
+  f << "Entries(SumInfo):";
+  bool isDoc=oleName=="DocumentSummaryInformation";
+  if (isDoc) f << "doc,";
+  int val=int(input->readULong(2));
+  if (val==0xfeff) {
+    input->setReadInverted(false);
+    val=0xfffe;
+  }
+  if (input->size()<48 || val!=0xfffe) {
+    MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryInformation: header seems bad\n"));
+    f << "###";
+    ascii.addPos(0);
+    ascii.addNote(f.str().c_str());
+    return true;
+  }
+  for (int i=0; i<11; ++i) { // f1=1, f2=0-2
+    val=int(input->readULong(2));
+    if (val) f << "f" << i << "=" << val << ",";
+  }
+  val=int(input->readULong(4));
+  if (val==0x1000000) {
+    val=1;
+    input->setReadInverted(!input->readInverted());
+  }
+  if (val!=1) {
+    MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryInformation: summary info is bad\n"));
+    f << "###sumInfo=" << val << ",";
+    ascii.addPos(0);
+    ascii.addNote(f.str().c_str());
+    return true;
+  }
+  for (int i=0; i<4; ++i) {
+    val=int(input->readULong(4));
+    static int const expected[]= {int(0xf29f85e0),0x10684ff9,0x891ab,int(0xd9b3272b)};
+    static int const docExpected[]= {int(0xd5cdd502),0x101b2e9c,0x89793,int(0xaef92c2b)};
+    if ((!isDoc && val==expected[i]) || (isDoc && val==docExpected[i])) continue;
+    f << "#fmid" << i << "=" << std::hex << val << std::dec << ",";
+    static bool first=true;
+    if (first) {
+      MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryInformation: fmid is bad\n"));
+      first=false;
+    }
+  }
+  int decal=int(input->readULong(4));
+  if (decal<0x30 || input->size()<decal) {
+    MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryInformation: decal is bad\n"));
+    f << "decal=" << val << ",";
+    ascii.addPos(0);
+    ascii.addNote(f.str().c_str());
+    return true;
+
+  }
+  ascii.addPos(0);
+  ascii.addNote(f.str().c_str());
+  if (decal!=0x30) {
+    ascii.addPos(0x30);
+    ascii.addNote("_");
+    input->seek(decal, librevenge::RVNG_SEEK_SET);
+  }
+
+  long pos=input->tell();
+  f.str("");
+  f << "SumInfo-A:";
+  long pSetSize=long(input->readULong(4));
+  int N=int(input->readULong(4));
+  f << "N=" << N << ",";
+  if (pSetSize<0 || input->size()-pos<pSetSize || (pSetSize-8)/8<N) {
+    MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryInformation: psetstruct is bad\n"));
+    f << "###";
+    ascii.addPos(pos);
+    ascii.addNote(f.str().c_str());
+    return true;
+  }
+  f << "[";
+  std::map<long,int> posToTypeMap;
+  for (int i=0; i<N; ++i) {
+    int type=int(input->readULong(4));
+    int depl=int(input->readULong(4));
+    if (depl==0) continue;
+    f << std::hex << depl << std::dec << ":" << type << ",";
+    if (depl<8+8*N || depl+4>pSetSize || posToTypeMap.find(pos+depl)!=posToTypeMap.end()) {
+      f << "###";
+      continue;
+    }
+    posToTypeMap[pos+depl]=type;
+  }
+  f << "],";
+  ascii.addPos(pos);
+  ascii.addNote(f.str().c_str());
+
+  for (std::map<long,int>::const_iterator it=posToTypeMap.begin(); it!=posToTypeMap.end(); ++it) {
+    pos=it->first;
+    long endPos=input->size();
+    std::map<long,int>::const_iterator nextIt=it;
+    if (++nextIt!=posToTypeMap.end()) endPos=nextIt->first;
+    input->seek(pos, librevenge::RVNG_SEEK_SET);
+    f.str("");
+    f << "SumInfo-B" << it->second << ":";
+    int type=int(input->readULong(4));
+    if (type==0x1e && !isDoc && ((it->second>=2 && it->second<=6) || it->second==8)) {
+      librevenge::RVNGString text;
+      if (readSummaryPropertyString(input, endPos, type, text, f) && !text.empty()) {
+        static char const *(attribNames[]) = {
+          "", "", "dc:title", "dc:subject", "meta:initial-creator",
+          "meta:keywords", "dc:description"/*comment*/, "", "dc:creator"
+        };
+        pList.insert(attribNames[it->second], text);
+      }
+    }
+    else if (!readSummaryProperty(input, endPos, type, ascii, f)) {
+      MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryInformation: find unknown type\n"));
+      f << "##type=" << std::hex << type << std::dec << ",";
+    }
+    if (input->tell()!=endPos && input->tell()!=pos)
+      ascii.addDelimiter(input->tell(),'|');
+    ascii.addPos(pos);
+    ascii.addNote(f.str().c_str());
+  }
+  return true;
+}
+
+bool MWAWOLEParser::readSummaryPropertyString(MWAWInputStreamPtr input, long endPos, int type,
+    librevenge::RVNGString &string, libmwaw::DebugStream &f) const
+{
+  if (!input) return false;
+  long pos=input->tell();
+  string.clear();
+  long sSz=long(input->readULong(4));
+  if (sSz<0 || (endPos-pos-4)<sSz || pos+4+sSz>endPos) {
+    MWAW_DEBUG_MSG(("MWAWOLEParser::readSummaryPropertyString: string size is bad\n"));
+    f << "##stringSz=" << sSz << ",";
+    return false;
+  }
+  std::string text("");
+  for (long c=0; c < sSz; ++c) {
+    char ch=char(input->readULong(1));
+    if (ch) {
+      text+=ch;
+      if (m_state->m_fontConverter) {
+        int unicode=m_state->m_fontConverter->unicode(m_state->m_fontId, static_cast<unsigned char>(ch));
+        if (unicode!=-1)
+          libmwaw::appendUnicode(uint32_t(unicode), string);
+      }
+    }
+    else if (c+1!=sSz)
+      text+="##";
+  }
+  f << text;
+  if (type==0x1f && (sSz%4))
+    input->seek(sSz%4, librevenge::RVNG_SEEK_CUR);
+  return true;
+}
+
+bool MWAWOLEParser::readSummaryProperty(MWAWInputStreamPtr input, long endPos, int type,
+                                        libmwaw::DebugFile &ascii, libmwaw::DebugStream &f) const
+{
+  if (!input) return false;
+  long pos=input->tell();
+  // see propread.cxx
+  if (type&0x1000) {
+    int N=int(input->readULong(4));
+    f << "N=" << N << ",";
+    f << "[";
+    for (int n=0; n<N; ++n) {
+      pos=input->tell();
+      f << "[";
+      if (!readSummaryProperty(input, endPos, type&0xFFF, ascii, f)) {
+        input->seek(pos, librevenge::RVNG_SEEK_SET);
+        return false;
+      }
+      f << "],";
+    }
+    f << "],";
+    return true;
+  }
+  switch (type) {
+  case 0x10: // int1
+  case 0x11: // uint1
+    if (pos+1>endPos)
+      return false;
+    f << "val=" << char(input->readULong(1));
+    break;
+  case 2: // int
+  case 0xb: // bool
+  case 0x12: // uint
+    if (pos+2>endPos)
+      return false;
+    if (type==2)
+      f << "val=" << int(input->readLong(2)) << ",";
+    else if (type==0x12)
+      f << "val=" << int(input->readULong(2)) << ",";
+    else if (input->readULong(2))
+      f << "true,";
+    break;
+  case 3: // int
+  case 4: // float
+  case 9: // uint
+    if (pos+4>endPos)
+      return false;
+    if (type==3)
+      f << "val=" << int(input->readLong(4)) << ",";
+    else if (type==9)
+      f << "val=" << int(input->readULong(4)) << ",";
+    else
+      f << "val[fl4]=" << std::hex << input->readULong(4) << std::dec << ",";
+    break;
+  case 5: // double
+  case 6:
+  case 7:
+  case 20:
+  case 21:
+  case 0x40:
+    if (pos+8>endPos)
+      return false;
+    ascii.addDelimiter(input->tell(),'|');
+    if (type==5)
+      f << "double,";
+    else if (type==6)
+      f << "cy,";
+    else if (type==7)
+      f << "date,";
+    else if (type==20)
+      f << "long,";
+    else if (type==21)
+      f << "ulong,";
+    else
+      f << "fileTime,"; // readme 8 byte
+    input->seek(pos+8, librevenge::RVNG_SEEK_SET);
+    break;
+  case 0xc: // variant
+    if (pos+4>endPos)
+      return false;
+    type=int(input->readULong(4));
+    return readSummaryProperty(input, endPos, type, ascii, f);
+  // case 20: int64
+  // case 21: uint64
+  case 8:
+  case 0x1e:
+  case 0x1f: {
+    librevenge::RVNGString string;
+    if (!readSummaryPropertyString(input, endPos, type, string, f))
+      return false;
+    break;
+  }
+  case 0x41:
+  case 0x46:
+  case 0x47: {
+    if (pos+4>endPos)
+      return false;
+    f << (type==0x41 ? "blob" : type==0x46 ? "blob[object]" : "clipboard") << ",";
+    long dSz=long(input->readULong(4));
+    if (dSz<0 || pos+4+dSz>endPos)
+      return false;
+    if (dSz) {
+      ascii.skipZone(pos+4, pos+4+dSz-1);
+      input->seek(dSz, librevenge::RVNG_SEEK_CUR);
+    }
+    break;
+  }
+  /* todo type==0x47, vtcf clipboard */
+  default:
+    return false;
+  }
+  return true;
+}
+//////////////////////////////////////////////////
 //
 // OlePres001 seems to contained standart picture file and size
 //    extract the picture if it is possible
diff --git a/src/lib/MWAWOLEParser.hxx b/src/lib/MWAWOLEParser.hxx
index 4518a81..5579979 100644
--- a/src/lib/MWAWOLEParser.hxx
+++ b/src/lib/MWAWOLEParser.hxx
@@ -76,6 +76,7 @@
 namespace MWAWOLEParserInternal
 {
 class CompObj;
+struct State;
 }
 
 /** \brief a class used to parse some basic oles
@@ -86,7 +87,7 @@ class MWAWOLEParser
 public:
   /** constructor
       \param mainName name of the main ole, we must avoid to parse */
-  explicit MWAWOLEParser(std::string mainName);
+  explicit MWAWOLEParser(std::string mainName, MWAWFontConverterPtr fontConverter, int fontId);
 
   /** destructor */
   ~MWAWOLEParser();
@@ -94,33 +95,18 @@ public:
   /** tries to parse basic OLE (excepted mainName)
       \return false if fileInput is not an Ole file */
   bool parse(MWAWInputStreamPtr fileInput);
-
+  /** update the meta data, using information find in SummaryInformation */
+  void updateMetaData(librevenge::RVNGPropertyList &metaData) const;
   //! returns the list of unknown ole
-  std::vector<std::string> const &getNotParse() const
-  {
-    return m_unknownOLEs;
-  }
-
+  std::vector<std::string> const &getNotParse() const;
   //! returns the list of id for which we have find a representation
-  std::vector<int> const &getObjectsId() const
-  {
-    return m_objectsId;
-  }
+  std::vector<int> const &getObjectsId() const;
   //! returns the list of data positions which have been read
-  std::vector<MWAWPosition> const &getObjectsPosition() const
-  {
-    return m_objectsPosition;
-  }
+  std::vector<MWAWPosition> const &getObjectsPosition() const;
   //! returns the list of data which have been read
-  std::vector<librevenge::RVNGBinaryData> const &getObjects() const
-  {
-    return m_objects;
-  }
+  std::vector<librevenge::RVNGBinaryData> const &getObjects() const;
   //! returns the list of data type
-  std::vector<std::string> const &getObjectsType() const
-  {
-    return m_objectsType;
-  }
+  std::vector<std::string> const &getObjectsType() const;
 
   //! returns the picture corresponding to an id
   bool getObject(int id, librevenge::RVNGBinaryData &obj, MWAWPosition &pos, std::string &type) const;
@@ -132,6 +118,15 @@ public:
                  std::string const &type);
 
 protected:
+  //! the summary information and the doc summary information
+  bool readSummaryInformation(MWAWInputStreamPtr input, std::string const &oleName, librevenge::RVNGPropertyList &pList,
+                              libmwaw::DebugFile &ascii) const;
+  //! try to read a summary property
+  bool readSummaryProperty(MWAWInputStreamPtr input, long endPos, int type,
+                           libmwaw::DebugFile &ascii, libmwaw::DebugStream &f) const;
+  //! try to read a summary property: type 1e
+  bool readSummaryPropertyString(MWAWInputStreamPtr input, long endPos, int type, librevenge::RVNGString &string,
+                                 libmwaw::DebugStream &f) const;
 
   //!  the "Ole" small structure : unknown contain
   static bool readOle(MWAWInputStreamPtr ip, std::string const &oleName,
@@ -175,21 +170,8 @@ protected:
 
   //! if filled, does not parse content with this name
   std::string m_avoidOLE;
-  //! list of ole which can not be parsed
-  std::vector<std::string> m_unknownOLEs;
-
-  //! list of pictures read
-  std::vector<librevenge::RVNGBinaryData> m_objects;
-  //! list of picture size ( if known)
-  std::vector<MWAWPosition> m_objectsPosition;
-  //! list of pictures id
-  std::vector<int> m_objectsId;
-  //! list of picture type
-  std::vector<std::string> m_objectsType;
-
-  //! a smart ptr used to stored the list of compobj id->name
-  shared_ptr<MWAWOLEParserInternal::CompObj> m_compObjIdName;
-
+  //! the main state
+  shared_ptr<MWAWOLEParserInternal::State> m_state;
 };
 
 #endif
diff --git a/src/lib/MWAWSpreadsheetListener.cxx b/src/lib/MWAWSpreadsheetListener.cxx
index 4b1a010..c8c7592 100644
--- a/src/lib/MWAWSpreadsheetListener.cxx
+++ b/src/lib/MWAWSpreadsheetListener.cxx
@@ -1137,7 +1137,11 @@ void MWAWSpreadsheetListener::insertPicture(MWAWPosition const &pos, MWAWEmbedde
 ///////////////////
 bool MWAWSpreadsheetListener::openGroup(MWAWPosition const &/*pos*/)
 {
-  MWAW_DEBUG_MSG(("MWAWSpreadsheetListener::openGroup is not implemented\n"));
+  static bool first=true;
+  if (first) {
+    MWAW_DEBUG_MSG(("MWAWSpreadsheetListener::openGroup is not implemented\n"));
+    first=false;
+  }
   return false;
 }
 
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 145a28f..2b8fe13 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -281,6 +281,8 @@ libmwaw_ at MWAW_MAJOR_VERSION@_ at MWAW_MINOR_VERSION@_la_SOURCES = \
 	PixelPaintParser.hxx		\
 	PowerPoint1Parser.cxx		\
 	PowerPoint1Parser.hxx		\
+	PowerPoint3OLE.cxx		\
+	PowerPoint3OLE.hxx		\
 	PowerPoint3Parser.cxx		\
 	PowerPoint3Parser.hxx		\
 	RagTimeParser.cxx		\
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
index d011ce0..10be9a1 100644
--- a/src/lib/Makefile.in
+++ b/src/lib/Makefile.in
@@ -180,15 +180,16 @@ am_libmwaw_ at MWAW_MAJOR_VERSION@_ at MWAW_MINOR_VERSION@_la_OBJECTS =  \
 	MWAWStringStream.lo MWAWSubDocument.lo MWAWTable.lo \
 	MWAWTextListener.lo NisusWrtGraph.lo NisusWrtParser.lo \
 	NisusWrtStruct.lo NisusWrtText.lo PixelPaintParser.lo \
-	PowerPoint1Parser.lo PowerPoint3Parser.lo RagTimeParser.lo \
-	RagTimeSpreadsheet.lo RagTimeStruct.lo RagTimeText.lo \
-	RagTime5Chart.lo RagTime5ClusterManager.lo RagTime5Graph.lo \
-	RagTime5Layout.lo RagTime5Parser.lo RagTime5Pipeline.lo \
-	RagTime5Spreadsheet.lo RagTime5StructManager.lo \
-	RagTime5StyleManager.lo RagTime5Text.lo StyleParser.lo \
-	SuperPaintParser.lo TeachTxtParser.lo WingzParser.lo \
-	WriteNowEntry.lo WriteNowParser.lo WriteNowText.lo \
-	WriterPlsParser.lo ZWrtParser.lo ZWrtText.lo
+	PowerPoint1Parser.lo PowerPoint3OLE.lo PowerPoint3Parser.lo \
+	RagTimeParser.lo RagTimeSpreadsheet.lo RagTimeStruct.lo \
+	RagTimeText.lo RagTime5Chart.lo RagTime5ClusterManager.lo \
+	RagTime5Graph.lo RagTime5Layout.lo RagTime5Parser.lo \
+	RagTime5Pipeline.lo RagTime5Spreadsheet.lo \
+	RagTime5StructManager.lo RagTime5StyleManager.lo \
+	RagTime5Text.lo StyleParser.lo SuperPaintParser.lo \
+	TeachTxtParser.lo WingzParser.lo WriteNowEntry.lo \
+	WriteNowParser.lo WriteNowText.lo WriterPlsParser.lo \
+	ZWrtParser.lo ZWrtText.lo
 libmwaw_ at MWAW_MAJOR_VERSION@_ at MWAW_MINOR_VERSION@_la_OBJECTS = $(am_libmwaw_ at MWAW_MAJOR_VERSION@_ at MWAW_MINOR_VERSION@_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -692,6 +693,8 @@ libmwaw_ at MWAW_MAJOR_VERSION@_ at MWAW_MINOR_VERSION@_la_SOURCES = \
 	PixelPaintParser.hxx		\
 	PowerPoint1Parser.cxx		\
 	PowerPoint1Parser.hxx		\
+	PowerPoint3OLE.cxx		\
+	PowerPoint3OLE.hxx		\
 	PowerPoint3Parser.cxx		\
 	PowerPoint3Parser.hxx		\
 	RagTimeParser.cxx		\
@@ -963,6 +966,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/NisusWrtText.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PixelPaintParser.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PowerPoint1Parser.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PowerPoint3OLE.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/PowerPoint3Parser.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/RagTime5Chart.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/RagTime5ClusterManager.Plo at am__quote@
diff --git a/src/lib/MsWksDBParser.cxx b/src/lib/MsWksDBParser.cxx
index c8966a2..efc57e8 100644
--- a/src/lib/MsWksDBParser.cxx
+++ b/src/lib/MsWksDBParser.cxx
@@ -530,7 +530,7 @@ void MsWksDBParser::parse(librevenge::RVNGSpreadsheetInterface *docInterface)
 #ifdef DEBUG
     MWAWInputStreamPtr &input= getInput();
     if (input->isStructured()) {
-      shared_ptr<MWAWOLEParser> oleParser(new MWAWOLEParser("MN0"));
+      shared_ptr<MWAWOLEParser> oleParser(new MWAWOLEParser("MN0", getParserState()->m_fontConverter, 3));
       oleParser->parse(input);
     }
 #endif
diff --git a/src/lib/MsWksDocument.cxx b/src/lib/MsWksDocument.cxx
index fa0e110..7c65579 100644
--- a/src/lib/MsWksDocument.cxx
+++ b/src/lib/MsWksDocument.cxx
@@ -592,7 +592,7 @@ std::vector<std::string> const &MsWksDocument::getUnparsedOLEZones() const
 bool MsWksDocument::createOLEZones(MWAWInputStreamPtr input)
 {
   if (!input || !input->isStructured()) return false;
-  m_state->m_oleParser.reset(new MWAWOLEParser("MN0"));
+  m_state->m_oleParser.reset(new MWAWOLEParser("MN0", m_parserState->m_fontConverter, 3));
 
   if (!m_state->m_oleParser->parse(input)) return false;
 
diff --git a/src/lib/MsWksSSParser.cxx b/src/lib/MsWksSSParser.cxx
index 09f44be..cde8b8b 100644
--- a/src/lib/MsWksSSParser.cxx
+++ b/src/lib/MsWksSSParser.cxx
@@ -253,7 +253,7 @@ void MsWksSSParser::parse(librevenge::RVNGSpreadsheetInterface *docInterface)
 #ifdef DEBUG
     MWAWInputStreamPtr &input= getInput();
     if (input->isStructured()) {
-      shared_ptr<MWAWOLEParser> oleParser(new MWAWOLEParser("MN0"));
+      shared_ptr<MWAWOLEParser> oleParser(new MWAWOLEParser("MN0", getParserState()->m_fontConverter, 3));
       oleParser->parse(input);
     }
 #endif
diff --git a/src/lib/PowerPoint1Parser.cxx b/src/lib/PowerPoint1Parser.cxx
index 82f9d06..2f735dc 100644
--- a/src/lib/PowerPoint1Parser.cxx
+++ b/src/lib/PowerPoint1Parser.cxx
@@ -31,6 +31,7 @@
 * instead of those above.
 */
 
+#include <algorithm>
 #include <iomanip>
 #include <iostream>
 #include <set>
@@ -78,14 +79,14 @@ struct Ruler {
         o << (i==0 ? "first[margin]" : "left[margin]") << "=" << outline.m_margins[i] << ",";
       }
       for (int i=0; i<2; ++i) {
-        if (outline.m_interlines[i]==10) continue;
-        o << (i==0 ? "space[interline]" : "space[paragraph]") << "=" << 10*outline.m_interlines[i] << "%,";
+        if (outline.m_interlines[i]==100) continue;
+        o << (i==0 ? "space[interline]" : "space[paragraph]") << "=" << outline.m_interlines[i] << "%,";
       }
       return o;
     }
     //! the first margin and left margin
     int m_margins[2];
-    //! the interline and paragraph spacing: 10 means 100%
+    //! the interline and paragraph spacing
     int m_interlines[2];
   };
   //! the tabs
@@ -107,13 +108,15 @@ struct TextZone {
   //! small structure used to store a line of text and its format
   struct Line {
     //! constructor
-    Line() : m_text(), m_format(), m_justify(MWAWParagraph::JustificationLeft), m_outlineLevel(0)
+    Line() : m_text(), m_format(), m_ruler(), m_justify(MWAWParagraph::JustificationLeft), m_outlineLevel(0)
     {
     }
     //! the text entry
     MWAWEntry m_text;
     //! the format entry
     MWAWEntry m_format;
+    //! the ruler entry (windows v2)
+    MWAWEntry m_ruler;
     //! the justification
     MWAWParagraph::Justification m_justify;
     //! the outline level
@@ -173,7 +176,7 @@ struct Slide {
 //! Internal: the state of a PowerPoint1Parser
 struct State {
   //! constructor
-  State() : m_isMacFile(true), m_zoneListBegin(0), m_zonesList(), m_origin(0,0), m_rulersList(), m_idToSlideMap(), m_idToSchemeMap(), m_idToUserColorMap(), m_picturesIdList(), m_schemesIdList(),
+  State() : m_isMacFile(true), m_unit(1), m_zoneListBegin(0), m_zonesList(), m_origin(0,0), m_rulersList(), m_idToSlideMap(), m_idToSchemeMap(), m_idToUserColorMap(), m_picturesIdList(), m_schemesIdList(),
     m_badEntry()
   {
     for (int i=0; i<2; ++i)
@@ -195,6 +198,8 @@ struct State {
   bool getPattern(int id, MWAWGraphicStyle::Pattern &pattern) const;
   //! flag to know if the file is a mac file or a pc file
   bool m_isMacFile;
+  //! the data unit: 1 if the file is a mac file, 1/8 if the file is a windows file
+  float m_unit;
   //! the begin position of the list of zones
   long m_zoneListBegin;
   //! the list of zone entries
@@ -458,8 +463,9 @@ bool PowerPoint1Parser::createZones()
     return false;
   }
   int const vers=version();
-  int numStyles=vers<=1 ? 4 : m_state->m_isMacFile ? 5 : 0;
-  if (m_state->m_isMacFile) {
+  bool const isMacFile=m_state->m_isMacFile;
+  int numStyles=vers<=1 ? 4 : m_state->m_isMacFile ? 6 : 8;
+  if (isMacFile) {
     for (int i=0; i<numStyles; ++i) {
       MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_zoneIds[i]);
       if (!entry.valid() || entry.isParsed()) continue;
@@ -471,19 +477,26 @@ bool PowerPoint1Parser::createZones()
         readFonts(entry);
       else if (i==4)
         readColorZone(entry);
+      else if (i==5)
+        readZone2(entry);
     }
   }
   else {
-    numStyles=3;
-    for (int i=0; i<3; ++i) {
-      // 0:
-      // 1: list of zone list?
-      // 2: schemes list?
+    for (int i=0; i<numStyles; ++i) {
       MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_zoneIds[i]);
       if (!entry.valid() || entry.isParsed()) continue;
-      readZoneIdList2(entry, i);
+      if (i<3) // list of 0: picture, 1: rulers, 2: scheme
+        readZoneIdList2(entry, i);
+      else if (i==3)
+        readColorZone(entry);
+      else if (i==4)
+        readZone2(entry);
+      // 5: never seens
+      else if (i==6)
+        readFonts(entry);
+      else if (i==7)
+        readFontNames(entry);
     }
-    // vers=3: i==3[4] readColorMode, i==4[5] readZone2, i==6[2] readFonts
   }
   readSchemes();
   for (int i=0; i<2; ++i) {
@@ -491,32 +504,38 @@ bool PowerPoint1Parser::createZones()
     if (!entry.valid() || entry.isParsed()) continue;
     readSlide(entry, m_state->m_slidesIdList[i]);
   }
-  if (m_state->m_printInfoIds[1]>=0) {
-    MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_printInfoIds[1]);
-    if (entry.valid() && !entry.isParsed())
-      readPrintInfo(entry);
-  }
-  for (int i=numStyles; i<10; ++i) {
-    MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_zoneIds[i]);
+  for (int i=0; i<2; ++i) {
+    MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_printInfoIds[i]);
     if (!entry.valid() || entry.isParsed()) continue;
-    if (i==5)
-      readZone2(entry);
-    else { // never seens
-      static bool first=true;
-      if (first) {
-        first=false;
-        MWAW_DEBUG_MSG(("PowerPoint1Parser::createZones: find unknown Zone5\n"));
-      }
+    if (m_state->m_isMacFile && i==1)
+      readPrintInfo(entry);
+    else {
       entry.setParsed(true);
       libmwaw::DebugStream f;
-      f << "Entries(Zone" << i << ")[Z" << entry.id() << "]:";
+      f << "Entries(PrintInfo" << i << ")[Z" << entry.id() << "]:";
       ascii().addPos(entry.begin());
       ascii().addNote(f.str().c_str());
       ascii().addPos(entry.end());
       ascii().addNote("_");
     }
   }
-  return m_state->m_isMacFile && !m_state->m_slidesIdList[0].empty();
+  for (int i=0; i<10; ++i) {
+    MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_zoneIds[i]);
+    if (!entry.valid() || entry.isParsed()) continue;
+    static bool first=true;
+    if (first) {
+      first=false;
+      MWAW_DEBUG_MSG(("PowerPoint1Parser::createZones: find unknown Zone%d\n", i));
+    }
+    entry.setParsed(true);
+    libmwaw::DebugStream f;
+    f << "Entries(Zone" << i << ")[Z" << entry.id() << "]:";
+    ascii().addPos(entry.begin());
+    ascii().addNote(f.str().c_str());
+    ascii().addPos(entry.end());
+    ascii().addNote("_");
+  }
+  return !m_state->m_slidesIdList[0].empty();
 }
 
 bool PowerPoint1Parser::readListZones(int &docInfoId)
@@ -676,11 +695,13 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
 {
   MWAWInputStreamPtr input=getInput();
   int const vers=version();
-  int const dataSz=m_state->m_isMacFile ? 28 : 32;
+  int const isMacFile=m_state->m_isMacFile;
+  int dataSz=isMacFile ? 28 : 32;
   if (!entry.valid() || (entry.length()%dataSz)!=0) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readFramesList: the entry seems bad\n"));
     return false;
   }
+  if (!isMacFile) dataSz=30;
   entry.setParsed(true);
   input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
   long pos=input->tell();
@@ -699,6 +720,10 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
     f << "Frames[F" << fr << "]:";
     int dim[4];
     for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
+    if (!isMacFile) {
+      std::swap(dim[0],dim[1]);
+      std::swap(dim[2],dim[3]);
+    }
     frame.m_dimension=MWAWBox2i(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2]));
     f << "dim=" << frame.m_dimension << ",";
     frame.m_type=int(input->readULong(1));
@@ -710,7 +735,12 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
       f << "rect,";
       break;
     case 2:
-      f << "textbox,";
+      if (isMacFile)
+        f << "textbox,";
+      else {
+        frame.m_textId=MWAWVec2i(tId,tId);
+        f << "textbox=T" << tId++ << ",";
+      }
       break;
     case 3:
       frame.m_textId=MWAWVec2i(tId,tId);
@@ -740,16 +770,36 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
       }
     }
     else {
-      val=int(input->readULong(1));
-      for (int i=0, bit=1; i<5; ++i, bit<<=1) {
-        flags[i]=(val&bit);
-        if (!flags[i]) continue;
-        char const *(wh[])= {"opaque", "frame", "filled", "shadowed", "sized to text"};
-        f << wh[i] << ",";
+      if (isMacFile) {
+        val=int(input->readULong(1));
+        for (int i=0, bit=1; i<5; ++i, bit<<=1) {
+          flags[i]=(val&bit);
+          if (!flags[i]) continue;
+          char const *(wh[])= {"opaque", "frame", "filled", "shadowed", "sized to text"};
+          f << wh[i] << ",";
+        }
+        if (val&0xE0) {
+          MWAW_DEBUG_MSG(("PowerPoint1Parser::readFramesList: find unexpected flags\n"));
+          f << "##fl=" << (val>>5) << ",";
+        }
       }
-      if (val&0xE0) {
-        MWAW_DEBUG_MSG(("PowerPoint1Parser::readFramesList: find unexpected flags\n"));
-        f << "##fl=" << (val>>5) << ",";
+      else {
+        val=int(input->readULong(1));
+        if (val) f << "fl0=" << val << ",";
+        val=int(input->readULong(1));
+        for (int i=0, bit=1; i<5; ++i, bit<<=1) {
+          int const(corresp[])= {2,1,3,0,4};
+          flags[corresp[i]]=(val&bit);
+          if (!flags[corresp[i]]) continue;
+          char const *(wh[])= {"filled", "frame", "shadowed", "opaque", "sized to text"};
+          f << wh[i] << ",";
+        }
+        if (val&0xE0) {
+          MWAW_DEBUG_MSG(("PowerPoint1Parser::readFramesList: find unexpected flags\n"));
+          f << "##fl=" << (val>>5) << ",";
+        }
+        val=int(input->readULong(1));
+        if (val) f << "fl2=" << val << ",";
       }
       for (int i=0; i<4; ++i) { // frame, fill, shadow, pat2
         int col=int(input->readULong(1));
@@ -757,6 +807,7 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
         if (schemeId>=0 && !getColor(col, schemeId, colors[i])) f << "##col,";
         if (col!=expected[i]) f << "col" << i << "=" << col << ",";
       }
+      if (!isMacFile) std::swap<MWAWColor>(colors[1],colors[3]);
     }
     MWAWGraphicStyle &style=frame.m_style;
     val=int(input->readULong(1));
@@ -817,7 +868,7 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
       pattern.m_colors[1]=colors[3];
       if (val!=1)
         f << "pat=" << pattern << ",";
-      if (flags[2]) { // textbox have no background color
+      if (flags[2]) { // filled
         MWAWColor color;
         if (pattern.getUniqueColor(color))
           style.setSurfaceColor(color);
@@ -838,7 +889,7 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
       f << "##pattern=" << val << ",";
       if (flags[0]) style.setSurfaceColor(colors[1]);
     }
-    if (flags[3]==1) {
+    if (flags[3]) {
       style.setShadowColor(colors[2]);
       style.m_shadowOffset=MWAWVec2f(3,3);
     }
@@ -877,7 +928,7 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
       f << "para=R" << val << ",";
     }
     val=int(input->readULong(2));
-    if (frame.m_type==2) {
+    if (frame.m_type==2 && isMacFile) {
       frame.m_textId=MWAWVec2i(tId,tId+val-1);
       tId+=val;
       f << "text=T" << frame.m_textId[0] << "<->T" << frame.m_textId[1] << ",";
@@ -895,6 +946,10 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
     ascii().addPos(pos);
     ascii().addNote(f.str().c_str());
   }
+  if (input->tell()!=entry.end()) {
+    ascii().addPos(input->tell());
+    ascii().addNote("Frames:extra");
+  }
   ascii().addPos(entry.end());
   ascii().addNote("_");
   return true;
@@ -903,7 +958,8 @@ bool PowerPoint1Parser::readFramesList(MWAWEntry const &entry, std::vector<Power
 bool PowerPoint1Parser::readTextZone(MWAWEntry const &entry, PowerPoint1ParserInternal::TextZone &zone)
 {
   MWAWInputStreamPtr input=getInput();
-  if (!entry.valid() || entry.length()<6) {
+  bool isMacFile=m_state->m_isMacFile;
+  if (!entry.valid() || entry.length()<(isMacFile ? 6 : 32)) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readTextZone: the entry seems bad\n"));
     return false;
   }
@@ -911,6 +967,7 @@ bool PowerPoint1Parser::readTextZone(MWAWEntry const &entry, PowerPoint1ParserIn
   long pos=input->tell();
   libmwaw::DebugStream f;
   f << "Entries(TextZone)[Z" << entry.id() << "]:";
+  int val;
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
   long const endPos=entry.end();
@@ -918,71 +975,136 @@ bool PowerPoint1Parser::readTextZone(MWAWEntry const &entry, PowerPoint1ParserIn
   while (input->tell()+6<=endPos) {
     PowerPoint1ParserInternal::TextZone::Line line;
     pos=input->tell();
+    if (!isMacFile && pos+32>endPos)
+      break;
     f.str("");
     f << "TextZone-T" << ++n << ":";
-    int val=int(input->readLong(1));
-    switch (val) {
-    case 0: // left
-      break;
-    case 1:
-      line.m_justify=MWAWParagraph::JustificationCenter;
-      f << "center,";
-      break;
-    case 2:
-      line.m_justify=MWAWParagraph::JustificationRight;
-      f << "right,";
-      break;
-    case 3:
-      line.m_justify=MWAWParagraph::JustificationFull;
-      f << "justify,";
+    if (isMacFile) {
+      val=int(input->readLong(1));
+      switch (val) {
+      case 0: // left
+        break;
+      case 1:
+        line.m_justify=MWAWParagraph::JustificationCenter;
+        f << "center,";
+        break;
+      case 2:
+        line.m_justify=MWAWParagraph::JustificationRight;
+        f << "right,";
+        break;
+      case 3:
+        line.m_justify=MWAWParagraph::JustificationFull;
+        f << "justify,";
+        break;
+      default:
+        MWAW_DEBUG_MSG(("PowerPoint1Parser::readTextZone: find unknown justification\n"));
+        f << "##justify=" << val << ",";
+      }
+      line.m_outlineLevel=int(input->readLong(1));
+      if (line.m_outlineLevel) f << "outline[levl]=" << line.m_outlineLevel << ",";
+    }
+    else if (entry.length()>32+16) {
+      for (int i=0; i<16; ++i) { // f0=1|8|c|10,f1=d|12,f2=1|3f,f3=0|c,f5=sz|big number,f6=0-3,f7=0-1a,f9=0|1,f13=0-2,f14=0|5
+        val=int(input->readLong(2));
+        if (val)
+          f << "f" << i << "=" << val << ",";
+      }
+      for (int i=0; i<4; ++i) {
+        val=int(input->readULong(2));
+        if (val) f << "g" << i << "=" << val << ",";
+      }
+    }
+    else {
+      input->seek(pos+32, librevenge::RVNG_SEEK_SET);
+      ascii().addPos(pos);
+      ascii().addNote(f.str().c_str());
+      zone.m_lineList.push_back(line);
       break;
-    default:
-      MWAW_DEBUG_MSG(("PowerPoint1Parser::readTextZone: find unknown justifcation\n"));
-      f << "##justify=" << val << ",";
     }
-    line.m_outlineLevel=int(input->readLong(1));
-    if (line.m_outlineLevel) f << "outline[levl]=" << line.m_outlineLevel << ",";
     int sSz=int(input->readULong(2));
-    if (pos+4+sSz+(sSz&1)+2>endPos) {
+    if (input->tell()+sSz+(isMacFile ? (sSz&1)+2:16)>endPos) {
       input->seek(pos, librevenge::RVNG_SEEK_SET);
       n--;
       break;
     }
-    line.m_text.setBegin(pos+4);
+    line.m_text.setBegin(input->tell());
     line.m_text.setLength(sSz);
     std::string text;
     for (int i=0; i<sSz; ++i) text+=char(input->readULong(1));
     f << text << ",";
-    if (sSz&1) input->seek(1, librevenge::RVNG_SEEK_CUR);
+    if (isMacFile && (sSz&1)) input->seek(1, librevenge::RVNG_SEEK_CUR);
     ascii().addPos(pos);
     ascii().addNote(f.str().c_str());
 
     pos=input->tell();
     f.str("");
     f << "TextZone-F" << n << ":";
-    sSz=int(input->readULong(2));
-    if ((sSz!=0 && sSz<6) || pos+2+sSz>endPos) {
-      input->seek(pos, librevenge::RVNG_SEEK_SET);
-      n--;
-      break;
+    if (isMacFile) {
+      sSz=int(input->readULong(2));
+      if ((sSz!=0 && sSz<6) || pos+2+sSz>endPos) {
+        input->seek(pos, librevenge::RVNG_SEEK_SET);
+        n--;
+        break;
+      }
+      line.m_format.setBegin(pos+2);
+      line.m_format.setLength(sSz);
+      input->seek(sSz, librevenge::RVNG_SEEK_CUR);
+      ascii().addPos(pos);
+      ascii().addNote(f.str().c_str());
     }
+    else {
+      for (int i=0; i<3; ++i) {
+        val=int(input->readULong(2));
+        if (val) f << "f" << i << "=" << val << ",";
+      }
+      int nFonts=int(input->readULong(2));
+      if (pos+nFonts*14+8>endPos) {
+        input->seek(pos, librevenge::RVNG_SEEK_SET);
+        n--;
+        break;
+      }
+      ascii().addPos(pos);
+      ascii().addNote(f.str().c_str());
+      line.m_format.setBegin(pos+8);
+      line.m_format.setLength(nFonts*14);
+      input->seek(nFonts*14, librevenge::RVNG_SEEK_CUR);
 
-    line.m_format.setBegin(pos+2);
-    line.m_format.setLength(sSz);
-    ascii().addPos(pos);
-    ascii().addNote(f.str().c_str());
-    input->seek(sSz, librevenge::RVNG_SEEK_CUR);
+      pos=input->tell();
+      f.str("");
+      f << "TextZone-R" << n << ":";
+      for (int i=0; i<3; ++i) {
+        val=int(input->readULong(2));
+        if (val) f << "f" << i << "=" << val << ",";
+      }
+      int nRulers=int(input->readULong(2));
+      if (pos+nRulers*6>endPos) {
+        input->seek(pos, librevenge::RVNG_SEEK_SET);
+        n--;
+        break;
+      }
+      line.m_ruler.setBegin(pos+8);
+      line.m_ruler.setLength(nRulers*6);
+      ascii().addPos(pos);
+      ascii().addNote(f.str().c_str());
+      input->seek(nRulers*6, librevenge::RVNG_SEEK_CUR);
+    }
     zone.m_lineList.push_back(line);
   }
-  if (n==0) return false;
+  if (n==0 && isMacFile) return false;
   entry.setParsed(true);
   ascii().addPos(endPos);
   ascii().addNote("_");
   pos=input->tell();
   if (pos!=endPos) {
-    MWAW_DEBUG_MSG(("PowerPoint1Parser::readTextZone: find extra data\n"));
-    ascii().addPos(pos);
-    ascii().addNote("TextZone-###extra");
+    if (!isMacFile && pos<endPos && endPos<pos+32) {
+      ascii().addPos(pos);
+      ascii().addNote("TextZone-extra");
+    }
+    else {
+      MWAW_DEBUG_MSG(("PowerPoint1Parser::readTextZone: find extra data\n"));
+      ascii().addPos(pos);
+      ascii().addNote("TextZone-###extra");
+    }
   }
   return true;
 }
@@ -1071,6 +1193,12 @@ bool PowerPoint1Parser::readSlide(MWAWEntry const &entry, std::vector<int> &list
     f << "#use[master]=" << val << ",";
   val=int(input->readLong(1)); // always 0
   if (val) f << "f6=" << val << ",";
+  if (!isMacFile) {
+    // maybe junk
+    val=int(input->readULong(2));
+    if (val)
+      f << "f7=" << std::hex << val << std::dec << ",";
+  }
   val=int(input->readULong(2));
   if (val>=0 && val<int(m_state->m_schemesIdList.size())) {
     slide->m_schemeId=val;
@@ -1078,10 +1206,12 @@ bool PowerPoint1Parser::readSlide(MWAWEntry const &entry, std::vector<int> &list
   }
   else if (val)
     f << "#scheme=" << val << ",";
-  // maybe junk
-  val=int(input->readULong(2));
-  if (val)
-    f << "f7=" << std::hex << val << std::dec << ",";
+  if (isMacFile) {
+    // maybe junk
+    val=int(input->readULong(2));
+    if (val)
+      f << "f7=" << std::hex << val << std::dec << ",";
+  }
   val=int(input->readULong(2)); // 0 or big number
   if (val) f << "g0=" << std::hex << val << std::dec << ",";
   val=int(input->readLong(2));
@@ -1208,9 +1338,17 @@ bool PowerPoint1Parser::readDocInfo(MWAWEntry const &entry)
     if (val) f << "id" << i+4 << "=" << std::hex << val << std::dec << ",";
   }
   for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
+  if (!isMacFile) {
+    std::swap(dim[0],dim[1]);
+    std::swap(dim[2],dim[3]);
+  }
   MWAWBox2i pageBox(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2]));
   f << "dim[page]=" << pageBox << ",";
   for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
+  if (!isMacFile) {
+    std::swap(dim[0],dim[1]);
+    std::swap(dim[2],dim[3]);
+  }
   MWAWBox2i paperBox(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2]));
   paperBox=MWAWBox2i(MWAWVec2i(dim[0],dim[1]),MWAWVec2i(dim[2],dim[3]));
   f << "dim[paper]=" << paperBox << ",";
@@ -1222,18 +1360,19 @@ bool PowerPoint1Parser::readDocInfo(MWAWEntry const &entry)
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readDocInfo: the page dimension seems bad\n"));
   }
   else {
+    double const unit=m_state->m_unit;
     // checkme, maybe better to define a slide with pageSize and no margins
     getPageSpan().setFormOrientation(MWAWPageSpan::PORTRAIT);
     if (pageBox[0][1]>=paperBox[0][1])
-      getPageSpan().setMarginTop(double(pageBox[0][1]-paperBox[0][1])/72.0);
+      getPageSpan().setMarginTop(double(pageBox[0][1]-paperBox[0][1])*unit/72.0);
     if (pageBox[1][1]<=paperBox[1][1])
-      getPageSpan().setMarginBottom(double(paperBox[1][1]-pageBox[1][1])/72.0);
+      getPageSpan().setMarginBottom(double(paperBox[1][1]-pageBox[1][1])*unit/72.0);
     if (pageBox[0][0]>=paperBox[0][0])
-      getPageSpan().setMarginLeft(double(pageBox[0][0]-paperBox[0][0])/72.0);
+      getPageSpan().setMarginLeft(double(pageBox[0][0]-paperBox[0][0])*unit/72.0);
     if (pageBox[1][0]<=paperBox[1][0])
-      getPageSpan().setMarginRight(double(paperBox[1][0]-pageBox[1][0])/72.0);
-    getPageSpan().setFormLength(double(paperSize.y())/72.);
-    getPageSpan().setFormWidth(double(paperSize.x())/72.);
+      getPageSpan().setMarginRight(double(paperBox[1][0]-pageBox[1][0])*unit/72.0);
+    getPageSpan().setFormLength(double(paperSize.y())*unit/72.);
+    getPageSpan().setFormWidth(double(paperSize.x())*unit/72.);
   }
   if (isMacFile) {
     val=int(input->readLong(2)); // 0
@@ -1341,6 +1480,71 @@ bool PowerPoint1Parser::readDocInfo(MWAWEntry const &entry)
   return true;
 }
 
+bool PowerPoint1Parser::readPictureDefinition(MWAWEntry const &entry, size_t pId)
+{
+  if (!entry.valid() || entry.length()<28) {
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readPictureDefinition: the zone seems bad\n"));
+    return false;
+  }
+  MWAWInputStreamPtr input = getInput();
+  long pos = entry.begin();
+  entry.setParsed(true);
+  ascii().addPos(entry.end());
+  ascii().addNote("_");
+  input->seek(pos, librevenge::RVNG_SEEK_SET);
+  libmwaw::DebugStream f;
+  f << "Entries(Picture)[Z"<< entry.id() << "-" << pId << "]:def,";
+  int val=int(input->readULong(2)); // big number [0-3]XXX
+  if (val) f << "id=" << std::hex << val << std::dec << ",";
+  int type=int(input->readULong(2)); // 1-4
+  if (type)
+    f << "type=" << type << ",";
+  int dim[4];
+  for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
+  f << "dim=" << MWAWBox2i(MWAWVec2i(dim[0],dim[1]),MWAWVec2i(dim[2],dim[3])) << ",";
+  val=int(input->readULong(2));
+  if (val!=2) {
+    f << "###type2=" << val << ",";
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readPictureDefinition: find unexpected type 2\n"));
+  }
+  int child=int(input->readULong(2));
+  if (child>=0 && child<int(m_state->m_zonesList.size())) {
+    f << "child[id]=Z" << child << ",";
+    if (pId>=m_state->m_picturesIdList.size())
+      m_state->m_picturesIdList.resize(pId+1,-1);
+    m_state->m_picturesIdList[pId]=child;
+  }
+  else {
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readPictureDefinition: find some bad child\n"));
+    f << "child[id]=##Z" << child << ",";
+  }
+  if (type==4) {
+    for (int i=0; i<3; ++i) {
+      val=int(input->readULong(2));
+      child=int(input->readULong(2));
+      if (child>=0 && child<int(m_state->m_zonesList.size())) {
+        f << "child" << i << "[id]=Z" << child << "[" << val << "],";
+        MWAWEntry const &cEntry=m_state->getZoneEntry(child);
+        if (!cEntry.valid() || cEntry.isParsed()) continue;
+        // find type=10,14(string: Graph),16(probably the graph structure)
+        cEntry.setParsed(true);
+        libmwaw::DebugStream f2;
+        f2 << "Entries(Pict" << val << "):";
+        ascii().addPos(cEntry.begin());
+        ascii().addNote(f2.str().c_str());
+      }
+      else {
+        MWAW_DEBUG_MSG(("PowerPoint1Parser::readPictureDefinition: find some bad child\n"));
+        f << "child" << i << "[id]=##Z" << child << "[" << val << "],";
+      }
+    }
+  }
+  ascii().addDelimiter(input->tell(),'|');
+  ascii().addPos(pos);
+  ascii().addNote(f.str().c_str());
+  return true;
+}
+
 bool PowerPoint1Parser::readPicture(MWAWEntry const &entry, MWAWEmbeddedObject &picture)
 {
   if (!entry.valid() || entry.length()<20) {
@@ -1438,7 +1642,8 @@ bool PowerPoint1Parser::readZoneIdList2(MWAWEntry const &entry, int zId)
   input->seek(pos, librevenge::RVNG_SEEK_SET);
 
   libmwaw::DebugStream f;
-  f << "Entries(UnkList)[" << zId << ",Z"<< entry.id() << "]:";
+  std::string const wh(zId==0 ? "Picture" : zId==1 ? "Ruler" : zId==2 ? "Scheme" : "UnknownList");
+  f << "Entries(" << wh << ")[Z"<< entry.id() << "]:list,";
   int val=int(input->readULong(2)); // 8001
   if (val!=0x8001) f << "f0=" << std::hex << val << std::dec << ",";
   val=int(input->readULong(2)); // big number
@@ -1458,7 +1663,7 @@ bool PowerPoint1Parser::readZoneIdList2(MWAWEntry const &entry, int zId)
     val=int(input->readULong(2));
     int const(expected[])= {0x7fff, 0, 2, 0, 0};
     if (val!=expected[i])
-      f << "f" << i+1 << "=" << val << ",";
+      f << "f" << i+2 << "=" << val << ",";
   }
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
@@ -1468,7 +1673,14 @@ bool PowerPoint1Parser::readZoneIdList2(MWAWEntry const &entry, int zId)
   for (size_t i=0; i<N; ++i) {
     pos=input->tell();
     f.str("");
-    f << "UnkList-" << i << ":";
+    if (zId==0)
+      f << "Picture-P" << i << ":";
+    else if (zId==1)
+      f << "Ruler-R" << i << ":";
+    else if (zId==2)
+      f << "Scheme-S" << i << ":";
+    else
+      f << wh << "-" << i << ":";
     int type=int(input->readULong(2));
     int id=int(input->readLong(2));
     if (type==0 || id==-1) {
@@ -1493,17 +1705,27 @@ bool PowerPoint1Parser::readZoneIdList2(MWAWEntry const &entry, int zId)
   }
   ascii().addPos(entry.end());
   ascii().addNote("_");
-  f.str("");
-  f << "Entries(Zone" << zId << "):";
-  for (size_t i=0; i<N; ++i) {
-    if (list[i]==-1) continue;
-    MWAWEntry const &cEntry=m_state->getZoneEntry(list[i]);
-    if (!cEntry.valid() || cEntry.isParsed()) continue;
-    cEntry.setParsed(true);
-    ascii().addPos(cEntry.begin());
-    ascii().addNote(f.str().c_str());
-    ascii().addPos(cEntry.end());
-    ascii().addNote("_");
+  if (zId==2)
+    m_state->m_schemesIdList=list;
+  else {
+    f.str("");
+    f << "Entries(UnknList" << zId << "):";
+    for (size_t i=0; i<N; ++i) {
+      if (list[i]==-1) continue;
+      MWAWEntry const &cEntry=m_state->getZoneEntry(list[i]);
+      if (!cEntry.valid() || cEntry.isParsed()) continue;
+      if (zId==0)
+        readPictureDefinition(cEntry, i);
+      else if (zId==1)
+        readRuler(cEntry, i);
+      else {
+        cEntry.setParsed(true);
+        ascii().addPos(cEntry.begin());
+        ascii().addNote(f.str().c_str());
+        ascii().addPos(cEntry.end());
+        ascii().addNote("_");
+      }
+    }
   }
   return true;
 }
@@ -1586,7 +1808,7 @@ bool PowerPoint1Parser::readRulers(MWAWEntry const &entry)
       PowerPoint1ParserInternal::Ruler::Outline &outline=ruler.m_outlines[j];
       f << "[";
       for (int k=0; k<2; ++k) outline.m_margins[k]=int(input->readULong(2));
-      for (int k=0; k<2; ++k) outline.m_interlines[k]=int(input->readULong(1));
+      for (int k=0; k<2; ++k) outline.m_interlines[k]=10*int(input->readULong(1));
       f << outline << ",";
       f << "fl=" << std::hex << input->readULong(2) << std::dec << ",";
       f << "],";
@@ -1601,6 +1823,75 @@ bool PowerPoint1Parser::readRulers(MWAWEntry const &entry)
   return true;
 }
 
+bool PowerPoint1Parser::readRuler(MWAWEntry const &entry, size_t id)
+{
+  if (!entry.valid() || (entry.length()<54)!=0) {
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readRuler: the zone seems bad\n"));
+    return false;
+  }
+  MWAWInputStreamPtr input = getInput();
+  long pos = entry.begin();
+  entry.setParsed(true);
+  input->seek(pos, librevenge::RVNG_SEEK_SET);
+  libmwaw::DebugStream f;
+  f << "Entries(Ruler)[Z"<< entry.id() << "]:R" << id << ",";
+
+  if (m_state->m_rulersList.size()<id+1)
+    m_state->m_rulersList.resize(id+1);
+  PowerPoint1ParserInternal::Ruler &ruler=m_state->m_rulersList[id];
+  f << "levels=[";
+  for (int j=0; j<5; ++j) {
+    PowerPoint1ParserInternal::Ruler::Outline &outline=ruler.m_outlines[j];
+    f << "[";
+    for (int k=0; k<2; ++k) outline.m_margins[k]=int(input->readULong(2));
+    for (int k=0; k<2; ++k) outline.m_interlines[k]=int(input->readULong(2));
+    f << outline << ",";
+    f << "fl=" << std::hex << input->readULong(2) << std::dec << ",";
+    f << "],";
+  }
+  f << "],";
+  int val=int(input->readULong(2)); // 2-3: align?
+  if (val!=3) f << "f0=" << val << ",";
+  int nTabs=int(input->readULong(2));
+  if (input->tell()+4*nTabs>entry.end()) {
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readRuler: the number of tab seems bad\n"));
+    f << "###n[tabs]=" << nTabs << ",";
+    nTabs=0;
+  }
+  f << "tabs=[";
+  for (int j=0, bit=1; j<nTabs; ++j, bit<<=1) {
+    MWAWTabStop tab;
+    tab.m_position=double(input->readULong(2))/8./72.;
+    val=int(input->readULong(2));
+    switch (val) {
+    case 0:
+      tab.m_alignment=MWAWTabStop::DECIMAL;
+      break;
+    case 1:
+      tab.m_alignment=MWAWTabStop::RIGHT;
+      break;
+    case 2:
+      tab.m_alignment=MWAWTabStop::CENTER;
+      break;
+    case 3:
+      tab.m_alignment=MWAWTabStop::LEFT;
+      break;
+    default:
+      MWAW_DEBUG_MSG(("PowerPoint1Parser::readRuler: find unknown alignment\n"));
+      f << "##align=" << val << ",";
+      break;
+    }
+    ruler.m_tabs.push_back(tab);
+    f << tab << ",";
+  }
+  f << "],";
+  if (input->tell()!=entry.end())
+    ascii().addDelimiter(input->tell(),'|');
+  ascii().addPos(pos);
+  ascii().addNote(f.str().c_str());
+  return true;
+}
+
 
 bool PowerPoint1Parser::readColors(MWAWEntry const &entry)
 {
@@ -1612,6 +1903,7 @@ bool PowerPoint1Parser::readColors(MWAWEntry const &entry)
   long pos = entry.begin();
   entry.setParsed(true);
   input->seek(pos, librevenge::RVNG_SEEK_SET);
+  bool const isMacFile=m_state->m_isMacFile;
   libmwaw::DebugStream f;
   f << "Entries(Color)[Z"<< entry.id() << "]:";
   int val;
@@ -1621,7 +1913,7 @@ bool PowerPoint1Parser::readColors(MWAWEntry const &entry)
   }
   int N=int(input->readULong(2));
   f << "N=" << N << ",";
-  if (8+(N+1)*8 != int(entry.length())) {
+  if ((isMacFile && 8+(N+1)*8 != int(entry.length())) || (!isMacFile && 8+(N+1)*8 > int(entry.length()))) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readColors: the N value seems bad\n"));
     f << "###";
     ascii().addPos(pos);
@@ -1653,12 +1945,17 @@ bool PowerPoint1Parser::readColors(MWAWEntry const &entry)
     ascii().addPos(pos);
     ascii().addNote(f.str().c_str());
   }
+  if (input->tell()!=entry.end()) {
+    ascii().addPos(input->tell());
+    ascii().addNote("Color:extra");
+  }
   return true;
 }
 
 bool PowerPoint1Parser::readColorZone(MWAWEntry const &entry)
 {
-  if (!entry.valid() || (entry.length()<48)) {
+  bool const isMacFile=m_state->m_isMacFile;
+  if (!entry.valid() || (entry.length()<(isMacFile ? 48 : 43))) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readColorZone: the zone seems bad\n"));
     return false;
   }
@@ -1670,7 +1967,7 @@ bool PowerPoint1Parser::readColorZone(MWAWEntry const &entry)
   f << "Entries(Color)[Z"<< entry.id() << "]:menu,";
   int N=int(input->readULong(2));
   f << "N=" << N << ",";
-  if (48+2*N!=int(entry.length())) {
+  if ((isMacFile && 48+2*N!=int(entry.length())) || (!isMacFile && 43+2*N>int(entry.length()))) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readColorZone: the N value seems bad\n"));
     f << "###";
     ascii().addPos(pos);
@@ -1681,7 +1978,7 @@ bool PowerPoint1Parser::readColorZone(MWAWEntry const &entry)
   }
   int val=int(input->readLong(2)); // always a
   if (val!=10) f << "f0=" << val << ",";
-  int id=int(input->readLong(4));
+  int id=int(input->readLong(isMacFile ? 4 : 2));
   int const numZones=int(m_state->m_zonesList.size());
   if (id>0 && id<numZones)
     f << "colors=Z" << id << ",";
@@ -1694,7 +1991,7 @@ bool PowerPoint1Parser::readColorZone(MWAWEntry const &entry)
   }
   ascii().addDelimiter(input->tell(),'|');
   // unsure probably some dimension here
-  input->seek(pos+46, librevenge::RVNG_SEEK_SET);
+  input->seek(pos+(isMacFile ? 46 : 43), librevenge::RVNG_SEEK_SET);
   ascii().addDelimiter(input->tell(),'|');
   f << "num[used]=[";
   for (int i=0; i<N; ++i) { // 0|1|2
@@ -1703,8 +2000,12 @@ bool PowerPoint1Parser::readColorZone(MWAWEntry const &entry)
     else f << "_,";
   }
   f << "],";
-  val=int(input->readULong(2));
-  if (val) f << "g0=" << std::hex << val << std::dec << ",";
+  if (isMacFile) {
+    val=int(input->readULong(2));
+    if (val) f << "g0=" << std::hex << val << std::dec << ",";
+  }
+  if (input->tell()!=entry.end())
+    ascii().addDelimiter(input->tell(),'|');
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
   ascii().addPos(entry.end());
@@ -1717,7 +2018,8 @@ bool PowerPoint1Parser::readColorZone(MWAWEntry const &entry)
 
 bool PowerPoint1Parser::readFonts(MWAWEntry const &entry)
 {
-  if (!entry.valid() || (entry.length()%6)!=0) {
+  static bool isMacFile=m_state->m_isMacFile;
+  if (!entry.valid() || entry.length()<(isMacFile ? 6 : 13) || (isMacFile && entry.length()%6)!=0) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readFonts: the zone seems bad\n"));
     return false;
   }
@@ -1726,19 +2028,28 @@ bool PowerPoint1Parser::readFonts(MWAWEntry const &entry)
   entry.setParsed(true);
   input->seek(pos, librevenge::RVNG_SEEK_SET);
   libmwaw::DebugStream f;
-  f << "Entries(Font)[Z"<< entry.id() << "]:";
+  f << "Entries(FontDef)[Z"<< entry.id() << "]:";
+  size_t N=size_t(entry.length()/6);
+  if (!isMacFile) {
+    N=size_t(input->readULong(2)); // always 6?
+    if (long(6+7*N)>entry.length()) {
+      MWAW_DEBUG_MSG(("PowerPoint1Parser::readFonts: the zone seems bad\n"));
+      return false;
+    }
+    f << "N=" << N << ",";
+    f << "id=" << std::hex << input->readULong(4) << std::dec << ","; // big number
+  }
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
 
-  size_t N=size_t(entry.length()/6);
   for (size_t i=0; i<N; ++i) {
     pos=input->tell();
     f.str("");
-    f << "Font-F" << i << ":";
+    f << "FontDef-F" << i << ":";
     MWAWFont font;
     font.setId(int(input->readULong(2)));
     font.setSize(float(input->readULong(2)));
-    int flag = int(input->readULong(1));
+    int flag = int(input->readULong(isMacFile ? 1 : 2));
     uint32_t flags=0;
     if (flag&0x1) flags |= MWAWFont::boldBit;
     if (flag&0x2) flags |= MWAWFont::italicBit;
@@ -1748,13 +2059,94 @@ bool PowerPoint1Parser::readFonts(MWAWEntry const &entry)
     if (flag&0xE0) f << "#flag=" << (flag>>5) << ",";
     font.setFlags(flags);
     f << font.getDebugString(getParserState()->m_fontConverter);
-    int val=int(input->readULong(1)); // another flag ?
+    int val=int(input->readULong(1)); // 1-4: another flag or maybe the font's color ?
     if (val) f << "fl=" << std::hex << val << std::dec << ",";
     ascii().addPos(pos);
     ascii().addNote(f.str().c_str());
   }
   ascii().addPos(entry.end());
   ascii().addNote("_");
+  if (input->tell()!=entry.end()) {
+    ascii().addPos(input->tell());
+    ascii().addNote("FontDef:extra");
+  }
+  return true;
+}
+
+bool PowerPoint1Parser::readFontNames(MWAWEntry const &entry)
+{
+  if (!entry.valid() || entry.length()<16) {
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readFontNames: the zone seems bad\n"));
+    return false;
+  }
+  MWAWInputStreamPtr input = getInput();
+  long pos = entry.begin();
+  entry.setParsed(true);
+  input->seek(pos, librevenge::RVNG_SEEK_SET);
+  libmwaw::DebugStream f;
+  f << "Entries(FontName)[Z"<< entry.id() << "]:";
+  int val;
+  for (int i=0; i<2; ++i) {
+    val=int(input->readULong(2));
+    int const(expected[])= {0x8001,0x25ba};
+    if (val!=expected[i])
+      f << "f" << i << "=" << std::hex << val << std::dec << ",";
+  }
+  size_t N=size_t(input->readULong(2)); // always 6?
+  if (long(16+52*N)>entry.length()) {
+    MWAW_DEBUG_MSG(("PowerPoint1Parser::readFontNames: the zone seems bad\n"));
+    return false;
+  }
+  f << "N=" << N << ",";
+  for (int i=0; i<5; ++i) {
+    val=int(input->readULong(2));
+    int const(expected[])= {0x7fff,0,0x32,0,0};
+    if (val!=expected[i])
+      f << "f" << i << "=" << std::hex << val << std::dec << ",";
+  }
+  ascii().addPos(pos);
+  ascii().addNote(f.str().c_str());
+
+  for (size_t i=0; i<N; ++i) {
+    pos=input->tell();
+    f.str("");
+    f << "FontName-FN" << i << ":";
+    val=int(input->readULong(2));
+    if (!val) {
+      f << "_,";
+      input->seek(pos+52,librevenge::RVNG_SEEK_SET);
+      ascii().addPos(pos);
+      ascii().addNote(f.str().c_str());
+      continue;
+    }
+    f << "id=" << val << ",";
+    for (int j=0; j<9; ++j) { // f4=0|190, f8=0|22|52
+      val=int(input->readULong(2));
+      if (val)
+        f << "f" << j << "=" << std::hex << val << std::dec << ",";
+    }
+    std::string name; // Helv, Tms Rmn, ZapfDingbats
+    for (int c=0; c<32; ++c) {
+      char ch=char(input->readULong(1));
+      if (!ch) break;
+      name+=ch;
+    }
+    if (!name.empty()) {
+      f << name << ",";
+      /* FIXME: by default, we force the family to be CP1252,
+         but we may want to use the file/font encoding */
+      getFontConverter()->setCorrespondance(int(i), name, (name=="MonoType Sorts" || name=="Wingdings") ? "" : "CP1252");
+    }
+    input->seek(pos+52,librevenge::RVNG_SEEK_SET);
+    ascii().addPos(pos);
+    ascii().addNote(f.str().c_str());
+  }
+  ascii().addPos(entry.end());
+  ascii().addNote("_");
+  if (input->tell()!=entry.end()) {
+    ascii().addPos(input->tell());
+    ascii().addNote("FontName:extra");
+  }
   return true;
 }
 
@@ -1769,7 +2161,8 @@ bool PowerPoint1Parser::readSchemes()
 }
 bool PowerPoint1Parser::readScheme(MWAWEntry const &entry, int id)
 {
-  if (!entry.valid() || entry.length()!=86) {
+  bool const isMacFile=m_state->m_isMacFile;
+  if (!entry.valid() || (isMacFile && entry.length()!=86) || (!isMacFile && entry.length() < 96)) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readScheme: the zone seems bad\n"));
     return false;
   }
@@ -1781,12 +2174,24 @@ bool PowerPoint1Parser::readScheme(MWAWEntry const &entry, int id)
   libmwaw::DebugStream f;
   f << "Entries(Scheme)[Z"<< entry.id() << "]:S" << id << ",";
   int val;
-  for (int i=0; i<11; ++i) { // f8=0|80
-    val=int(input->readLong(2));
-    int const(expected[])= {16,0,0,100,100,100, 0x101, 0, 0, 0, 7};
-    if (val!=expected[i])
-      f << "f" << i << "=" << val << ",";
+  if (isMacFile) {
+    for (int i=0; i<10; ++i) { // f8=0|80
+      val=int(input->readLong(2));
+      int const(expected[])= {16,0,0,100,100,100, 0x101, 0, 0, 0};
+      if (val!=expected[i])
+        f << "f" << i << "=" << val << ",";
+    }
+  }
+  else {
+    for (int i=0; i<12; ++i) { // f9=0|80
+      val=int(input->readLong(i==3 ? 1 : 2));
+      int const(expected[])= {0,16,0,0, 100,100,100, 1, 1, 0, 0, 0};
+      if (val!=expected[i])
+        f << "f" << i << "=" << val << ",";
+    }
   }
+  val=int(input->readLong(2));
+  if (val!=7) f << "max[color]=##" << val << ",";
   f << "colors=[";
   for (int i=0; i<8; ++i) {
     val=int(input->readULong(2));
@@ -1801,6 +2206,8 @@ bool PowerPoint1Parser::readScheme(MWAWEntry const &entry, int id)
   }
   else
     m_state->m_idToSchemeMap[id]=scheme;
+  if (input->tell()!=entry.end())
+    ascii().addDelimiter(input->tell(),'|');
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
   ascii().addPos(entry.end());
@@ -1810,6 +2217,7 @@ bool PowerPoint1Parser::readScheme(MWAWEntry const &entry, int id)
 
 bool PowerPoint1Parser::readZone2(MWAWEntry const &entry)
 {
+  // probably the document current style
   int const expectedSize=m_state->m_isMacFile ? 22 : 32;
   if (!entry.valid() || entry.length()!=expectedSize) {
     MWAW_DEBUG_MSG(("PowerPoint1Parser::readZone2: the zone seems bad\n"));
@@ -1913,6 +2321,7 @@ bool PowerPoint1Parser::sendText(PowerPoint1ParserInternal::TextZone const &text
     tId[1]=tId[0];
   }
   PowerPoint1ParserInternal::Ruler ruler;
+  bool const isMacFile=m_state->m_isMacFile;
   bool hasRuler=false;
   if (rulerId>=0 && rulerId<int(m_state->m_rulersList.size())) {
     ruler=m_state->m_rulersList[size_t(rulerId)];
@@ -1924,10 +2333,12 @@ bool PowerPoint1Parser::sendText(PowerPoint1ParserInternal::TextZone const &text
   MWAWInputStreamPtr input = getInput();
   long pos;
   int const vers=version();
+  double const unit=double(m_state->m_unit);
   for (int z=tId[0]; z<=tId[1]; ++z) {
     if (z!=tId[0]) listener->insertEOL();
     PowerPoint1ParserInternal::TextZone::Line const &line=textZone.m_lineList[size_t(z)];
     MWAWEntry const &fEntry=line.m_format;
+    MWAWEntry const &rEntry=line.m_ruler;
     MWAWEntry const &tEntry=line.m_text;
     // update the paragraph
     MWAWParagraph para;
@@ -1937,28 +2348,32 @@ bool PowerPoint1Parser::sendText(PowerPoint1ParserInternal::TextZone const &text
       PowerPoint1ParserInternal::Ruler::Outline const &outline=ruler.m_outlines[line.m_outlineLevel];
       para.m_marginsUnit=librevenge::RVNG_POINT;
       for (int i=0; i<2; ++i)
-        para.m_margins[i]=double(outline.m_margins[i]);
+        para.m_margins[i]=unit*double(outline.m_margins[i]);
       *para.m_margins[0]-=*(para.m_margins[1]);
-      para.setInterline(double(outline.m_interlines[0])*0.1, librevenge::RVNG_PERCENT);
+      para.setInterline(double(outline.m_interlines[0])*0.01, librevenge::RVNG_PERCENT);
       if (outline.m_interlines[1]>outline.m_interlines[0]) // assume 12 pt
-        para.m_spacings[2]=double(outline.m_interlines[1]-outline.m_interlines[0])*0.1*12/72;
+        para.m_spacings[2]=double(outline.m_interlines[1]-outline.m_interlines[0])*0.01*12/72;
     }
     listener->setParagraph(para);
     // now read the format
     input->seek(fEntry.begin(), librevenge::RVNG_SEEK_SET);
-    int const dtSz=vers==1 ? 6 : 8;
+    int const dtSz=vers==1 ? 6 : isMacFile ? 8 : 14;
     int N=(fEntry.length()%dtSz)==0 ? int(fEntry.length()/dtSz) : 0;
     libmwaw::DebugStream f;
     std::map<int, MWAWFont> posToFontMap;
+    int cPos=0;
     for (int i=0; i<N; ++i) {
       pos=input->tell();
       f.str("");
       f << "TextZone-F[" << i << "]:";
-      int cPos=int(input->readULong(2));
+      int numC=int(input->readULong(2));
+      if (isMacFile) cPos=numC;
       f << "pos=" << cPos << ",";
       MWAWFont font;
-      font.setSize(float(input->readULong(1)));
-      int flag = int(input->readULong(1));
+      if (!isMacFile)
+        font.setId(int(input->readULong(2)));
+      font.setSize(float(input->readULong(isMacFile ? 1 : 2)));
+      int flag = int(input->readULong(isMacFile ? 1 : 2));
       uint32_t flags=0;
       if (flag&0x1) flags |= MWAWFont::boldBit;
       if (flag&0x2) flags |= MWAWFont::italicBit;
@@ -1967,8 +2382,9 @@ bool PowerPoint1Parser::sendText(PowerPoint1ParserInternal::TextZone const &text
       if (flag&0x10) flags |= MWAWFont::shadowBit;
       if (flag&0xE0) f << "#flag=" << (flag>>5) << ",";
       font.setFlags(flags);
-      font.setId(int(input->readULong(2)));
-      if (dtSz==8) {
+      if (isMacFile)
+        font.setId(int(input->readULong(2)));
+      if (dtSz>=8) {
         int col=int(input->readULong(1));
         MWAWColor color;
         if (textZone.m_schemeId>=0 && getColor(col, textZone.m_schemeId, color)) {
@@ -1988,13 +2404,79 @@ bool PowerPoint1Parser::sendText(PowerPoint1ParserInternal::TextZone const &text
       else
         posToFontMap[cPos]=font;
       f << font.getDebugString(getParserState()->m_fontConverter);
+      if (input->tell()!=pos+dtSz)
+        ascii().addDelimiter(input->tell(),'|');
       input->seek(pos+dtSz, librevenge::RVNG_SEEK_SET);
       ascii().addPos(pos);
       ascii().addNote(f.str().c_str());
+      if (!isMacFile) cPos+=numC;
+    }
+    std::map<int, MWAWParagraph> posToRulerMap;
+    if (rEntry.valid()) {
+      // now read the rulers
+      input->seek(rEntry.begin(), librevenge::RVNG_SEEK_SET);
+      N=(rEntry.length()%6)==0 ? int(rEntry.length()/6) : 0;
+      cPos=0;
+      for (int i=0; i<N; ++i) {
+        pos=input->tell();
+        f.str("");
+        f << "TextZone-R[" << i << "]:";
+        int numC=int(input->readULong(2));
+        f << "pos=" << cPos << ",";
+        MWAWParagraph cPara(para);
+        int outlineLevel=int(input->readULong(2));
+        if (hasRuler && outlineLevel>0 && outlineLevel<=4) {
+          f << "level=" << outlineLevel << ",";
+          PowerPoint1ParserInternal::Ruler::Outline const &outline=ruler.m_outlines[outlineLevel];
+          cPara.m_marginsUnit=librevenge::RVNG_POINT;
+          for (int j=0; j<2; ++j)
+            cPara.m_margins[j]=unit*double(outline.m_margins[j]);
+          *cPara.m_margins[0]-=*(cPara.m_margins[1]);
+          cPara.setInterline(double(outline.m_interlines[0])*0.01, librevenge::RVNG_PERCENT);
+          if (outline.m_interlines[1]>outline.m_interlines[0]) // assume 12 pt
+            cPara.m_spacings[2]=double(outline.m_interlines[1]-outline.m_interlines[0])*0.01*12/72;
+        }
+        else if (outlineLevel>4) {
+          MWAW_DEBUG_MSG(("PowerPoint1Parser::sendText: oops, the outline level seems bad\n"));
+          f << "###outlineLevel=" << outlineLevel << ",";
+        }
+        int adjust=int(input->readULong(2));
+        switch (adjust) {
+        case 0: // left
+          cPara.m_justify=MWAWParagraph::JustificationLeft;
+          break;
+        case 1:
+          cPara.m_justify=MWAWParagraph::JustificationCenter;
+          f << "center,";
+          break;
+        case 2:
+          cPara.m_justify=MWAWParagraph::JustificationRight;
+          f << "right,";
+          break;
+        case 3:
+          cPara.m_justify=MWAWParagraph::JustificationFull;
+          f << "justify,";
+          break;
+        default:
+          MWAW_DEBUG_MSG(("PowerPoint1Parser::sendText: find unknown alignment\n"));
+          f << "##align=" << adjust << ",";
+          break;
+        }
+        if (posToRulerMap.find(cPos)!=posToRulerMap.end()) {
+          MWAW_DEBUG_MSG(("PowerPoint1Parser::sendText: oops, find duplicated paragraph\n"));
+          f << "##dup,";
+        }
+        else
+          posToRulerMap[cPos]=cPara;
+        ascii().addPos(pos);
+        ascii().addNote(f.str().c_str());
+        cPos+=numC;
+      }
     }
-
     input->seek(tEntry.begin(), librevenge::RVNG_SEEK_SET);
     for (int i=0; i<int(tEntry.length()); ++i) {
+      if (posToRulerMap.find(i)!=posToRulerMap.end())
+        listener->setParagraph(posToRulerMap.find(i)->second);
       if (posToFontMap.find(i)!=posToFontMap.end())
         listener->setFont(posToFontMap.find(i)->second);
       unsigned char c=static_cast<unsigned char>(input->readULong(1));
@@ -2039,7 +2521,8 @@ bool PowerPoint1Parser::sendFrame(PowerPoint1ParserInternal::Frame const &frame,
     MWAW_DEBUG_MSG(("PowerPoint1Parser::sendFrame: can not find the listener\n"));
     return false;
   }
-  MWAWBox2i fBox(frame.m_dimension[0]+m_state->m_origin, frame.m_dimension[1]+m_state->m_origin);
+  MWAWBox2f fBox(m_state->m_unit*MWAWVec2f(frame.m_dimension[0]+m_state->m_origin),
+                 m_state->m_unit*MWAWVec2f(frame.m_dimension[1]+m_state->m_origin));
   if (frame.m_textId[0]>=0) {
     MWAWPosition pos(fBox[0], fBox.size(), librevenge::RVNG_POINT);
     pos.m_anchorTo = MWAWPosition::Page;
@@ -2054,7 +2537,7 @@ bool PowerPoint1Parser::sendFrame(PowerPoint1ParserInternal::Frame const &frame,
     if (frame.m_type==0)
       shape=MWAWGraphicShape::line(fBox[0], fBox[1]);
     else {
-      if (frame.m_cornerSize >= frame.m_dimension.size()[0] || frame.m_cornerSize >= frame.m_dimension.size()[1])
+      if (frame.m_cornerSize >= fBox.size()[0] || frame.m_cornerSize >= fBox.size()[1])
         shape=MWAWGraphicShape::circle(fBox);
       else
         shape=MWAWGraphicShape::rectangle(fBox, MWAWVec2f(float(frame.m_cornerSize)/2.f, float(frame.m_cornerSize)/2.f));
@@ -2096,17 +2579,13 @@ bool PowerPoint1Parser::checkHeader(MWAWHeader *header, bool strict)
   input->setReadInverted(false);
   input->seek(pos, librevenge::RVNG_SEEK_SET);
   unsigned long signature=input->readULong(4);
-#ifdef DEBUG
   if (signature==0xeddead0b) {
     input->setReadInverted(true);
     m_state->m_isMacFile=false;
+    m_state->m_unit=1.f/8.f;
   }
   else if (signature!=0xbaddeed)
     return false;
-#else
-  if (signature!=0xbaddeed)
-    return false;
-#endif
   f << "FileHeader:";
   int vers=int(input->readLong(4));
   if (vers!=2) return false;
diff --git a/src/lib/PowerPoint1Parser.hxx b/src/lib/PowerPoint1Parser.hxx
index 58cc2aa..1e02caa 100644
--- a/src/lib/PowerPoint1Parser.hxx
+++ b/src/lib/PowerPoint1Parser.hxx
@@ -101,12 +101,18 @@ protected:
   bool readColorZone(MWAWEntry const &entry);
   //! try to read a font style list
   bool readFonts(MWAWEntry const &entry);
+  //! try to read a font names list
+  bool readFontNames(MWAWEntry const &entry);
   //! try to read a picture zone
   bool readPicture(MWAWEntry const &entry, MWAWEmbeddedObject &picture);
+  //! try to read the picture definition: windows v2
+  bool readPictureDefinition(MWAWEntry const &entry, size_t id);
   //! try to read a print info zone
   bool readPrintInfo(MWAWEntry const &entry);
   //! try to read the paragraph style
   bool readRulers(MWAWEntry const &entry);
+  //! try to read some ruler: windows v2
+  bool readRuler(MWAWEntry const &entry, size_t id);
   //! try to read a scheme
   bool readScheme(MWAWEntry const &entry, int id);
   //! try to read the schemes
diff --git a/src/lib/PowerPoint3OLE.cxx b/src/lib/PowerPoint3OLE.cxx
new file mode 100644
index 0000000..ad7b884
--- /dev/null
+++ b/src/lib/PowerPoint3OLE.cxx
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
+
+/* libmwaw
+* Version: MPL 2.0 / LGPLv2+
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 2.0 (the "License"); you may not use this file except in compliance with
+* the License or as specified alternatively below. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* Major Contributor(s):
+* Copyright (C) 2002 William Lachance (wrlach at gmail.com)
+* Copyright (C) 2002,2004 Marc Maurer (uwog at uwog.net)
+* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+* Copyright (C) 2006, 2007 Andrew Ziem
+* Copyright (C) 2011, 2012 Alonso Laurent (alonso at loria.fr)
+*
+*
+* All Rights Reserved.
+*
+* For minor contributions see the git repository.
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
+* in which case the provisions of the LGPLv2+ are applicable
+* instead of those above.
+*/
+
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <set>
+#include <sstream>
+#include <utility>
+
+#include <librevenge/librevenge.h>
+
+#include "MWAWDebug.hxx"
+#include "MWAWEntry.hxx"
+#include "MWAWOLEParser.hxx"
+
+#include "PowerPoint3OLE.hxx"
+
+/** Internal: the structures of a PowerPoint3OLE */
+namespace PowerPoint3OLEInternal
+{
+////////////////////////////////////////
+//! Internal: the state of a PowerPoint3OLE
+struct State {
+  //! constructor
+  explicit State(MWAWInputStreamPtr input) : m_input(input), m_oleParser(), m_unparsedNameSet()
+  {
+  }
+  /** the input */
+  MWAWInputStreamPtr m_input;
+  /** the ole parser */
+  shared_ptr<MWAWOLEParser> m_oleParser;
+  /** the list of unparsed zone */
+  std::set<std::string> m_unparsedNameSet;
+};
+
+}
+
+////////////////////////////////////////////////////////////
+// constructor/destructor, ...
+////////////////////////////////////////////////////////////
+PowerPoint3OLE::PowerPoint3OLE(MWAWInputStreamPtr input, MWAWFontConverterPtr fontConverter, int fId) : m_state(new PowerPoint3OLEInternal::State(input))
+{
+  if (input && input->isStructured() && input->getSubStreamByName("PP40"))
+    m_state->m_oleParser.reset(new MWAWOLEParser("PP40", fontConverter, fId));
+}
+
+PowerPoint3OLE::~PowerPoint3OLE()
+{
+}
+
+void PowerPoint3OLE::updateMetaData(librevenge::RVNGPropertyList &metaData) const
+{
+  if (m_state->m_oleParser)
+    m_state->m_oleParser->updateMetaData(metaData);
+}
+
+////////////////////////////////////////////////////////////
+// the parser
+////////////////////////////////////////////////////////////
+bool PowerPoint3OLE::parse()
+{
+  MWAWInputStreamPtr input=m_state->m_input;
+  if (!input || !m_state->m_oleParser || !m_state->m_oleParser->parse(input)) return false;
+  std::vector<std::string> unparsed = m_state->m_oleParser->getNotParse();
+
+  size_t numUnparsed = unparsed.size();
+  for (size_t i = 0; i < numUnparsed; i++) {
+    std::string const &name = unparsed[i];
+    // separated the directory and the name
+    //    MatOST/MatadorObject1/Ole10Native
+    //      -> dir="MatOST/MatadorObject1", base="Ole10Native"
+    std::string::size_type pos = name.find_last_of('/');
+    std::string dir, base;
+    if (pos == std::string::npos) base = name;
+    else if (pos == 0) base = name.substr(1);
+    else {
+      dir = name.substr(0,pos);
+      base = name.substr(pos+1);
+    }
+    if (dir.empty() && base=="PP40") continue;
+
+    MWAWInputStreamPtr ole = input->getSubStreamByName(name.c_str());
+    if (!ole.get()) {
+      MWAW_DEBUG_MSG(("PowerPoint3OLE::createZones: error: can not find OLE part: \"%s\"\n", name.c_str()));
+      continue;
+    }
+    ole->setReadInverted(true);
+    bool done=false;
+    switch (base[0]) {
+    case 'C':
+      if (base=="Current User")
+        done=parseCurrentUser(ole, name);
+      else if (base=="Current ID")
+        done=parseCurrentId(ole, name);
+      break;
+    default:
+      break;
+    }
+    if (done) continue;
+    m_state->m_unparsedNameSet.insert(name);
+  }
+  return true;
+}
+
+void PowerPoint3OLE::checkForUnparsedStream()
+{
+  for (std::set<std::string>::const_iterator it=m_state->m_unparsedNameSet.begin(); it!=m_state->m_unparsedNameSet.end(); ++it) {
+    std::string const &name = *it;
+    std::string::size_type pos = name.find_last_of('/');
+    std::string dir, base;
+    if (pos == std::string::npos) base = name;
+    else if (pos == 0) base = name.substr(1);
+    else {
+      dir = name.substr(0,pos);
+      base = name.substr(pos+1);
+    }
+
+    MWAWInputStreamPtr ole = m_state->m_input->getSubStreamByName(name.c_str());
+    if (!ole.get()) {
+      MWAW_DEBUG_MSG(("PowerPoint3OLE::checkForUnparsedStream: error: can not find OLE part: \"%s\"\n", name.c_str()));
+      continue;
+    }
+    libmwaw::DebugFile asciiFile(ole);
+    asciiFile.open(name);
+    libmwaw::DebugStream f;
+    f << "Entries(" << base << "):";
+    asciiFile.addPos(0);
+    asciiFile.addNote(f.str().c_str());
+  }
+}
+
+////////////////////////////////////////////////////////////
+// try to read the different stream
+////////////////////////////////////////////////////////////
+bool PowerPoint3OLE::parseCurrentId(MWAWInputStreamPtr input, std::string const &name)
+{
+  if (!input||input->size()!=4) {
+    MWAW_DEBUG_MSG(("PowerPoint3OLE::parseCurrentId: can not find the input\n"));
+    return false;
+  }
+  libmwaw::DebugFile ascFile(input);
+  ascFile.open(name);
+  input->seek(0, librevenge::RVNG_SEEK_SET);
+  libmwaw::DebugStream f;
+  f << "Entries(CurrentId):";
+  int val=int(input->readLong(4));
+  if (val) f << "id=" << val << ",";
+  ascFile.addPos(0);
+  ascFile.addNote(f.str().c_str());
+  return true;
+}
+
+bool PowerPoint3OLE::parseCurrentUser(MWAWInputStreamPtr input, std::string const &name)
+{
+  if (!input||input->size()==0) {
+    MWAW_DEBUG_MSG(("PowerPoint3OLE::parseCurrentUser: can not find the input\n"));
+    return false;
+  }
+  libmwaw::DebugFile ascFile(input);
+  ascFile.open(name);
+  input->seek(0, librevenge::RVNG_SEEK_SET);
+  long endPos=input->size();
+  libmwaw::DebugStream f;
+  f << "Entries(CurrentUser):";
+  int sSz=int(input->readULong(1));
+  if (sSz<0 || sSz+1>input->size()) {
+    MWAW_DEBUG_MSG(("PowerPoint3OLE::parseCurrentUser: the stream size seems bad\n"));
+    f << "###sSz,";
+    ascFile.addPos(0);
+    ascFile.addNote(f.str().c_str());
+    return true;
+  }
+  std::string user;
+  for (int c=0; c<sSz; ++c) {
+    char ch=char(input->readULong(1));
+    if (ch)
+      user+=ch;
+    else if (c+1!=sSz)
+      f << "###";
+  }
+  f << user;
+  ascFile.addPos(0);
+  ascFile.addNote(f.str().c_str());
+  if (input->tell()!=endPos) {
+    ascFile.addPos(input->tell());
+    ascFile.addNote("CurrentUser:##extra");
+  }
+  return true;
+}
+
+
+////////////////////////////////////////////////////////////
+// try to send data
+////////////////////////////////////////////////////////////
+
+
+// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
diff --git a/src/lib/PowerPoint3OLE.hxx b/src/lib/PowerPoint3OLE.hxx
new file mode 100644
index 0000000..bb62203
--- /dev/null
+++ b/src/lib/PowerPoint3OLE.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
+
+/* libmwaw
+* Version: MPL 2.0 / LGPLv2+
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 2.0 (the "License"); you may not use this file except in compliance with
+* the License or as specified alternatively below. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* Major Contributor(s):
+* Copyright (C) 2002 William Lachance (wrlach at gmail.com)
+* Copyright (C) 2002,2004 Marc Maurer (uwog at uwog.net)
+* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+* Copyright (C) 2006, 2007 Andrew Ziem
+* Copyright (C) 2011, 2012 Alonso Laurent (alonso at loria.fr)
+*
+*
+* All Rights Reserved.
+*
+* For minor contributions see the git repository.
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
+* in which case the provisions of the LGPLv2+ are applicable
+* instead of those above.
+*/
+
+#ifndef POWER_POINT3_OLE
+#  define POWER_POINT3_OLE
+
+#include <string>
+
+#include "MWAWInputStream.hxx"
+
+#include "MWAWParser.hxx"
+
+namespace PowerPoint3OLEInternal
+{
+struct State;
+}
+
+/** \brief the main class to read the ole stream in a Microsoft PowerPoint v4 files (MacOs and Windows)
+ */
+class PowerPoint3OLE
+{
+public:
+  //! constructor
+  PowerPoint3OLE(MWAWInputStreamPtr input, MWAWFontConverterPtr fontConverter, int fId);
+  //! destructor
+  virtual ~PowerPoint3OLE();
+
+  // the main parse function
+  bool parse();
+  /** update the meta data, using information find in SummaryInformation */
+  void updateMetaData(librevenge::RVNGPropertyList &metaData) const;
+  //! check for unparsed stream
+  void checkForUnparsedStream();
+
+protected:
+  //
+  // internal level
+  //
+
+  //! try to parse the "Current User" stream
+  bool parseCurrentUser(MWAWInputStreamPtr input, std::string const &name);
+  //! try to parse the "Current Id" stream
+  bool parseCurrentId(MWAWInputStreamPtr input, std::string const &name);
+
+  //
+  // send data
+  //
+
+  //
+  // low level
+  //
+
+protected:
+  //
+  // data
+  //
+  //! the state
+  shared_ptr<PowerPoint3OLEInternal::State> m_state;
+};
+#endif
+// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
diff --git a/src/lib/PowerPoint3Parser.cxx b/src/lib/PowerPoint3Parser.cxx
index 9ecbe1b..a1eaea1 100644
--- a/src/lib/PowerPoint3Parser.cxx
+++ b/src/lib/PowerPoint3Parser.cxx
@@ -52,6 +52,8 @@
 
 #include "PowerPoint3Parser.hxx"
 
+#include "PowerPoint3OLE.hxx"
+
 /** Internal: the structures of a PowerPoint3Parser */
 namespace PowerPoint3ParserInternal
 {
@@ -223,7 +225,7 @@ struct Ruler {
   {
     o << "margins=[";
     for (int i=0; i<5; ++i)
-      o << double(ruler.m_margins[1]-ruler.m_margins[0])/8 << ":" << double(ruler.m_margins[0])/8 << ",";
+      o << double(ruler.m_margins[2*i+1]-ruler.m_margins[2*i])/8 << ":" << double(ruler.m_margins[2*i])/8 << ",";
     o << "],";
     o << ruler.m_paragraph;
     return o;
@@ -232,7 +234,7 @@ struct Ruler {
   void updateParagraph(MWAWParagraph &para, int level) const
   {
     if (level<0 || level>4) {
-      MWAW_DEBUG_MSG(("PowerPoint3ParserInternal::ListZoneIdParser::parse: the level %d seems bad\n", level));
+      MWAW_DEBUG_MSG(("PowerPoint3ParserInternal::Ruler::updateParagraph: the level %d seems bad\n", level));
       level=0;
     }
     para.m_marginsUnit=librevenge::RVNG_POINT;
@@ -416,7 +418,7 @@ struct Slide {
 //! Internal: the state of a PowerPoint3Parser
 struct State {
   //! constructor
-  State() : m_isMacFile(true), m_zoneListBegin(0), m_zonesList(),
+  State() : m_isMacFile(true), m_oleParser(), m_zoneListBegin(0), m_zonesList(),
     m_slidesIdList(), m_idToSlideMap(), m_idToSlideContentMap(), m_idToSchemeMap(), m_pictIdToZoneIdMap(), m_idToPictureContentMap(),
     m_origin(0,0), m_idToUserColorMap(), m_idToFontIdMap(), m_idToRulerMap(),
     m_monoTypeFontId(-1), m_badEntry()
@@ -442,6 +444,8 @@ struct State {
   static bool getCustomShape(int id, MWAWGraphicShape &shape);
   //! flag to know if the file is a mac file or a pc file
   bool m_isMacFile;
+  //! the ole parser
+  shared_ptr<PowerPoint3OLE> m_oleParser;
   //! the begin position of the list of zones
   long m_zoneListBegin;
   //! the list of zone entries
@@ -650,11 +654,11 @@ class SubDocument : public MWAWSubDocument
 {
 public:
   //! constructor for text
-  SubDocument(PowerPoint3Parser &pars, MWAWInputStreamPtr input, SlideContent const *slide, int tId, bool mainZone) :
-    MWAWSubDocument(&pars, input, MWAWEntry()), m_slide(slide), m_textId(tId), m_mainTextBox(mainZone) {}
+  SubDocument(PowerPoint3Parser &pars, MWAWInputStreamPtr input, SlideContent const *slide, int tId, bool mainZone, bool master) :
+    MWAWSubDocument(&pars, input, MWAWEntry()), m_slide(slide), m_textId(tId), m_mainTextBox(mainZone), m_isMaster(master) {}
   //! constructor for note
   SubDocument(PowerPoint3Parser &pars, MWAWInputStreamPtr input, SlideContent const *slide) :
-    MWAWSubDocument(&pars, input, MWAWEntry()), m_slide(slide), m_textId(-1), m_mainTextBox(false) {}
+    MWAWSubDocument(&pars, input, MWAWEntry()), m_slide(slide), m_textId(-1), m_mainTextBox(false), m_isMaster(false) {}
 
   //! destructor
   virtual ~SubDocument() {}
@@ -668,6 +672,7 @@ public:
     if (m_slide != sDoc->m_slide) return true;
     if (m_textId != sDoc->m_textId) return true;
     if (m_mainTextBox != sDoc->m_mainTextBox) return true;
+    if (m_isMaster != sDoc->m_isMaster) return true;
     return false;
   }
   //! operator!==
@@ -686,6 +691,8 @@ protected:
   int m_textId;
   //! flag to know if we send the title or the body
   bool m_mainTextBox;
+  //! flag to know if we send a master text zone
+  bool m_isMaster;
 private:
   SubDocument(SubDocument const &);
   SubDocument &operator=(SubDocument const &);
@@ -708,7 +715,7 @@ void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType)
   }
 
   long pos = m_input->tell();
-  parser->sendText(*m_slide, m_textId, m_mainTextBox);
+  parser->sendText(*m_slide, m_textId, m_mainTextBox, m_isMaster);
   m_input->seek(pos, librevenge::RVNG_SEEK_SET);
 }
 }
@@ -751,10 +758,6 @@ void PowerPoint3Parser::parse(librevenge::RVNGPresentationInterface *docInterfac
   if (!getInput().get() || !checkHeader(0L))  throw(libmwaw::ParseException());
   bool ok = true;
   try {
-    // create the asciiFile
-    ascii().setStream(getInput());
-    ascii().open(asciiName());
-    checkHeader(0L);
     ok = createZones();
     if (ok) {
       createDocument(docInterface);
@@ -763,6 +766,8 @@ void PowerPoint3Parser::parse(librevenge::RVNGPresentationInterface *docInterfac
 
 #ifdef DEBUG
     checkForUnparsedZones();
+    if (m_state->m_oleParser)
+      m_state->m_oleParser->checkForUnparsedStream();
 #endif
     ascii().reset();
   }
@@ -807,6 +812,11 @@ void PowerPoint3Parser::createDocument(librevenge::RVNGPresentationInterface *do
   //
   MWAWPresentationListenerPtr listen(new MWAWPresentationListener(*getParserState(), pageList, documentInterface));
   setPresentationListener(listen);
+  if (m_state->m_oleParser) {
+    librevenge::RVNGPropertyList metaData;
+    m_state->m_oleParser->updateMetaData(metaData);
+    listen->setDocumentMetaData(metaData);
+  }
   listen->startDocument();
 }
 
@@ -823,6 +833,31 @@ bool PowerPoint3Parser::createZones()
     MWAW_DEBUG_MSG(("PowerPoint3Parser::createZones: can not find the main input\n"));
     return false;
   }
+  bool const isMacFile=m_state->m_isMacFile;
+
+  shared_ptr<PowerPoint3OLE> oleParser;
+  if (input->isStructured()) {
+    MWAWInputStreamPtr mainOle=input->getSubStreamByName("PP40");
+    if (!mainOle) {
+      MWAW_DEBUG_MSG(("PowerPoint3Parser::createZones: can not find the main ole\n"));
+      return false;
+    }
+    int fId=3;
+    if (!isMacFile) {
+      // create a temporary font, to use a CP1252 encoding
+      fId=99999;
+      getFontConverter()->setCorrespondance(fId, "ConvertOLEFont", "CP1252");
+    }
+    oleParser.reset(new PowerPoint3OLE(input, getFontConverter(), fId));
+    oleParser->parse();
+    getParserState()->m_input=input=mainOle;
+    input->setReadInverted(!isMacFile);
+  }
+  // create the asciiFile
+  ascii().setStream(input);
+  ascii().open(asciiName());
+  if (!checkHeader(0L)) return false;
+  m_state->m_oleParser=oleParser;
   int docInfo;
   if (!readListZones(docInfo)) return false;
   size_t numZones=m_state->m_zonesList.size();
@@ -832,17 +867,21 @@ bool PowerPoint3Parser::createZones()
   }
   // first try to read the font name and scheme
   libmwaw::DebugStream f;
-  for (int w=0; w<2; ++w) {
-    int id=w==0 ? 11 : 7;
+  for (int w=0; w<3; ++w) {
+    int id=w==0 ? 11 : w==1 ? 7 : 8;
     MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_zoneIds[id]);
     if (!entry.valid()) continue;
-    if (w==0 && !m_state->m_isMacFile) {
+    if (w==2) {
+      readColorZone(entry);
+      continue;
+    }
+    if (w==0 && !isMacFile) {
       PowerPoint3ParserInternal::FontNameFieldParser parser(static_cast<int>(numZones));
       readStructList(entry, parser);
       for (std::map<int, std::string>::const_iterator it=parser.m_idToNameMap.begin(); it!=parser.m_idToNameMap.end(); ++it) {
         m_state->m_idToFontIdMap[it->first]=it->first;
         /* FIXME: by default, we force the family to be CP1252,
-         but we may want to use the font data */
+         but we may want to use the file/font encoding */
         getFontConverter()->setCorrespondance(it->first, it->second, it->second=="MonoType Sorts" || it->second=="Wingdings" ? "" : "CP1252");
       }
       for (size_t c=0; c<parser.m_childList.size(); ++c) {
@@ -899,9 +938,6 @@ bool PowerPoint3Parser::createZones()
       }
       break;
     }
-    case 8:
-      readColorZone(entry);
-      break;
     case 9:
       readZone9(entry);
       break;
@@ -929,7 +965,7 @@ bool PowerPoint3Parser::createZones()
   for (int i=0; i<2; ++i) {
     MWAWEntry const &entry=m_state->getZoneEntry(m_state->m_printInfoIds[i]);
     if (!entry.valid() || entry.isParsed()) continue;
-    if (m_state->m_isMacFile && i==0)
+    if (isMacFile && i==0)
       readPrintInfo(entry);
     else {
       entry.setParsed(true);
@@ -989,6 +1025,10 @@ bool PowerPoint3Parser::readListZones(int &docInfoId)
       f << "*";
       length&=0x7FFFFFFF;
     }
+    if (length&0x40000000) {
+      f << "@";
+      length&=0xBFFFFFFF;
+    }
     if (length==0) {
       f << "_,";
       continue;
@@ -1055,7 +1095,8 @@ void PowerPoint3Parser::checkForUnparsedZones()
 bool PowerPoint3Parser::readDocInfo(MWAWEntry const &entry)
 {
   MWAWInputStreamPtr input=getInput();
-  if (entry.length()!=142) {
+  int const vers=version();
+  if (entry.length()!=(vers<=3 ? 142 : 146)) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readDocInfo: the entry %d seems bad\n", entry.id()));
     return false;
   }
@@ -1076,15 +1117,15 @@ bool PowerPoint3Parser::readDocInfo(MWAWEntry const &entry)
   f << "],";
   for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
   if (!m_state->m_isMacFile) {
-    std::swap<int>(dim[0],dim[1]);
-    std::swap<int>(dim[2],dim[3]);
+    std::swap(dim[0],dim[1]);
+    std::swap(dim[2],dim[3]);
   }
   MWAWBox2i pageBox(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2]));
   f << "dim[page]=" << pageBox << ",";
   for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
   if (!m_state->m_isMacFile) {
-    std::swap<int>(dim[0],dim[1]);
-    std::swap<int>(dim[2],dim[3]);
+    std::swap(dim[0],dim[1]);
+    std::swap(dim[2],dim[3]);
   }
   MWAWBox2i paperBox=MWAWBox2i(MWAWVec2i(dim[0],dim[1]),MWAWVec2i(dim[2],dim[3]));
   f << "dim[paper]=" << paperBox << ",";
@@ -1190,12 +1231,20 @@ bool PowerPoint3Parser::readDocInfo(MWAWEntry const &entry)
     if (val!=expected[i])
       f << "g" << i << "=" << val << ",";
   }
-  for (int i=0; i<2; ++i) { // two big number
-    val=int(input->readULong(2));
-    if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ",";
+  if (vers<=3) {
+    for (int i=0; i<2; ++i) { // two big number
+      val=int(input->readULong(2));
+      if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ",";
+    }
+    val=int(input->readLong(2)); // 3|4
+    if (val) f << "g3=" << val << ",";
+  }
+  else {
+    for (int i=0; i<5; ++i) { // three big number
+      val=int(input->readULong(2));
+      if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ",";
+    }
   }
-  val=int(input->readLong(2)); // 3|4
-  if (val) f << "g3=" << val << ",";
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
   ascii().addPos(entry.end());
@@ -1249,7 +1298,7 @@ bool PowerPoint3Parser::readDocRoot(MWAWEntry const &entry)
   int val;
   for (int i=0; i<2; ++i) { // fl0=[359][4c], fl1=0|c
     val=int(input->readULong(1));
-    if (val) f << "fl" << i << std::hex << val << std::dec << ",";
+    if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ",";
   }
   for (int i=0; i<2; ++i) { // big numbers, maybe a int32t
     val=int(input->readLong(2));
@@ -1299,7 +1348,8 @@ bool PowerPoint3Parser::readDocRoot(MWAWEntry const &entry)
 
 bool PowerPoint3Parser::readScheme(MWAWEntry const &entry, int id)
 {
-  if (!entry.valid() || entry.length()<94) {
+  int const vers=version();
+  if (!entry.valid() || entry.length()<(vers<=3 ? 94 : 118)) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readScheme: the zone seems bad\n"));
     return false;
   }
@@ -1311,11 +1361,19 @@ bool PowerPoint3Parser::readScheme(MWAWEntry const &entry, int id)
   libmwaw::DebugStream f;
   f << "Entries(Scheme)[Z"<< entry.id() << "]:S" << id << ",";
   int val;
-  for (int i=0; i<15; ++i) { // f0=-2|-6, f2=X, f3=X|0, f4,f5,f6:small number, f7=0|1|101, f8=0|1, f9=0|e1c,f10=0|3715,f11=0|80
+  val=int(input->readLong(2)); // -2|-6
+  if (val!=-2) f << "f0=" << val << ",";
+  if (vers>=4) {
+    for (int i=0; i<12; ++i) {
+      val=int(input->readLong(2));
+      if (val) f << "g" << i << "=" << val << ",";
+    }
+  }
+  for (int i=0; i<14; ++i) { // f2=X, f3=X|0, f4,f5,f6:small number, f7=0|1|101, f8=0|1, f9=0|e1c,f10=0|3715,f11=0|80
     val=int(input->readLong(2));
-    int const(expected[])= {-2,0,0,0,100,100,100, 0x101, 0, 0, 0, 0, 0, 7, 0};
+    int const(expected[])= {0,0,0,100,100,100, 0x101, 0, 0, 0, 0, 0, 7, 0};
     if (val!=expected[i])
-      f << "f" << i << "=" << val << ",";
+      f << "f" << i+1 << "=" << val << ",";
   }
   f << "colors=[";
   for (int i=0; i<8; ++i) {
@@ -1412,7 +1470,8 @@ bool PowerPoint3Parser::readSlidesList(MWAWEntry const &entry)
 
 bool PowerPoint3Parser::readSlide(MWAWEntry const &entry, PowerPoint3ParserInternal::Slide &slide, int zId)
 {
-  if (!entry.valid() || entry.length()!=32) {
+  int const vers=version();
+  if (!entry.valid() || entry.length()!=(vers<=3 ? 32 : 34)) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readSlide: the zone seems bad\n"));
     return false;
   }
@@ -1643,7 +1702,9 @@ bool PowerPoint3Parser::readSlideContent(MWAWEntry const &entry, PowerPoint3Pars
 
 bool PowerPoint3Parser::readSlideFormats(MWAWEntry const &entry, std::vector<PowerPoint3ParserInternal::SlideFormat> &formatList)
 {
-  if (!entry.valid() || (entry.length()%20)!=0) {
+  int const vers=version();
+  int const dSz = vers<=3 ? 20 : 26;
+  if (!entry.valid() || (entry.length()%dSz)!=0) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readSlideFormats: the zone Z%d seems bad\n", entry.id()));
     return false;
   }
@@ -1656,7 +1717,7 @@ bool PowerPoint3Parser::readSlideFormats(MWAWEntry const &entry, std::vector<Pow
   ascii().addPos(pos);
   ascii().addNote(f.str().c_str());
   bool const isMacFile=m_state->m_isMacFile;
-  size_t N=size_t(entry.length()/20);
+  size_t N=size_t(entry.length()/dSz);
   formatList.resize(N);
   for (size_t i=0; i<N; ++i) {
     PowerPoint3ParserInternal::SlideFormat &format=formatList[i];
@@ -1673,19 +1734,23 @@ bool PowerPoint3Parser::readSlideFormats(MWAWEntry const &entry, std::vector<Pow
     if (val) f << "id=" << std::hex << val << std::dec << ",";
     int dim[2];
     for (int j=0; j<2; ++j) dim[j]=int(input->readLong(2));
-    if (!isMacFile) std::swap<int>(dim[0],dim[1]);
+    if (!isMacFile) std::swap(dim[0],dim[1]);
     f << "dim0=" << MWAWVec2i(dim[1], dim[0]) << ",";
     format.m_gradientOffset=int(input->readLong(2));
     if (format.m_gradientOffset) f << "grad[col,offset]=" << format.m_gradientOffset << ",";
     for (int j=0; j<2; ++j) dim[j]=int(input->readLong(2));
-    if (!isMacFile) std::swap<int>(dim[0],dim[1]);
+    if (!isMacFile) std::swap(dim[0],dim[1]);
     format.m_margins=MWAWVec2i(dim[1], dim[0]);
     f << "box[margins]=" << format.m_margins << ",";
     for (int j=0; j<2; ++j) dim[j]=int(input->readLong(2));
-    if (!isMacFile) std::swap<int>(dim[0],dim[1]);
+    if (!isMacFile) std::swap(dim[0],dim[1]);
     format.m_shadowOffset=MWAWVec2i(dim[1], dim[0]);
     if (format.m_shadowOffset!=MWAWVec2i(0,0))
       f << "shadow[offset]=" << format.m_shadowOffset << ",";
+    if (input->tell()!=pos+dSz) {
+      ascii().addDelimiter(input->tell(),'|');
+      input->seek(pos+dSz, librevenge::RVNG_SEEK_SET);
+    }
     ascii().addPos(pos);
     ascii().addNote(f.str().c_str());
   }
@@ -1727,15 +1792,15 @@ bool PowerPoint3Parser::readSlidePolygons(MWAWEntry const &entry, std::vector<Po
     int dim[4];
     for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
     if (!isMacFile) {
-      std::swap<int>(dim[0],dim[1]);
-      std::swap<int>(dim[2],dim[3]);
+      std::swap(dim[0],dim[1]);
+      std::swap(dim[2],dim[3]);
     }
     poly.m_box=MWAWBox2i(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2]));
     f << "box=" << poly.m_box << ",";
     f << "pts=[";
     for (int pt=0; pt<N; ++pt) {
       for (int i=0; i<2; ++i) dim[i]=int(input->readLong(2));
-      if (!isMacFile) std::swap<int>(dim[0],dim[1]);
+      if (!isMacFile) std::swap(dim[0],dim[1]);
       poly.m_vertices.push_back(MWAWVec2f(float(dim[1])/8.f, float(dim[0])/8.f));
       f << poly.m_vertices.back() << ",";
     }
@@ -1759,6 +1824,7 @@ bool PowerPoint3Parser::readFramesList(MWAWEntry const &entry, PowerPoint3Parser
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readFramesList: the zone seems bad\n"));
     return false;
   }
+  int const vers=version();
   MWAWInputStreamPtr input = getInput();
   long pos = entry.begin();
   entry.setParsed(true);
@@ -1782,9 +1848,66 @@ bool PowerPoint3Parser::readFramesList(MWAWEntry const &entry, PowerPoint3Parser
     f << "Frames-" << i << ":";
     PowerPoint3ParserInternal::Frame &frame=content.m_frameList[i];
     MWAWGraphicStyle &style=frame.m_style;
-    int type=int(input->readULong(1));
-    if (!isMacFile) type=PowerPoint3ParserInternal::swapUInt8(type);
-    frame.m_type=(type>>4);
+    if (vers<=3) {
+      int type=int(input->readULong(1));
+      if (!isMacFile) type=PowerPoint3ParserInternal::swapUInt8(type);
+      frame.m_type=(type>>4)&7;
+      showTypes[0]=type&0x7;
+      type&=0x88;
+      if (type) f << "fl0=" << std::hex << type << std::dec << ",";
+      int type2=int(input->readULong(1));
+      if (!isMacFile) type2=PowerPoint3ParserInternal::swapUInt8(type2);
+      showTypes[2]=type2&3;
+      showTypes[1]=(type2>>4)&3;
+      type2&=0xCC;
+      if (type2) f << "fl1=" << std::hex << type2 << std::dec << ",";
+    }
+    else {
+      int type=int(input->readULong(2));
+      int dashId=0;
+      if (isMacFile) {
+        frame.m_type=(type>>13)&7;
+        showTypes[0]=(type>>10)&0x7;
+        dashId=(type>>6)&7;
+        showTypes[2]=(type>>4)&3;
+        type &= 0x20F;
+      }
+      else {
+        frame.m_type=(type&7);
+        showTypes[0]=(type>>3)&0x7;
+        dashId=(type>>6)&7;
+        showTypes[2]=(type>>10)&3;
+        type&=0xF200;
+      }
+      showTypes[1]=1;
+      switch (dashId) {
+      case 0: // none
+      case 1: // normal
+      case 2: // unsure
+        showTypes[1]=dashId;
+        break;
+      case 3:
+        style.m_lineDashWidth.resize(2,1);
+        f << "dot,";
+        break;
+      case 4:
+        style.m_lineDashWidth.resize(2,2);
+        f << "dot[2x2],";
+        break;
+      case 5:
+        style.m_lineDashWidth.resize(2,4);
+        f << "dot[4x2],";
+        break;
+      case 6:
+        style.m_lineDashWidth.resize(4,2);
+        style.m_lineDashWidth[2]=1;
+        f << "dot[4,4,1,4],";
+        break;
+      default:
+        f << "##dashId=" << dashId << ",";
+      }
+      if (type) f << "fl0=" << std::hex << type << std::dec << ",";
+    }
     switch (frame.m_type) {
     case 0:
       f << "line,";
@@ -1806,7 +1929,6 @@ bool PowerPoint3Parser::readFramesList(MWAWEntry const &entry, PowerPoint3Parser
       f << "type=" << frame.m_type << ",";
       break;
     }
-    showTypes[0]=type&0x7;
     switch (showTypes[0]) {
     case 0: // none
       break;
@@ -1827,13 +1949,6 @@ bool PowerPoint3Parser::readFramesList(MWAWEntry const &entry, PowerPoint3Parser
       f << "###surf[type]=" << showTypes[0] << ",";
       break;
     }
-    if (type&0x8) f << "fl0=" << std::hex << (type&0x8) << std::dec << ",";
-    int type2=int(input->readULong(1));
-    if (!isMacFile) type2=PowerPoint3ParserInternal::swapUInt8(type2);
-    showTypes[2]=type2&3;
-    if (type2&1) f << "shadow,";
-    if (type2&2) f << "emboss,";
-    showTypes[1]=(type2>>4)&3;
     switch (showTypes[1]) {
     case 0:
       f << "no[line],";
@@ -1848,7 +1963,8 @@ bool PowerPoint3Parser::readFramesList(MWAWEntry const &entry, PowerPoint3Parser
     default:
       break;
     }
-    if (type2&0xCC) f << "fl1=" << std::hex << (type2&0xCC) << std::dec << ",";
+    if (showTypes[2]&1) f << "shadow,";
+    if (showTypes[2]&2) f << "emboss,";
     bool hasPicture=false;
     int val=int(input->readULong(1));
     if (!isMacFile) val=PowerPoint3ParserInternal::swapBool8(val);
@@ -1918,8 +2034,8 @@ bool PowerPoint3Parser::readFramesList(MWAWEntry const &entry, PowerPoint3Parser
     int dim[4];
     for (int d=0; d<4; ++d) dim[d]=int(input->readLong(2));
     if (!isMacFile) {
-      std::swap<int>(dim[0],dim[1]);
-      std::swap<int>(dim[2],dim[3]);
+      std::swap(dim[0],dim[1]);
+      std::swap(dim[2],dim[3]);
     }
     frame.m_dimension=MWAWBox2i(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2]));
     f << "dim=" << frame.m_dimension << ",";
@@ -2233,8 +2349,8 @@ bool PowerPoint3Parser::readTextZone(MWAWEntry const &entry, PowerPoint3ParserIn
     int dim[4];
     for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
     if (!isMacFile) {
-      std::swap<int>(dim[0],dim[1]);
-      std::swap<int>(dim[2],dim[3]);
+      std::swap(dim[0],dim[1]);
+      std::swap(dim[2],dim[3]);
     }
     tZone.m_box=MWAWBox2i(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2]));
     f << "dim=" << tZone.m_box << ",";
@@ -2256,7 +2372,7 @@ bool PowerPoint3Parser::readTextZone(MWAWEntry const &entry, PowerPoint3ParserIn
     val=int(input->readLong(2));
     if (val) f << "f3=" << val << ",";
     int sSz=int(input->readULong(4));
-    if (sSz<0 || pos+58+sSz+8+10>endPos) {
+    if (sSz<0 || endPos-pos-58-8-10<sSz || pos+58+sSz+8+10>endPos) {
       input->seek(pos, librevenge::RVNG_SEEK_SET);
       break;
     }
@@ -2370,8 +2486,8 @@ bool PowerPoint3Parser::readTextZone(MWAWEntry const &entry, PowerPoint3ParserIn
 
 bool PowerPoint3Parser::readStructList(MWAWEntry const &entry, PowerPoint3ParserInternal::FieldParser &parser)
 {
-  bool const isMacFile=m_state->m_isMacFile;
-  int const headerSize= isMacFile ? 18 : 16;
+  bool useInt16 = (!m_state->m_isMacFile && version()<=3);
+  int const headerSize= useInt16 ? 16 : 18;
   if (!entry.valid() || entry.length()<headerSize) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readStructList: the zone seems bad\n"));
     return false;
@@ -2385,7 +2501,7 @@ bool PowerPoint3Parser::readStructList(MWAWEntry const &entry, PowerPoint3Parser
   int val=int(input->readULong(2));
   if (val!=0x8001)
     f << "f0=" << std::hex << val << std::dec << ",";
-  f << "id=" << std::hex << input->readULong(isMacFile ? 4 : 2) << std::dec << ",";
+  f << "id=" << std::hex << input->readULong(useInt16 ? 2 : 4) << std::dec << ",";
   int N=int(input->readULong(2));
   f << "N=" << N << ",";
   for (int i=0; i<2; ++i) {
@@ -2552,7 +2668,8 @@ bool PowerPoint3Parser::readPictureDefinition(MWAWEntry const &entry, int pId)
 bool PowerPoint3Parser::readPictureContent(MWAWEntry const &entry, MWAWEmbeddedObject &pict)
 {
   bool isMacFile=m_state->m_isMacFile;
-  if (!entry.valid() || entry.length()!=(isMacFile ? 50 : 48)) {
+  int const vers=version();
+  if (!entry.valid() || entry.length()!=(vers>=4 ? 60 : isMacFile ? 50 : 48)) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readPictureContent: the zone seems bad\n"));
     return false;
   }
@@ -2589,7 +2706,7 @@ bool PowerPoint3Parser::readPictureContent(MWAWEntry const &entry, MWAWEmbeddedO
       val=int(input->readLong(2));
       if (val) f << "f" << i+1 << "=" << val << ",";
     }
-    val=int(input->readULong(2));
+    val=int(input->readULong(vers>=4 ? 4 : 2));
     if (val!=0x262a) f << "id=" << std::hex << val << std::dec << ",";
     int dim[4];
     for (int i=0; i<4; ++i) dim[i]=int(input->readLong(2));
@@ -2863,9 +2980,10 @@ bool PowerPoint3Parser::readParagraph(MWAWParagraph &para, PowerPoint3ParserInte
       }
       break;
     case 4:
-      level=val;
+      level=val&0xFF;
       ruler.updateParagraph(para, level);
       if (level) f << "level=" << level << ",";
+      if (val&0xFF00) f << "level[high]=" << (val>>8) << ",";
       break;
     case 5:
       switch (val) {
@@ -2977,8 +3095,7 @@ bool PowerPoint3Parser::readRuler(MWAWEntry const &entry, int pId)
     MWAW_DEBUG_MSG(("PowerPoint3Parser::readRuler: paragraph %d already exists\n", pId));
   }
   if (input->tell()!=entry.end()) {
-    MWAW_DEBUG_MSG(("PowerPoint3Parser::readRuler: find extra data\n"));
-    f << "##extra,";
+    f << "#extra,";
     ascii().addDelimiter(input->tell(),'|');
   }
   ascii().addPos(pos);
@@ -3260,7 +3377,7 @@ bool PowerPoint3Parser::readZone10(MWAWEntry const &entry)
 ////////////////////////////////////////////////////////////
 // try to send data
 ////////////////////////////////////////////////////////////
-bool PowerPoint3Parser::sendText(PowerPoint3ParserInternal::SlideContent const &content, int tId, bool mainText)
+bool PowerPoint3Parser::sendText(PowerPoint3ParserInternal::SlideContent const &content, int tId, bool mainText, bool master)
 {
   MWAWListenerPtr listener=getPresentationListener();
   if (!listener) {
@@ -3376,7 +3493,7 @@ bool PowerPoint3Parser::sendText(PowerPoint3ParserInternal::SlideContent const &
       case ':': // time
       case '#': { // page number
         pos=input->tell();
-        if (i+1<int(tEntry.length()) && char(input->readULong(1))==char(c)) {
+        if (master && i+1<int(tEntry.length()) && char(input->readULong(1))==char(c)) {
           ++i;
           listener->insertField(MWAWField(c=='#' ? MWAWField::PageNumber : c=='/' ? MWAWField::Date : MWAWField::Time));
         }
@@ -3459,12 +3576,12 @@ bool PowerPoint3Parser::sendSlide(PowerPoint3ParserInternal::SlideContent const
     if (master && slide.m_frameList[f].m_mainTextBox) continue;
     std::set<int> seen;
     seen.insert(int(f));
-    sendFrame(slide.m_frameList[f], slide, seen);
+    sendFrame(slide.m_frameList[f], slide, master, seen);
   }
   return true;
 }
 
-bool PowerPoint3Parser::sendFrame(PowerPoint3ParserInternal::Frame const &frame, PowerPoint3ParserInternal::SlideContent const &content, std::set<int> &seen)
+bool PowerPoint3Parser::sendFrame(PowerPoint3ParserInternal::Frame const &frame, PowerPoint3ParserInternal::SlideContent const &content, bool master, std::set<int> &seen)
 {
   frame.m_isSent=true;
   MWAWListenerPtr listener=getPresentationListener();
@@ -3478,7 +3595,7 @@ bool PowerPoint3Parser::sendFrame(PowerPoint3ParserInternal::Frame const &frame,
   if (frame.m_textId>=0) {
     MWAWPosition pos(fBox[0], fBox.size(), librevenge::RVNG_POINT);
     pos.m_anchorTo = MWAWPosition::Page;
-    MWAWSubDocumentPtr subdoc(new PowerPoint3ParserInternal::SubDocument(*this, getInput(), &content, frame.m_textId, frame.m_mainTextBox));
+    MWAWSubDocumentPtr subdoc(new PowerPoint3ParserInternal::SubDocument(*this, getInput(), &content, frame.m_textId, frame.m_mainTextBox, master));
     listener->insertTextBox(pos, subdoc, frame.m_style);
     return true;
   }
@@ -3544,7 +3661,7 @@ bool PowerPoint3Parser::sendFrame(PowerPoint3ParserInternal::Frame const &frame,
   case 3: {
     float angle[2] = { frame.m_angles[0], frame.m_angles[0]+frame.m_angles[1] };
     if (angle[1]<angle[0])
-      std::swap<float>(angle[0],angle[1]);
+      std::swap(angle[0],angle[1]);
     if (angle[1]>360) {
       int numLoop=int(angle[1]/360)-1;
       angle[0]-=float(numLoop*360);
@@ -3606,7 +3723,7 @@ bool PowerPoint3Parser::sendFrame(PowerPoint3ParserInternal::Frame const &frame,
           continue;
         }
         seen.insert(i);
-        sendFrame(content.m_frameList[size_t(i)], content, seen);
+        sendFrame(content.m_frameList[size_t(i)], content, master, seen);
         seen.erase(i);
       }
     }
@@ -3635,7 +3752,11 @@ bool PowerPoint3Parser::checkHeader(MWAWHeader *header, bool strict)
   MWAWInputStreamPtr input = getInput();
   if (!input || !input->hasDataFork())
     return false;
-
+  if (input->isStructured()) {
+    input=input->getSubStreamByName("PP40");
+    if (!input)
+      return false;
+  }
   libmwaw::DebugStream f;
   if (!input->checkPosition(24+8)) {
     MWAW_DEBUG_MSG(("PowerPoint3Parser::checkHeader: file is too short\n"));
@@ -3653,7 +3774,7 @@ bool PowerPoint3Parser::checkHeader(MWAWHeader *header, bool strict)
     return false;
   f << "FileHeader:";
   int vers=int(input->readLong(4));
-  if (vers!=3) return false;
+  if (vers!=3 && vers!=4) return false;
   m_state->m_zoneListBegin=long(input->readULong(4));
   if (m_state->m_zoneListBegin<24 || !input->checkPosition(m_state->m_zoneListBegin))
     return false;
diff --git a/src/lib/PowerPoint3Parser.hxx b/src/lib/PowerPoint3Parser.hxx
index 4cebdc2..799e108 100644
--- a/src/lib/PowerPoint3Parser.hxx
+++ b/src/lib/PowerPoint3Parser.hxx
@@ -58,7 +58,7 @@ struct TextZone;
 class SubDocument;
 }
 
-/** \brief the main class to read a Microsoft PowerPoint v3 files (MacOs and Windows)
+/** \brief the main class to read a Microsoft PowerPoint v3 or v4 files (MacOs and Windows)
  */
 class PowerPoint3Parser : public MWAWPresentationParser
 {
@@ -147,9 +147,9 @@ protected:
   //! try to send a slide
   bool sendSlide(PowerPoint3ParserInternal::SlideContent const &slide, bool master);
   //! try to send a frame zone
-  bool sendFrame(PowerPoint3ParserInternal::Frame const &frame, PowerPoint3ParserInternal::SlideContent const &content, std::set<int> &seen);
+  bool sendFrame(PowerPoint3ParserInternal::Frame const &frame, PowerPoint3ParserInternal::SlideContent const &content, bool master, std::set<int> &seen);
   //! try to send a text zone
-  bool sendText(PowerPoint3ParserInternal::SlideContent const &slide, int tId, bool placeHolder);
+  bool sendText(PowerPoint3ParserInternal::SlideContent const &slide, int tId, bool placeHolder, bool master);
 
   //
   // low level
diff --git a/src/lib/README b/src/lib/README
index 96b8d10..1978f30 100644
--- a/src/lib/README
+++ b/src/lib/README
@@ -268,8 +268,9 @@ NisusWrtParser : parser of a Nisus Writer document : v4.0
 
 PixelPaintParser : parser of PixelPaint : v1-v2
 
-PowerPoint1Parser : parser of PowerPoint : mac v1-v2
-PowerPoint3Parser : parser of PowerPoint : mac v3 and windows v3
+PowerPoint1Parser : parser of PowerPoint : mac v1-v2 and windows v2
+PowerPoint3Parser : parser of PowerPoint : mac v3-v4 and windows v3-v4
+- PowerPoint3OLE : parser of the non essential OLE stream
 
 RagTimeParser : parser of RagTime : v2-3
 -   RagTimeSpreadsheet: class which reads the spreadsheet's zones
diff --git a/src/lib/ZWrtParser.cxx b/src/lib/ZWrtParser.cxx
index 6c554bc..84db22c 100644
--- a/src/lib/ZWrtParser.cxx
+++ b/src/lib/ZWrtParser.cxx
@@ -884,7 +884,7 @@ bool ZWrtParser::checkHeader(MWAWHeader *header, bool strict)
     MWAW_DEBUG_MSG(("ZWrtParser::checkHeader: can not find the RANG[128] resource\n"));
     return false;
   }
-  if (getInput()->hasDataFork()) {
+  if (getInput()->hasDataFork() && getInput()->size()>0) {
     MWAW_DEBUG_MSG(("ZWrtParser::checkHeader: find some data fork\n"));
     if (strict)
       return false;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-openoffice/libmwaw.git



More information about the Pkg-openoffice-commits mailing list