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

Generated by: LCOV version 1.11