LCOV - code coverage report
Current view: top level - sw/source/filter/ww8 - wrtw8nds.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 979 1446 67.7 %
Date: 2014-04-11 Functions: 55 66 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <vector>
      21             : #include <list>
      22             : #include <utility>
      23             : #include <algorithm>
      24             : #include <functional>
      25             : #include <iostream>
      26             : 
      27             : #include <i18nlangtag/mslangid.hxx>
      28             : #include <hintids.hxx>
      29             : #include <comphelper/string.hxx>
      30             : #include <tools/urlobj.hxx>
      31             : #include <editeng/boxitem.hxx>
      32             : #include <editeng/cmapitem.hxx>
      33             : #include <editeng/langitem.hxx>
      34             : #include <editeng/svxfont.hxx>
      35             : #include <editeng/lrspitem.hxx>
      36             : #include <editeng/brushitem.hxx>
      37             : #include <editeng/fontitem.hxx>
      38             : #include <editeng/keepitem.hxx>
      39             : #include <editeng/fhgtitem.hxx>
      40             : #include <editeng/ulspitem.hxx>
      41             : #include <editeng/formatbreakitem.hxx>
      42             : #include <editeng/frmdiritem.hxx>
      43             : #include <editeng/tstpitem.hxx>
      44             : #include "svl/urihelper.hxx"
      45             : #include <svl/whiter.hxx>
      46             : #include <fmtpdsc.hxx>
      47             : #include <fmtfsize.hxx>
      48             : #include <fmtornt.hxx>
      49             : #include <fmtlsplt.hxx>
      50             : #include <fmtflcnt.hxx>
      51             : #include <fmtanchr.hxx>
      52             : #include <fmtcntnt.hxx>
      53             : #include <frmatr.hxx>
      54             : #include <paratr.hxx>
      55             : #include <txatbase.hxx>
      56             : #include <fmtinfmt.hxx>
      57             : #include <fmtrfmrk.hxx>
      58             : #include <fchrfmt.hxx>
      59             : #include <fmtautofmt.hxx>
      60             : #include <charfmt.hxx>
      61             : #include <tox.hxx>
      62             : #include <ndtxt.hxx>
      63             : #include <pam.hxx>
      64             : #include <doc.hxx>
      65             : #include <docary.hxx>
      66             : #include <swtable.hxx>
      67             : #include <swtblfmt.hxx>
      68             : #include <section.hxx>
      69             : #include <pagedesc.hxx>
      70             : #include <swrect.hxx>
      71             : #include <reffld.hxx>
      72             : #include <redline.hxx>
      73             : #include <wrtswtbl.hxx>
      74             : #include <htmltbl.hxx>
      75             : #include <txttxmrk.hxx>
      76             : #include <fmtline.hxx>
      77             : #include <fmtruby.hxx>
      78             : #include <breakit.hxx>
      79             : #include <txtatr.hxx>
      80             : #include <fmtsrnd.hxx>
      81             : #include <fmtrowsplt.hxx>
      82             : #include <com/sun/star/i18n/ScriptType.hpp>
      83             : #include <com/sun/star/i18n/WordType.hpp>
      84             : #include <oox/export/vmlexport.hxx>
      85             : 
      86             : #include <filter/msfilter/sprmids.hxx>
      87             : 
      88             : #include "writerhelper.hxx"
      89             : #include "writerwordglue.hxx"
      90             : #include <numrule.hxx>
      91             : #include "wrtww8.hxx"
      92             : #include "ww8par.hxx"
      93             : #include <IMark.hxx>
      94             : #include "ww8attributeoutput.hxx"
      95             : 
      96             : #include <ndgrf.hxx>
      97             : #include <ndole.hxx>
      98             : 
      99             : #include <cstdio>
     100             : 
     101             : using namespace ::com::sun::star;
     102             : using namespace ::com::sun::star::i18n;
     103             : using namespace sw::util;
     104             : using namespace sw::types;
     105             : using namespace sw::mark;
     106             : using namespace nsFieldFlags;
     107             : using namespace ::oox::vml;
     108             : 
     109          26 : static OUString lcl_getFieldCode( const IFieldmark* pFieldmark )
     110             : {
     111             :     OSL_ENSURE(pFieldmark!=NULL, "where is my fieldmark???");
     112             : 
     113          26 :     if ( !pFieldmark)
     114           0 :         return OUString();
     115          26 :     if ( pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
     116           0 :         return OUString(" FORMTEXT ");
     117          26 :     if ( pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN )
     118           0 :         return OUString(" FORMDROPDOWN ");
     119          26 :     if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
     120           1 :         return OUString(" FORMCHECKBOX ");
     121          25 :     if ( pFieldmark->GetFieldname( ) == ODF_TOC )
     122           0 :         return OUString(" TOC ");
     123          25 :     if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
     124           0 :         return OUString(" HYPERLINK ");
     125          25 :     if ( pFieldmark->GetFieldname( ) == ODF_PAGEREF )
     126           0 :         return OUString(" PAGEREF ");
     127          25 :     return pFieldmark->GetFieldname();
     128             : }
     129             : 
     130          77 : static ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) {
     131             :     OSL_ENSURE(pFieldmark!=NULL, "where is my fieldmark???");
     132          77 :     if ( !pFieldmark )
     133           0 :         return ww::eUNKNOWN;
     134          77 :     if ( pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
     135           0 :         return ww::eFORMTEXT;
     136          77 :     if ( pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN )
     137           0 :         return ww::eFORMDROPDOWN;
     138          77 :     if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
     139           2 :         return ww::eFORMCHECKBOX;
     140          75 :     if ( pFieldmark->GetFieldname( ) == ODF_TOC )
     141           0 :         return ww::eTOC;
     142          75 :     if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
     143           0 :         return ww::eHYPERLINK;
     144          75 :     if ( pFieldmark->GetFieldname( ) == ODF_PAGEREF )
     145           0 :         return ww::ePAGEREF;
     146          75 :     return ww::eUNKNOWN;
     147             : }
     148             : 
     149       12266 : MSWordAttrIter::MSWordAttrIter( MSWordExportBase& rExport )
     150       12266 :     : pOld( rExport.pChpIter ), m_rExport( rExport )
     151             : {
     152       12266 :     m_rExport.pChpIter = this;
     153       12266 : }
     154             : 
     155       12266 : MSWordAttrIter::~MSWordAttrIter()
     156             : {
     157       12266 :     m_rExport.pChpIter = pOld;
     158       12266 : }
     159             : 
     160             : class sortswflys :
     161             :     public std::binary_function<const sw::Frame&, const sw::Frame&, bool>
     162             : {
     163             : public:
     164        1006 :     bool operator()(const sw::Frame &rOne, const sw::Frame &rTwo) const
     165             :     {
     166        1006 :         return rOne.GetPosition() < rTwo.GetPosition();
     167             :     }
     168             : };
     169             : 
     170       25535 : void SwWW8AttrIter::IterToCurrent()
     171             : {
     172             :     OSL_ENSURE(maCharRuns.begin() != maCharRuns.end(), "Impossible");
     173       25535 :     mnScript = maCharRunIter->mnScript;
     174       25535 :     meChrSet = maCharRunIter->meCharSet;
     175       25535 :     mbCharIsRTL = maCharRunIter->mbRTL;
     176       25535 : }
     177             : 
     178       12070 : SwWW8AttrIter::SwWW8AttrIter(MSWordExportBase& rWr, const SwTxtNode& rTxtNd) :
     179             :     MSWordAttrIter(rWr),
     180             :     rNd(rTxtNd),
     181       12070 :     maCharRuns(GetPseudoCharRuns(rTxtNd, 0, !rWr.SupportsUnicode())),
     182             :     pCurRedline(0),
     183             :     nAktSwPos(0),
     184             :     nCurRedlinePos(USHRT_MAX),
     185       24140 :     mrSwFmtDrop(rTxtNd.GetSwAttrSet().GetDrop())
     186             : {
     187             : 
     188       12070 :     SwPosition aPos(rTxtNd);
     189       12070 :     if (FRMDIR_HORI_RIGHT_TOP == rWr.pDoc->GetTextDirection(aPos))
     190          56 :         mbParaIsRTL = true;
     191             :     else
     192       12014 :         mbParaIsRTL = false;
     193             : 
     194       12070 :     maCharRunIter = maCharRuns.begin();
     195       12070 :     IterToCurrent();
     196             : 
     197             :     /*
     198             :      #i2916#
     199             :      Get list of any graphics which may be anchored from this paragraph.
     200             :     */
     201       12070 :     maFlyFrms = GetFramesInNode(rWr.maFrames, rNd);
     202       12070 :     std::sort(maFlyFrms.begin(), maFlyFrms.end(), sortswflys());
     203             : 
     204             :     /*
     205             :      #i18480#
     206             :      If we are inside a frame then anything anchored inside this frame can
     207             :      only be supported by word anchored inline ("as character"), so force
     208             :      this in the supportable case.
     209             :     */
     210       12070 :     if (rWr.SupportsUnicode() && rWr.bInWriteEscher)
     211             :     {
     212             :         std::for_each(maFlyFrms.begin(), maFlyFrms.end(),
     213          28 :             std::mem_fun_ref(&sw::Frame::ForceTreatAsInline));
     214             :     }
     215             : 
     216       12070 :     maFlyIter = maFlyFrms.begin();
     217             : 
     218       12070 :     if ( !m_rExport.pDoc->GetRedlineTbl().empty() )
     219             :     {
     220         114 :         SwPosition aPosition( rNd, SwIndex( (SwTxtNode*)&rNd ) );
     221         114 :         pCurRedline = m_rExport.pDoc->GetRedline( aPosition, &nCurRedlinePos );
     222             :     }
     223             : 
     224       12070 :     nAktSwPos = SearchNext(1);
     225       12070 : }
     226             : 
     227       38998 : sal_Int32 lcl_getMinPos( sal_Int32 pos1, sal_Int32 pos2 )
     228             : {
     229       38998 :     if ( pos1 >= 0 && pos2 >= 0 )
     230             :     {
     231             :         // both valid: return minimum one
     232          20 :         return std::min(pos1, pos2);
     233             :     }
     234             : 
     235             :     // return the valid one, if any, or -1
     236       38978 :     return std::max(pos1, pos2);
     237             : }
     238             : 
     239       19499 : sal_Int32 SwWW8AttrIter::SearchNext( sal_Int32 nStartPos )
     240             : {
     241       19499 :     const OUString aTxt = rNd.GetTxt();
     242       19499 :     sal_Int32 fieldEndPos = aTxt.indexOf(CH_TXT_ATR_FIELDEND, nStartPos);
     243       19499 :     sal_Int32 fieldStartPos = aTxt.indexOf(CH_TXT_ATR_FIELDSTART, nStartPos);
     244       19499 :     sal_Int32 formElementPos = aTxt.indexOf(CH_TXT_ATR_FORMELEMENT, nStartPos);
     245             : 
     246             :     const sal_Int32 pos = lcl_getMinPos(
     247             :         lcl_getMinPos( fieldEndPos, fieldStartPos ),
     248       19499 :         formElementPos );
     249             : 
     250       19499 :     sal_Int32 nMinPos = (pos>=0) ? pos : SAL_MAX_INT32;
     251             : 
     252             :     // first the redline, then the attributes
     253       19499 :     if( pCurRedline )
     254             :     {
     255          21 :         const SwPosition* pEnd = pCurRedline->End();
     256          21 :         if (pEnd->nNode == rNd)
     257             :         {
     258          15 :             const sal_Int32 i = pEnd->nContent.GetIndex();
     259          15 :             if ( i >= nStartPos && i < nMinPos )
     260             :             {
     261          10 :                 nMinPos = i;
     262             :             }
     263             :         }
     264             :     }
     265             : 
     266       19499 :     if ( nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().size() )
     267             :     {
     268             :         // nCurRedlinePos point to the next redline
     269         130 :         sal_uInt16 nRedLinePos = nCurRedlinePos;
     270         130 :         if( pCurRedline )
     271          21 :             ++nRedLinePos;
     272             : 
     273         151 :         for ( ; nRedLinePos < m_rExport.pDoc->GetRedlineTbl().size(); ++nRedLinePos )
     274             :         {
     275         113 :             const SwRangeRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nRedLinePos ];
     276             : 
     277         113 :             const SwPosition* pStt = pRedl->Start();
     278         113 :             const SwPosition* pEnd = pStt == pRedl->GetPoint()
     279         110 :                                         ? pRedl->GetMark()
     280         223 :                                         : pRedl->GetPoint();
     281             : 
     282         113 :             if( pStt->nNode == rNd )
     283             :             {
     284          21 :                 const sal_Int32 i = pStt->nContent.GetIndex();
     285          21 :                 if( i >= nStartPos && i < nMinPos )
     286          14 :                     nMinPos = i;
     287             :             }
     288             :             else
     289          92 :                 break;
     290             : 
     291          21 :             if( pEnd->nNode == rNd )
     292             :             {
     293          12 :                 const sal_Int32 i = pEnd->nContent.GetIndex();
     294          12 :                 if( i >= nStartPos && i < nMinPos )
     295             :                 {
     296           4 :                     nMinPos = i;
     297             :                 }
     298             :             }
     299             :         }
     300             :     }
     301             : 
     302       19499 :     if (mrSwFmtDrop.GetWholeWord() && nStartPos <= rNd.GetDropLen(0))
     303           0 :         nMinPos = rNd.GetDropLen(0);
     304       19499 :     else if(nStartPos <= mrSwFmtDrop.GetChars())
     305           0 :         nMinPos = mrSwFmtDrop.GetChars();
     306             : 
     307       19499 :     if(const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
     308             :     {
     309             : 
     310             : // can be optimized if we consider that the TxtAttrs are sorted by start position.
     311             : // but then we'd have to save 2 indices
     312       39558 :         for( sal_uInt16 i = 0; i < pTxtAttrs->Count(); i++ )
     313             :         {
     314       29394 :             const SwTxtAttr* pHt = (*pTxtAttrs)[i];
     315       29394 :             sal_Int32 nPos = *pHt->GetStart();    // first Attr characters
     316       29394 :             if( nPos >= nStartPos && nPos <= nMinPos )
     317        5843 :                 nMinPos = nPos;
     318             : 
     319       29394 :             if( pHt->End() )         // Attr with end
     320             :             {
     321       27394 :                 nPos = *pHt->End();      // last Attr character + 1
     322       27394 :                 if( nPos >= nStartPos && nPos <= nMinPos )
     323       10694 :                     nMinPos = nPos;
     324             :             }
     325       29394 :             if (pHt->HasDummyChar())
     326             :             {
     327             :                 // pos + 1 because of CH_TXTATR in Text
     328        2000 :                 nPos = *pHt->GetStart() + 1;
     329        2000 :                 if( nPos >= nStartPos && nPos <= nMinPos )
     330         622 :                     nMinPos = nPos;
     331             :             }
     332             :         }
     333             :     }
     334             : 
     335       19499 :     if (maCharRunIter != maCharRuns.end())
     336             :     {
     337       13465 :         if (maCharRunIter->mnEndPos < nMinPos)
     338        6370 :             nMinPos = maCharRunIter->mnEndPos;
     339       13465 :         IterToCurrent();
     340             :     }
     341             : 
     342             :     /*
     343             :      #i2916#
     344             :      Check to see if there are any graphics anchored to characters in this
     345             :      paragraph's text. Set nMinPos to 1 past the placement for anchored to
     346             :      character because anchors in Word appear after the character they are
     347             :      anchored to.
     348             :     */
     349       19499 :     if (maFlyIter != maFlyFrms.end())
     350             :     {
     351         255 :         const SwPosition &rAnchor = maFlyIter->GetPosition();
     352             : 
     353         255 :         sal_Int32 nPos = rAnchor.nContent.GetIndex();
     354         255 :         if (nPos >= nStartPos && nPos <= nMinPos)
     355          11 :             nMinPos = nPos;
     356             : 
     357         255 :         if (maFlyIter->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR)
     358             :         {
     359          81 :             ++nPos;
     360          81 :             if (nPos >= nStartPos && nPos <= nMinPos)
     361          12 :                 nMinPos = nPos;
     362             :         }
     363             :     }
     364             : 
     365             :     //nMinPos found and not going to change at this point
     366             : 
     367       19499 :     if (maCharRunIter != maCharRuns.end())
     368             :     {
     369       13465 :         if (maCharRunIter->mnEndPos == nMinPos)
     370       11610 :             ++maCharRunIter;
     371             :     }
     372             : 
     373       19499 :     return nMinPos;
     374             : }
     375             : 
     376           0 : static bool lcl_isFontsizeItem( const SfxPoolItem& rItem )
     377             : {
     378           0 :     return ( rItem.Which( ) == RES_CHRATR_FONTSIZE ||
     379           0 :             rItem.Which( ) == RES_CHRATR_CJK_FONTSIZE ||
     380           0 :             rItem.Which( ) == RES_CHRATR_CTL_FONTSIZE );
     381             : }
     382             : 
     383        7457 : void SwWW8AttrIter::OutAttr( sal_Int32 nSwPos, bool bRuby )
     384             : {
     385        7457 :     m_rExport.AttrOutput().RTLAndCJKState( IsCharRTL(), GetScript() );
     386             : 
     387             :     /*
     388             :      Depending on whether text is in CTL/CJK or Western, get the id of that
     389             :      script, the idea is that the font that is actually in use to render this
     390             :      range of text ends up in pFont
     391             :     */
     392        7457 :     sal_uInt16 nFontId = GetWhichOfScript( RES_CHRATR_FONT, GetScript() );
     393             : 
     394             :     const SvxFontItem &rParentFont = ItemGet<SvxFontItem>(
     395        7457 :         (const SwTxtFmtColl&)rNd.GetAnyFmtColl(), nFontId);
     396        7457 :     const SvxFontItem *pFont = &rParentFont;
     397        7457 :     const SfxPoolItem *pGrabBag = 0;
     398             : 
     399        7457 :     SfxItemSet aExportSet(*rNd.GetSwAttrSet().GetPool(),
     400        7457 :         RES_CHRATR_BEGIN, RES_TXTATR_END - 1);
     401             : 
     402             :     //The hard formatting properties that affect the entire paragraph
     403        7457 :     if (rNd.HasSwAttrSet())
     404             :     {
     405        5802 :         sal_Bool bDeep = sal_False;
     406             :         // only copy hard attributes - bDeep = false
     407        5802 :         aExportSet.Set(rNd.GetSwAttrSet(), bDeep);
     408             :         // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
     409        5802 :         const SvxFontItem &rNdFont = ItemGet<SvxFontItem>(rNd.GetSwAttrSet(), nFontId);
     410        5802 :         pFont = &rNdFont;
     411        5802 :         aExportSet.ClearItem(nFontId);
     412             :     }
     413             : 
     414             :     //The additional hard formatting properties that affect this range in the
     415             :     //paragraph
     416       14914 :     sw::PoolItems aRangeItems;
     417        7457 :     if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
     418             :     {
     419       13295 :         for( sal_Int32 i = 0; i < pTxtAttrs->Count(); ++i )
     420             :         {
     421       12527 :             const SwTxtAttr* pHt = (*pTxtAttrs)[i];
     422       12527 :             const sal_Int32* pEnd = pHt->End();
     423             : 
     424       13524 :             if (pEnd ? ( nSwPos >= *pHt->GetStart() && nSwPos < *pEnd)
     425         997 :                         : nSwPos == *pHt->GetStart() )
     426             :             {
     427        4271 :                 sal_uInt16 nWhich = pHt->GetAttr().Which();
     428        4271 :                 if (nWhich == RES_TXTATR_AUTOFMT)
     429             :                 {
     430        3437 :                     const SwFmtAutoFmt& rAutoFmt = static_cast<const SwFmtAutoFmt&>(pHt->GetAttr());
     431        3437 :                     const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle();
     432        6874 :                     SfxWhichIter aIter( *pSet );
     433             :                     const SfxPoolItem* pItem;
     434        3437 :                     sal_uInt16 nWhichId = aIter.FirstWhich();
     435      168405 :                     while( nWhichId )
     436             :                     {
     437      161531 :                         if( SFX_ITEM_SET == pSet->GetItemState( nWhichId, false, &pItem ))
     438             :                         {
     439       16073 :                             if (nWhichId == nFontId)
     440        1641 :                                 pFont = &(item_cast<SvxFontItem>(*pItem));
     441       14432 :                             else if (nWhichId == RES_CHRATR_GRABBAG)
     442        1270 :                                 pGrabBag = pItem;
     443             :                             else
     444       13162 :                                 aRangeItems[nWhichId] = pItem;
     445             :                         }
     446      161531 :                         nWhichId = aIter.NextWhich();
     447        3437 :                     }
     448             :                 }
     449             :                 else
     450         834 :                     aRangeItems[nWhich] = (&(pHt->GetAttr()));
     451             :             }
     452        8256 :             else if (nSwPos < *pHt->GetStart())
     453        3553 :                 break;
     454             :         }
     455             :     }
     456             : 
     457             :     /*
     458             :      For #i24291# we need to explictly remove any properties from the
     459             :      aExportSet which a SwCharFmt would override, we can't rely on word doing
     460             :      this for us like writer does
     461             :     */
     462             :     const SwFmtCharFmt *pCharFmtItem =
     463        7457 :         HasItem< SwFmtCharFmt >( aRangeItems, RES_TXTATR_CHARFMT );
     464        7457 :     if ( pCharFmtItem )
     465          52 :         ClearOverridesFromSet( *pCharFmtItem, aExportSet );
     466             : 
     467       14914 :     sw::PoolItems aExportItems;
     468        7457 :     GetPoolItems( aExportSet, aExportItems, false );
     469             : 
     470        7457 :     if( rNd.GetpSwpHints() == 0 )
     471        3136 :         m_rExport.SetCurItemSet(&aExportSet);
     472             : 
     473        7457 :     sw::cPoolItemIter aEnd = aRangeItems.end();
     474       21453 :     for ( sw::cPoolItemIter aI = aRangeItems.begin(); aI != aEnd; ++aI )
     475             :     {
     476       13996 :         if ( !bRuby || !lcl_isFontsizeItem( *aI->second ) )
     477       13996 :             aExportItems[aI->first] = aI->second;
     478             :     }
     479             : 
     480        7457 :     if ( !aExportItems.empty() )
     481             :     {
     482        5365 :         const SwModify* pOldMod = m_rExport.pOutFmtNode;
     483        5365 :         m_rExport.pOutFmtNode = &rNd;
     484        5365 :         m_rExport.m_aCurrentCharPropStarts.push( nSwPos );
     485             : 
     486        5365 :         m_rExport.ExportPoolItemsToCHP( aExportItems, GetScript() );
     487             : 
     488             :         // HasTextItem only allowed in the above range
     489        5365 :         m_rExport.m_aCurrentCharPropStarts.pop();
     490        5365 :         m_rExport.pOutFmtNode = pOldMod;
     491             :     }
     492             : 
     493        7457 :     if( rNd.GetpSwpHints() == 0 )
     494        3136 :         m_rExport.SetCurItemSet(0);
     495             : 
     496             :     OSL_ENSURE( pFont, "must be *some* font associated with this txtnode" );
     497        7457 :     if ( pFont )
     498             :     {
     499        7457 :         SvxFontItem aFont( *pFont );
     500             : 
     501             :         /*
     502             :          If we are a nonunicode aware format then we set the charset we want to
     503             :          use for export of this range. If necessary this will generate a pseudo
     504             :          font to use for this range.
     505             : 
     506             :          So now we are guaranteed to have a font with the correct charset set
     507             :          for WW6/95 which will match the script we have exported this range in,
     508             :          this makes older nonunicode aware versions of word display the correct
     509             :          characters.
     510             :         */
     511        7457 :         if ( !m_rExport.SupportsUnicode() )
     512           0 :             aFont.SetCharSet( GetCharSet() );
     513             : 
     514        7457 :         if ( rParentFont != aFont )
     515        2436 :             m_rExport.AttrOutput().OutputItem( aFont );
     516             :     }
     517             : 
     518             :     // Output grab bag attributes
     519        7457 :     if (pGrabBag)
     520        8727 :         m_rExport.AttrOutput().OutputItem( *pGrabBag );
     521        7457 : }
     522             : 
     523        5575 : bool SwWW8AttrIter::IsWatermarkFrame()
     524             : {
     525        5575 :     if (maFlyFrms.size() != 1)
     526        5482 :         return false;
     527             : 
     528         277 :     while ( maFlyIter != maFlyFrms.end() )
     529             :     {
     530          93 :         const SdrObject* pSdrObj = maFlyIter->GetFrmFmt().FindRealSdrObject();
     531             : 
     532          93 :         if (pSdrObj)
     533             :         {
     534          90 :             if (VMLExport::IsWaterMarkShape(pSdrObj->GetName()))
     535           2 :                   return true;
     536             :         }
     537          91 :         ++maFlyIter;
     538             :     }
     539             : 
     540          91 :     return false;
     541             : }
     542             : 
     543       13491 : void SwWW8AttrIter::OutFlys(sal_Int32 nSwPos)
     544             : {
     545             :     /*
     546             :      #i2916#
     547             :      May have an anchored graphic to be placed, loop through sorted array
     548             :      and output all at this position
     549             :     */
     550       27241 :     while ( maFlyIter != maFlyFrms.end() )
     551             :     {
     552         266 :         const SwPosition &rAnchor = maFlyIter->GetPosition();
     553         266 :         const sal_Int32 nPos = rAnchor.nContent.GetIndex();
     554             : 
     555         266 :         if ( nPos != nSwPos )
     556           7 :             break;
     557             : 
     558         259 :         const SdrObject* pSdrObj = maFlyIter->GetFrmFmt().FindRealSdrObject();
     559             : 
     560         259 :         if (pSdrObj)
     561             :         {
     562         255 :             if (VMLExport::IsWaterMarkShape(pSdrObj->GetName()))
     563             :             {
     564             :                  // This is a watermark object. Should be written ONLY in the header
     565           4 :                  if(m_rExport.nTxtTyp == TXT_HDFT)
     566             :                  {
     567             :                        // Should write a watermark in the header
     568           4 :                        m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter );
     569             :                  }
     570             :                  else
     571             :                  {
     572             :                        // Should not write watermark object in the main body text
     573             :                  }
     574             :             }
     575             :             else
     576             :             {
     577             :                  // This is not a watermark object - write normally
     578         251 :                  m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter );
     579             :             }
     580             :         }
     581             :         else
     582             :         {
     583             :             // This is not a watermark object - write normally
     584           4 :             m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter );
     585             :         }
     586         259 :         ++maFlyIter;
     587             :     }
     588       13491 : }
     589             : 
     590        7457 : bool SwWW8AttrIter::IsTxtAttr( sal_Int32 nSwPos )
     591             : {
     592             :     // search for attrs with dummy character or content
     593        7457 :     if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
     594             :     {
     595       20660 :         for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i)
     596             :         {
     597       16731 :             const SwTxtAttr* pHt = (*pTxtAttrs)[i];
     598       49106 :             if ( ( pHt->HasDummyChar() || pHt->HasContent() )
     599       17818 :                  && (*pHt->GetStart() == nSwPos) )
     600             :             {
     601         392 :                 return true;
     602             :             }
     603             :         }
     604             :     }
     605             : 
     606        7065 :     return false;
     607             : }
     608             : 
     609        7457 : bool SwWW8AttrIter::IsDropCap( int nSwPos )
     610             : {
     611             :     // see if the current position falls on a DropCap
     612        7457 :     int nDropChars = mrSwFmtDrop.GetChars();
     613        7457 :     bool bWholeWord = mrSwFmtDrop.GetWholeWord();
     614        7457 :     if (bWholeWord)
     615             :     {
     616           0 :         short nWordLen = rNd.GetDropLen(0);
     617           0 :         if(nSwPos == nWordLen && nSwPos != 0)
     618           0 :             return true;
     619             :     }
     620             :     else
     621             :     {
     622        7457 :         if (nSwPos == nDropChars && nSwPos != 0)
     623           0 :             return true;
     624             :     }
     625        7457 :     return false;
     626             : }
     627             : 
     628        6034 : bool SwWW8AttrIter::RequiresImplicitBookmark()
     629             : {
     630        6034 :     SwImplBookmarksIter bkmkIterEnd = m_rExport.maImplicitBookmarks.end();
     631        6034 :     for ( SwImplBookmarksIter aIter = m_rExport.maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter )
     632             :     {
     633           0 :         sal_uLong sample  = aIter->second;
     634             : 
     635           0 :         if ( sample == rNd.GetIndex() )
     636           0 :             return true;
     637             :     }
     638        6034 :     return false;
     639             : }
     640             : 
     641             : //HasItem is for the summary of the double attributes: Underline and WordlineMode as TextItems.
     642             : // OutAttr () calls the output function, which can call HasItem() for other items at the attribute's start position.
     643             : // Only attributes with end can be queried.
     644             : // It searches with bDeep
     645        4894 : const SfxPoolItem* SwWW8AttrIter::HasTextItem( sal_uInt16 nWhich ) const
     646             : {
     647        4894 :     const SfxPoolItem* pRet = 0;
     648        4894 :     const SwpHints* pTxtAttrs = rNd.GetpSwpHints();
     649        4894 :     if (pTxtAttrs && !m_rExport.m_aCurrentCharPropStarts.empty())
     650             :     {
     651        3996 :         const sal_Int32 nTmpSwPos = m_rExport.m_aCurrentCharPropStarts.top();
     652       12424 :         for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i)
     653             :         {
     654       11889 :             const SwTxtAttr* pHt = (*pTxtAttrs)[i];
     655       11889 :             const SfxPoolItem* pItem = &pHt->GetAttr();
     656       11889 :             const sal_Int32 * pAtrEnd = 0;
     657       23384 :             if( 0 != ( pAtrEnd = pHt->End() ) &&        // only Attr with an end
     658       20112 :                 nTmpSwPos >= *pHt->GetStart() && nTmpSwPos < *pAtrEnd )
     659             :             {
     660        3882 :                 if ( nWhich == pItem->Which() )
     661             :                 {
     662           0 :                     pRet = pItem;       // found it
     663           0 :                     break;
     664             :                 }
     665       11261 :                 else if( RES_TXTATR_INETFMT == pHt->Which() ||
     666        7342 :                          RES_TXTATR_CHARFMT == pHt->Which() ||
     667        3460 :                          RES_TXTATR_AUTOFMT == pHt->Which() )
     668             :                 {
     669        3882 :                     const SfxItemSet* pSet = CharFmt::GetItemSet( pHt->GetAttr() );
     670             :                     const SfxPoolItem* pCharItem;
     671        7764 :                     if ( pSet &&
     672        3882 :                          SFX_ITEM_SET == pSet->GetItemState( nWhich, pHt->Which() != RES_TXTATR_AUTOFMT, &pCharItem ) )
     673             :                     {
     674          61 :                         pRet = pCharItem;       // found it
     675          61 :                         break;
     676             :                     }
     677             :                 }
     678             :             }
     679        8007 :             else if (nTmpSwPos < *pHt->GetStart())
     680        3400 :                 break;              // nothing more to come
     681             :         }
     682             :     }
     683        4894 :     return pRet;
     684             : }
     685             : 
     686           6 : void WW8Export::GetCurrentItems(ww::bytes &rItems) const
     687             : {
     688           6 :     rItems.insert(rItems.end(), pO->begin(), pO->end());
     689           6 : }
     690             : 
     691        4865 : const SfxPoolItem& SwWW8AttrIter::GetItem(sal_uInt16 nWhich) const
     692             : {
     693        4865 :     const SfxPoolItem* pRet = HasTextItem(nWhich);
     694        4865 :     return pRet ? *pRet : rNd.SwCntntNode::GetAttr(nWhich);
     695             : }
     696             : 
     697           0 : void WW8AttributeOutput::StartRuby( const SwTxtNode& rNode, sal_Int32 /*nPos*/, const SwFmtRuby& rRuby )
     698             : {
     699           0 :     OUString aStr( FieldString( ww::eEQ ) );
     700           0 :     aStr += "\\* jc";
     701           0 :     sal_Int32 nJC = 0;
     702           0 :     sal_Char cDirective = 0;
     703           0 :     switch ( rRuby.GetAdjustment() )
     704             :     {
     705             :         case 0:
     706           0 :             nJC = 3;
     707           0 :             cDirective = 'l';
     708           0 :             break;
     709             :         case 1:
     710             :             //defaults to 0
     711           0 :             break;
     712             :         case 2:
     713           0 :             nJC = 4;
     714           0 :             cDirective = 'r';
     715           0 :             break;
     716             :         case 3:
     717           0 :             nJC = 1;
     718           0 :             cDirective = 'd';
     719           0 :             break;
     720             :         case 4:
     721           0 :             nJC = 2;
     722           0 :             cDirective = 'd';
     723           0 :             break;
     724             :         default:
     725             :             OSL_ENSURE( !this,"Unhandled Ruby justication code" );
     726           0 :             break;
     727             :     }
     728           0 :     aStr += OUString::number( nJC );
     729             : 
     730             :     /*
     731             :      MS needs to know the name and size of the font used in the ruby item,
     732             :      but we coud have written it in a mixture of asian and western
     733             :      scripts, and each of these can be a different font and size than the
     734             :      other, so we make a guess based upon the first character of the text,
     735             :      defaulting to asian.
     736             :      */
     737             :     sal_uInt16 nRubyScript;
     738           0 :     if( g_pBreakIt->GetBreakIter().is() )
     739           0 :         nRubyScript = g_pBreakIt->GetBreakIter()->getScriptType( rRuby.GetText(), 0);
     740             :     else
     741           0 :         nRubyScript = i18n::ScriptType::ASIAN;
     742             : 
     743           0 :     const SwTxtRuby* pRubyTxt = rRuby.GetTxtRuby();
     744           0 :     const SwCharFmt* pFmt = pRubyTxt ? pRubyTxt->GetCharFmt() : 0;
     745           0 :     OUString sFamilyName;
     746             :     long nHeight;
     747           0 :     if ( pFmt )
     748             :     {
     749             :         const SvxFontItem &rFont = ItemGet< SvxFontItem >( *pFmt,
     750           0 :                 GetWhichOfScript(RES_CHRATR_FONT,nRubyScript) );
     751           0 :         sFamilyName = rFont.GetFamilyName();
     752             : 
     753             :         const SvxFontHeightItem &rHeight = ItemGet< SvxFontHeightItem >( *pFmt,
     754           0 :                 GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
     755           0 :         nHeight = rHeight.GetHeight();
     756             :     }
     757             :     else
     758             :     {
     759             :         /*Get defaults if no formatting on ruby text*/
     760             : 
     761           0 :         const SfxItemPool *pPool = rNode.GetSwAttrSet().GetPool();
     762           0 :         pPool = pPool ? pPool : &m_rWW8Export.pDoc->GetAttrPool();
     763             : 
     764             :         const SvxFontItem &rFont  = DefaultItemGet< SvxFontItem >( *pPool,
     765           0 :                 GetWhichOfScript( RES_CHRATR_FONT,nRubyScript ) );
     766           0 :         sFamilyName = rFont.GetFamilyName();
     767             : 
     768             :         const SvxFontHeightItem &rHeight = DefaultItemGet< SvxFontHeightItem >
     769           0 :             ( *pPool, GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
     770           0 :         nHeight = rHeight.GetHeight();
     771             :     }
     772           0 :     nHeight = (nHeight + 5)/10;
     773             : 
     774           0 :     aStr += " \\* \"Font:";
     775           0 :     aStr += sFamilyName;
     776           0 :     aStr += "\" \\* hps";
     777           0 :     aStr += OUString::number( nHeight );
     778           0 :     aStr += " \\o";
     779           0 :     if ( cDirective )
     780             :     {
     781           0 :         aStr += "\\a" + OUString(cDirective);
     782             :     }
     783           0 :     aStr += "(\\s\\up ";
     784             : 
     785           0 :     if ( g_pBreakIt->GetBreakIter().is() )
     786           0 :         nRubyScript = g_pBreakIt->GetBreakIter()->getScriptType( rNode.GetTxt(),
     787           0 :                 *( pRubyTxt->GetStart() ) );
     788             :     else
     789           0 :         nRubyScript = i18n::ScriptType::ASIAN;
     790             : 
     791           0 :     const SwAttrSet& rSet = rNode.GetSwAttrSet();
     792             :     const SvxFontHeightItem &rHeightItem  =
     793             :         ( const SvxFontHeightItem& )rSet.Get(
     794           0 :                                              GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
     795           0 :     nHeight = (rHeightItem.GetHeight() + 10)/20-1;
     796           0 :     aStr += OUString::number(nHeight);
     797           0 :     aStr += "(";
     798           0 :     aStr += rRuby.GetText();
     799           0 :     aStr += ")";
     800             : 
     801             :     // The parameter separator depends on the FIB.lid
     802           0 :     if ( m_rWW8Export.pFib->getNumDecimalSep() == '.' )
     803           0 :         aStr += ",";
     804             :     else
     805           0 :         aStr += ";";
     806             : 
     807             :     m_rWW8Export.OutputField( 0, ww::eEQ, aStr,
     808           0 :             WRITEFIELD_START | WRITEFIELD_CMD_START );
     809           0 : }
     810             : 
     811           0 : void WW8AttributeOutput::EndRuby()
     812             : {
     813           0 :     m_rWW8Export.WriteChar( ')' );
     814           0 :     m_rWW8Export.OutputField( 0, ww::eEQ, OUString(), WRITEFIELD_END | WRITEFIELD_CLOSE );
     815           0 : }
     816             : 
     817             : /*#i15387# Better ideas welcome*/
     818          12 : OUString &TruncateBookmark( OUString &rRet )
     819             : {
     820          12 :     if ( rRet.getLength() > 40 )
     821           0 :         rRet = rRet.copy( 0, 40 );
     822             :     OSL_ENSURE( rRet.getLength() <= 40, "Word cannot have bookmarks longer than 40 chars" );
     823          12 :     return rRet;
     824             : }
     825             : 
     826         303 : bool AttributeOutputBase::AnalyzeURL( const OUString& rUrl, const OUString& /*rTarget*/, OUString* pLinkURL, OUString* pMark )
     827             : {
     828         303 :     bool bBookMarkOnly = false;
     829             : 
     830         303 :     OUString sMark;
     831         606 :     OUString sURL;
     832             : 
     833         303 :     if ( rUrl.getLength() > 1 && rUrl[0] == '#' )
     834             :     {
     835          88 :         sMark = BookmarkToWriter( rUrl.copy(1) );
     836             : 
     837          88 :         const sal_Int32 nPos = sMark.lastIndexOf( cMarkSeparator );
     838             : 
     839           2 :         const OUString sRefType(nPos>=0 && nPos+1<sMark.getLength() ?
     840             :                                 sMark.copy(nPos+1).replaceAll(" ", "") :
     841          90 :                                 OUString());
     842             : 
     843             :         // #i21465# Only interested in outline references
     844          88 :         if ( sRefType == "outline" )
     845             :         {
     846           0 :             OUString sLink = sMark.copy(0, nPos);
     847           0 :             SwImplBookmarksIter bkmkIterEnd = GetExport().maImplicitBookmarks.end();
     848           0 :             for ( SwImplBookmarksIter aIter = GetExport().maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter )
     849             :             {
     850           0 :                 if ( aIter->first == sLink )
     851             :                 {
     852           0 :                     sMark = "_toc" + OUString::number( aIter->second );
     853             :                 }
     854           0 :             }
     855          88 :         }
     856             :     }
     857             :     else
     858             :     {
     859         215 :         INetURLObject aURL( rUrl, INET_PROT_NOT_VALID );
     860         215 :         sURL = aURL.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS );
     861         215 :         sMark = aURL.GetMark( INetURLObject::DECODE_UNAMBIGUOUS );
     862             :     }
     863             : 
     864         303 :     if ( !sMark.isEmpty() && sURL.isEmpty() )
     865          88 :         bBookMarkOnly = true;
     866             : 
     867         303 :     *pMark = sMark;
     868         303 :     *pLinkURL = sURL;
     869         606 :     return bBookMarkOnly;
     870             : }
     871             : 
     872           1 : bool WW8AttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark )
     873             : {
     874           1 :     bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
     875             : 
     876           1 :     OUString sURL = *pLinkURL;
     877             : 
     878           1 :     if ( !sURL.isEmpty() )
     879           1 :         sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
     880             : 
     881           1 :     if ( bBookMarkOnly )
     882           0 :         sURL = FieldString( ww::eHYPERLINK );
     883             :     else
     884           1 :         sURL = FieldString( ww::eHYPERLINK ) + "\"" + sURL + "\"";
     885             : 
     886           1 :     if ( !pMark->isEmpty() )
     887           0 :         sURL += " \\l \"" + *pMark + "\"";
     888             : 
     889           1 :     if ( !rTarget.isEmpty() )
     890           0 :         sURL += " \\n " + rTarget;
     891             : 
     892           1 :     *pLinkURL = sURL;
     893             : 
     894           1 :     return bBookMarkOnly;
     895             : }
     896             : 
     897           1 : bool WW8AttributeOutput::StartURL( const OUString &rUrl, const OUString &rTarget )
     898             : {
     899             :     // hyperlinks only in WW8
     900           1 :     if ( !m_rWW8Export.bWrtWW8 )
     901           0 :         return false;
     902             : 
     903           1 :     INetURLObject aURL( rUrl );
     904           2 :     OUString sURL;
     905           2 :     OUString sMark;
     906             : 
     907           1 :     bool bBookMarkOnly = AnalyzeURL( rUrl, rTarget, &sURL, &sMark );
     908             : 
     909           1 :     m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_START | WRITEFIELD_CMD_START );
     910             : 
     911             :     // write the refence to the "picture" structure
     912           1 :     sal_uLong nDataStt = m_rWW8Export.pDataStrm->Tell();
     913           1 :     m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() );
     914             : 
     915             :     // WinWord 2000 doesn't write this - so it's a temp solution by W97 ?
     916           1 :     m_rWW8Export.WriteChar( 0x01 );
     917             : 
     918             :     static sal_uInt8 aArr1[] = {
     919             :         0x03, 0x6a, 0,0,0,0,    // sprmCPicLocation
     920             : 
     921             :         0x06, 0x08, 0x01,       // sprmCFData
     922             :         0x55, 0x08, 0x01,       // sprmCFSpec
     923             :         0x02, 0x08, 0x01        // sprmCFFldVanish
     924             :     };
     925           1 :     sal_uInt8* pDataAdr = aArr1 + 2;
     926           1 :     Set_UInt32( pDataAdr, nDataStt );
     927             : 
     928           1 :     m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), sizeof( aArr1 ), aArr1 );
     929             : 
     930           1 :     m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_CMD_END );
     931             : 
     932             :     // now write the picture structur
     933           1 :     sURL = aURL.GetURLNoMark();
     934             : 
     935             :     // Compare the URL written by AnalyzeURL with the original one to see if
     936             :     // the output URL is absolute or relative.
     937           2 :     OUString sRelativeURL;
     938           1 :     if ( !rUrl.isEmpty() )
     939           1 :         sRelativeURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), rUrl );
     940           1 :     bool bAbsolute = sRelativeURL == rUrl;
     941             : 
     942             :     static sal_uInt8 aURLData1[] = {
     943             :         0,0,0,0,        // len of struct
     944             :         0x44,0,         // the start of "next" data
     945             :         0,0,0,0,0,0,0,0,0,0,                // PIC-Structure!
     946             :         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    //  |
     947             :         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    //  |
     948             :         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    //  |
     949             :         0,0,0,0,                            // /
     950             :     };
     951             :     static sal_uInt8 MAGIC_A[] = {
     952             :         // start of "next" data
     953             :         0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
     954             :         0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
     955             :     };
     956             : 
     957           1 :     m_rWW8Export.pDataStrm->Write( aURLData1, sizeof( aURLData1 ) );
     958             :     /* Write HFD Structure */
     959           1 :     sal_uInt8 nAnchor = 0x00;
     960           1 :     if ( !sMark.isEmpty() )
     961           0 :         nAnchor = 0x08;
     962           1 :     m_rWW8Export.pDataStrm->Write( &nAnchor, 1 ); // HFDBits
     963           1 :     m_rWW8Export.pDataStrm->Write( MAGIC_A, sizeof(MAGIC_A) ); //clsid
     964             : 
     965             :     /* Write Hyperlink Object see [MS-OSHARED] spec*/
     966           1 :     SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 0x00000002);
     967           1 :     sal_uInt32 nFlag = bBookMarkOnly ? 0 : 0x01;
     968           1 :     if ( bAbsolute )
     969           1 :         nFlag |= 0x02;
     970           1 :     if ( !sMark.isEmpty() )
     971           0 :         nFlag |= 0x08;
     972           1 :     SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nFlag );
     973             : 
     974           1 :     INetProtocol eProto = aURL.GetProtocol();
     975           1 :     if ( eProto == INET_PROT_FILE || eProto == INET_PROT_SMB )
     976             :     {
     977             :         // version 1 (for a document)
     978             : 
     979             :         static sal_uInt8 MAGIC_C[] = {
     980             :             0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     981             :             0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
     982             :             0x00, 0x00
     983             :         };
     984             : 
     985             :         static sal_uInt8 MAGIC_D[] = {
     986             :             0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
     987             :             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     988             :             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     989             :         };
     990             : 
     991             :         // save the links to files as relative
     992           0 :         sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
     993           0 :         if ( eProto == INET_PROT_FILE && sURL.startsWith( "/" ) )
     994           0 :             sURL = aURL.PathToFileName();
     995             : 
     996             :         // special case for the absolute windows names
     997             :         // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
     998           0 :         if (sURL.getLength()>=3)
     999             :         {
    1000           0 :             const sal_Unicode aDrive = sURL[1];
    1001           0 :             if ( sURL[0]=='/' && sURL[2]==':' &&
    1002           0 :                  ( (aDrive>='A' && aDrive<='Z' ) || (aDrive>='a' && aDrive<='z') ) )
    1003             :             {
    1004           0 :                 sURL = sURL.copy(1).replaceAll("/", "\\");
    1005             :             }
    1006             :         }
    1007             : 
    1008             :         // n#261623 convert smb notation to '\\'
    1009           0 :         const char pSmb[] = "smb://";
    1010           0 :         if ( eProto == INET_PROT_SMB && sURL.startsWith( pSmb ) )
    1011             :         {
    1012           0 :             sURL = sURL.copy( sizeof(pSmb)-3 ).replaceAll( "/", "\\" );
    1013             :         }
    1014             : 
    1015           0 :         m_rWW8Export.pDataStrm->Write( MAGIC_C, sizeof(MAGIC_C) );
    1016           0 :         SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sURL.getLength()+1 );
    1017             :         SwWW8Writer::WriteString8( *m_rWW8Export.pDataStrm, sURL, true,
    1018           0 :                                     RTL_TEXTENCODING_MS_1252 );
    1019           0 :         m_rWW8Export.pDataStrm->Write( MAGIC_D, sizeof( MAGIC_D ) );
    1020             : 
    1021           0 :         SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.getLength() + 6 );
    1022           0 :         SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.getLength() );
    1023           0 :         SwWW8Writer::WriteShort( *m_rWW8Export.pDataStrm, 3 );
    1024           0 :         SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, false );
    1025             :     }
    1026           1 :     else if ( eProto != INET_PROT_NOT_VALID )
    1027             :     {
    1028             :         // version 2 (simple url)
    1029             :         // an write some data to the data stream, but dont ask
    1030             :         // what the data mean, except for the URL.
    1031             :         // The First piece is the WW8_PIC structure.
    1032             :         static sal_uInt8 MAGIC_B[] = {
    1033             :             0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
    1034             :             0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
    1035             :         };
    1036             : 
    1037           1 :         m_rWW8Export.pDataStrm->Write( MAGIC_B, sizeof(MAGIC_B) );
    1038           1 :         SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2 * ( sURL.getLength() + 1 ) );
    1039           1 :         SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, true );
    1040             :     }
    1041             : 
    1042           1 :     if ( !sMark.isEmpty() )
    1043             :     {
    1044           0 :         SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sMark.getLength()+1 );
    1045           0 :         SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sMark, true );
    1046             :     }
    1047             :     SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nDataStt,
    1048           1 :         m_rWW8Export.pDataStrm->Tell() - nDataStt );
    1049             : 
    1050           2 :     return true;
    1051             : }
    1052             : 
    1053           1 : bool WW8AttributeOutput::EndURL()
    1054             : {
    1055             :     // hyperlinks only in WW8
    1056           1 :     if ( !m_rWW8Export.bWrtWW8 )
    1057           0 :         return false;
    1058             : 
    1059           1 :     m_rWW8Export.OutputField( 0, ww::eHYPERLINK, OUString(), WRITEFIELD_CLOSE );
    1060             : 
    1061           1 :     return true;
    1062             : }
    1063             : 
    1064          12 : OUString BookmarkToWord(const OUString &rBookmark)
    1065             : {
    1066             :     OUString sRet(INetURLObject::encode(rBookmark,
    1067             :         INetURLObject::PART_REL_SEGMENT_EXTRA, '%',
    1068          12 :         INetURLObject::ENCODE_ALL, RTL_TEXTENCODING_ASCII_US));
    1069          12 :     return TruncateBookmark(sRet);
    1070             : }
    1071             : 
    1072         194 : OUString BookmarkToWriter(const OUString &rBookmark)
    1073             : {
    1074             :     return INetURLObject::decode(rBookmark, '%',
    1075         194 :         INetURLObject::DECODE_UNAMBIGUOUS, RTL_TEXTENCODING_ASCII_US);
    1076             : }
    1077             : 
    1078           0 : void SwWW8AttrIter::OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool)
    1079             : {
    1080           0 :     if ( m_rExport.HasRefToObject( REF_SETREFATTR, &rAttr.GetRefName(), 0 ) )
    1081             :         m_rExport.AppendBookmark( m_rExport.GetBookmarkName( REF_SETREFATTR,
    1082           0 :                                             &rAttr.GetRefName(), 0 ));
    1083           0 : }
    1084             : 
    1085           0 : void WW8AttributeOutput::FieldVanish( const OUString& rTxt, ww::eField /*eType*/ )
    1086             : {
    1087           0 :     ww::bytes aItems;
    1088           0 :     m_rWW8Export.GetCurrentItems( aItems );
    1089             : 
    1090             :     // sprmCFFldVanish
    1091           0 :     if ( m_rWW8Export.bWrtWW8 )
    1092           0 :         SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish );
    1093             :     else
    1094           0 :         aItems.push_back( 67 );
    1095           0 :     aItems.push_back( 1 );
    1096             : 
    1097           0 :     sal_uInt16 nStt_sprmCFSpec = aItems.size();
    1098             : 
    1099             :     // sprmCFSpec --  fSpec-Attribut true
    1100           0 :     if ( m_rWW8Export.bWrtWW8 )
    1101           0 :         SwWW8Writer::InsUInt16( aItems, 0x855 );
    1102             :     else
    1103           0 :         aItems.push_back( 117 );
    1104           0 :     aItems.push_back( 1 );
    1105             : 
    1106           0 :     m_rWW8Export.WriteChar( '\x13' );
    1107           0 :     m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.size(),
    1108           0 :                                     aItems.data() );
    1109           0 :     m_rWW8Export.OutSwString( rTxt, 0, rTxt.getLength(), m_rWW8Export.IsUnicode(),
    1110           0 :                         RTL_TEXTENCODING_MS_1252 );
    1111           0 :     m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), nStt_sprmCFSpec,
    1112           0 :                                     aItems.data() );
    1113           0 :     m_rWW8Export.WriteChar( '\x15' );
    1114           0 :     m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.size(),
    1115           0 :                                     aItems.data() );
    1116           0 : }
    1117             : 
    1118          42 : void AttributeOutputBase::TOXMark( const SwTxtNode& rNode, const SwTOXMark& rAttr )
    1119             : {
    1120             :     // it's a field; so get the Text form the Node and build the field
    1121          42 :     OUString sTxt;
    1122          42 :     ww::eField eType = ww::eNONE;
    1123             : 
    1124          42 :     const SwTxtTOXMark& rTxtTOXMark = *rAttr.GetTxtTOXMark();
    1125          42 :     const sal_Int32* pTxtEnd = rTxtTOXMark.End();
    1126          42 :     if ( pTxtEnd ) // has range?
    1127             :     {
    1128           0 :         sTxt = rNode.GetExpandTxt( *rTxtTOXMark.GetStart(),
    1129           0 :                                    *pTxtEnd - *rTxtTOXMark.GetStart() );
    1130             :     }
    1131             :     else
    1132          42 :         sTxt = rAttr.GetAlternativeText();
    1133             : 
    1134          42 :     switch ( rAttr.GetTOXType()->GetType() )
    1135             :     {
    1136             :         case TOX_INDEX:
    1137          42 :             eType = ww::eXE;
    1138          42 :             if ( !rAttr.GetPrimaryKey().isEmpty() )
    1139             :             {
    1140          42 :                 if ( !rAttr.GetSecondaryKey().isEmpty() )
    1141             :                 {
    1142           0 :                     sTxt = rAttr.GetSecondaryKey() + ":" + sTxt;
    1143             :                 }
    1144             : 
    1145          42 :                 sTxt = rAttr.GetPrimaryKey() + ":" + sTxt;
    1146             :             }
    1147          42 :             sTxt = " XE \"" + sTxt + "\" ";
    1148          42 :             break;
    1149             : 
    1150             :         case TOX_USER:
    1151           0 :             sTxt += "\" \\f \"" + OUString((sal_Char)( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) ));
    1152             :             // fall through - no break;
    1153             :         case TOX_CONTENT:
    1154             :             {
    1155           0 :                 eType = ww::eTC;
    1156           0 :                 sTxt = " TC \"" + sTxt;
    1157           0 :                 sal_uInt16 nLvl = rAttr.GetLevel();
    1158           0 :                 if (nLvl > WW8ListManager::nMaxLevel)
    1159           0 :                     nLvl = WW8ListManager::nMaxLevel;
    1160             : 
    1161           0 :                 sTxt += "\" \\l " + OUString::number(nLvl) + " ";
    1162             :             }
    1163           0 :             break;
    1164             :         default:
    1165             :             OSL_ENSURE( !this, "Unhandled option for toc export" );
    1166           0 :             break;
    1167             :     }
    1168             : 
    1169          42 :     if (!sTxt.isEmpty())
    1170          42 :         FieldVanish( sTxt, eType );
    1171          42 : }
    1172             : 
    1173       11262 : int SwWW8AttrIter::OutAttrWithRange(sal_Int32 nPos)
    1174             : {
    1175       11262 :     int nRet = 0;
    1176       11262 :     if ( const SwpHints* pTxtAttrs = rNd.GetpSwpHints() )
    1177             :     {
    1178        7245 :         m_rExport.m_aCurrentCharPropStarts.push( nPos );
    1179             :         const sal_Int32* pEnd;
    1180       30500 :         for ( sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i )
    1181             :         {
    1182       23255 :             const SwTxtAttr* pHt = (*pTxtAttrs)[i];
    1183       23255 :             const SfxPoolItem* pItem = &pHt->GetAttr();
    1184       23255 :             switch ( pItem->Which() )
    1185             :             {
    1186             :                 case RES_TXTATR_INETFMT:
    1187        3688 :                     if ( nPos == *pHt->GetStart() )
    1188             :                     {
    1189         304 :                         const SwFmtINetFmt *rINet = static_cast< const SwFmtINetFmt* >( pItem );
    1190         304 :                         if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) )
    1191         304 :                             ++nRet;
    1192             :                     }
    1193        3688 :                     if ( 0 != ( pEnd = pHt->End() ) && nPos == *pEnd )
    1194             :                     {
    1195         304 :                         if ( m_rExport.AttrOutput().EndURL() )
    1196         304 :                             --nRet;
    1197             :                     }
    1198        3688 :                     break;
    1199             :                 case RES_TXTATR_REFMARK:
    1200           0 :                     if ( nPos == *pHt->GetStart() )
    1201             :                     {
    1202           0 :                         OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), true );
    1203           0 :                         ++nRet;
    1204             :                     }
    1205           0 :                     if ( 0 != ( pEnd = pHt->End() ) && nPos == *pEnd )
    1206             :                     {
    1207           0 :                         OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), false );
    1208           0 :                         --nRet;
    1209             :                     }
    1210           0 :                     break;
    1211             :                 case RES_TXTATR_TOXMARK:
    1212         336 :                     if ( nPos == *pHt->GetStart() )
    1213          42 :                         m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) );
    1214         336 :                     break;
    1215             :                 case RES_TXTATR_CJK_RUBY:
    1216           0 :                     if ( nPos == *pHt->GetStart() )
    1217             :                     {
    1218           0 :                         m_rExport.AttrOutput().StartRuby( rNd, nPos, *static_cast< const SwFmtRuby* >( pItem ) );
    1219           0 :                         ++nRet;
    1220             :                     }
    1221           0 :                     if ( 0 != ( pEnd = pHt->End() ) && nPos == *pEnd )
    1222             :                     {
    1223           0 :                         m_rExport.AttrOutput().EndRuby();
    1224           0 :                         --nRet;
    1225             :                     }
    1226           0 :                     break;
    1227             :             }
    1228             :         }
    1229        7245 :         m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem only allowed in the above range
    1230             :     }
    1231       11262 :     return nRet;
    1232             : }
    1233             : 
    1234        5655 : bool SwWW8AttrIter::IsRedlineAtEnd( sal_Int32 nEnd ) const
    1235             : {
    1236             :     // search next Redline
    1237       11310 :     for( sal_uInt16 nPos = nCurRedlinePos;
    1238        5655 :         nPos < m_rExport.pDoc->GetRedlineTbl().size(); ++nPos )
    1239             :     {
    1240          38 :         const SwPosition* pEnd = m_rExport.pDoc->GetRedlineTbl()[ nPos ]->End();
    1241          38 :         if( pEnd->nNode != rNd )
    1242             :         {
    1243          35 :             break;
    1244             :         }
    1245             : 
    1246           3 :         if( pEnd->nContent.GetIndex() == nEnd )
    1247             :         {
    1248           3 :             return true;
    1249             :         }
    1250             :     }
    1251        5652 :     return false;
    1252             : }
    1253             : 
    1254        6034 : const SwRedlineData* SwWW8AttrIter::GetParagraphLevelRedline( )
    1255             : {
    1256        6034 :     pCurRedline = NULL;
    1257             : 
    1258             :     // ToDo : this is not the most ideal ... should start maybe from 'nCurRedlinePos'
    1259        6093 :     for( sal_uInt16 nRedlinePos = 0; nRedlinePos < m_rExport.pDoc->GetRedlineTbl().size(); ++nRedlinePos )
    1260             :     {
    1261          60 :         const SwRangeRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nRedlinePos ];
    1262             : 
    1263          60 :         const SwPosition* pCheckedStt = pRedl->Start();
    1264             : 
    1265          60 :         if( pCheckedStt->nNode == rNd )
    1266             :         {
    1267             :             // Maybe add here a check that also the start & end of the redline is the entire paragraph
    1268             : 
    1269             :             // Only return if this is a paragraph formatting redline
    1270          13 :             if (pRedl->GetType() == nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT)
    1271             :             {
    1272             :                 // write data of this redline
    1273           1 :                 pCurRedline = pRedl;
    1274           1 :                 return &( pCurRedline->GetRedlineData() );
    1275             :             }
    1276             :         }
    1277             :     }
    1278        6033 :     return NULL;
    1279             : }
    1280             : 
    1281        7460 : const SwRedlineData* SwWW8AttrIter::GetRunLevelRedline( sal_Int32 nPos )
    1282             : {
    1283        7460 :     if( pCurRedline )
    1284             :     {
    1285          14 :         const SwPosition* pEnd = pCurRedline->End();
    1286          26 :         if( pEnd->nNode == rNd &&
    1287          12 :             pEnd->nContent.GetIndex() <= nPos )
    1288             :         {
    1289           7 :             pCurRedline = 0;
    1290           7 :             ++nCurRedlinePos;
    1291             :         }
    1292             :         else
    1293             :         {
    1294           7 :             switch( pCurRedline->GetType() )
    1295             :             {
    1296             :                 case nsRedlineType_t::REDLINE_INSERT:
    1297             :                 case nsRedlineType_t::REDLINE_DELETE:
    1298             :                 case nsRedlineType_t::REDLINE_FORMAT:
    1299             :                     // write data of this redline
    1300           6 :                     return &( pCurRedline->GetRedlineData() );
    1301             :                     break;
    1302             :                 default:
    1303           1 :                     break;
    1304             :             };
    1305           1 :             pCurRedline = 0;
    1306           1 :             ++nCurRedlinePos;
    1307             :         }
    1308             :     }
    1309             : 
    1310        7454 :     if( !pCurRedline )
    1311             :     {
    1312             :         // search next Redline
    1313        7454 :         for( ; nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().size();
    1314             :                 ++nCurRedlinePos )
    1315             :         {
    1316          41 :             const SwRangeRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nCurRedlinePos ];
    1317             : 
    1318          41 :             const SwPosition* pStt = pRedl->Start();
    1319          41 :             const SwPosition* pEnd = pStt == pRedl->GetPoint()
    1320          40 :                                         ? pRedl->GetMark()
    1321          81 :                                         : pRedl->GetPoint();
    1322             : 
    1323          41 :             if( pStt->nNode == rNd )
    1324             :             {
    1325          11 :                 if( pStt->nContent.GetIndex() >= nPos )
    1326             :                 {
    1327          11 :                     if( pStt->nContent.GetIndex() == nPos )
    1328             :                     {
    1329           4 :                             switch( pRedl->GetType() )
    1330             :                             {
    1331             :                                 case nsRedlineType_t::REDLINE_INSERT:
    1332             :                                 case nsRedlineType_t::REDLINE_DELETE:
    1333             :                                 case nsRedlineType_t::REDLINE_FORMAT:
    1334             :                                     // write data of this redline
    1335           4 :                                     pCurRedline = pRedl;
    1336           4 :                                     return &( pCurRedline->GetRedlineData() );
    1337             :                                     break;
    1338             :                                 default:
    1339           0 :                                     break;
    1340             :                             };
    1341             :                     }
    1342           7 :                     break;
    1343             :                 }
    1344             :             }
    1345             :             else
    1346             :             {
    1347          30 :                 break;
    1348             :             }
    1349             : 
    1350           0 :             if( pEnd->nNode == rNd &&
    1351           0 :                 pEnd->nContent.GetIndex() < nPos )
    1352             :             {
    1353           0 :                 pCurRedline = pRedl;
    1354           0 :                 break;
    1355             :             }
    1356             :         }
    1357             :     }
    1358        7450 :     return NULL;
    1359             : }
    1360             : 
    1361        2850 : short MSWordExportBase::GetCurrentPageDirection() const
    1362             : {
    1363             :     const SwFrmFmt &rFmt = pAktPageDesc
    1364        2850 :                     ? pAktPageDesc->GetMaster()
    1365        5700 :                     : pDoc->GetPageDesc( 0 ).GetMaster();
    1366        2850 :     return rFmt.GetFrmDir().GetValue();
    1367             : }
    1368             : 
    1369          96 : short MSWordExportBase::GetDefaultFrameDirection( ) const
    1370             : {
    1371          96 :     short nDir = FRMDIR_ENVIRONMENT;
    1372             : 
    1373          96 :     if ( bOutPageDescs )
    1374           0 :         nDir = GetCurrentPageDirection(  );
    1375          96 :     else if ( pOutFmtNode )
    1376             :     {
    1377          29 :         if ( bOutFlyFrmAttrs ) //frame
    1378             :         {
    1379           0 :             nDir = TrueFrameDirection( *( const SwFrmFmt * ) pOutFmtNode );
    1380             :         }
    1381          29 :         else if ( pOutFmtNode->ISA( SwCntntNode ) )    //pagagraph
    1382             :         {
    1383           1 :             const SwCntntNode *pNd = ( const SwCntntNode * ) pOutFmtNode;
    1384           1 :             SwPosition aPos( *pNd );
    1385           1 :             nDir = pDoc->GetTextDirection( aPos );
    1386             :         }
    1387          28 :         else if ( pOutFmtNode->ISA( SwTxtFmtColl ) )
    1388             :         {
    1389          28 :             if ( MsLangId::isRightToLeft( static_cast<LanguageType>(GetAppLanguage())) )
    1390           0 :                 nDir = FRMDIR_HORI_RIGHT_TOP;
    1391             :             else
    1392          28 :                 nDir = FRMDIR_HORI_LEFT_TOP;    //what else can we do :-(
    1393             :         }
    1394             :     }
    1395             : 
    1396          96 :     if ( nDir == FRMDIR_ENVIRONMENT )
    1397             :     {
    1398             :         // fdo#44029 put direction right when the locale are RTL.
    1399          67 :         if( MsLangId::isRightToLeft( static_cast<LanguageType>(GetAppLanguage())) )
    1400           0 :             nDir = FRMDIR_HORI_RIGHT_TOP;
    1401             :         else
    1402          67 :             nDir = FRMDIR_HORI_LEFT_TOP;        //Set something
    1403             :     }
    1404             : 
    1405          96 :     return nDir;
    1406             : }
    1407             : 
    1408        3104 : short MSWordExportBase::TrueFrameDirection( const SwFrmFmt &rFlyFmt ) const
    1409             : {
    1410        3104 :     const SwFrmFmt *pFlyFmt = &rFlyFmt;
    1411        3104 :     const SvxFrameDirectionItem* pItem = 0;
    1412        9312 :     while ( pFlyFmt )
    1413             :     {
    1414        3104 :         pItem = &pFlyFmt->GetFrmDir();
    1415        3104 :         if ( FRMDIR_ENVIRONMENT == pItem->GetValue() )
    1416             :         {
    1417        2850 :             pItem = 0;
    1418        2850 :             const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
    1419        2858 :             if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
    1420           8 :                 pAnchor->GetCntntAnchor() )
    1421             :             {
    1422           8 :                 pFlyFmt = pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
    1423             :             }
    1424             :             else
    1425        2842 :                 pFlyFmt = 0;
    1426             :         }
    1427             :         else
    1428         254 :             pFlyFmt = 0;
    1429             :     }
    1430             : 
    1431             :     short nRet;
    1432        3104 :     if ( pItem )
    1433         254 :         nRet = pItem->GetValue();
    1434             :     else
    1435        2850 :         nRet = GetCurrentPageDirection();
    1436             : 
    1437             :     OSL_ENSURE( nRet != FRMDIR_ENVIRONMENT, "leaving with environment direction" );
    1438        3104 :     return nRet;
    1439             : }
    1440             : 
    1441           3 : const SvxBrushItem* WW8Export::GetCurrentPageBgBrush() const
    1442             : {
    1443             :     const SwFrmFmt  &rFmt = pAktPageDesc
    1444           3 :                     ? pAktPageDesc->GetMaster()
    1445           6 :                     : pDoc->GetPageDesc(0).GetMaster();
    1446             : 
    1447           3 :     const SfxPoolItem* pItem = 0;
    1448             :     //If not set, or "no fill", get real bg
    1449           3 :     SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true, &pItem);
    1450             : 
    1451           3 :     const SvxBrushItem* pRet = (const SvxBrushItem*)pItem;
    1452           8 :     if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() &&
    1453           5 :         pRet->GetColor() == COL_TRANSPARENT))
    1454             :     {
    1455           2 :         pRet = &(DefaultItemGet<SvxBrushItem>(*pDoc,RES_BACKGROUND));
    1456             :     }
    1457           3 :     return pRet;
    1458             : }
    1459             : 
    1460           3 : SvxBrushItem WW8Export::TrueFrameBgBrush(const SwFrmFmt &rFlyFmt) const
    1461             : {
    1462           3 :     const SwFrmFmt *pFlyFmt = &rFlyFmt;
    1463           3 :     const SvxBrushItem* pRet = 0;
    1464             : 
    1465           9 :     while (pFlyFmt)
    1466             :     {
    1467             :         //If not set, or "no fill", get real bg
    1468           3 :         const SfxPoolItem* pItem = 0;
    1469             :         SfxItemState eState =
    1470           3 :             pFlyFmt->GetItemState(RES_BACKGROUND, true, &pItem);
    1471           3 :         pRet = (const SvxBrushItem*)pItem;
    1472           6 :         if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() &&
    1473           3 :             pRet->GetColor() == COL_TRANSPARENT))
    1474             :         {
    1475           3 :             pRet = 0;
    1476           3 :             const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
    1477           6 :             if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
    1478           3 :                 pAnchor->GetCntntAnchor())
    1479             :             {
    1480             :                 pFlyFmt =
    1481           3 :                     pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
    1482             :             }
    1483             :             else
    1484           0 :                 pFlyFmt = 0;
    1485             :         }
    1486             :         else
    1487           0 :             pFlyFmt = 0;
    1488             :     }
    1489             : 
    1490           3 :     if (!pRet)
    1491           3 :         pRet = GetCurrentPageBgBrush();
    1492             : 
    1493           3 :     const Color aTmpColor( COL_WHITE );
    1494           3 :     SvxBrushItem aRet( aTmpColor, RES_BACKGROUND );
    1495           3 :     if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
    1496           1 :         aRet = *pRet;
    1497             : 
    1498           3 :     return aRet;
    1499             : }
    1500             : 
    1501             : /*
    1502             : Convert characters that need to be converted, the basic replacements and the
    1503             : ridicously complicated title case attribute mapping to hardcoded upper case
    1504             : because word doesn't have the feature
    1505             : */
    1506        4836 : OUString SwWW8AttrIter::GetSnippet(const OUString &rStr, sal_Int32 nAktPos,
    1507             :     sal_Int32 nLen) const
    1508             : {
    1509        4836 :     if (!nLen)
    1510          37 :         return OUString();
    1511             : 
    1512        4799 :     OUString aSnippet(rStr.copy(nAktPos, nLen));
    1513             :     // 0x0a     ( Hard Line Break ) -> 0x0b
    1514             :     // 0xad     ( soft hyphen )     -> 0x1f
    1515             :     // 0x2011   ( hard hyphen )     -> 0x1e
    1516        4799 :     aSnippet = aSnippet.replace(0x0A, 0x0B);
    1517        4799 :     aSnippet = aSnippet.replace(CHAR_HARDHYPHEN, 0x1e);
    1518        4799 :     aSnippet = aSnippet.replace(CHAR_SOFTHYPHEN, 0x1f);
    1519             : 
    1520        4799 :     m_rExport.m_aCurrentCharPropStarts.push( nAktPos );
    1521        4799 :     const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP);
    1522             : 
    1523        4799 :     if (SVX_CASEMAP_TITEL == ((const SvxCaseMapItem&)rItem).GetValue())
    1524             :     {
    1525           0 :         sal_uInt16 nScriptType = i18n::ScriptType::LATIN;
    1526           0 :         if (g_pBreakIt->GetBreakIter().is())
    1527           0 :             nScriptType = g_pBreakIt->GetBreakIter()->getScriptType(aSnippet, 0);
    1528             : 
    1529             :         LanguageType nLanguage;
    1530           0 :         switch (nScriptType)
    1531             :         {
    1532             :         case i18n::ScriptType::ASIAN:
    1533           0 :                 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CJK_LANGUAGE)).GetLanguage();
    1534           0 :                 break;
    1535             :         case i18n::ScriptType::COMPLEX:
    1536           0 :                 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage();
    1537           0 :                 break;
    1538             :         case i18n::ScriptType::LATIN:
    1539             :             default:
    1540           0 :                 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_LANGUAGE)).GetLanguage();
    1541           0 :                 break;
    1542             :         }
    1543             : 
    1544           0 :         SvxFont aFontHelper;
    1545           0 :         aFontHelper.SetCaseMap(SVX_CASEMAP_TITEL);
    1546           0 :         aFontHelper.SetLanguage(nLanguage);
    1547           0 :         aSnippet = aFontHelper.CalcCaseMap(aSnippet);
    1548             : 
    1549             :         //If we weren't at the begin of a word undo the case change.
    1550             :         //not done before doing the casemap because the sequence might start
    1551             :         //with whitespace
    1552           0 :         if (g_pBreakIt->GetBreakIter().is() && !g_pBreakIt->GetBreakIter()->isBeginWord(
    1553           0 :             rStr, nAktPos, g_pBreakIt->GetLocale(nLanguage),
    1554           0 :             i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
    1555             :         {
    1556           0 :             aSnippet = OUString(rStr[nAktPos]) + aSnippet.copy(1);
    1557           0 :         }
    1558             :     }
    1559        4799 :     m_rExport.m_aCurrentCharPropStarts.pop();
    1560             : 
    1561        4799 :     return aSnippet;
    1562             : }
    1563             : 
    1564             : /** Delivers the right paragraph style
    1565             : 
    1566             :     Because of the different style handling for delete operations,
    1567             :     the track changes have to be analysed. A deletion, starting in paragraph A
    1568             :     with style A, ending in paragraph B with style B, needs a hack.
    1569             : */
    1570        6030 : static SwTxtFmtColl& lcl_getFormatCollection( MSWordExportBase& rExport, const SwTxtNode* pTxtNode )
    1571             : {
    1572        6030 :     sal_uInt16 nPos = 0;
    1573        6030 :     sal_uInt16 nMax = rExport.pDoc->GetRedlineTbl().size();
    1574       12123 :     while( nPos < nMax )
    1575             :     {
    1576          63 :         const SwRangeRedline* pRedl = rExport.pDoc->GetRedlineTbl()[ nPos++ ];
    1577          63 :         const SwPosition* pStt = pRedl->Start();
    1578          63 :         const SwPosition* pEnd = pStt == pRedl->GetPoint()
    1579          60 :                                     ? pRedl->GetMark()
    1580         123 :                                     : pRedl->GetPoint();
    1581             :         // Looking for deletions, which ends in current pTxtNode
    1582         280 :         if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetRedlineData().GetType() &&
    1583         253 :             pEnd->nNode == *pTxtNode && pStt->nNode != *pTxtNode &&
    1584           3 :             pStt->nNode.GetNode().IsTxtNode() )
    1585             :         {
    1586           3 :             pTxtNode = pStt->nNode.GetNode().GetTxtNode();
    1587           3 :             nMax = nPos;
    1588           3 :             nPos = 0;
    1589             :         }
    1590             :     }
    1591        6030 :     return static_cast<SwTxtFmtColl&>( pTxtNode->GetAnyFmtColl() );
    1592             : }
    1593             : 
    1594           0 : void WW8AttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop &rSwFmtDrop, sal_uInt16 nStyle,
    1595             :         ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
    1596             : {
    1597           0 :     short nDropLines = rSwFmtDrop.GetLines();
    1598           0 :     short nDistance = rSwFmtDrop.GetDistance();
    1599             :     int rFontHeight, rDropHeight, rDropDescent;
    1600             : 
    1601             :     SVBT16 nSty;
    1602           0 :     ShortToSVBT16( nStyle, nSty );
    1603           0 :     m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), (sal_uInt8*)&nSty, (sal_uInt8*)&nSty+2 );     // Style #
    1604             : 
    1605           0 :     if ( m_rWW8Export.bWrtWW8 )
    1606             :     {
    1607           0 :         m_rWW8Export.InsUInt16( NS_sprm::LN_PPc );            // Alignment (sprmPPc)
    1608           0 :         m_rWW8Export.pO->push_back( 0x20 );
    1609             : 
    1610           0 :         m_rWW8Export.InsUInt16( NS_sprm::LN_PWr );            // Wrapping (sprmPWr)
    1611           0 :         m_rWW8Export.pO->push_back( 0x02 );
    1612             : 
    1613           0 :         m_rWW8Export.InsUInt16( NS_sprm::LN_PDcs );            // Dropcap (sprmPDcs)
    1614           0 :         int nDCS = ( nDropLines << 3 ) | 0x01;
    1615           0 :         m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
    1616             : 
    1617           0 :         m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText );            // Distance from text (sprmPDxaFromText)
    1618           0 :         m_rWW8Export.InsUInt16( nDistance );
    1619             : 
    1620           0 :         if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
    1621             :         {
    1622           0 :             m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaLine );            // Line spacing
    1623           0 :             m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
    1624           0 :             m_rWW8Export.InsUInt16( 0 );
    1625             :         }
    1626             :     }
    1627             :     else
    1628             :     {
    1629           0 :         m_rWW8Export.pO->push_back( 29 );    // Alignment (sprmPPc)
    1630           0 :         m_rWW8Export.pO->push_back( 0x20 );
    1631             : 
    1632           0 :         m_rWW8Export.pO->push_back( 37 );    // Wrapping (sprmPWr)
    1633           0 :         m_rWW8Export.pO->push_back( 0x02 );
    1634             : 
    1635           0 :         m_rWW8Export.pO->push_back( 46 );    // Dropcap (sprmPDcs)
    1636           0 :         int nDCS = ( nDropLines << 3 ) | 0x01;
    1637           0 :         m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
    1638             : 
    1639           0 :         m_rWW8Export.pO->push_back( 49 );      // Distance from text (sprmPDxaFromText)
    1640           0 :         m_rWW8Export.InsUInt16( nDistance );
    1641             : 
    1642           0 :         if (rNode.GetDropSize(rFontHeight, rDropHeight, rDropDescent))
    1643             :         {
    1644           0 :             m_rWW8Export.pO->push_back( 20 );  // Line spacing
    1645           0 :             m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
    1646           0 :             m_rWW8Export.InsUInt16( 0 );
    1647             :         }
    1648             :     }
    1649             : 
    1650           0 :     m_rWW8Export.WriteCR( pTextNodeInfoInner );
    1651             : 
    1652           0 :     if ( pTextNodeInfo.get() != NULL )
    1653             :     {
    1654             : #ifdef DBG_UTIL
    1655             :         SAL_INFO( "sw.ww8", pTextNodeInfo->toString());
    1656             : #endif
    1657           0 :         TableInfoCell( pTextNodeInfoInner );
    1658             :     }
    1659             : 
    1660           0 :     m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
    1661           0 :     m_rWW8Export.pO->clear();
    1662             : 
    1663           0 :     if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
    1664             :     {
    1665           0 :         if ( m_rWW8Export.bWrtWW8 )
    1666             :         {
    1667           0 :             const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
    1668           0 :             if ( pSwCharFmt )
    1669             :             {
    1670           0 :                 m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
    1671           0 :                 m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) );
    1672             :             }
    1673             : 
    1674           0 :             m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsPos );            // Lower the chars
    1675           0 :             m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
    1676             : 
    1677           0 :             m_rWW8Export.InsUInt16( NS_sprm::LN_CHps );            // Font Size
    1678           0 :             m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
    1679             :         }
    1680             :         else
    1681             :         {
    1682           0 :             const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
    1683           0 :             if ( pSwCharFmt )
    1684             :             {
    1685           0 :                 m_rWW8Export.InsUInt16( 80 );
    1686           0 :                 m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) );
    1687             :             }
    1688             : 
    1689           0 :             m_rWW8Export.pO->push_back( 101 );      // Lower the chars
    1690           0 :             m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
    1691             : 
    1692           0 :             m_rWW8Export.pO->push_back( 99 );      // Font Size
    1693           0 :             m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
    1694             :         }
    1695             :     }
    1696             : 
    1697           0 :     m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
    1698           0 :     m_rWW8Export.pO->clear();
    1699           0 : }
    1700             : 
    1701        7457 : sal_Int32 MSWordExportBase::GetNextPos( SwWW8AttrIter* aAttrIter, const SwTxtNode& rNode, sal_Int32 nAktPos )
    1702             : {
    1703             :     // Get the bookmarks for the normal run
    1704        7457 :     const sal_Int32 nNextPos = aAttrIter->WhereNext();
    1705        7457 :     sal_Int32 nNextBookmark = nNextPos;
    1706        7457 :     sal_Int32 nNextAnnotationMark = nNextPos;
    1707             : 
    1708        7457 :     if( nNextBookmark > nAktPos ) //no need to search for bookmarks otherwise (checked in UpdatePosition())
    1709             :     {
    1710        5228 :         GetSortedBookmarks( rNode, nAktPos, nNextBookmark - nAktPos );
    1711        5228 :         NearestBookmark( nNextBookmark, nAktPos, false );
    1712        5228 :         GetSortedAnnotationMarks( rNode, nAktPos, nNextAnnotationMark - nAktPos );
    1713        5228 :         NearestAnnotationMark( nNextAnnotationMark, nAktPos, false );
    1714             :     }
    1715        7457 :     return std::min( nNextPos, std::min( nNextBookmark, nNextAnnotationMark ) );
    1716             : }
    1717             : 
    1718        7457 : void MSWordExportBase::UpdatePosition( SwWW8AttrIter* aAttrIter, sal_Int32 nAktPos, sal_Int32 /*nEnd*/ )
    1719             : {
    1720             :     sal_Int32 nNextPos;
    1721             : 
    1722             :     // go to next attribute if no bookmark is found or if the bookmark is behind the next attribute position
    1723             :     // It may happened that the WhereNext() wasn't used in the previous increment because there was a
    1724             :     // bookmark before it. Use that position before trying to find another one.
    1725        7457 :     bool bNextBookmark = NearestBookmark( nNextPos, nAktPos, true );
    1726        7457 :     if( nAktPos == aAttrIter->WhereNext() && ( !bNextBookmark || nNextPos > aAttrIter->WhereNext() ) )
    1727        7429 :         aAttrIter->NextPos();
    1728        7457 : }
    1729             : 
    1730       18024 : bool MSWordExportBase::GetBookmarks( const SwTxtNode& rNd, sal_Int32 nStt,
    1731             :                     sal_Int32 nEnd, IMarkVector& rArr )
    1732             : {
    1733       18024 :     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    1734       18024 :     sal_uLong nNd = rNd.GetIndex( );
    1735             : 
    1736       18024 :     const sal_Int32 nMarks = pMarkAccess->getCommonMarksCount();
    1737      302261 :     for ( sal_Int32 i = 0; i < nMarks; i++ )
    1738             :     {
    1739      284237 :         IMark* pMark = ( pMarkAccess->getCommonMarksBegin() + i )->get();
    1740             : 
    1741             :         // Only keep the bookmarks starting or ending in this node
    1742      566297 :         if ( pMark->GetMarkStart().nNode == nNd ||
    1743      282060 :              pMark->GetMarkEnd().nNode == nNd )
    1744             :         {
    1745        2361 :             const sal_Int32 nBStart = pMark->GetMarkStart().nContent.GetIndex();
    1746        2361 :             const sal_Int32 nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
    1747             : 
    1748             :             // Keep only the bookmars starting or ending in the snippet
    1749        2361 :             bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
    1750        2361 :             bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
    1751             : 
    1752        2361 :             if ( bIsStartOk || bIsEndOk )
    1753             :             {
    1754        1735 :                 rArr.push_back( pMark );
    1755             :             }
    1756             :         }
    1757             :     }
    1758       18024 :     return ( rArr.size() > 0 );
    1759             : }
    1760             : 
    1761       18719 : bool MSWordExportBase::GetAnnotationMarks( const SwTxtNode& rNd, sal_Int32 nStt,
    1762             :                     sal_Int32 nEnd, IMarkVector& rArr )
    1763             : {
    1764       18719 :     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    1765       18719 :     sal_uLong nNd = rNd.GetIndex( );
    1766             : 
    1767       18719 :     const sal_Int32 nMarks = pMarkAccess->getAnnotationMarksCount();
    1768       18919 :     for ( sal_Int32 i = 0; i < nMarks; i++ )
    1769             :     {
    1770         200 :         IMark* pMark = ( pMarkAccess->getAnnotationMarksBegin() + i )->get();
    1771             : 
    1772             :         // Only keep the bookmarks starting or ending in this node
    1773         276 :         if ( pMark->GetMarkStart().nNode == nNd ||
    1774          76 :              pMark->GetMarkEnd().nNode == nNd )
    1775             :         {
    1776         134 :             const sal_Int32 nBStart = pMark->GetMarkStart().nContent.GetIndex();
    1777         134 :             const sal_Int32 nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
    1778             : 
    1779             :             // Keep only the bookmars starting or ending in the snippet
    1780         134 :             bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
    1781         134 :             bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
    1782             : 
    1783         134 :             if ( bIsStartOk || bIsEndOk )
    1784             :             {
    1785          88 :                 rArr.push_back( pMark );
    1786             :             }
    1787             :         }
    1788             :     }
    1789       18719 :     return ( rArr.size() > 0 );
    1790             : }
    1791             : 
    1792             : class CompareMarksEnd : public std::binary_function < const IMark *, const IMark *, bool >
    1793             : {
    1794             : public:
    1795         137 :     inline bool operator() ( const IMark * pOneB, const IMark * pTwoB ) const
    1796             :     {
    1797         137 :         const sal_Int32 nOEnd = pOneB->GetMarkEnd().nContent.GetIndex();
    1798         137 :         const sal_Int32 nTEnd = pTwoB->GetMarkEnd().nContent.GetIndex();
    1799             : 
    1800         137 :         return nOEnd < nTEnd;
    1801             :     }
    1802             : };
    1803             : 
    1804       12685 : bool MSWordExportBase::NearestBookmark( sal_Int32& rNearest, const sal_Int32 nAktPos, bool bNextPositionOnly )
    1805             : {
    1806       12685 :     bool bHasBookmark = false;
    1807             : 
    1808       12685 :     if ( !m_rSortedBookmarksStart.empty() )
    1809             :     {
    1810         331 :         IMark* pMarkStart = m_rSortedBookmarksStart.front();
    1811         331 :         const sal_Int32 nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
    1812         331 :         if( !bNextPositionOnly || (nNext > nAktPos ))
    1813             :         {
    1814         195 :             rNearest = nNext;
    1815         195 :             bHasBookmark = true;
    1816             :         }
    1817             :     }
    1818             : 
    1819       12685 :     if ( !m_rSortedBookmarksEnd.empty() )
    1820             :     {
    1821        1067 :         IMark* pMarkEnd = m_rSortedBookmarksEnd[0];
    1822        1067 :         const sal_Int32 nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
    1823        1067 :         if( !bNextPositionOnly || nNext > nAktPos )
    1824             :         {
    1825         802 :             if ( !bHasBookmark )
    1826         617 :                 rNearest = nNext;
    1827             :             else
    1828         185 :                 rNearest = std::min( rNearest, nNext );
    1829         802 :             bHasBookmark = true;
    1830             :         }
    1831             :     }
    1832             : 
    1833       12685 :     return bHasBookmark;
    1834             : }
    1835             : 
    1836        5228 : bool MSWordExportBase::NearestAnnotationMark( sal_Int32& rNearest, const sal_Int32 nAktPos, bool bNextPositionOnly )
    1837             : {
    1838        5228 :     bool bHasAnnotationMark = false;
    1839             : 
    1840        5228 :     if ( !m_rSortedAnnotationMarksStart.empty() )
    1841             :     {
    1842          10 :         IMark* pMarkStart = m_rSortedAnnotationMarksStart.front();
    1843          10 :         const sal_Int32 nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
    1844          10 :         if( !bNextPositionOnly || (nNext > nAktPos ))
    1845             :         {
    1846          10 :             rNearest = nNext;
    1847          10 :             bHasAnnotationMark = true;
    1848             :         }
    1849             :     }
    1850             : 
    1851        5228 :     if ( !m_rSortedAnnotationMarksEnd.empty() )
    1852             :     {
    1853          11 :         IMark* pMarkEnd = m_rSortedAnnotationMarksEnd[0];
    1854          11 :         const sal_Int32 nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
    1855          11 :         if( !bNextPositionOnly || nNext > nAktPos )
    1856             :         {
    1857          11 :             if ( !bHasAnnotationMark )
    1858          11 :                 rNearest = nNext;
    1859             :             else
    1860           0 :                 rNearest = std::min( rNearest, nNext );
    1861          11 :             bHasAnnotationMark = true;
    1862             :         }
    1863             :     }
    1864             : 
    1865        5228 :     return bHasAnnotationMark;
    1866             : }
    1867             : 
    1868        5228 : void MSWordExportBase::GetSortedAnnotationMarks( const SwTxtNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen )
    1869             : {
    1870        5228 :     IMarkVector aMarksStart;
    1871        5228 :     if ( GetAnnotationMarks( rNode, nAktPos, nAktPos + nLen, aMarksStart ) )
    1872             :     {
    1873          38 :         IMarkVector aSortedEnd;
    1874          76 :         IMarkVector aSortedStart;
    1875          82 :         for ( IMarkVector::const_iterator it = aMarksStart.begin(), end = aMarksStart.end();
    1876             :               it != end; ++it )
    1877             :         {
    1878          44 :             IMark* pMark = (*it);
    1879             : 
    1880             :             // Remove the positions egals to the current pos
    1881          44 :             const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
    1882          44 :             const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
    1883             : 
    1884          44 :             if ( nStart > nAktPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
    1885          13 :                 aSortedStart.push_back( pMark );
    1886             : 
    1887          44 :             if ( nEnd > nAktPos && nEnd <= ( nAktPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
    1888          11 :                 aSortedEnd.push_back( pMark );
    1889             :         }
    1890             : 
    1891             :         // Sort the bookmarks by end position
    1892          38 :         std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
    1893             : 
    1894          38 :         m_rSortedAnnotationMarksStart.swap( aSortedStart );
    1895          76 :         m_rSortedAnnotationMarksEnd.swap( aSortedEnd );
    1896             :     }
    1897             :     else
    1898             :     {
    1899        5190 :         m_rSortedAnnotationMarksStart.clear( );
    1900        5190 :         m_rSortedAnnotationMarksEnd.clear( );
    1901        5228 :     }
    1902        5228 : }
    1903             : 
    1904        5228 : void MSWordExportBase::GetSortedBookmarks( const SwTxtNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen )
    1905             : {
    1906        5228 :     IMarkVector aMarksStart;
    1907        5228 :     if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarksStart ) )
    1908             :     {
    1909         387 :         IMarkVector aSortedEnd;
    1910         774 :         IMarkVector aSortedStart;
    1911         958 :         for ( IMarkVector::const_iterator it = aMarksStart.begin(), end = aMarksStart.end();
    1912             :               it != end; ++it )
    1913             :         {
    1914         571 :             IMark* pMark = (*it);
    1915             : 
    1916             :             // Remove the positions egals to the current pos
    1917         571 :             const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
    1918         571 :             const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
    1919             : 
    1920         571 :             if ( nStart > nAktPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
    1921         137 :                 aSortedStart.push_back( pMark );
    1922             : 
    1923         571 :             if ( nEnd > nAktPos && nEnd <= ( nAktPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
    1924         335 :                 aSortedEnd.push_back( pMark );
    1925             :         }
    1926             : 
    1927             :         // Sort the bookmarks by end position
    1928         387 :         std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
    1929             : 
    1930         387 :         m_rSortedBookmarksStart.swap( aSortedStart );
    1931         774 :         m_rSortedBookmarksEnd.swap( aSortedEnd );
    1932             :     }
    1933             :     else
    1934             :     {
    1935        4841 :         m_rSortedBookmarksStart.clear( );
    1936        4841 :         m_rSortedBookmarksEnd.clear( );
    1937        5228 :     }
    1938        5228 : }
    1939             : 
    1940        6036 : void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
    1941             : {
    1942             :     SAL_INFO( "sw.ww8", "<OutWW8_SwTxtNode>" );
    1943             : 
    1944        6036 :     ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( mpTableInfo->getTableNodeInfo( &rNode ) );
    1945             : 
    1946             :     //For i120928,identify the last node
    1947        6036 :     bool bLastCR = false;
    1948        6036 :     bool bExported = false;
    1949             :     {
    1950        6036 :         SwNodeIndex aNextIdx(rNode,1);
    1951       12072 :         SwNodeIndex aLastIdx(rNode.GetNodes().GetEndOfContent());
    1952        6036 :         if (aNextIdx == aLastIdx)
    1953        6366 :             bLastCR = true;
    1954             :     }
    1955             : 
    1956             :     // In order to make sure watermark is stored in 'header.xml', check nTxtTyp.
    1957             :     // if it is document.xml, don't write the tags (watermark should be only in the 'header')
    1958       12070 :     SwWW8AttrIter aWatermarkAttrIter( *this, rNode );
    1959        6036 :     if (( TXT_HDFT != nTxtTyp) && aWatermarkAttrIter.IsWatermarkFrame())
    1960             :     {
    1961        6038 :        return;
    1962             :     }
    1963             : 
    1964        6034 :     bool bFlyInTable = mpParentFrame && IsInTable();
    1965             : 
    1966        6034 :     if ( !bFlyInTable )
    1967        6030 :         nStyleBeforeFly = GetId( lcl_getFormatCollection( *this, &rNode ) );
    1968             : 
    1969             :     // nStyleBeforeFly may change when we recurse into another node, so we
    1970             :     // have to remember it in nStyle
    1971        6034 :     sal_uInt16 nStyle = nStyleBeforeFly;
    1972             : 
    1973       12068 :     SwWW8AttrIter aAttrIter( *this, rNode );
    1974        6034 :     rtl_TextEncoding eChrSet = aAttrIter.GetCharSet();
    1975             : 
    1976        6034 :     if ( bStartTOX )
    1977             :     {
    1978             :         // ignore TOX header section
    1979          25 :         const SwSectionNode* pSectNd = rNode.FindSectionNode();
    1980          25 :         if ( pSectNd && TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
    1981             :         {
    1982          24 :             AttrOutput().StartTOX( pSectNd->GetSection() );
    1983          24 :             m_aCurrentCharPropStarts.push( 0 );
    1984             :         }
    1985             :     }
    1986             : 
    1987        6034 :     AttrOutput().StartParagraph( pTextNodeInfo );
    1988             : 
    1989        6034 :     const SwSection* pTOXSect = 0;
    1990        6034 :     if( bInWriteTOX )
    1991             :     {
    1992             :         // check for end of TOX
    1993         170 :         SwNodeIndex aIdx( rNode, 1 );
    1994         170 :         if( !aIdx.GetNode().IsTxtNode() )
    1995             :         {
    1996          24 :             const SwSectionNode* pTOXSectNd = rNode.FindSectionNode();
    1997          24 :             if ( pTOXSectNd )
    1998             :             {
    1999          24 :                 pTOXSect = &pTOXSectNd->GetSection();
    2000             : 
    2001          24 :                 const SwNode* pNxt = rNode.GetNodes().GoNext( &aIdx );
    2002          24 :                 if( pNxt && pNxt->FindSectionNode() == pTOXSectNd )
    2003           0 :                     pTOXSect = 0;
    2004             :             }
    2005         170 :         }
    2006             :     }
    2007             : 
    2008        6034 :     if ( aAttrIter.RequiresImplicitBookmark() )
    2009             :     {
    2010           0 :         OUString sBkmkName =  "_toc" + OUString::number( rNode.GetIndex() );
    2011           0 :         AppendWordBookmark( sBkmkName );
    2012             :     }
    2013             : 
    2014       12068 :     OUString aStr( rNode.GetTxt() );
    2015             : 
    2016        6034 :     sal_Int32 nAktPos = 0;
    2017        6034 :     sal_Int32 const nEnd = aStr.getLength();
    2018        6034 :     bool bRedlineAtEnd = false;
    2019        6034 :     sal_Int32 nOpenAttrWithRange = 0;
    2020             : 
    2021       12068 :     ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner;
    2022        6034 :     if ( pTextNodeInfo.get() != NULL )
    2023        2011 :         pTextNodeInfoInner = pTextNodeInfo->getFirstInner();
    2024             : 
    2025        7457 :     do {
    2026        7457 :         const SwRedlineData* pRedlineData = aAttrIter.GetRunLevelRedline( nAktPos );
    2027             : 
    2028        7457 :         sal_Int32 nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos );
    2029             :         // Is this the only run in this paragraph and it's empty?
    2030        7457 :         bool bSingleEmptyRun = nAktPos == 0 && nNextAttr == 0;
    2031        7457 :         AttrOutput().StartRun( pRedlineData, bSingleEmptyRun );
    2032        7457 :         if( nTxtTyp == TXT_FTN || nTxtTyp == TXT_EDN )
    2033          23 :             AttrOutput().FootnoteEndnoteRefTag();
    2034             : 
    2035        7457 :         if( nNextAttr > nEnd )
    2036           0 :             nNextAttr = nEnd;
    2037             : 
    2038        7457 :         aAttrIter.OutFlys( nAktPos );
    2039             :         // Append bookmarks in this range after flys, exclusive of final
    2040             :         // position of this range
    2041        7457 :         AppendBookmarks( rNode, nAktPos, nNextAttr - nAktPos );
    2042        7457 :         AppendAnnotationMarks( rNode, nAktPos, nNextAttr - nAktPos );
    2043        7457 :         bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
    2044        7457 :         nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nAktPos);
    2045             : 
    2046        7457 :         sal_Int32 nLen = nNextAttr - nAktPos;
    2047        7457 :         if ( !bTxtAtr && nLen )
    2048             :         {
    2049        4836 :             sal_Unicode ch = aStr[nAktPos];
    2050        4836 :             const sal_Int32 ofs = ( ch == CH_TXT_ATR_FIELDSTART || ch == CH_TXT_ATR_FIELDEND || ch == CH_TXT_ATR_FORMELEMENT? 1 : 0 );
    2051             : 
    2052        4836 :             IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    2053        4836 :             if ( ch == CH_TXT_ATR_FIELDSTART )
    2054             :             {
    2055          25 :                 SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
    2056          25 :                 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
    2057             :                 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
    2058             : 
    2059          25 :                 if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT )
    2060           0 :                     AppendBookmark( pFieldmark->GetName(), false );
    2061          25 :                 ww::eField eFieldId = lcl_getFieldId( pFieldmark );
    2062          50 :                 OUString sCode = lcl_getFieldCode( pFieldmark );
    2063          25 :                 if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
    2064             :                 {
    2065           0 :                     IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
    2066           0 :                     if ( it != pFieldmark->GetParameters()->end() )
    2067             :                     {
    2068           0 :                         OUString sFieldId;
    2069           0 :                         it->second >>= sFieldId;
    2070           0 :                         eFieldId = (ww::eField)sFieldId.toInt32();
    2071             :                     }
    2072             : 
    2073           0 :                     it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM );
    2074           0 :                     if ( it != pFieldmark->GetParameters()->end() )
    2075             :                     {
    2076           0 :                         it->second >>= sCode;
    2077             :                     }
    2078             :                 }
    2079             : 
    2080          25 :                 OutputField( NULL, eFieldId, sCode, WRITEFIELD_START | WRITEFIELD_CMD_START );
    2081             : 
    2082          25 :                 if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
    2083           0 :                     WriteFormData( *pFieldmark );
    2084          25 :                 else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
    2085           0 :                     WriteHyperlinkData( *pFieldmark );
    2086          25 :                 OutputField( NULL, lcl_getFieldId( pFieldmark ), OUString(), WRITEFIELD_CMD_END );
    2087             : 
    2088          25 :                 if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
    2089             :                 {
    2090             :                     // Check for the presence of a linked OLE object
    2091           0 :                     IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM );
    2092           0 :                     if ( it != pFieldmark->GetParameters()->end() )
    2093             :                     {
    2094           0 :                         OUString sOleId;
    2095           0 :                         uno::Any aValue = it->second;
    2096           0 :                         aValue >>= sOleId;
    2097           0 :                         if ( !sOleId.isEmpty() )
    2098           0 :                             OutputLinkedOLE( sOleId );
    2099             :                     }
    2100          25 :                 }
    2101             :             }
    2102        4811 :             else if ( ch == CH_TXT_ATR_FIELDEND )
    2103             :             {
    2104          25 :                 SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
    2105          25 :                 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
    2106             : 
    2107             :                 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" );
    2108             : 
    2109          25 :                 ww::eField eFieldId = lcl_getFieldId( pFieldmark );
    2110          25 :                 if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
    2111             :                 {
    2112           0 :                     IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
    2113           0 :                     if ( it != pFieldmark->GetParameters()->end() )
    2114             :                     {
    2115           0 :                         OUString sFieldId;
    2116           0 :                         it->second >>= sFieldId;
    2117           0 :                         eFieldId = (ww::eField)sFieldId.toInt32();
    2118             :                     }
    2119             :                 }
    2120             : 
    2121          25 :                 OutputField( NULL, eFieldId, OUString(), WRITEFIELD_CLOSE );
    2122             : 
    2123          25 :                 if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT )
    2124           0 :                     AppendBookmark( pFieldmark->GetName(), false );
    2125             :             }
    2126        4786 :             else if ( ch == CH_TXT_ATR_FORMELEMENT )
    2127             :             {
    2128           1 :                 SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
    2129           1 :                 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
    2130             :                 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
    2131             : 
    2132           5 :                 bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
    2133           3 :                     pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
    2134             : 
    2135           1 :                 if ( isDropdownOrCheckbox )
    2136           1 :                     AppendBookmark( pFieldmark->GetName(), false );
    2137             :                 OutputField( NULL, lcl_getFieldId( pFieldmark ),
    2138             :                         lcl_getFieldCode( pFieldmark ),
    2139           1 :                         WRITEFIELD_START | WRITEFIELD_CMD_START );
    2140           1 :                 if ( isDropdownOrCheckbox )
    2141           1 :                     WriteFormData( *pFieldmark );
    2142           1 :                 OutputField( NULL, lcl_getFieldId( pFieldmark ), OUString(), WRITEFIELD_CLOSE );
    2143           1 :                 if ( isDropdownOrCheckbox )
    2144           1 :                     AppendBookmark( pFieldmark->GetName(), false );
    2145             :             }
    2146        4836 :             nLen -= ofs;
    2147             : 
    2148        4836 :             OUString aSnippet( aAttrIter.GetSnippet( aStr, nAktPos + ofs, nLen ) );
    2149        4836 :             if ( ( nTxtTyp == TXT_EDN || nTxtTyp == TXT_FTN ) && nAktPos == 0 && nLen > 0 )
    2150             :             {
    2151             :                 // Insert tab for aesthetic puposes #i24762#
    2152           8 :                 if ( aSnippet[0] != 0x09 )
    2153           8 :                     aSnippet = OUString( 0x09 ) + aSnippet;
    2154             :             }
    2155        4836 :             AttrOutput().RunText( aSnippet, eChrSet );
    2156             :         }
    2157             : 
    2158        7457 :         if ( aAttrIter.IsDropCap( nNextAttr ) )
    2159           0 :             AttrOutput().FormatDrop( rNode, aAttrIter.GetSwFmtDrop(), nStyle, pTextNodeInfo, pTextNodeInfoInner );
    2160             : 
    2161        7457 :         if (0 != nEnd)
    2162             :         {
    2163             :             // Output the character attributes
    2164             :             // #i51277# do this before writing flys at end of paragraph
    2165        5228 :             AttrOutput().StartRunProperties();
    2166        5228 :             aAttrIter.OutAttr( nAktPos );
    2167        5228 :             AttrOutput().EndRunProperties( pRedlineData );
    2168             :         }
    2169             : 
    2170             :         // At the end of line, output the attributes until the CR.
    2171             :         // Exception: footnotes at the end of line
    2172        7457 :         if ( nNextAttr == nEnd )
    2173             :         {
    2174             :             OSL_ENSURE( nOpenAttrWithRange >= 0, "odd to see this happening, expected >= 0" );
    2175        6034 :             if ( !bTxtAtr && nOpenAttrWithRange <= 0 )
    2176             :             {
    2177        5655 :                 if ( aAttrIter.IsRedlineAtEnd( nEnd ) )
    2178           3 :                     bRedlineAtEnd = true;
    2179             :                 else
    2180             :                 {
    2181             :                     // insert final graphic anchors if any before CR
    2182        5652 :                     aAttrIter.OutFlys( nEnd );
    2183             :                     // insert final bookmarks if any before CR and after flys
    2184        5652 :                     AppendBookmarks( rNode, nEnd, 1 );
    2185        5652 :                     AppendAnnotationMarks( rNode, nEnd, 1 );
    2186        5652 :                     if ( pTOXSect )
    2187             :                     {
    2188          23 :                         m_aCurrentCharPropStarts.pop();
    2189          23 :                         AttrOutput().EndTOX( *pTOXSect ,false);
    2190             :                     }
    2191             :                     //For i120928,the position of the bullet's graphic is at end of doc
    2192        5652 :                     if (bLastCR && (!bExported))
    2193             :                     {
    2194         251 :                         ExportGrfBullet(rNode);
    2195         251 :                         bExported = true;
    2196             :                     }
    2197             : 
    2198        5652 :                     WriteCR( pTextNodeInfoInner );
    2199             :                 }
    2200             :             }
    2201             :         }
    2202             : 
    2203        7457 :         if (0 == nEnd)
    2204             :         {
    2205             :             // Output the character attributes
    2206             :             // do it after WriteCR for an empty paragraph (otherwise
    2207             :             // WW8_WrFkp::Append throws SPRMs away...)
    2208        2229 :             AttrOutput().StartRunProperties();
    2209        2229 :             aAttrIter.OutAttr( nAktPos );
    2210        2229 :             AttrOutput().EndRunProperties( pRedlineData );
    2211             :         }
    2212             : 
    2213             :         // Exception: footnotes at the end of line
    2214        7457 :         if ( nNextAttr == nEnd )
    2215             :         {
    2216             :             OSL_ENSURE(nOpenAttrWithRange >= 0,
    2217             :                 "odd to see this happening, expected >= 0");
    2218        6034 :             bool bAttrWithRange = (nOpenAttrWithRange > 0);
    2219        6034 :             if ( nAktPos != nEnd )
    2220             :             {
    2221        3805 :                 nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nEnd);
    2222             :                 OSL_ENSURE(nOpenAttrWithRange == 0,
    2223             :                     "odd to see this happening, expected 0");
    2224             :             }
    2225             : 
    2226        6034 :             AttrOutput().OutputFKP();
    2227             : 
    2228        6034 :             if ( bTxtAtr || bAttrWithRange || bRedlineAtEnd )
    2229             :             {
    2230             :                 // insert final graphic anchors if any before CR
    2231         382 :                 aAttrIter.OutFlys( nEnd );
    2232             :                 // insert final bookmarks if any before CR and after flys
    2233         382 :                 AppendBookmarks( rNode, nEnd, 1 );
    2234         382 :                 AppendAnnotationMarks( rNode, nEnd, 1 );
    2235         382 :                 WriteCR( pTextNodeInfoInner );
    2236             :                 // #i120928 - position of the bullet's graphic is at end of doc
    2237         382 :                 if (bLastCR && (!bExported))
    2238             :                 {
    2239          77 :                     ExportGrfBullet(rNode);
    2240          77 :                     bExported = true;
    2241             :                 }
    2242             : 
    2243         382 :                 if ( pTOXSect )
    2244             :                 {
    2245           1 :                     m_aCurrentCharPropStarts.pop();
    2246           1 :                     AttrOutput().EndTOX( *pTOXSect );
    2247             :                 }
    2248             : 
    2249         382 :                 if ( bRedlineAtEnd )
    2250             :                 {
    2251           3 :                     AttrOutput().Redline( aAttrIter.GetRunLevelRedline( nEnd ) );
    2252           3 :                     AttrOutput().OutputFKP();
    2253             :                 }
    2254             :             }
    2255             :         }
    2256             : 
    2257        7457 :         AttrOutput().WritePostitFieldReference();
    2258             : 
    2259        7457 :         AttrOutput().EndRun();
    2260             : 
    2261        7457 :         nAktPos = nNextAttr;
    2262        7457 :         UpdatePosition( &aAttrIter, nAktPos, nEnd );
    2263        7457 :         eChrSet = aAttrIter.GetCharSet();
    2264             :     }
    2265             :     while ( nAktPos < nEnd );
    2266             : 
    2267        6034 :     AttrOutput().SectionBreaks(rNode);
    2268             : 
    2269        6034 :     AttrOutput().StartParagraphProperties();
    2270             : 
    2271        6034 :     AttrOutput().ParagraphStyle( nStyle );
    2272             : 
    2273        6034 :     if ( mpParentFrame && IsInTable() )    // Fly-Attrs
    2274           4 :         OutputFormat( mpParentFrame->GetFrmFmt(), false, false, true );
    2275             : 
    2276        6034 :     if ( pTextNodeInfo.get() != NULL )
    2277             :     {
    2278             : #ifdef DBG_UTIL
    2279             :         SAL_INFO( "sw.ww8", pTextNodeInfo->toString());
    2280             : #endif
    2281             : 
    2282        2011 :         AttrOutput().TableInfoCell( pTextNodeInfoInner );
    2283        2011 :         if (pTextNodeInfoInner->isFirstInTable())
    2284             :         {
    2285         107 :             const SwTable * pTable = pTextNodeInfoInner->getTable();
    2286             : 
    2287         107 :             const SwTableFmt * pTabFmt = pTable->GetTableFmt();
    2288         107 :             if (pTabFmt != NULL)
    2289             :             {
    2290         107 :                 if (pTabFmt->GetBreak().GetBreak() == SVX_BREAK_PAGE_BEFORE)
    2291           0 :                     AttrOutput().PageBreakBefore(true);
    2292             :             }
    2293             :         }
    2294             :     }
    2295             : 
    2296        6034 :     if ( !bFlyInTable )
    2297             :     {
    2298        6030 :         SfxItemSet* pTmpSet = 0;
    2299        6030 :         const sal_uInt8 nPrvNxtNd = rNode.HasPrevNextLayNode();
    2300             : 
    2301        6030 :         if( (ND_HAS_PREV_LAYNODE|ND_HAS_NEXT_LAYNODE ) != nPrvNxtNd )
    2302             :         {
    2303             :             const SfxPoolItem* pItem;
    2304        5574 :             if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(
    2305        4703 :                     RES_UL_SPACE, true, &pItem ) &&
    2306        3251 :                 ( ( !( ND_HAS_PREV_LAYNODE & nPrvNxtNd ) &&
    2307        3134 :                    ((SvxULSpaceItem*)pItem)->GetUpper()) ||
    2308        3050 :                   ( !( ND_HAS_NEXT_LAYNODE & nPrvNxtNd ) &&
    2309        1466 :                    ((SvxULSpaceItem*)pItem)->GetLower()) ))
    2310             :             {
    2311         215 :                 pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
    2312         215 :                 SvxULSpaceItem aUL( *(SvxULSpaceItem*)pItem );
    2313             :                 // #i25901#- consider compatibility option
    2314         215 :                 if (!pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES))
    2315             :                 {
    2316           0 :                     if( !(ND_HAS_PREV_LAYNODE & nPrvNxtNd ))
    2317           0 :                         aUL.SetUpper( 0 );
    2318             :                 }
    2319             :                 // #i25901# - consider compatibility option
    2320         215 :                 if (!pDoc->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS))
    2321             :                 {
    2322           0 :                     if( !(ND_HAS_NEXT_LAYNODE & nPrvNxtNd ))
    2323           0 :                         aUL.SetLower( 0 );
    2324             :                 }
    2325         215 :                 pTmpSet->Put( aUL );
    2326             :             }
    2327             :         }
    2328             : 
    2329        6030 :         bool bParaRTL = aAttrIter.IsParaRTL();
    2330             : 
    2331        6030 :         int nNumberLevel = -1;
    2332        6030 :         if (rNode.IsNumbered())
    2333         365 :             nNumberLevel = rNode.GetActualListLevel();
    2334        6030 :         if (nNumberLevel >= 0 && nNumberLevel < MAXLEVEL)
    2335             :         {
    2336         365 :             const SwNumRule* pRule = rNode.GetNumRule();
    2337         365 :             sal_uInt8 nLvl = static_cast< sal_uInt8 >(nNumberLevel);
    2338         365 :             const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
    2339         365 :             if( !pFmt )
    2340           0 :                 pFmt = &pRule->Get( nLvl );
    2341             : 
    2342         365 :             if( !pTmpSet )
    2343         350 :                 pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
    2344             : 
    2345         365 :             SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*pTmpSet, RES_LR_SPACE));
    2346             :             // #i86652#
    2347         365 :             if ( pFmt->GetPositionAndSpaceMode() ==
    2348             :                                     SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
    2349             :             {
    2350          38 :                 aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetAbsLSpace() );
    2351             :             }
    2352             : 
    2353         365 :             if( rNode.IsNumbered() && rNode.IsCountedInList() )
    2354             :             {
    2355             :                 // #i86652#
    2356         365 :                 if ( pFmt->GetPositionAndSpaceMode() ==
    2357             :                                         SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
    2358             :                 {
    2359          38 :                     if (bParaRTL)
    2360           0 :                         aLR.SetTxtFirstLineOfstValue(pFmt->GetAbsLSpace() - pFmt->GetFirstLineOffset());
    2361             :                     else
    2362          38 :                         aLR.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt));
    2363             :                 }
    2364             : 
    2365             :                 // correct fix for issue i94187
    2366         365 :                 if (SFX_ITEM_SET !=
    2367         365 :                     pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
    2368             :                 {
    2369             :                     // List style set via paragraph style - then put it into the itemset.
    2370             :                     // This is needed to get list level and list id exported for
    2371             :                     // the paragraph.
    2372          29 :                     pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
    2373             : 
    2374             :                     // Put indent values into the itemset in case that the list
    2375             :                     // style is applied via paragraph style and the list level
    2376             :                     // indent values are not applicable.
    2377          58 :                     if ( pFmt->GetPositionAndSpaceMode() ==
    2378          32 :                                             SvxNumberFormat::LABEL_ALIGNMENT &&
    2379           3 :                          !rNode.AreListLevelIndentsApplicable() )
    2380             :                     {
    2381           0 :                         pTmpSet->Put( aLR );
    2382             :                     }
    2383             :                 }
    2384             :             }
    2385             :             else
    2386           0 :                 pTmpSet->ClearItem(RES_PARATR_NUMRULE);
    2387             : 
    2388             :             // #i86652#
    2389         365 :             if ( pFmt->GetPositionAndSpaceMode() ==
    2390             :                                     SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
    2391             :             {
    2392          38 :                 pTmpSet->Put(aLR);
    2393             : 
    2394             :                 //#i21847#
    2395             :                 SvxTabStopItem aItem(
    2396          38 :                     ItemGet<SvxTabStopItem>(*pTmpSet, RES_PARATR_TABSTOP));
    2397          38 :                 SvxTabStop aTabStop(pFmt->GetAbsLSpace());
    2398          38 :                 aItem.Insert(aTabStop);
    2399          38 :                 pTmpSet->Put(aItem);
    2400             : 
    2401          38 :                 MSWordExportBase::CorrectTabStopInSet(*pTmpSet, pFmt->GetAbsLSpace());
    2402         365 :             }
    2403             :         }
    2404             : 
    2405             :         /*
    2406             :         If a given para is using the FRMDIR_ENVIRONMENT direction we
    2407             :         cannot export that, its its ltr then that's ok as thats word's
    2408             :         default. Otherwise we must add a RTL attribute to our export list
    2409             :         */
    2410             :         const SvxFrameDirectionItem* pItem = (const SvxFrameDirectionItem*)
    2411        6030 :             rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR);
    2412        6030 :         if (
    2413        6616 :             (!pItem || pItem->GetValue() == FRMDIR_ENVIRONMENT) &&
    2414         586 :             aAttrIter.IsParaRTL()
    2415             :            )
    2416             :         {
    2417           0 :             if ( !pTmpSet )
    2418           0 :                 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
    2419             : 
    2420           0 :             pTmpSet->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP, RES_FRAMEDIR));
    2421             :         }
    2422             :         // move code for handling of numbered,
    2423             :         // but not counted paragraphs to this place. Otherwise, the paragraph
    2424             :         // isn't exported as numbered, but not counted, if no other attribute
    2425             :         // is found in <pTmpSet>
    2426             :         // #i44815# adjust numbering/indents for numbered paragraphs
    2427             :         //          without number (NO_NUMLEVEL)
    2428             :         // #i47013# need to check rNode.GetNumRule()!=NULL as well.
    2429        6030 :         if ( ! rNode.IsCountedInList() && rNode.GetNumRule()!=NULL )
    2430             :         {
    2431             :             // WW8 does not know numbered paragraphs without number
    2432             :             // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
    2433             :             // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
    2434             :             // no numbering. Here, we will adjust the indents to match
    2435             :             // visually.
    2436             : 
    2437           0 :             if ( !pTmpSet )
    2438           0 :                 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
    2439             : 
    2440             :             // create new LRSpace item, based on the current (if present)
    2441           0 :             const SfxPoolItem* pPoolItem = NULL;
    2442           0 :             pTmpSet->GetItemState(RES_LR_SPACE, true, &pPoolItem);
    2443             :             SvxLRSpaceItem aLRSpace(
    2444           0 :                 ( pPoolItem == NULL )
    2445             :                     ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE)
    2446           0 :                     : *static_cast<const SvxLRSpaceItem*>( pPoolItem ) );
    2447             : 
    2448             :             // new left margin = old left + label space
    2449           0 :             const SwNumRule* pRule = rNode.GetNumRule();
    2450           0 :             const SwNumFmt& rNumFmt = pRule->Get( static_cast< sal_uInt16 >(rNode.GetActualListLevel()) );
    2451             :             // #i86652#
    2452           0 :             if ( rNumFmt.GetPositionAndSpaceMode() ==
    2453             :                                     SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
    2454             :             {
    2455           0 :                 aLRSpace.SetTxtLeft( aLRSpace.GetLeft() + rNumFmt.GetAbsLSpace() );
    2456             : 
    2457             :                 // new first line indent = 0
    2458             :                 // (first line indent is ignored for NO_NUMLEVEL)
    2459           0 :                 if (!bParaRTL)
    2460           0 :                     aLRSpace.SetTxtFirstLineOfst( 0 );
    2461             : 
    2462             :                 // put back the new item
    2463           0 :                 pTmpSet->Put( aLRSpace );
    2464             :             }
    2465             : 
    2466             :             // assure that numbering rule is in <pTmpSet>
    2467           0 :             if (SFX_ITEM_SET != pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
    2468             :             {
    2469           0 :                 pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
    2470           0 :             }
    2471             :         }
    2472             : 
    2473             :         // #i75457#
    2474             :         // Export page break after attribute from paragraph style.
    2475             :         // If page break attribute at the text node exist, an existing page
    2476             :         // break after at the paragraph style hasn't got to be considered.
    2477       10718 :         if ( !rNode.GetpSwAttrSet() ||
    2478        4688 :              SFX_ITEM_SET != rNode.GetpSwAttrSet()->GetItemState(RES_BREAK, false) )
    2479             :         {
    2480             :             const SvxFmtBreakItem* pBreakAtParaStyle =
    2481        5932 :                 &(ItemGet<SvxFmtBreakItem>(rNode.GetSwAttrSet(), RES_BREAK));
    2482       11864 :             if ( pBreakAtParaStyle &&
    2483        5932 :                  pBreakAtParaStyle->GetBreak() == SVX_BREAK_PAGE_AFTER )
    2484             :             {
    2485           0 :                 if ( !pTmpSet )
    2486             :                 {
    2487           0 :                     pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
    2488             :                 }
    2489           0 :                 pTmpSet->Put( *pBreakAtParaStyle );
    2490             :             }
    2491        5932 :             else if( pTmpSet )
    2492             :             {   // Even a pagedesc item is set, the break item can be set 'NONE',
    2493             :                 // this has to be overruled.
    2494             :                 const SwFmtPageDesc& rPageDescAtParaStyle =
    2495         546 :                     ItemGet<SwFmtPageDesc>( rNode, RES_PAGEDESC );
    2496         546 :                 if( rPageDescAtParaStyle.KnowsPageDesc() )
    2497          40 :                     pTmpSet->ClearItem( RES_BREAK );
    2498             :             }
    2499             :         }
    2500             : 
    2501             :         // #i76520# Emulate non-splitting tables
    2502        6030 :         if ( bOutTable )
    2503             :         {
    2504           0 :             const SwTableNode* pTableNode = rNode.FindTableNode();
    2505             : 
    2506           0 :             if ( pTableNode )
    2507             :             {
    2508           0 :                 const SwTable& rTable = pTableNode->GetTable();
    2509           0 :                 const SvxFmtKeepItem& rKeep = rTable.GetFrmFmt()->GetKeep();
    2510           0 :                 const bool bKeep = rKeep.GetValue();
    2511           0 :                 const bool bDontSplit = !bKeep ?
    2512           0 :                                         !rTable.GetFrmFmt()->GetLayoutSplit().GetValue() :
    2513           0 :                                         false;
    2514             : 
    2515           0 :                 if ( bKeep || bDontSplit )
    2516             :                 {
    2517             :                     // bKeep: set keep at first paragraphs in all lines
    2518             :                     // bDontSplit : set keep at first paragraphs in all lines except from last line
    2519             :                     // but only for non-complex tables
    2520           0 :                     const SwTableBox* pBox = rNode.GetTblBox();
    2521           0 :                     const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0;
    2522             : 
    2523           0 :                     if ( pLine && !pLine->GetUpper() )
    2524             :                     {
    2525             :                         // check if box is first in that line:
    2526           0 :                         if ( 0 == pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() )
    2527             :                         {
    2528             :                             // check if paragraph is first in that line:
    2529           0 :                             if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
    2530             :                             {
    2531           0 :                                 bool bSetAtPara = false;
    2532           0 :                                 if ( bKeep )
    2533           0 :                                     bSetAtPara = true;
    2534           0 :                                 else if ( bDontSplit )
    2535             :                                 {
    2536             :                                     // check if pLine isn't last line in table
    2537           0 :                                     if ( rTable.GetTabLines().size() - rTable.GetTabLines().GetPos( pLine ) != 1 )
    2538           0 :                                         bSetAtPara = true;
    2539             :                                 }
    2540             : 
    2541           0 :                                 if ( bSetAtPara )
    2542             :                                 {
    2543           0 :                                     if ( !pTmpSet )
    2544           0 :                                         pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
    2545             : 
    2546           0 :                                     const SvxFmtKeepItem aKeepItem( true, RES_KEEP );
    2547           0 :                                     pTmpSet->Put( aKeepItem );
    2548             :                                 }
    2549             :                             }
    2550             :                         }
    2551             :                     }
    2552             :                 }
    2553             :             }
    2554             :         }
    2555             : 
    2556        6030 :         const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet();
    2557        6030 :         if( pNewSet )
    2558             :         {                                               // Para-Attrs
    2559        4721 :             pStyAttr = &rNode.GetAnyFmtColl().GetAttrSet();
    2560             : 
    2561        4721 :             const SwModify* pOldMod = pOutFmtNode;
    2562        4721 :             pOutFmtNode = &rNode;
    2563             : 
    2564             :             // Pap-Attrs, so script is not necessary
    2565        4721 :             OutputItemSet( *pNewSet, true, false, i18n::ScriptType::LATIN, false);
    2566             : 
    2567        4721 :             pStyAttr = 0;
    2568        4721 :             pOutFmtNode = pOldMod;
    2569             : 
    2570        4721 :             if( pNewSet != rNode.GetpSwAttrSet() )
    2571         565 :                 delete pNewSet;
    2572             :         }
    2573             :     }
    2574             : 
    2575        6034 :     const SfxItemSet* sfxItemSet = NULL;
    2576        6034 :     if(const SwpHints* pTxtAttrs = rNode.GetpSwpHints())
    2577             :     {
    2578        9111 :         for( sal_uInt16 i = 0; i < pTxtAttrs->Count(); i++ )
    2579             :         {
    2580        6179 :             const SwTxtAttr* pHt = (*pTxtAttrs)[i];
    2581        6179 :             const sal_Int32* startPos = pHt->GetStart();    // first Attr characters
    2582        6179 :             const sal_Int32* endPos = pHt->End();    // end Attr characters
    2583             :             // Check if these attributes are for the last character in the paragraph
    2584             :             // - which means the paragraph marker. If a paragraph has 7 characters,
    2585             :             // then properties on character 8 are for the paragraph marker
    2586        6179 :             if( (startPos && endPos) && (*startPos == *endPos ) && (*endPos == rNode.GetTxt().getLength()) )
    2587             :             {
    2588             :                 SAL_INFO( "sw.ww8", *startPos << "startPos == endPos" << *endPos);
    2589        2296 :                 sal_uInt16 nWhich = pHt->GetAttr().Which();
    2590             :                 SAL_INFO( "sw.ww8", "nWhich" << nWhich);
    2591        2296 :                 if (nWhich == RES_TXTATR_AUTOFMT)
    2592             :                 {
    2593        2273 :                     const SwFmtAutoFmt& rAutoFmt = static_cast<const SwFmtAutoFmt&>(pHt->GetAttr());
    2594        2273 :                     sfxItemSet = rAutoFmt.GetStyleHandle().get();
    2595             :                 }
    2596             :             }
    2597             :         }
    2598             :     }
    2599             :     else
    2600             :     {
    2601        3102 :         sfxItemSet = rNode.GetpSwAttrSet();
    2602             :     }
    2603        6034 :     const SwRedlineData* pRedlineParagraphMarkerDelete = AttrOutput().GetParagraphMarkerRedline( rNode, nsRedlineType_t::REDLINE_DELETE );
    2604        6034 :     const SwRedlineData* pRedlineParagraphMarkerInsert = AttrOutput().GetParagraphMarkerRedline( rNode, nsRedlineType_t::REDLINE_INSERT );
    2605        6034 :     const SwRedlineData* pParagraphRedlineData = aAttrIter.GetParagraphLevelRedline( );
    2606        6034 :     AttrOutput().EndParagraphProperties( sfxItemSet, pParagraphRedlineData, pRedlineParagraphMarkerDelete, pRedlineParagraphMarkerInsert);
    2607             : 
    2608        6034 :     AttrOutput().EndParagraph( pTextNodeInfoInner );
    2609             : 
    2610        6034 :     SAL_INFO( "sw.ww8", "</OutWW8_SwTxtNode>" );
    2611             : }
    2612             : 
    2613           0 : void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )
    2614             : {
    2615             :     SVBT16 nSty;
    2616           0 :     ShortToSVBT16( GetExport().nStyleBeforeFly, nSty );
    2617             : 
    2618           0 :     ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt( pNodeInfo->getInners().begin() );
    2619           0 :     ww8::WW8TableNodeInfo::Inners_t::const_iterator aItEnd( pNodeInfo->getInners().end() );
    2620             : 
    2621           0 :     while (aIt != aItEnd)
    2622             :     {
    2623           0 :         ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
    2624           0 :         if ( pInner->isEndOfCell() )
    2625             :         {
    2626           0 :             TableRowEnd( pInner->getDepth() );
    2627             : 
    2628           0 :             m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), (sal_uInt8*)&nSty, (sal_uInt8*)&nSty+2);     // Style #
    2629           0 :             TableInfoRow( pInner );
    2630           0 :             m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data());
    2631           0 :             m_rWW8Export.pO->clear();
    2632             :         }
    2633             : 
    2634           0 :         if ( pInner->isEndOfLine() )
    2635             :         {
    2636             :         }
    2637             : 
    2638           0 :         ++aIt;
    2639           0 :     }
    2640           0 : }
    2641             : 
    2642             : // Tables
    2643             : 
    2644           0 : void WW8AttributeOutput::EmptyParagraph()
    2645             : {
    2646           0 :     m_rWW8Export.WriteStringAsPara( OUString() );
    2647           0 : }
    2648             : 
    2649           9 : bool MSWordExportBase::NoPageBreakSection( const SfxItemSet* pSet )
    2650             : {
    2651           9 :     bool bRet = false;
    2652             :     const SfxPoolItem* pI;
    2653           9 :     if( pSet)
    2654             :     {
    2655           9 :         bool bNoPageBreak = true;
    2656          18 :         if ( SFX_ITEM_ON != pSet->GetItemState(RES_PAGEDESC, true, &pI)
    2657           9 :             || 0 == ((SwFmtPageDesc*)pI)->GetPageDesc() )
    2658             :         {
    2659           2 :             if (SFX_ITEM_ON != pSet->GetItemState(RES_BREAK, true, &pI))
    2660           2 :                 bNoPageBreak = true;
    2661             :             else
    2662             :             {
    2663           0 :                 SvxBreak eBreak = ((const SvxFmtBreakItem*)pI)->GetBreak();
    2664           0 :                 switch (eBreak)
    2665             :                 {
    2666             :                     case SVX_BREAK_PAGE_BEFORE:
    2667             :                     case SVX_BREAK_PAGE_AFTER:
    2668           0 :                         bNoPageBreak = false;
    2669           0 :                         break;
    2670             :                     default:
    2671           0 :                         break;
    2672             :                 }
    2673             :             }
    2674             :         }
    2675           9 :         bRet = bNoPageBreak;
    2676             :     }
    2677           9 :     return bRet;
    2678             : }
    2679             : 
    2680          34 : void MSWordExportBase::OutputSectionNode( const SwSectionNode& rSectionNode )
    2681             : {
    2682          34 :     const SwSection& rSection = rSectionNode.GetSection();
    2683             : 
    2684          34 :     SwNodeIndex aIdx( rSectionNode, 1 );
    2685          34 :     const SwNode& rNd = aIdx.GetNode();
    2686         101 :     if ( !rNd.IsSectionNode() && !IsInTable()
    2687          67 :         && rSection.GetType() != TOX_CONTENT_SECTION && rSection.GetType() != TOX_HEADER_SECTION) //No sections in table
    2688             :     {
    2689             :         // if the first Node inside the section has an own
    2690             :         // PageDesc or PageBreak attribut, then dont write
    2691             :         // here the section break
    2692           9 :         sal_uLong nRstLnNum = 0;
    2693             :         const SfxItemSet* pSet;
    2694           9 :         if ( rNd.IsTableNode() )
    2695           0 :             pSet = &rNd.GetTableNode()->GetTable().GetFrmFmt()->GetAttrSet();
    2696           9 :         else if ( rNd.IsCntntNode() )
    2697             :         {
    2698           9 :             pSet = &rNd.GetCntntNode()->GetSwAttrSet();
    2699             :             nRstLnNum = ((SwFmtLineNumber&)pSet->Get(
    2700           9 :                             RES_LINENUMBER )).GetStartValue();
    2701             :         }
    2702             :         else
    2703           0 :             pSet = 0;
    2704             : 
    2705           9 :         if ( pSet && NoPageBreakSection( pSet ) )
    2706           9 :             pSet = 0;
    2707             : 
    2708           9 :         if ( !pSet )
    2709             :         {
    2710             :             // new Section with no own PageDesc/-Break
    2711             :             //  -> write follow section break;
    2712           9 :             const SwSectionFmt& rFmt = *rSection.GetFmt();
    2713           9 :             ReplaceCr( msword::PageBreak ); // Indikator fuer Page/Section-Break
    2714             : 
    2715             :             // Get the page in use at the top of this section
    2716           9 :             SwNodeIndex aIdxTmp(rSectionNode, 1);
    2717             :             const SwPageDesc *pCurrent =
    2718           9 :                 SwPageDesc::GetPageDescOfNode(aIdxTmp.GetNode());
    2719           9 :             if (!pCurrent)
    2720           0 :                 pCurrent = pAktPageDesc;
    2721             : 
    2722           9 :             AppendSection( pCurrent, &rFmt, nRstLnNum );
    2723             :         }
    2724             :     }
    2725          34 :     if ( TOX_CONTENT_SECTION == rSection.GetType() )
    2726          24 :         bStartTOX = true;
    2727          34 : }
    2728             : 
    2729           0 : void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
    2730             : {
    2731           0 :     pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFmt, nLnNum);
    2732           0 : }
    2733             : 
    2734             : // Flys
    2735             : 
    2736           0 : void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode& rNd )
    2737             : {
    2738             :     OSL_ENSURE(!bWrtWW8, "I shouldn't be needed for Word >=8");
    2739           0 :     if ( bWrtWW8 )
    2740           0 :         return;
    2741             : 
    2742           0 :     if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
    2743             :     {
    2744           0 :         for( sal_uInt16 n=0; n < pTxtAttrs->Count(); ++n )
    2745             :         {
    2746           0 :             const SwTxtAttr* pAttr = (*pTxtAttrs)[ n ];
    2747           0 :             if( RES_TXTATR_FLYCNT == pAttr->Which() )
    2748             :             {
    2749             :                 // attribute bound to a character
    2750           0 :                 const SwFmtFlyCnt& rFlyCntnt = pAttr->GetFlyCnt();
    2751           0 :                 const SwFlyFrmFmt& rFlyFrmFmt = *(SwFlyFrmFmt*)rFlyCntnt.GetFrmFmt();
    2752           0 :                 const SwNodeIndex* pNodeIndex = rFlyFrmFmt.GetCntnt().GetCntntIdx();
    2753             : 
    2754           0 :                 if( pNodeIndex )
    2755             :                 {
    2756           0 :                     sal_uLong nStt = pNodeIndex->GetIndex()+1,
    2757           0 :                           nEnd = pNodeIndex->GetNode().EndOfSectionIndex();
    2758             : 
    2759           0 :                     if( (nStt < nEnd) && !pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
    2760             :                     {
    2761           0 :                         Point aOffset;
    2762             :                         // get rectangle (bounding box?) of Fly and paragraph
    2763           0 :                         SwRect aParentRect(rNd.FindLayoutRect(false, &aOffset)),
    2764           0 :                                aFlyRect(rFlyFrmFmt.FindLayoutRect(false, &aOffset ) );
    2765             : 
    2766           0 :                         aOffset = aFlyRect.Pos() - aParentRect.Pos();
    2767             : 
    2768             :                         // let PaM point to content of Fly-frame format
    2769           0 :                         SaveData( nStt, nEnd );
    2770             : 
    2771             :                         // is analysed in OutputFormat()
    2772           0 :                         pFlyOffset = &aOffset;
    2773           0 :                         eNewAnchorType = rFlyFrmFmt.GetAnchor().GetAnchorId();
    2774           0 :                         sw::Frame aFrm(rFlyFrmFmt, SwPosition(rNd));
    2775           0 :                         mpParentFrame = &aFrm;
    2776             :                         // Ok, write it out:
    2777           0 :                         WriteText();
    2778             : 
    2779           0 :                         RestoreData();
    2780             :                     }
    2781             :                 }
    2782             :             }
    2783             :         }
    2784             :     }
    2785             : }
    2786             : 
    2787          10 : void WW8AttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft )
    2788             : {
    2789          10 :     const SwFrmFmt &rFrmFmt = rFmt.GetFrmFmt();
    2790          10 :     const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor();
    2791             : 
    2792          10 :     bool bUseEscher = m_rWW8Export.bWrtWW8;
    2793             : 
    2794          10 :     if ( m_rWW8Export.bWrtWW8 && rFmt.IsInline() )
    2795             :     {
    2796           1 :         sw::Frame::WriterSource eType = rFmt.GetWriterType();
    2797           1 :         if ((eType == sw::Frame::eGraphic) || (eType == sw::Frame::eOle))
    2798           1 :             bUseEscher = false;
    2799             :         else
    2800           0 :             bUseEscher = true;
    2801             : 
    2802             :         /*
    2803             :          A special case for converting some inline form controls to form fields
    2804             :          when in winword 8+ mode
    2805             :         */
    2806           1 :         if ((bUseEscher == true) && (eType == sw::Frame::eFormControl))
    2807             :         {
    2808           0 :             if ( m_rWW8Export.MiserableFormFieldExportHack( rFrmFmt ) )
    2809           0 :                 return ;
    2810             :         }
    2811             :     }
    2812             : 
    2813          10 :     if (bUseEscher)
    2814             :     {
    2815             :         OSL_ENSURE( m_rWW8Export.bWrtWW8, "this has gone horribly wrong" );
    2816             :         // write as escher
    2817           9 :         m_rWW8Export.AppendFlyInFlys(rFmt, rNdTopLeft);
    2818             :     }
    2819             :     else
    2820             :     {
    2821           1 :         bool bDone = false;
    2822             : 
    2823             :         // Hole vom Node und vom letzten Node die Position in der Section
    2824           1 :         const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
    2825             : 
    2826           1 :         sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1                  : 0;
    2827           1 :         sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
    2828             : 
    2829           1 :         if( nStt >= nEnd )      // no range, hence no valid node
    2830           0 :             return;
    2831             : 
    2832           1 :         if ( !m_rWW8Export.IsInTable() && rFmt.IsInline() )
    2833             :         {
    2834             :             //Test to see if this textbox contains only a single graphic/ole
    2835           1 :             SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
    2836           1 :             if ( pParTxtNode && !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
    2837           0 :                 bDone = true;
    2838             :         }
    2839           1 :         if( !bDone )
    2840             :         {
    2841             : 
    2842           1 :             m_rWW8Export.SaveData( nStt, nEnd );
    2843             : 
    2844           1 :             Point aOffset;
    2845           1 :             if ( m_rWW8Export.mpParentFrame )
    2846             :             {
    2847             :                 /* Munge flys in fly into absolutely positioned elements for word 6 */
    2848           0 :                 const SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
    2849           0 :                 const SwRect aPageRect = pParTxtNode->FindPageFrmRect( sal_False, 0, sal_False );
    2850             : 
    2851           0 :                 aOffset = rFrmFmt.FindLayoutRect().Pos();
    2852           0 :                 aOffset -= aPageRect.Pos();
    2853             : 
    2854           0 :                 m_rWW8Export.pFlyOffset = &aOffset;
    2855           0 :                 m_rWW8Export.eNewAnchorType = FLY_AT_PAGE;
    2856             :             }
    2857             : 
    2858           1 :             m_rWW8Export.mpParentFrame = &rFmt;
    2859           1 :             if (
    2860           1 :                 m_rWW8Export.IsInTable() &&
    2861           1 :                  (FLY_AT_PAGE != rAnch.GetAnchorId()) &&
    2862           0 :                  !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode()
    2863             :                )
    2864             :             {
    2865             :                 // note: set Flag  bOutTable again,
    2866             :                 // because we deliver the normal content of the table cell, and no border
    2867             :                 // ( Flag was deleted above in aSaveData() )
    2868           0 :                 m_rWW8Export.bOutTable = true;
    2869           0 :                 const OUString aName = rFrmFmt.GetName();
    2870           0 :                 m_rWW8Export.StartCommentOutput(aName);
    2871           0 :                 m_rWW8Export.WriteText();
    2872           0 :                 m_rWW8Export.EndCommentOutput(aName);
    2873             :             }
    2874             :             else
    2875           1 :                 m_rWW8Export.WriteText();
    2876             : 
    2877           1 :             m_rWW8Export.RestoreData();
    2878             :         }
    2879             :     }
    2880             : }
    2881             : 
    2882         259 : void AttributeOutputBase::OutputFlyFrame( const sw::Frame& rFmt )
    2883             : {
    2884         259 :     if ( !rFmt.GetCntntNode() )
    2885         259 :         return;
    2886             : 
    2887         259 :     const SwCntntNode &rNode = *rFmt.GetCntntNode();
    2888         259 :     Point aNdPos, aPgPos;
    2889             :     Point* pLayPos;
    2890         259 :     bool bValidNdPos = false, bValidPgPos = false;
    2891             : 
    2892         259 :     if (FLY_AT_PAGE == rFmt.GetFrmFmt().GetAnchor().GetAnchorId())
    2893             :     {
    2894             :         // get the Layout Node-Position.
    2895           0 :         if ( !bValidPgPos )
    2896             :         {
    2897           0 :             aPgPos = rNode.FindPageFrmRect(false, &aPgPos).Pos();
    2898           0 :             bValidPgPos = true;
    2899             :         }
    2900           0 :         pLayPos = &aPgPos;
    2901             :     }
    2902             :     else
    2903             :     {
    2904             :         // get the Layout Node-Position.
    2905         259 :         if ( !bValidNdPos )
    2906             :         {
    2907         259 :             aNdPos = rNode.FindLayoutRect(false, &aNdPos).Pos();
    2908         259 :             bValidNdPos = true;
    2909             :         }
    2910         259 :         pLayPos = &aNdPos;
    2911             :     }
    2912             : 
    2913         259 :     OutputFlyFrame_Impl( rFmt, *pLayPos );
    2914             : }
    2915             : 
    2916             : // write data of any redline
    2917         371 : void WW8AttributeOutput::Redline( const SwRedlineData* pRedline )
    2918             : {
    2919         371 :     if ( !pRedline )
    2920         742 :         return;
    2921             : 
    2922           0 :     if ( pRedline->Next() )
    2923           0 :         Redline( pRedline->Next() );
    2924             : 
    2925             :     static const sal_uInt16 aSprmIds[ 2 * 2 * 3 ] =
    2926             :     {
    2927             :         // Ids for insert
    2928             :             NS_sprm::LN_CFRMark, NS_sprm::LN_CIbstRMark, NS_sprm::LN_CDttmRMark,         // for WW8
    2929             :             0x0042, 0x0045, 0x0046,         // for WW6
    2930             :         // Ids for delete
    2931             :             NS_sprm::LN_CFRMarkDel, NS_sprm::LN_CIbstRMarkDel, NS_sprm::LN_CDttmRMarkDel,         // for WW8
    2932             :             0x0041, 0x0045, 0x0046          // for WW6
    2933             :     };
    2934             : 
    2935           0 :     const sal_uInt16* pSprmIds = 0;
    2936           0 :     switch( pRedline->GetType() )
    2937             :     {
    2938             :     case nsRedlineType_t::REDLINE_INSERT:
    2939           0 :         pSprmIds = aSprmIds;
    2940           0 :         break;
    2941             : 
    2942             :     case nsRedlineType_t::REDLINE_DELETE:
    2943           0 :         pSprmIds = aSprmIds + (2 * 3);
    2944           0 :         break;
    2945             : 
    2946             :     case nsRedlineType_t::REDLINE_FORMAT:
    2947           0 :         if( m_rWW8Export.bWrtWW8 )
    2948             :         {
    2949           0 :             m_rWW8Export.InsUInt16( NS_sprm::LN_CPropRMark );
    2950           0 :             m_rWW8Export.pO->push_back( 7 );       // len
    2951           0 :             m_rWW8Export.pO->push_back( 1 );
    2952           0 :             m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) );
    2953           0 :             m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
    2954             :         }
    2955           0 :         break;
    2956             :     default:
    2957             :         OSL_ENSURE(!this, "Unhandled redline type for export");
    2958           0 :         break;
    2959             :     }
    2960             : 
    2961           0 :     if ( pSprmIds )
    2962             :     {
    2963           0 :         if ( !m_rWW8Export.bWrtWW8 )
    2964           0 :             pSprmIds += 3;
    2965             : 
    2966           0 :         if ( m_rWW8Export.bWrtWW8 )
    2967           0 :             m_rWW8Export.InsUInt16( pSprmIds[0] );
    2968             :         else
    2969           0 :             m_rWW8Export.pO->push_back( msword_cast<sal_uInt8>(pSprmIds[0]) );
    2970           0 :         m_rWW8Export.pO->push_back( 1 );
    2971             : 
    2972           0 :         if ( m_rWW8Export.bWrtWW8 )
    2973           0 :             m_rWW8Export.InsUInt16( pSprmIds[1] );
    2974             :         else
    2975           0 :             m_rWW8Export.pO->push_back( msword_cast<sal_uInt8>(pSprmIds[1]) );
    2976           0 :         m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) );
    2977             : 
    2978           0 :         if ( m_rWW8Export.bWrtWW8 )
    2979           0 :             m_rWW8Export.InsUInt16( pSprmIds[2] );
    2980             :         else
    2981           0 :             m_rWW8Export.pO->push_back( msword_cast<sal_uInt8>(pSprmIds[2]) );
    2982           0 :         m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
    2983             :     }
    2984             : }
    2985             : 
    2986        6037 : void MSWordExportBase::OutputContentNode( const SwCntntNode& rNode )
    2987             : {
    2988        6037 :     switch ( rNode.GetNodeType() )
    2989             :     {
    2990             :         case ND_TEXTNODE:
    2991             :         {
    2992        6036 :             const SwTxtNode& rTextNode = *rNode.GetTxtNode();
    2993        6036 :             if( !mbOutOutlineOnly || rTextNode.IsOutline() )
    2994        6036 :                 OutputTextNode( rTextNode );
    2995             :         }
    2996        6036 :         break;
    2997             :         case ND_GRFNODE:
    2998           1 :             OutputGrfNode( *rNode.GetGrfNode() );
    2999           1 :             break;
    3000             :         case ND_OLENODE:
    3001           0 :             OutputOLENode( *rNode.GetOLENode() );
    3002           0 :             break;
    3003             :         default:
    3004             :             OSL_TRACE("Unhandled node, type == %d", rNode.GetNodeType() );
    3005           0 :             break;
    3006             :     }
    3007        6070 : }
    3008             : 
    3009             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10