[Libreoffice-commits] core.git: sw/source writerfilter/source

Serge Krot Serge.Krot at cib.de
Tue Oct 10 17:35:49 UTC 2017


 sw/source/filter/ww8/docxattributeoutput.cxx      |  206 ++++++++++++++++++----
 sw/source/filter/ww8/docxattributeoutput.hxx      |   15 +
 writerfilter/source/dmapper/DomainMapper.cxx      |   25 ++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |  117 ++++++++++++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |   53 +++++
 writerfilter/source/ooxml/model.xml               |   70 ++++---
 6 files changed, 416 insertions(+), 70 deletions(-)

New commits:
commit f5c266695a4a88da7db971a21915e2bbf758d48e
Author: Serge Krot <Serge.Krot at cib.de>
Date:   Mon Oct 9 12:15:05 2017 +0200

    tdf#66398 Parse and output permissions for DOCX using bookmarks
    
    Change-Id: Id08998ae775c5f383edc4bf0410d16f88c70dfd6
    Reviewed-on: https://gerrit.libreoffice.org/43275
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 3d7d8b53957e..e2e000c00bc0 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1235,8 +1235,13 @@ void DocxAttributeOutput::EndRun()
     // if there is some redlining in the document, output it
     StartRedline( m_pRedlineData );
 
-    DoWriteBookmarks( );
-    DoWriteAnnotationMarks( );
+    // XML_r node should be surrounded with bookmark-begin and bookmark-end nodes if it has bookmarks.
+    // The same is applied for permission ranges.
+    // But due to unit test "testFdo85542" let's output bookmark-begin with bookmark-end.
+    DoWriteBookmarksStart();
+    DoWriteBookmarksEnd();
+    DoWritePermissionsStart();
+    DoWriteAnnotationMarks();
 
     if( m_closeHyperlinkInThisRun && m_startedHyperlink && !m_hyperLinkAnchor.isEmpty() && m_hyperLinkAnchor.startsWith("_Toc"))
     {
@@ -1312,6 +1317,9 @@ void DocxAttributeOutput::EndRun()
 
     m_pSerializer->mergeTopMarks(Tag_StartRun_1);
 
+    // XML_r node should be surrounded with permission-begin and permission-end nodes if it has permission.
+    DoWritePermissionsEnd();
+
     for (std::vector<const SwOLENode*>::iterator it = m_aPostponedMaths.begin(); it != m_aPostponedMaths.end(); ++it)
         WritePostponedMath(*it);
     m_aPostponedMaths.clear();
@@ -1371,41 +1379,159 @@ void DocxAttributeOutput::EndRun()
     }
 }
 
-void DocxAttributeOutput::DoWriteBookmarks()
+void DocxAttributeOutput::DoWriteBookmarkTagStart(const OUString & bookmarkName)
+{
+    const OString rId   = OString::number(m_nNextBookmarkId);
+    const OString rName = OUStringToOString(BookmarkToWord(bookmarkName), RTL_TEXTENCODING_UTF8).getStr();
+
+    m_pSerializer->singleElementNS(XML_w, XML_bookmarkStart,
+        FSNS(XML_w, XML_id), rId.getStr(),
+        FSNS(XML_w, XML_name), rName.getStr(),
+        FSEND);
+}
+
+void DocxAttributeOutput::DoWriteBookmarkTagEnd(const OUString & bookmarkName)
 {
-    // Write the start bookmarks
-    for ( const auto & it : m_rBookmarksStart )
+    const auto nameToIdIter = m_rOpenedBookmarksIds.find(bookmarkName);
+    if (nameToIdIter != m_rOpenedBookmarksIds.end())
     {
-        OString rName = OUStringToOString( BookmarkToWord( it ), RTL_TEXTENCODING_UTF8 ).getStr();
+        const sal_Int32 nId = nameToIdIter->second;
+        const OString   rId = OString::number(nId);
+
+        m_pSerializer->singleElementNS(XML_w, XML_bookmarkEnd,
+            FSNS(XML_w, XML_id), rId.getStr(),
+            FSEND);
+    }
+}
 
+/// Write the start bookmarks
+void DocxAttributeOutput::DoWriteBookmarksStart()
+{
+    for (const OUString & bookmarkName : m_rBookmarksStart)
+    {
         // Output the bookmark
-        const sal_Int32 nId = m_nNextBookmarkId++;
-        m_rOpenedBookmarksIds[it] = nId;
-        m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
-            FSNS( XML_w, XML_id ), OString::number( nId ).getStr(  ),
-            FSNS( XML_w, XML_name ), rName.getStr(),
-            FSEND );
-        m_sLastOpenedBookmark = rName;
+        DoWriteBookmarkTagStart(bookmarkName);
+
+        m_rOpenedBookmarksIds[bookmarkName] = m_nNextBookmarkId;
+        m_sLastOpenedBookmark = OUStringToOString(BookmarkToWord(bookmarkName), RTL_TEXTENCODING_UTF8).getStr();
+        m_nNextBookmarkId++;
     }
     m_rBookmarksStart.clear();
+}
 
-    // export the end bookmarks
-    for ( const auto & it : m_rBookmarksEnd )
+/// export the end bookmarks
+void DocxAttributeOutput::DoWriteBookmarksEnd()
+{
+    for (const OUString & bookmarkName : m_rBookmarksEnd)
     {
         // Get the id of the bookmark
-        auto pPos = m_rOpenedBookmarksIds.find(it);
-        if ( pPos != m_rOpenedBookmarksIds.end() )
+        auto pPos = m_rOpenedBookmarksIds.find(bookmarkName);
+        if (pPos != m_rOpenedBookmarksIds.end())
         {
-            const sal_Int32 nId = ( *pPos ).second;
-            m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
-                FSNS( XML_w, XML_id ), OString::number( nId ).getStr(),
-                FSEND );
-            m_rOpenedBookmarksIds.erase( it );
+            // Output the bookmark
+            DoWriteBookmarkTagEnd(bookmarkName);
+
+            m_rOpenedBookmarksIds.erase(bookmarkName);
         }
     }
     m_rBookmarksEnd.clear();
 }
 
+// For construction of the special bookmark name template for permissions:
+// see, PermInsertPosition::createBookmarkName()
+//
+// Syntax:
+// - "permission-for-user:<permission-id>:<permission-user-name>"
+// - "permission-for-group:<permission-id>:<permission-group-name>"
+//
+void DocxAttributeOutput::DoWritePermissionTagStart(const OUString & permission)
+{
+    OUString permissionIdAndName;
+
+    if (permission.startsWith("permission-for-group:", &permissionIdAndName))
+    {
+        const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+        const OUString permissionId   = permissionIdAndName.copy(0, sparatorIndex);
+        const OUString permissionName = permissionIdAndName.copy(sparatorIndex + 1);
+
+        const OString rId   = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+        const OString rName = OUStringToOString(BookmarkToWord(permissionName), RTL_TEXTENCODING_UTF8).getStr();
+
+        m_pSerializer->singleElementNS(XML_w, XML_permStart,
+            FSNS(XML_w, XML_id), rId.getStr(),
+            FSNS(XML_w, XML_edGrp), rName.getStr(),
+            FSEND);
+    }
+    else // if (permission.startsWith("permission-for-user:", &permissionIdAndName))
+    {
+        const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+        const OUString permissionId   = permissionIdAndName.copy(0, sparatorIndex);
+        const OUString permissionName = permissionIdAndName.copy(sparatorIndex + 1);
+
+        const OString rId   = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+        const OString rName = OUStringToOString(BookmarkToWord(permissionName), RTL_TEXTENCODING_UTF8).getStr();
+
+        m_pSerializer->singleElementNS(XML_w, XML_permStart,
+            FSNS(XML_w, XML_id), rId.getStr(),
+            FSNS(XML_w, XML_ed), rName.getStr(),
+            FSEND);
+    }
+}
+
+
+// For construction of the special bookmark name template for permissions:
+// see, PermInsertPosition::createBookmarkName()
+//
+// Syntax:
+// - "permission-for-user:<permission-id>:<permission-user-name>"
+// - "permission-for-group:<permission-id>:<permission-group-name>"
+//
+void DocxAttributeOutput::DoWritePermissionTagEnd(const OUString & permission)
+{
+    OUString permissionIdAndName;
+
+    if (permission.startsWith("permission-for-group:", &permissionIdAndName))
+    {
+        const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+        const OUString permissionId   = permissionIdAndName.copy(0, sparatorIndex);
+        const OString rId             = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+
+        m_pSerializer->singleElementNS(XML_w, XML_permEnd,
+            FSNS(XML_w, XML_id), rId.getStr(),
+            FSEND);
+    }
+    else // if (permission.startsWith("permission-for-user:", &permissionIdAndName))
+    {
+        const sal_Int32 sparatorIndex = permissionIdAndName.indexOf(':');
+        const OUString permissionId   = permissionIdAndName.copy(0, sparatorIndex);
+        const OString rId             = OUStringToOString(BookmarkToWord(permissionId), RTL_TEXTENCODING_UTF8).getStr();
+
+        m_pSerializer->singleElementNS(XML_w, XML_permEnd,
+            FSNS(XML_w, XML_id), rId.getStr(),
+            FSEND);
+    }
+}
+
+/// Write the start permissions
+void DocxAttributeOutput::DoWritePermissionsStart()
+{
+    for (const OUString & permission : m_rPermissionsStart)
+    {
+        DoWritePermissionTagStart(permission);
+    }
+    m_rPermissionsStart.clear();
+}
+
+/// export the end permissions
+void DocxAttributeOutput::DoWritePermissionsEnd()
+{
+    for (const OUString & permission : m_rPermissionsEnd)
+    {
+        DoWritePermissionTagEnd(permission);
+    }
+    m_rPermissionsEnd.clear();
+}
+
 void DocxAttributeOutput::DoWriteAnnotationMarks()
 {
     // Write the start annotation marks
@@ -1629,10 +1755,7 @@ void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
     OUString aBkmName( m_sFieldBkm );
     if ( !aBkmName.isEmpty() )
     {
-        m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
-               FSNS( XML_w, XML_id ), OString::number( m_nNextBookmarkId ).getStr( ),
-               FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
-               FSEND );
+        DoWriteBookmarkTagEnd(aBkmName);
     }
 
     if (rInfos.pField ) // For hyperlinks and TOX
@@ -1658,9 +1781,7 @@ void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
     // Write the bookmark end if any
     if ( !aBkmName.isEmpty() )
     {
-        m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
-               FSNS( XML_w, XML_id ), OString::number( m_nNextBookmarkId ).getStr( ),
-               FSEND );
+        DoWriteBookmarkTagEnd(aBkmName);
 
         m_nNextBookmarkId++;
     }
@@ -6980,18 +7101,33 @@ void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFie
         m_Fields.begin()->pFieldmark = &rFieldmark;
 }
 
-void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
-        std::vector< OUString >& rEnds )
+void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds )
 {
-    for ( const auto & it : rStarts )
+    for ( const OUString & name : rStarts )
     {
-        m_rBookmarksStart.push_back( it );
+        if (name.startsWith("permission-for-group:") ||
+            name.startsWith("permission-for-user:"))
+        {
+            m_rPermissionsStart.push_back(name);
+        }
+        else
+        {
+            m_rBookmarksStart.push_back(name);
+        }
     }
     rStarts.clear();
 
-    for ( const auto & it : rEnds )
+    for ( const OUString & name : rEnds )
     {
-        m_rBookmarksEnd.push_back( it );
+        if (name.startsWith("permission-for-group:") ||
+            name.startsWith("permission-for-user:"))
+        {
+            m_rPermissionsEnd.push_back(name);
+        }
+        else
+        {
+            m_rBookmarksEnd.push_back(name);
+        }
     }
     rEnds.clear();
 }
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 65334bc07a50..3fdfd95cd312 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -695,7 +695,16 @@ protected:
 
 private:
 
-    void DoWriteBookmarks( );
+    void DoWriteBookmarkTagStart(const OUString & bookmarkName);
+    void DoWriteBookmarkTagEnd(const OUString & bookmarkName);
+    void DoWriteBookmarksStart();
+    void DoWriteBookmarksEnd();
+
+    void DoWritePermissionTagStart(const OUString & permission);
+    void DoWritePermissionTagEnd(const OUString & permission);
+    void DoWritePermissionsStart();
+    void DoWritePermissionsEnd();
+
     void DoWriteAnnotationMarks( );
     void WritePostponedGraphic();
     void WritePostponedMath(const SwOLENode* pObject);
@@ -776,6 +785,10 @@ private:
     std::vector<OUString> m_rBookmarksStart;
     std::vector<OUString> m_rBookmarksEnd;
 
+    /// Permissions to output
+    std::vector<OUString> m_rPermissionsStart;
+    std::vector<OUString> m_rPermissionsEnd;
+
     /// Annotation marks to output
     std::vector<OString> m_rAnnotationMarksStart;
     std::vector<OString> m_rAnnotationMarksEnd;
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index f492c2c2d033..227f55935ee3 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1125,6 +1125,26 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
             }
             break;
         }
+        case NS_ooxml::LN_CT_PermStart_ed:
+        {
+            m_pImpl->setPermissionRangeEd(sStringValue);
+            break;
+        }
+        case NS_ooxml::LN_CT_PermStart_edGrp:
+        {
+            m_pImpl->setPermissionRangeEdGrp(sStringValue);
+            break;
+        }
+        case NS_ooxml::LN_CT_PermStart_id:
+        {
+            m_pImpl->startOrEndPermissionRange(nIntValue);
+            break;
+        }
+        case NS_ooxml::LN_CT_PermEnd_id:
+        {
+            m_pImpl->startOrEndPermissionRange(nIntValue);
+            break;
+        }
         default:
             SAL_WARN("writerfilter", "DomainMapper::lcl_attribute: unhandled token: " << nName);
         }
@@ -2816,11 +2836,6 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
             pProperties->resolve(*this);
     }
     break;
-    case NS_ooxml::LN_EG_RunLevelElts_permStart: // 93164
-    case NS_ooxml::LN_EG_RunLevelElts_permEnd: // 93165
-    {
-        break;
-    }
     default:
         {
 #ifdef DEBUG_WRITERFILTER
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index be16a2307eaf..8e1423cf1380 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -202,6 +202,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bStartBibliography(false),
         m_bStartGenericField(false),
         m_bTextInserted(false),
+        m_sCurrentPermId(0),
         m_pLastSectionContext( ),
         m_pLastCharacterContext(),
         m_sCurrentParaStyleId(),
@@ -4791,6 +4792,7 @@ void DomainMapper_Impl::SetBookmarkName( const OUString& rBookmarkName )
         m_sCurrentBkmkName = rBookmarkName;
 }
 
+// This method was used as-is for DomainMapper_Impl::startOrEndPermissionRange() implementation.
 void DomainMapper_Impl::StartOrEndBookmark( const OUString& rId )
 {
     /*
@@ -4869,6 +4871,121 @@ void DomainMapper_Impl::StartOrEndBookmark( const OUString& rId )
     }
 }
 
+void DomainMapper_Impl::setPermissionRangeEd(const OUString& user)
+{
+    PermMap_t::iterator aPremIter = m_aPermMap.find(m_sCurrentPermId);
+    if (aPremIter != m_aPermMap.end())
+        aPremIter->second.m_Ed = user;
+    else
+        m_sCurrentPermEd = user;
+}
+
+void DomainMapper_Impl::setPermissionRangeEdGrp(const OUString& group)
+{
+    PermMap_t::iterator aPremIter = m_aPermMap.find(m_sCurrentPermId);
+    if (aPremIter != m_aPermMap.end())
+        aPremIter->second.m_EdGrp = group;
+    else
+        m_sCurrentPermEdGrp = group;
+}
+
+// This method is based on implementation from DomainMapper_Impl::StartOrEndBookmark()
+void DomainMapper_Impl::startOrEndPermissionRange(sal_Int32 permissinId)
+{
+    /*
+    * Add the dummy paragraph to handle section properties
+    * if the first element in the section is a table. If the dummy para is not added yet, then add it;
+    * So permission is not attached to the wrong paragraph.
+    */
+    if (getTableManager().isInCell() && m_nTableDepth == 0 && GetIsFirstParagraphInSection()
+        && !GetIsDummyParaAddedForTableInSection() && !GetIsTextFrameInserted())
+    {
+        AddDummyParaForTableInSection();
+    }
+
+    if (m_aTextAppendStack.empty())
+        return;
+
+    const bool bIsAfterDummyPara = GetIsDummyParaAddedForTableInSection() && GetIsFirstParagraphInSection();
+
+    uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend;
+    PermMap_t::iterator aPermIter = m_aPermMap.find(permissinId);
+
+    //is the bookmark name already registered?
+    try
+    {
+        if (aPermIter == m_aPermMap.end())
+        {
+            //otherwise insert a text range as marker
+            bool bIsStart = true;
+            uno::Reference< text::XTextRange > xCurrent;
+            if (xTextAppend.is())
+            {
+                uno::Reference< text::XTextCursor > xCursor = xTextAppend->createTextCursorByRange(xTextAppend->getEnd());
+
+                if (!bIsAfterDummyPara)
+                    bIsStart = !xCursor->goLeft(1, false);
+                xCurrent = xCursor->getStart();
+            }
+
+            // register the start of the new permission
+            m_sCurrentPermId = permissinId;
+            m_aPermMap.emplace(permissinId, PermInsertPosition(bIsStart, permissinId, m_sCurrentPermEd, m_sCurrentPermEdGrp, xCurrent));
+
+            // clean up
+            m_sCurrentPermEd.clear();
+            m_sCurrentPermEdGrp.clear();
+        }
+        else
+        {
+            if (m_xTextFactory.is())
+            {
+                uno::Reference< text::XTextCursor > xCursor;
+                uno::Reference< text::XText > xText = aPermIter->second.m_xTextRange->getText();
+                if (aPermIter->second.m_bIsStartOfText && !bIsAfterDummyPara)
+                {
+                    xCursor = xText->createTextCursorByRange(xText->getStart());
+                }
+                else
+                {
+                    xCursor = xText->createTextCursorByRange(aPermIter->second.m_xTextRange);
+                    xCursor->goRight(1, false);
+                }
+
+                xCursor->gotoRange(xTextAppend->getEnd(), true);
+                // A Paragraph was recently finished, and a new Paragraph has not been started as yet
+                // then  move the bookmark-End to the earlier paragraph
+                if (IsOutsideAParagraph())
+                {
+                    xCursor->goLeft(1, false);
+                }
+
+                // create a new bookmark using specific bookmark name pattern for permissions
+                uno::Reference< text::XTextContent > xPerm(m_xTextFactory->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY_THROW);
+                uno::Reference< container::XNamed > xPermNamed(xPerm, uno::UNO_QUERY_THROW);
+                xPermNamed->setName(aPermIter->second.createBookmarkName());
+
+                // add new bookmark
+                const bool bAbsorb = !xCursor->isCollapsed();
+                uno::Reference< text::XTextRange > xCurrent = uno::Reference< text::XTextRange >(xCursor, uno::UNO_QUERY_THROW);
+                xTextAppend->insertTextContent(xCurrent, xPerm, bAbsorb);
+            }
+
+            // remove proccessed permission
+            m_aPermMap.erase(aPermIter);
+
+            // clean up
+            m_sCurrentPermId = 0;
+            m_sCurrentPermEd.clear();
+            m_sCurrentPermEdGrp.clear();
+        }
+    }
+    catch (const uno::Exception&)
+    {
+        //TODO: What happens to bookmarks where start and end are at different XText objects?
+    }
+}
+
 void DomainMapper_Impl::AddAnnotationPosition(
     const bool bStart,
     const sal_Int32 nAnnotationId)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 208318c81c12..df22413a8cbd 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -258,6 +258,49 @@ struct BookmarkInsertPosition
      {}
 };
 
+struct PermInsertPosition
+{
+    bool        m_bIsStartOfText;
+    sal_Int32   m_Id;
+    OUString    m_Ed;
+    OUString    m_EdGrp;
+
+    css::uno::Reference<css::text::XTextRange> m_xTextRange;
+
+    PermInsertPosition(bool bIsStartOfText, sal_Int32 id, const OUString& ed, const OUString& edGrp, css::uno::Reference<css::text::XTextRange> const& xTextRange)
+        : m_bIsStartOfText(bIsStartOfText)
+        , m_Id(id)
+        , m_Ed(ed)
+        , m_EdGrp(edGrp)
+        , m_xTextRange(xTextRange)
+    {}
+
+    OUString createBookmarkName() const
+    {
+        OUString bookmarkName;
+
+        assert((!m_Ed.isEmpty()) || (!m_EdGrp.isEmpty()));
+
+        if (m_Ed.isEmpty())
+        {
+            bookmarkName += "permission-for-group:";
+            bookmarkName += OUString::number(m_Id);
+            bookmarkName += ":";
+            bookmarkName += m_EdGrp;
+        }
+        else
+        {
+            bookmarkName += "permission-for-user:";
+            bookmarkName += OUString::number(m_Id);
+            bookmarkName += ":";
+            bookmarkName += m_Ed;
+        }
+
+        //todo: make sure the name is not used already!
+        return bookmarkName;
+    }
+};
+
 /// Stores the start/end positions of an annotation before its insertion.
 struct AnnotationPosition
 {
@@ -334,6 +377,7 @@ class DomainMapper_Impl final
 {
 public:
     typedef std::map < OUString, BookmarkInsertPosition > BookmarkMap_t;
+    typedef std::map < sal_Int32, PermInsertPosition >    PermMap_t;
 
 private:
     SourceDocumentType                                                              m_eDocumentType;
@@ -375,6 +419,11 @@ private:
     OUString                                                                        m_sCurrentBkmkId;
     OUString                                                                        m_sCurrentBkmkName;
 
+    PermMap_t                                                                       m_aPermMap;
+    sal_Int32                                                                       m_sCurrentPermId;
+    OUString                                                                        m_sCurrentPermEd;
+    OUString                                                                        m_sCurrentPermEdGrp;
+
     PageMar                                                                        m_aPageMargins;
     SymbolData                                                                      m_aSymbolData;
 
@@ -705,6 +754,10 @@ public:
     void SetBookmarkName( const OUString& rBookmarkName );
     void StartOrEndBookmark( const OUString& rId );
 
+    void setPermissionRangeEd(const OUString& user);
+    void setPermissionRangeEdGrp(const OUString& group);
+    void startOrEndPermissionRange(sal_Int32 permissinId);
+
     void AddAnnotationPosition(
         const bool bStart,
         const sal_Int32 nAnnotationId );
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index 81cdc3ff9c77..a9ffbdfa6c65 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -12126,6 +12126,9 @@
         </attribute>
         <ref name="CT_MarkupRange"/>
       </define>
+      <define name="CT_MarkupRangePerm">
+        <ref name="CT_MarkupRange"/>
+      </define>
       <define name="CT_MarkupRangeCommentStart">
         <ref name="CT_Markup"/>
       </define>
@@ -12166,6 +12169,24 @@
           <ref name="ST_String"/>
         </attribute>
       </define>
+      <define name="CT_PermStart">
+        <ref name="CT_MarkupRangePerm"/>
+        <attribute name="ed">
+          <data type="string"/>
+        </attribute>
+        <attribute name="edGrp">
+          <data type="string"/>
+        </attribute>
+        <attribute name="colFirst">
+          <data type="ST_DecimalNumber"/>
+        </attribute>
+        <attribute name="colLast">
+          <data type="ST_DecimalNumber"/>
+        </attribute>
+      </define>
+      <define name="CT_PermEnd">
+        <ref name="CT_MarkupRangePerm"/>
+      </define>
       <define name="CT_TrackChangeNumbering">
         <ref name="CT_TrackChange"/>
         <attribute name="original">
@@ -12254,6 +12275,12 @@
           <element name="bookmarkEnd">
             <ref name="CT_MarkupRangeBookmark"/>
           </element>
+          <element name="permStart">
+            <ref name="CT_PermStart"/>
+          </element>
+          <element name="permEnd">
+            <ref name="CT_PermEnd"/>
+          </element>
           <element name="moveFromRangeStart">
             <ref name="CT_MoveBookmark"/>
           </element>
@@ -13279,29 +13306,6 @@
           <data type="string"/>
         </attribute>
       </define>
-      <define name="CT_Perm">
-        <attribute name="id">
-          <data type="string"/>
-        </attribute>
-        <attribute name="displacedByCustomXml">
-          <data type="string"/>
-        </attribute>
-      </define>
-      <define name="CT_PermStart">
-        <ref name="CT_Perm"/>
-        <attribute name="edGrp">
-          <data type="string"/>
-        </attribute>
-        <attribute name="ed">
-          <data type="string"/>
-        </attribute>
-        <attribute name="colFirst">
-          <data type="string"/>
-        </attribute>
-        <attribute name="colLast">
-          <data type="string"/>
-        </attribute>
-      </define>
       <define name="CT_Text">
         <ref name="ST_String"/>
         <attribute name="xml:space">
@@ -16291,12 +16295,6 @@
           <element name="proofErr">
             <ref name="CT_ProofErr"/>
           </element>
-          <element name="permStart">
-            <ref name="CT_PermStart"/>
-          </element>
-          <element name="permEnd">
-            <ref name="CT_Perm"/>
-          </element>
           <ref name="EG_RangeMarkupElements"/>
           <element name="ins">
             <ref name="CT_RunTrackChange"/>
@@ -17363,6 +17361,18 @@
     <resource name="CT_MarkupRangeBookmark" resource="Properties">
       <attribute name="id" tokenid="ooxml:CT_MarkupRangeBookmark_id"/>
     </resource>
+    <resource name="CT_PermStart" resource="Properties">
+      <attribute name="id" tokenid="ooxml:CT_PermStart_id"/>
+      <attribute name="colFirst" tokenid="ooxml:CT_PermStart_colFirst"/>
+      <attribute name="colLast" tokenid="ooxml:CT_PermStart_colLast"/>
+      <attribute name="ed" tokenid="ooxml:CT_PermStart_ed"/>
+      <attribute name="edGrp" tokenid="ooxml:CT_PermStart_edGrp"/>
+      <attribute name="displacedByCustomXml" tokenid="ooxml:CT_PermStart_displacedByCustomXml"/>
+    </resource>
+    <resource name="CT_PermEnd" resource="Properties">
+      <attribute name="id" tokenid="ooxml:CT_PermEnd_id"/>
+      <attribute name="displacedByCustomXml" tokenid="ooxml:CT_PermEnd_displacedByCustomXml"/>
+    </resource>
     <resource name="CT_MarkupRangeCommentStart" resource="Properties">
       <attribute name="id" tokenid="ooxml:EG_RangeMarkupElements_commentRangeStart"/>
     </resource>
@@ -17425,6 +17435,8 @@
     <resource name="EG_RangeMarkupElements" resource="Properties">
       <element name="bookmarkStart" tokenid="ooxml:EG_RangeMarkupElements_bookmarkStart"/>
       <element name="bookmarkEnd" tokenid="ooxml:EG_RangeMarkupElements_bookmarkEnd"/>
+      <element name="permStart" tokenid="ooxml:EG_RangeMarkupElements_PermStart"/>
+      <element name="permEnd" tokenid="ooxml:EG_RangeMarkupElements_PermEnd"/>
       <element name="moveFromRangeStart" tokenid="ooxml:EG_RangeMarkupElements_moveFromRangeStart"/>
       <element name="moveFromRangeEnd" tokenid="ooxml:EG_RangeMarkupElements_moveFromRangeEnd"/>
       <element name="moveToRangeStart" tokenid="ooxml:EG_RangeMarkupElements_moveToRangeStart"/>


More information about the Libreoffice-commits mailing list