[Libreoffice-commits] .: 6 commits - sw/inc sw/source

Cédric Bosdonnat cbosdo at kemper.freedesktop.org
Tue Oct 12 01:23:40 PDT 2010


 sw/inc/unobookmark.hxx                 |    6 +
 sw/source/core/crsr/bookmrk.cxx        |   23 ++++-
 sw/source/core/crsr/pam.cxx            |   22 ++++
 sw/source/core/crsr/swcrsr.cxx         |   46 +++++++---
 sw/source/core/doc/docbm.cxx           |    2 
 sw/source/core/inc/bookmrk.hxx         |    3 
 sw/source/core/unocore/unobkm.cxx      |   29 ++++++
 sw/source/core/unocore/unoportenum.cxx |    6 -
 sw/source/filter/ww8/docxexport.cxx    |    5 +
 sw/source/filter/ww8/docxexport.hxx    |    3 
 sw/source/filter/ww8/rtfexport.cxx     |    5 +
 sw/source/filter/ww8/rtfexport.hxx     |    2 
 sw/source/filter/ww8/wrtw8nds.cxx      |   56 +++++++++++-
 sw/source/filter/ww8/wrtww8.hxx        |    5 +
 sw/source/filter/ww8/wrtww8gr.cxx      |   43 +++++++++
 sw/source/filter/ww8/ww8par.hxx        |    4 
 sw/source/filter/ww8/ww8par5.cxx       |  146 +++++++++++++++++++++++++++++----
 sw/source/filter/ww8/ww8par6.cxx       |   14 ++-
 18 files changed, 377 insertions(+), 43 deletions(-)

New commits:
commit 76a04d38a0916775ae7dd0d0f96832ef42211ac6
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date:   Tue Oct 12 10:17:41 2010 +0200

    Fixed the double-click behavior on enhanced fields
    
    n#639288

diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index 517aef7..9d8cfa1 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1370,22 +1370,44 @@ BOOL SwCursor::SelectWordWT( sal_Int16 nWordType, const Point* pPt )
     const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
     if( pTxtNd && pBreakIt->GetBreakIter().is() )
     {
-        xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
-        Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary(
-                            pTxtNd->GetTxt(), nPtPos,
-                            pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
-                            nWordType,
-                            bForward ));
-
-        if( aBndry.startPos != aBndry.endPos )
+        // Should we select the whole fieldmark?
+        const IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
+        sw::mark::IMark* pMark = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
+        if ( pMark )
         {
-            GetPoint()->nContent = (xub_StrLen)aBndry.endPos;
-            if( !IsSelOvr() )
+            const SwPosition rStart = pMark->GetMarkStart();
+            GetPoint()->nNode = rStart.nNode;
+            GetPoint()->nContent = rStart.nContent;
+
+            const SwPosition rEnd = pMark->GetMarkEnd();
+
+            if ( rStart != rEnd )
             {
                 SetMark();
-                GetMark()->nContent = (xub_StrLen)aBndry.startPos;
+                GetMark()->nNode = rEnd.nNode;
+                GetMark()->nContent = rEnd.nContent;
+            }
+            bRet = TRUE;
+        }
+        else
+        {
+            xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+            Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary(
+                                pTxtNd->GetTxt(), nPtPos,
+                                pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+                                nWordType,
+                                bForward ));
+
+            if( aBndry.startPos != aBndry.endPos )
+            {
+                GetPoint()->nContent = (xub_StrLen)aBndry.endPos;
                 if( !IsSelOvr() )
-                    bRet = TRUE;
+                {
+                    SetMark();
+                    GetMark()->nContent = (xub_StrLen)aBndry.startPos;
+                    if( !IsSelOvr() )
+                        bRet = TRUE;
+                }
             }
         }
     }
commit 61d2b26a9479ff75bbfc60ee627bc8b984b1a81b
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date:   Tue Oct 12 10:15:39 2010 +0200

    WW8: Fixed the import of nested SET / FILLIN fields
    
    n#634478

diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 5b80db4..7110001 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -234,19 +234,28 @@ xub_StrLen _ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart)
     while( (nLen > n) && (aData.GetChar( n ) == ' ') )
         ++n;
 
+    if ( aData.GetChar( n ) == 0x13 )
+    {
+        // Skip the nested field code since it's not supported
+        while ( ( nLen > n ) && ( aData.GetChar( n ) != 0x14 ) )
+            n++;
+    }
+
     if( nLen == n )
         return STRING_NOTFOUND;     // String End reached!
 
     if(     (aData.GetChar( n ) == '"')     // Anfuehrungszeichen vor Para?
         ||  (aData.GetChar( n ) == 0x201c)
-        ||  (aData.GetChar( n ) == 132) )
+        ||  (aData.GetChar( n ) == 132)
+        ||  (aData.GetChar( n ) == 0x14) )
     {
         n++;                        // Anfuehrungszeichen ueberlesen
         n2 = n;                     // ab hier nach Ende suchen
         while(     (nLen > n2)
                 && (aData.GetChar( n2 ) != '"')
                 && (aData.GetChar( n2 ) != 0x201d)
-                && (aData.GetChar( n2 ) != 147) )
+                && (aData.GetChar( n2 ) != 147)
+                && (aData.GetChar( n2 ) != 0x15) )
             n2++;                   // Ende d. Paras suchen
     }
     else                        // keine Anfuehrungszeichen
@@ -1025,6 +1034,8 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
 
     ASSERT(bOk, "WW8: Bad Field!\n");
     if (aF.nId == 33) aF.bCodeNest=false; //#124716#: do not recurse into nested page fields
+    bool bCodeNest = aF.bCodeNest;
+    if ( aF.nId == 6 ) bCodeNest = false; // We can handle them and loose the inner data
 
     maFieldStack.push_back(FieldEntry(*pPaM->GetPoint(), aF.nId));
 
@@ -1054,7 +1065,7 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
         return aF.nLen;
 
     // keine Routine vorhanden
-    if (bNested || !aWW8FieldTab[aF.nId] || aF.bCodeNest)
+    if (bNested || !aWW8FieldTab[aF.nId] || bCodeNest)
     {
         if( nFieldTagBad[nI] & nMask )      // Flag: Tag it when bad
             return Read_F_Tag( &aF );       // Resultat nicht als Text
@@ -1073,8 +1084,9 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
         if ( STRING_NOTFOUND == nSpacePos )
             nSpacePos = aStr.Len( );
         xub_StrLen nSearchPos = STRING_NOTFOUND;
-        if ( ( ( nSearchPos = aStr.Search('.') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) ||
-             ( ( nSearchPos = aStr.Search('/') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) )
+        if ( !( aStr.EqualsAscii( "=", 1, 1 ) ) && (
+                ( ( nSearchPos = aStr.Search('.') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) ||
+                ( ( nSearchPos = aStr.Search('/') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) ) )
             return aF.nLen;
         else
         {
@@ -1092,8 +1104,17 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
     {                                   // Lies Feld
         long nOldPos = pStrm->Tell();
         String aStr;
-        aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
-            aF.nSCode, aF.nLCode, eTextCharSet );
+        if ( aF.nId == 6 && aF.bCodeNest )
+        {
+            // TODO Extract the whole code string using the nested codes
+            aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs() +
+                aF.nSCode, aF.nSRes - aF.nSCode - 1, eTextCharSet );
+        }
+        else
+        {
+            aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
+                aF.nSCode, aF.nLCode, eTextCharSet );
+        }
 
         // --> OD 2005-07-25 #i51312# - graphics inside field code not supported
         // by Writer. Thus, delete character 0x01, which stands for such a graphic.
@@ -2147,7 +2168,7 @@ eF_ResT SwWW8ImplReader::Read_F_Ref( WW8FieldDesc*, String& rStr )
             */
             SwGetRefField aFld(
                 (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
-                sOrigBkmName,REF_BOOKMARK,0,REF_CONTENT);
+                sBkmName,REF_BOOKMARK,0,REF_CONTENT);
             pReffingStck->NewAttr( *pPaM->GetPoint(), SwFmtFld(aFld) );
             pReffingStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_FIELD);
         }
commit 27b84ceb96936e3918cbca235273168c9e79b0c1
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date:   Tue Oct 12 10:11:30 2010 +0200

    OLE Links roundtrip fixed for links as pictures
    
    n#628098

diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 5419ccd..a61dec4 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -368,6 +368,7 @@ class FieldEntry
     public:
         sw::hack::Position maStartPos;
         sal_uInt16 mnFieldId;
+        ULONG mnObjLocFc;
         FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw();
         FieldEntry(const FieldEntry &rOther) throw();
         FieldEntry &operator=(const FieldEntry &rOther) throw();
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index fe2119c..5b80db4 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -762,11 +762,11 @@ sal_uInt16 SwWW8ImplReader::End_Field()
                                     rtl::OUString::createFromAscii( ODF_CODE_PARAM ),
                                     uno::makeAny( aCode ) ) );
 
-                        if ( nObjLocFc > 0 )
+                        if ( maFieldStack.back().mnObjLocFc > 0 )
                         {
                             // Store the OLE object as an internal link
                             String sOleId = '_';
-                            sOleId += String::CreateFromInt32( nObjLocFc );
+                            sOleId += String::CreateFromInt32( maFieldStack.back().mnObjLocFc );
 
                             SvStorageRef xSrc0 = pStg->OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool));
                             SvStorageRef xSrc1 = xSrc0->OpenSotStorage( sOleId, STREAM_READ );
@@ -830,12 +830,12 @@ bool AcceptableNestedField(sal_uInt16 nFieldCode)
 }
 
 FieldEntry::FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw()
-    : maStartPos(rPos), mnFieldId(nFieldId)
+    : maStartPos(rPos), mnFieldId(nFieldId), mnObjLocFc(0)
 {
 }
 
 FieldEntry::FieldEntry(const FieldEntry &rOther) throw()
-    : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId)
+    : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId), mnObjLocFc(rOther.mnObjLocFc)
 {
 }
 
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index dbac410..e6e1bc7 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -2827,7 +2827,14 @@ void SwWW8ImplReader::Read_Obj(USHORT , const BYTE* pData, short nLen)
         bObj = 0 != *pData;
 
         if( bObj && nPicLocFc && bEmbeddObj )
-            nObjLocFc = nPicLocFc;
+        {
+            if ( maFieldStack.back().mnFieldId == 56 ) {
+                // For LINK fields, store the nObjLocFc value in the field entry
+                maFieldStack.back().mnObjLocFc = nPicLocFc;
+            } else {
+                nObjLocFc = nPicLocFc;
+            }
+        }
     }
 }
 
commit 554cf2609b0e33018b443bbc2e99e4fa1b1b8d8e
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date:   Tue Oct 12 10:08:27 2010 +0200

    Fixed the frame surrounding in ww8 import
    
    n#617593

diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index f1ee7eb..dbac410 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -2209,7 +2209,10 @@ WW8FlySet::WW8FlySet(SwWW8ImplReader& rReader, const WW8FlyPara* pFW,
         Put(SvxULSpaceItem(pFS->nUpMgn, pFS->nLoMgn, RES_UL_SPACE));
 
     //we no longer need to hack around the header/footer problems
-    Put(SwFmtSurround(pFS->eSurround));
+    SwFmtSurround aSurround(pFS->eSurround);
+    if ( pFS->eSurround == SURROUND_IDEAL )
+        aSurround.SetAnchorOnly( TRUE );
+    Put( aSurround );
 
     short aSizeArray[5]={0};
     rReader.SetFlyBordersShadow(*this,(const WW8_BRC*)pFW->brc,&aSizeArray[0]);
commit 1cf32df745c4025cf932de6a1fa53e4685d3c025
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date:   Tue Oct 12 10:02:36 2010 +0200

    WW8: Don't show the result of the fields with 0x01 code
    
    Fix for n#623944

diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 2b9cb00..fe2119c 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -898,7 +898,7 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
     static FNReadField aWW8FieldTab[eMax+1] =
     {
         0,
-        0,
+        &SwWW8ImplReader::Read_F_Input,
         0,
         &SwWW8ImplReader::Read_F_Ref,               // 3
         0,
@@ -1289,9 +1289,12 @@ eF_ResT SwWW8ImplReader::Read_F_Input( WW8FieldDesc* pF, String& rStr )
     if( !aDef.Len() )
         aDef = GetFieldResult( pF );
 
-    SwInputField aFld( (SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
-                        aDef, aQ, INP_TXT, 0 ); // sichtbar ( geht z.Zt. nicht anders )
-    rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+    if ( pF->nId != 0x01 ) // 0x01 fields have no result
+    {
+        SwInputField aFld( (SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
+                            aDef, aQ, INP_TXT, 0 ); // sichtbar ( geht z.Zt. nicht anders )
+        rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+    }
 
     return FLD_OK;
 }
commit 92018a4c66b67391a9cddfa7442214d40bc59f71
Author: Cédric Bosdonnat <cedricbosdo at openoffice.org>
Date:   Tue Oct 12 09:59:30 2010 +0200

    Fix the roundtrip of DOC unhandled fields
    
    Partly fixes n#628098 (roundtripping OLE Links)

diff --git a/sw/inc/unobookmark.hxx b/sw/inc/unobookmark.hxx
index d1062eb..729c556 100644
--- a/sw/inc/unobookmark.hxx
+++ b/sw/inc/unobookmark.hxx
@@ -80,6 +80,8 @@ protected:
 
     const ::sw::mark::IMark* GetBookmark() const;
 
+    void registerInMark( SwXBookmark& rXMark, ::sw::mark::IMark* const pMarkBase );
+
     virtual ~SwXBookmark();
 
     /// @param pDoc and pMark != 0, but not & because of ImplInheritanceHelper
@@ -239,6 +241,10 @@ private:
 
 public:
 
+    static ::com::sun::star::uno::Reference<
+            ::com::sun::star::text::XTextContent>
+        CreateXFieldmark( SwDoc & rDoc, ::sw::mark::IMark & rMark );
+
     SwXFieldmark(bool isReplacementObject,
             ::sw::mark::IMark* pBkm = 0, SwDoc* pDoc = 0);
 
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
index 5bca4c8..dca5995 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -82,15 +82,17 @@ namespace
         SwTxtNode const * const pStartTxtNode = io_pDoc->GetNodes()[rStart.nNode]->GetTxtNode();
         SwTxtNode const * const pEndTxtNode = io_pDoc->GetNodes()[rEnd.nNode]->GetTxtNode();
         const sal_Unicode ch_start=pStartTxtNode->GetTxt().GetChar(rStart.nContent.GetIndex());
-        const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar(rEnd.nContent.GetIndex()-1);
+        xub_StrLen nEndPos = rEnd.nContent.GetIndex() == 0 ? 0 : rEnd.nContent.GetIndex() - 1;
+        const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar( nEndPos );
         SwPaM aStartPaM(rStart);
         SwPaM aEndPaM(rEnd);
         io_pDoc->StartUndo(UNDO_UI_REPLACE, NULL);
-        if(ch_start != aStartMark)
+        if( ( ch_start != aStartMark ) && ( rStart != rEnd ) )
         {
             io_pDoc->InsertString(aStartPaM, aStartMark);
+            rStart.nContent--;
         }
-        if ( aEndMark && ( ch_end != aEndMark ) && ( rStart != rEnd ) )
+        if ( aEndMark && ( ch_end != aEndMark ) )
         {
             io_pDoc->InsertString(aEndPaM, aEndMark);
         }
@@ -323,7 +325,7 @@ namespace sw { namespace mark
 
     void CheckboxFieldmark::InitDoc(SwDoc* const io_pDoc)
     {
-        lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FORMELEMENT, CH_TXT_ATR_FIELDEND);
+        lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
 
         // For some reason the end mark is moved from 1 by the Insert: we don't
         // want this for checkboxes
@@ -343,4 +345,17 @@ namespace sw { namespace mark
         return bResult;
     }
 
+    rtl::OUString CheckboxFieldmark::toString( ) const
+    {
+        rtl::OUStringBuffer buf;
+        buf.appendAscii( "CheckboxFieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " );
+        buf.append( m_aName ).appendAscii( ", " );
+        buf.append( GetFieldname() ).appendAscii( ", [ " );
+        buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+        buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ], [" );
+        buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+        buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ] ) " );
+
+        return buf.makeStringAndClear( );
+    }
 }}
diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx
index 6de3089..0f071a1 100644
--- a/sw/source/core/crsr/pam.cxx
+++ b/sw/source/core/crsr/pam.cxx
@@ -55,6 +55,8 @@
 #include <IMark.hxx>
 #include <hints.hxx>
 
+#include <xmloff/odffields.hxx>
+
 // fuer den dummen ?MSC-? Compiler
 inline xub_StrLen GetSttOrEnd( BOOL bCondition, const SwCntntNode& rNd )
 {
@@ -828,19 +830,31 @@ BOOL SwPaM::HasReadonlySel( bool bFormView ) const
     const SwDoc *pDoc = GetDoc();
     sw::mark::IMark* pA = NULL;
     sw::mark::IMark* pB = NULL;
+    bool bUnhandledMark = false;
     if ( pDoc )
     {
         const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( );
         pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
         pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA;
+
+        sw::mark::IFieldmark* pFieldmark = pMarksAccess->getFieldmarkFor( *GetPoint() );
+        if ( pFieldmark )
+            bUnhandledMark = pFieldmark->GetFieldname( ).equalsAscii( ODF_UNHANDLED );
     }
 
     if (!bRet)
     {
-        bRet = ( pA != pB );
-        bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
-        if ( bProtectForm )
-            bRet |= ( pA == NULL || pB == NULL );
+        // Unhandled fieldmarks case shouldn't be edited manually to avoid breaking anything
+        if ( ( pA == pB ) && bUnhandledMark )
+            bRet = TRUE;
+        else
+        {
+            // Form protection case
+            bRet = ( pA != pB );
+            bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
+            if ( bProtectForm )
+                bRet |= ( pA == NULL || pB == NULL );
+        }
     }
     else
     {
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 4c3c50b..3f5ab76 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -419,6 +419,7 @@ namespace sw { namespace mark
         OSL_TRACE("Fieldmarks");
         lcl_DebugMarks(m_vFieldmarks);
 #endif
+
         return pMark.get();
     }
 
@@ -811,6 +812,7 @@ namespace sw { namespace mark
     IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
         { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
 
+
     ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
     {
         OSL_ENSURE(rName.getLength(),
diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx
index a47a059..2ff0409 100644
--- a/sw/source/core/inc/bookmrk.hxx
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -35,6 +35,7 @@
 #include <boost/scoped_ptr.hpp>
 #include <boost/noncopyable.hpp>
 #include <map>
+#include <rtl/ustring.hxx>
 
 #include <IMark.hxx>
 
@@ -255,6 +256,8 @@ namespace sw { namespace mark
             virtual void InitDoc(SwDoc* const io_pDoc);
             bool IsChecked() const;
             void SetChecked(bool checked);
+
+            virtual rtl::OUString toString( ) const;
     };
 
 }}
diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx
index 0527242..d10093c 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -129,6 +129,11 @@ void SwXBookmark::Impl::registerInMark(SwXBookmark & rThis,
     m_pRegisteredBookmark = pBkmk;
 }
 
+void SwXBookmark::registerInMark(SwXBookmark & rThis,
+        ::sw::mark::IMark *const pBkmk)
+{
+    m_pImpl->registerInMark( rThis, pBkmk );
+}
 
 const ::sw::mark::IMark* SwXBookmark::GetBookmark() const
 {
@@ -647,3 +652,27 @@ uno::Reference<container::XNameContainer> SwXFieldmark::getParameters()
     return uno::Reference<container::XNameContainer>(new SwXFieldmarkParameters(pBkm));
 }
 
+uno::Reference<text::XTextContent>
+SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark & rMark)
+{
+    // #i105557#: do not iterate over the registered clients: race condition
+    ::sw::mark::MarkBase *const pMarkBase(
+        dynamic_cast< ::sw::mark::MarkBase * >(&rMark));
+    OSL_ENSURE(pMarkBase, "CreateXBookmark: no MarkBase?");
+    if (!pMarkBase) { return 0; }
+    uno::Reference<text::XTextContent> xMark(pMarkBase->GetXBookmark());
+    if (!xMark.is())
+    {
+        // FIXME: These belong in XTextFieldsSupplier
+        SwXFieldmark* pXBkmk = NULL;
+        if (dynamic_cast< ::sw::mark::TextFieldmark* >(&rMark))
+            pXBkmk = new SwXFieldmark(false, &rMark, &rDoc);
+        else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(&rMark))
+            pXBkmk = new SwXFieldmark(true, &rMark, &rDoc);
+
+        xMark.set(pXBkmk);
+        pXBkmk->registerInMark(*pXBkmk, pMarkBase);
+    }
+    return xMark;
+}
+
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index 0a5115b..d68f505 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -376,7 +376,7 @@ lcl_ExportFieldMark(
             pUnoCrsr, i_xParentText, PORTION_FIELD_START);
         xRef = pPortion;
         if (pPortion && pFieldmark && pDoc)
-            pPortion->SetBookmark(new SwXFieldmark(false, pFieldmark, pDoc));
+            pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
     }
     else if (CH_TXT_ATR_FIELDEND == Char)
     {
@@ -390,7 +390,7 @@ lcl_ExportFieldMark(
             pUnoCrsr, i_xParentText, PORTION_FIELD_END);
         xRef = pPortion;
         if (pPortion && pFieldmark && pDoc)
-            pPortion->SetBookmark(new SwXFieldmark(false, pFieldmark, pDoc));
+            pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
     }
     else if (CH_TXT_ATR_FORMELEMENT == Char)
     {
@@ -404,7 +404,7 @@ lcl_ExportFieldMark(
             pUnoCrsr, i_xParentText, PORTION_FIELD_START_END);
         xRef = pPortion;
         if (pPortion && pFieldmark && pDoc)
-            pPortion->SetBookmark(new SwXFieldmark(true, pFieldmark, pDoc));
+            pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
     }
     else
     {
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 1bb810c..ed0177b 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -373,6 +373,11 @@ void DocxExport::OutputOLENode( const SwOLENode& )
     OSL_TRACE( "TODO DocxExport::OutputOLENode( const SwOLENode& )\n" );
 }
 
+void DocxExport::OutputLinkedOLE( const OUString& )
+{
+    // Nothing to implement here: WW8 only
+}
+
 ULONG DocxExport::ReplaceCr( BYTE )
 {
     // Completely unused for Docx export... only here for code sharing 
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 1bf9e22..4fee76a 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -147,6 +147,9 @@ protected:
     /// Output SwOLENode
     virtual void OutputOLENode( const SwOLENode& );
 
+    virtual void OutputLinkedOLE( const rtl::OUString& );
+
+
 
     virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, ULONG nLnNum );
 
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index cc9bb82..ea3e17e 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -728,6 +728,11 @@ void RtfExport::OutputOLENode( const SwOLENode& )
     /* noop, see RtfAttributeOutput::FlyFrameOLE */
 }
 
+void RtfExport::OutputLinkedOLE( const rtl::OUString& )
+{
+    OSL_TRACE("%s", OSL_THIS_FUNC);
+}
+
 void RtfExport::AppendSection( const SwPageDesc* pPageDesc, const SwSectionFmt* pFmt, ULONG nLnNum )
 {
     OSL_TRACE("%s", OSL_THIS_FUNC);
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
index 0a2f3f4..ea96f9c 100644
--- a/sw/source/filter/ww8/rtfexport.hxx
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -142,6 +142,8 @@ protected:
     /// Output SwOLENode
     virtual void OutputOLENode( const SwOLENode& );
 
+    virtual void OutputLinkedOLE(const rtl::OUString&);
+
     virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, ULONG nLnNum );
 
 public:
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 5c295de..8af512b 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -116,9 +116,9 @@ using namespace sw::types;
 using namespace sw::mark;
 using namespace nsFieldFlags;
 
-
 static String lcl_getFieldCode( const IFieldmark* pFieldmark ) {
     ASSERT(pFieldmark!=NULL, "where is my fieldmark???");
+
     if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) ) {
         return String::CreateFromAscii(" FORMTEXT ");
     } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) ) {
@@ -1818,12 +1818,49 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
 
                 if ( pFieldmark->GetFieldname().equalsAscii( ODF_FORMTEXT ) )
                     AppendBookmark( pFieldmark->GetName(), false );
-                OutputField( NULL, lcl_getFieldId( pFieldmark ), lcl_getFieldCode( pFieldmark ), WRITEFIELD_START | WRITEFIELD_CMD_START );
+                ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+                String sCode = lcl_getFieldCode( pFieldmark );
+                if ( pFieldmark->GetFieldname().equalsAscii( ODF_UNHANDLED ) )
+                {
+                    IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find(
+                            rtl::OUString::createFromAscii( ODF_ID_PARAM ) );
+                    if ( it != pFieldmark->GetParameters()->end() )
+                    {
+                        rtl::OUString sFieldId;
+                        it->second >>= sFieldId;
+                        eFieldId = (ww::eField)sFieldId.toInt32();
+                    }
+
+                    it = pFieldmark->GetParameters()->find(
+                            rtl::OUString::createFromAscii( ODF_CODE_PARAM ) );
+                    if ( it != pFieldmark->GetParameters()->end() )
+                    {
+                        rtl::OUString sOUCode;
+                        it->second >>= sOUCode;
+                        sCode = sOUCode;
+                    }
+                }
+                OutputField( NULL, eFieldId, sCode, WRITEFIELD_START | WRITEFIELD_CMD_START );
                 if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) )
                     WriteFormData( *pFieldmark );
                 else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) )
                     WriteHyperlinkData( *pFieldmark );
                 OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CMD_END );
+
+                if ( pFieldmark->GetFieldname().equalsAscii( ODF_UNHANDLED ) )
+                {
+                    // Check for the presence of a linked OLE object
+                    IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find(
+                            rtl::OUString::createFromAscii( ODF_OLE_PARAM ) );
+                    if ( it != pFieldmark->GetParameters()->end() )
+                    {
+                        rtl::OUString sOleId;
+                        uno::Any aValue = it->second;
+                        aValue >>= sOleId;
+                        if ( sOleId.getLength( ) > 0 )
+                            OutputLinkedOLE( sOleId );
+                    }
+                }
             }
             else if ( ch == CH_TXT_ATR_FIELDEND )
             {
@@ -1831,7 +1868,20 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
                 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
                 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
 
-                OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CLOSE );
+                ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+                if ( pFieldmark->GetFieldname().equalsAscii( ODF_UNHANDLED ) )
+                {
+                    IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find(
+                            rtl::OUString::createFromAscii( ODF_ID_PARAM ) );
+                    if ( it != pFieldmark->GetParameters()->end() )
+                    {
+                        rtl::OUString sFieldId;
+                        it->second >>= sFieldId;
+                        eFieldId = (ww::eField)sFieldId.toInt32();
+                    }
+                }
+
+                OutputField( NULL, eFieldId, String(), WRITEFIELD_CLOSE );
                 if ( pFieldmark->GetFieldname().equalsAscii( ODF_FORMTEXT ) )
                     AppendBookmark( pFieldmark->GetName(), false );
             }
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 546edb0..6afe863 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -784,6 +784,9 @@ protected:
     /// Output SwOLENode
     virtual void OutputOLENode( const SwOLENode& ) = 0;
 
+    virtual void OutputLinkedOLE( const rtl::OUString& ) = 0;
+
+
     /// Output SwSectionNode
     virtual void OutputSectionNode( const SwSectionNode& );
 
@@ -1123,6 +1126,8 @@ protected:
     /// Output SwOLENode
     virtual void OutputOLENode( const SwOLENode& );
 
+    virtual void OutputLinkedOLE( const rtl::OUString& );
+
     virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, ULONG nLnNum );
 
 private:
diff --git a/sw/source/filter/ww8/wrtww8gr.cxx b/sw/source/filter/ww8/wrtww8gr.cxx
index 88670de..9e18faf 100644
--- a/sw/source/filter/ww8/wrtww8gr.cxx
+++ b/sw/source/filter/ww8/wrtww8gr.cxx
@@ -36,6 +36,7 @@
 
 #include <com/sun/star/embed/XEmbedPersist.hpp>
 #include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
 #include <rtl/math.hxx>
 #include <svtools/filter.hxx>
 #include <svl/itemiter.hxx>
@@ -368,6 +369,48 @@ void WW8Export::OutputOLENode( const SwOLENode& rOLENode )
     }
 }
 
+void WW8Export::OutputLinkedOLE( const rtl::OUString& rOleId )
+{
+    uno::Reference< embed::XStorage > xDocStg = pDoc->GetDocStorage();
+    uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
+            rtl::OUString::createFromAscii( "OLELinks" ), embed::ElementModes::READ );
+    SotStorageRef xObjSrc = SotStorage::OpenOLEStorage( xOleStg, rOleId, STREAM_READ );
+
+    SotStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
+        CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
+        STREAM_SHARE_DENYALL );
+
+    if( xObjStg.Is() && xObjSrc.Is() )
+    {
+        SotStorageRef xOleDst = xObjStg->OpenSotStorage( rOleId,
+                STREAM_READWRITE | STREAM_SHARE_DENYALL );
+        if ( xOleDst.Is() )
+            xObjSrc->CopyTo( xOleDst );
+
+        if ( !xOleDst->GetError( ) )
+        {
+            xOleDst->Commit();
+
+            // Ouput the cPicLocation attribute
+            WW8Bytes* pBuf = new WW8Bytes( 128, 128 );
+            GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CPicLocation );
+            GetWriter().InsUInt32( *pBuf, rOleId.copy( 1 ).toInt32() );
+
+            GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFOle2 );
+            pBuf->Insert( 1, pBuf->Count() );
+
+            GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFSpec );
+            pBuf->Insert( 1, pBuf->Count() );
+
+            GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFObj );
+            pBuf->Insert( 1, pBuf->Count() );
+
+            pChpPlc->AppendFkpEntry( Strm().Tell(), pBuf->Count(), pBuf->GetData() );
+            delete pBuf;
+        }
+    }
+}
+
 void WW8Export::OutGrf(const sw::Frame &rFrame)
 {
     // GrfNode fuer spaeteres rausschreiben der Grafik merken
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 7123e69..5419ccd 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -362,6 +362,7 @@ class FieldEntry
     private:
         ::rtl::OUString msBookmarkName;
         ::rtl::OUString msMarkType;
+        ::rtl::OUString msMarkCode;
         ::sw::mark::IFieldmark::parameter_map_t maParams;
 
     public:
@@ -377,8 +378,10 @@ class FieldEntry
 
         ::rtl::OUString GetBookmarkName();
         ::rtl::OUString GetBookmarkType();
+        ::rtl::OUString GetBookmarkCode();
         void SetBookmarkName(::rtl::OUString bookmarkName);
         void SetBookmarkType(::rtl::OUString bookmarkType);
+        void SetBookmarkCode(::rtl::OUString bookmarkCode);
         ::sw::mark::IFieldmark::parameter_map_t& getParameters();
 };
 
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 57dfd8a..2b9cb00 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -36,6 +36,13 @@
 #include <sal/types.h>
 #include <tools/solar.h>
 
+#include <comphelper/storagehelper.hxx>
+#include <sot/storinfo.hxx>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/io/XStream.hpp>
+
 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
 #include <svl/urihelper.hxx>
 #include <svl/zforlist.hxx>
@@ -87,6 +94,7 @@
 #include "writerhelper.hxx"
 #include "fields.hxx"
 #include <unotools/fltrcfg.hxx>
+#include <xmloff/odffields.hxx>
 
 #include <algorithm> // #i24377#
 
@@ -725,6 +733,72 @@ sal_uInt16 SwWW8ImplReader::End_Field()
                 *pPaM->GetPoint() = maFieldStack.back().maStartPos;
                 break;
             default:
+                rtl::OUString aCode = maFieldStack.back().GetBookmarkCode();
+                if ( aCode.getLength() > 0 )
+                {
+                    // Unhandled field with stored code
+                    SwPosition aEndPos = *pPaM->GetPoint();
+                    SwPaM aFldPam(
+                            maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(),
+                            aEndPos.nNode, aEndPos.nContent.GetIndex());
+
+                    IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
+
+                    IFieldmark* pFieldmark = pMarksAccess->makeFieldBookmark(
+                                aFldPam,
+                                maFieldStack.back().GetBookmarkName(),
+                                rtl::OUString::createFromAscii( ODF_UNHANDLED ) );
+                    if ( pFieldmark )
+                    {
+                        const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
+                        pFieldmark->GetParameters()->insert(pParametersToAdd.begin(), pParametersToAdd.end());
+                        rtl::OUString sFieldId = rtl::OUString::valueOf( sal_Int32( maFieldStack.back().mnFieldId ) );
+                        pFieldmark->GetParameters()->insert(
+                                std::pair< rtl::OUString, uno::Any > (
+                                    rtl::OUString::createFromAscii( ODF_ID_PARAM ),
+                                    uno::makeAny( sFieldId ) ) );
+                        pFieldmark->GetParameters()->insert(
+                                std::pair< rtl::OUString, uno::Any > (
+                                    rtl::OUString::createFromAscii( ODF_CODE_PARAM ),
+                                    uno::makeAny( aCode ) ) );
+
+                        if ( nObjLocFc > 0 )
+                        {
+                            // Store the OLE object as an internal link
+                            String sOleId = '_';
+                            sOleId += String::CreateFromInt32( nObjLocFc );
+
+                            SvStorageRef xSrc0 = pStg->OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool));
+                            SvStorageRef xSrc1 = xSrc0->OpenSotStorage( sOleId, STREAM_READ );
+
+                            // Store it now!
+                            uno::Reference< embed::XStorage > xDocStg = GetDoc().GetDocStorage();
+                            uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
+                                    rtl::OUString::createFromAscii( "OLELinks" ), embed::ElementModes::WRITE );
+                            SotStorageRef xObjDst = SotStorage::OpenOLEStorage( xOleStg, sOleId );
+
+                            if ( xObjDst.Is() )
+                            {
+                                xSrc1->CopyTo( xObjDst );
+
+                                if ( !xObjDst->GetError() )
+                                    xObjDst->Commit();
+                            }
+
+                            uno::Reference< embed::XTransactedObject > xTransact( xOleStg, uno::UNO_QUERY );
+                            if ( xTransact.is() )
+                                xTransact->commit();
+
+                            // Store the OLE Id as a parameter
+                            pFieldmark->GetParameters()->insert(
+                                    std::pair< rtl::OUString, uno::Any >(
+                                        rtl::OUString::createFromAscii( ODF_OLE_PARAM ),
+                                        uno::makeAny( rtl::OUString( sOleId ) ) ) );
+                        }
+
+                    }
+                }
+
                 break;
         }
         maFieldStack.pop_back();
@@ -788,6 +862,11 @@ FieldEntry &FieldEntry::operator=(const FieldEntry &rOther) throw()
     return msMarkType;
 }
 
+::rtl::OUString FieldEntry::GetBookmarkCode()
+{
+    return msMarkCode;
+}
+
 void FieldEntry::SetBookmarkName(::rtl::OUString bookmarkName) 
 {
     msBookmarkName=bookmarkName;
@@ -798,6 +877,11 @@ void FieldEntry::SetBookmarkType(::rtl::OUString bookmarkType)
     msMarkType=bookmarkType;
 }
 
+void FieldEntry::SetBookmarkCode(::rtl::OUString bookmarkCode)
+{
+    msMarkCode = bookmarkCode;
+}
+
 
 ::sw::mark::IFieldmark::parameter_map_t& FieldEntry::getParameters() {
     return maParams;
@@ -871,7 +955,7 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
         0,
 
 
-        0,      // 56: VERKNUePFUNG     // fehlt noch !!!!!!!!!!!!!!!!!!!!!!!
+        0,                                          // 56
 
 
         &SwWW8ImplReader::Read_F_Symbol,            // 57
@@ -993,8 +1077,16 @@ long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
              ( ( nSearchPos = aStr.Search('/') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) )
             return aF.nLen;
         else
+        {
+            // Link fields aren't supported, but they are bound to an OLE object
+            // that needs to be roundtripped
+            if ( aF.nId == 56 )
+                bEmbeddObj = true;
+            // Field not supported: store the field code for later use
+            maFieldStack.back().SetBookmarkCode( aStr );
             return aF.nLen - aF.nLRes - 1;  // so viele ueberlesen, das Resultfeld
                                             // wird wie Haupttext eingelesen
+        }
     }
     else
     {                                   // Lies Feld


More information about the Libreoffice-commits mailing list