1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
55 #include <txatbase.hxx>
56 #include <fmtinfmt.hxx>
57 #include <fmtrfmrk.hxx>
58 #include <fchrfmt.hxx>
59 #include <fmtautofmt.hxx>
60 #include <charfmt.hxx>
66 #include <swtable.hxx>
67 #include <swtblfmt.hxx>
68 #include <section.hxx>
69 #include <pagedesc.hxx>
72 #include <redline.hxx>
73 #include <wrtswtbl.hxx>
74 #include <htmltbl.hxx>
75 #include <txttxmrk.hxx>
76 #include <fmtline.hxx>
77 #include <fmtruby.hxx>
78 #include <breakit.hxx>
80 #include <fmtsrnd.hxx>
81 #include <fmtrowsplt.hxx>
82 #include <com/sun/star/i18n/ScriptType.hpp>
83 #include <com/sun/star/i18n/WordType.hpp>
85 #include <doctok/sprmids.hxx>
87 #include "writerhelper.hxx"
88 #include "writerwordglue.hxx"
89 #include <numrule.hxx>
93 #include "ww8attributeoutput.hxx"
100 using namespace ::com::sun::star
;
101 using namespace ::com::sun::star::i18n
;
102 using namespace sw::util
;
103 using namespace sw::types
;
104 using namespace sw::mark
;
105 using namespace nsFieldFlags
;
107 static String
lcl_getFieldCode( const IFieldmark
* pFieldmark
) {
108 OSL_ENSURE(pFieldmark
!=NULL
, "where is my fieldmark???");
112 } else if ( pFieldmark
->GetFieldname( ) == ODF_FORMTEXT
) {
113 return OUString(" FORMTEXT ");
114 } else if ( pFieldmark
->GetFieldname( ) == ODF_FORMDROPDOWN
) {
115 return OUString(" FORMDROPDOWN ");
116 } else if ( pFieldmark
->GetFieldname( ) == ODF_FORMCHECKBOX
) {
117 return OUString(" FORMCHECKBOX ");
118 } else if ( pFieldmark
->GetFieldname( ) == ODF_TOC
) {
119 return OUString(" TOC ");
120 } else if ( pFieldmark
->GetFieldname( ) == ODF_HYPERLINK
) {
121 return OUString(" HYPERLINK ");
122 } else if ( pFieldmark
->GetFieldname( ) == ODF_PAGEREF
) {
123 return OUString(" PAGEREF ");
125 return pFieldmark
->GetFieldname();
129 static ww::eField
lcl_getFieldId( const IFieldmark
* pFieldmark
) {
130 OSL_ENSURE(pFieldmark
!=NULL
, "where is my fieldmark???");
133 } else if ( pFieldmark
->GetFieldname( ) == ODF_FORMTEXT
) {
134 return ww::eFORMTEXT
;
135 } else if ( pFieldmark
->GetFieldname( ) == ODF_FORMDROPDOWN
) {
136 return ww::eFORMDROPDOWN
;
137 } else if ( pFieldmark
->GetFieldname( ) == ODF_FORMCHECKBOX
) {
138 return ww::eFORMCHECKBOX
;
139 } else if ( pFieldmark
->GetFieldname( ) == ODF_TOC
) {
141 } else if ( pFieldmark
->GetFieldname( ) == ODF_HYPERLINK
) {
142 return ww::eHYPERLINK
;
143 } else if ( pFieldmark
->GetFieldname( ) == ODF_PAGEREF
) {
150 MSWordAttrIter::MSWordAttrIter( MSWordExportBase
& rExport
)
151 : pOld( rExport
.pChpIter
), m_rExport( rExport
)
153 m_rExport
.pChpIter
= this;
156 MSWordAttrIter::~MSWordAttrIter()
158 m_rExport
.pChpIter
= pOld
;
162 public std::binary_function
<const sw::Frame
&, const sw::Frame
&, bool>
165 bool operator()(const sw::Frame
&rOne
, const sw::Frame
&rTwo
) const
167 return rOne
.GetPosition() < rTwo
.GetPosition();
171 void SwWW8AttrIter::IterToCurrent()
173 OSL_ENSURE(maCharRuns
.begin() != maCharRuns
.end(), "Impossible");
174 mnScript
= maCharRunIter
->mnScript
;
175 meChrSet
= maCharRunIter
->meCharSet
;
176 mbCharIsRTL
= maCharRunIter
->mbRTL
;
179 SwWW8AttrIter::SwWW8AttrIter(MSWordExportBase
& rWr
, const SwTxtNode
& rTxtNd
) :
182 maCharRuns(GetPseudoCharRuns(rTxtNd
, 0, !rWr
.SupportsUnicode())),
185 nCurRedlinePos(USHRT_MAX
),
186 mrSwFmtDrop(rTxtNd
.GetSwAttrSet().GetDrop())
189 SwPosition
aPos(rTxtNd
);
190 if (FRMDIR_HORI_RIGHT_TOP
== rWr
.pDoc
->GetTextDirection(aPos
))
195 maCharRunIter
= maCharRuns
.begin();
200 Get list of any graphics which may be anchored from this paragraph.
202 maFlyFrms
= GetFramesInNode(rWr
.maFrames
, rNd
);
203 std::sort(maFlyFrms
.begin(), maFlyFrms
.end(), sortswflys());
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.
211 if (rWr
.SupportsUnicode() && rWr
.bInWriteEscher
)
213 std::for_each(maFlyFrms
.begin(), maFlyFrms
.end(),
214 std::mem_fun_ref(&sw::Frame::ForceTreatAsInline
));
217 maFlyIter
= maFlyFrms
.begin();
219 if ( !m_rExport
.pDoc
->GetRedlineTbl().empty() )
221 SwPosition
aPosition( rNd
, SwIndex( (SwTxtNode
*)&rNd
) );
222 pCurRedline
= m_rExport
.pDoc
->GetRedline( aPosition
, &nCurRedlinePos
);
225 nAktSwPos
= SearchNext(1);
228 xub_StrLen
lcl_getMinPos( xub_StrLen pos1
, xub_StrLen pos2
)
230 xub_StrLen min
= STRING_NOTFOUND
;
231 if ( pos1
== STRING_NOTFOUND
&& pos2
!= STRING_NOTFOUND
)
233 else if ( pos2
== STRING_NOTFOUND
&& pos1
!= STRING_NOTFOUND
)
235 else if ( pos1
!= STRING_NOTFOUND
&& pos2
!= STRING_NOTFOUND
)
246 xub_StrLen
SwWW8AttrIter::SearchNext( xub_StrLen nStartPos
)
249 xub_StrLen nMinPos
= STRING_MAXLEN
;
252 const String aTxt
= rNd
.GetTxt();
253 xub_StrLen fieldEndPos
= aTxt
.Search(CH_TXT_ATR_FIELDEND
, nStartPos
);
254 xub_StrLen fieldStartPos
= aTxt
.Search(CH_TXT_ATR_FIELDSTART
, nStartPos
);
255 xub_StrLen formElementPos
= aTxt
.Search(CH_TXT_ATR_FORMELEMENT
, nStartPos
);
257 xub_StrLen pos
= lcl_getMinPos( fieldEndPos
, fieldStartPos
);
258 pos
= lcl_getMinPos( pos
, formElementPos
);
260 if (pos
!=STRING_NOTFOUND
)
263 // first the redline, then the attributes
266 const SwPosition
* pEnd
= pCurRedline
->End();
267 if (pEnd
->nNode
== rNd
&& ((i
= pEnd
->nContent
.GetIndex()) >= nStartPos
) && i
< nMinPos
)
271 if ( nCurRedlinePos
< m_rExport
.pDoc
->GetRedlineTbl().size() )
273 // nCurRedlinePos point to the next redline
274 nPos
= nCurRedlinePos
;
278 for ( ; nPos
< m_rExport
.pDoc
->GetRedlineTbl().size(); ++nPos
)
280 const SwRedline
* pRedl
= m_rExport
.pDoc
->GetRedlineTbl()[ nPos
];
282 const SwPosition
* pStt
= pRedl
->Start();
283 const SwPosition
* pEnd
= pStt
== pRedl
->GetPoint()
287 if( pStt
->nNode
== rNd
)
289 if( ( i
= pStt
->nContent
.GetIndex() ) >= nStartPos
&&
296 if( pEnd
->nNode
== rNd
&&
297 ( i
= pEnd
->nContent
.GetIndex() ) < nMinPos
&&
304 if (mrSwFmtDrop
.GetWholeWord() && nStartPos
<= rNd
.GetDropLen(0))
305 nMinPos
= rNd
.GetDropLen(0);
306 else if(nStartPos
<= mrSwFmtDrop
.GetChars())
307 nMinPos
= mrSwFmtDrop
.GetChars();
309 if(const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
312 // can be optimized if we consider that the TxtAttrs are sorted by start position.
313 // but then we'd have to save 2 indices
314 for( i
= 0; i
< pTxtAttrs
->Count(); i
++ )
316 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
317 nPos
= *pHt
->GetStart(); // first Attr characters
318 if( nPos
>= nStartPos
&& nPos
<= nMinPos
)
321 if( pHt
->GetEnd() ) // Attr with end
323 nPos
= *pHt
->GetEnd(); // last Attr character + 1
324 if( nPos
>= nStartPos
&& nPos
<= nMinPos
)
327 if (pHt
->HasDummyChar())
329 // pos + 1 because of CH_TXTATR in Text
330 nPos
= *pHt
->GetStart() + 1;
331 if( nPos
>= nStartPos
&& nPos
<= nMinPos
)
337 if (maCharRunIter
!= maCharRuns
.end())
339 if (maCharRunIter
->mnEndPos
< nMinPos
)
340 nMinPos
= maCharRunIter
->mnEndPos
;
346 Check to see if there are any graphics anchored to characters in this
347 paragraph's text. Set nMinPos to 1 past the placement for anchored to
348 character because anchors in Word appear after the character they are
351 if (maFlyIter
!= maFlyFrms
.end())
353 const SwPosition
&rAnchor
= maFlyIter
->GetPosition();
355 nPos
= rAnchor
.nContent
.GetIndex();
356 if (nPos
>= nStartPos
&& nPos
<= nMinPos
)
359 if (maFlyIter
->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR
)
362 if (nPos
>= nStartPos
&& nPos
<= nMinPos
)
367 //nMinPos found and not going to change at this point
369 if (maCharRunIter
!= maCharRuns
.end())
371 if (maCharRunIter
->mnEndPos
== nMinPos
)
378 static bool lcl_isFontsizeItem( const SfxPoolItem
& rItem
)
380 return ( rItem
.Which( ) == RES_CHRATR_FONTSIZE
||
381 rItem
.Which( ) == RES_CHRATR_CJK_FONTSIZE
||
382 rItem
.Which( ) == RES_CHRATR_CTL_FONTSIZE
);
385 void SwWW8AttrIter::OutAttr( xub_StrLen nSwPos
, bool bRuby
)
387 m_rExport
.AttrOutput().RTLAndCJKState( IsCharRTL(), GetScript() );
390 Depending on whether text is in CTL/CJK or Western, get the id of that
391 script, the idea is that the font that is actually in use to render this
392 range of text ends up in pFont
394 sal_uInt16 nFontId
= GetWhichOfScript( RES_CHRATR_FONT
, GetScript() );
396 const SvxFontItem
&rParentFont
= ItemGet
<SvxFontItem
>(
397 (const SwTxtFmtColl
&)rNd
.GetAnyFmtColl(), nFontId
);
398 const SvxFontItem
*pFont
= &rParentFont
;
400 SfxItemSet
aExportSet(*rNd
.GetSwAttrSet().GetPool(),
401 RES_CHRATR_BEGIN
, RES_TXTATR_END
- 1);
403 //The hard formatting properties that affect the entire paragraph
404 if (rNd
.HasSwAttrSet())
406 sal_Bool bDeep
= sal_False
;
407 // only copy hard attributes - bDeep = false
408 aExportSet
.Set(rNd
.GetSwAttrSet(), bDeep
);
409 // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
410 const SvxFontItem
&rNdFont
= ItemGet
<SvxFontItem
>(rNd
.GetSwAttrSet(), nFontId
);
412 aExportSet
.ClearItem(nFontId
);
415 //The additional hard formatting properties that affect this range in the
417 sw::PoolItems aRangeItems
;
418 if (const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
420 for (xub_StrLen i
= 0; i
< pTxtAttrs
->Count(); ++i
)
422 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
423 const xub_StrLen
* pEnd
= pHt
->GetEnd();
425 if (pEnd
? ( nSwPos
>= *pHt
->GetStart() && nSwPos
< *pEnd
)
426 : nSwPos
== *pHt
->GetStart() )
428 sal_uInt16 nWhich
= pHt
->GetAttr().Which();
429 if (nWhich
== RES_TXTATR_AUTOFMT
)
431 const SwFmtAutoFmt
& rAutoFmt
= static_cast<const SwFmtAutoFmt
&>(pHt
->GetAttr());
432 const boost::shared_ptr
<SfxItemSet
> pSet
= rAutoFmt
.GetStyleHandle();
433 SfxWhichIter
aIter( *pSet
);
434 const SfxPoolItem
* pItem
;
435 sal_uInt16 nWhichId
= aIter
.FirstWhich();
438 if( SFX_ITEM_SET
== pSet
->GetItemState( nWhichId
, sal_False
, &pItem
))
440 if (nWhichId
== nFontId
)
441 pFont
= &(item_cast
<SvxFontItem
>(*pItem
));
443 aRangeItems
[nWhichId
] = pItem
;
445 nWhichId
= aIter
.NextWhich();
449 aRangeItems
[nWhich
] = (&(pHt
->GetAttr()));
451 else if (nSwPos
< *pHt
->GetStart())
457 For #i24291# we need to explictly remove any properties from the
458 aExportSet which a SwCharFmt would override, we can't rely on word doing
459 this for us like writer does
461 const SwFmtCharFmt
*pCharFmtItem
=
462 HasItem
< SwFmtCharFmt
>( aRangeItems
, RES_TXTATR_CHARFMT
);
464 ClearOverridesFromSet( *pCharFmtItem
, aExportSet
);
466 sw::PoolItems aExportItems
;
467 GetPoolItems( aExportSet
, aExportItems
, false );
469 sw::cPoolItemIter aEnd
= aRangeItems
.end();
470 for ( sw::cPoolItemIter aI
= aRangeItems
.begin(); aI
!= aEnd
; ++aI
)
472 if ( !bRuby
|| !lcl_isFontsizeItem( *aI
->second
) )
473 aExportItems
[aI
->first
] = aI
->second
;
476 if ( !aExportItems
.empty() )
478 const SwModify
* pOldMod
= m_rExport
.pOutFmtNode
;
479 m_rExport
.pOutFmtNode
= &rNd
;
480 m_rExport
.m_aCurrentCharPropStarts
.push( nSwPos
);
482 m_rExport
.ExportPoolItemsToCHP( aExportItems
, GetScript() );
484 // HasTextItem only allowed in the above range
485 m_rExport
.m_aCurrentCharPropStarts
.pop();
486 m_rExport
.pOutFmtNode
= pOldMod
;
489 OSL_ENSURE( pFont
, "must be *some* font associated with this txtnode" );
492 SvxFontItem
aFont( *pFont
);
495 If we are a nonunicode aware format then we set the charset we want to
496 use for export of this range. If necessary this will generate a pseudo
497 font to use for this range.
499 So now we are guaranteed to have a font with the correct charset set
500 for WW6/95 which will match the script we have exported this range in,
501 this makes older nonunicode aware versions of word display the correct
504 if ( !m_rExport
.SupportsUnicode() )
505 aFont
.SetCharSet( GetCharSet() );
507 if ( rParentFont
!= aFont
)
508 m_rExport
.AttrOutput().OutputItem( aFont
);
512 void SwWW8AttrIter::OutFlys(xub_StrLen nSwPos
)
516 May have an anchored graphic to be placed, loop through sorted array
517 and output all at this position
519 while ( maFlyIter
!= maFlyFrms
.end() )
521 const SwPosition
&rAnchor
= maFlyIter
->GetPosition();
522 xub_StrLen nPos
= rAnchor
.nContent
.GetIndex();
524 if ( nPos
!= nSwPos
)
528 m_rExport
.AttrOutput().OutputFlyFrame( *maFlyIter
);
534 bool SwWW8AttrIter::IsTxtAttr( xub_StrLen nSwPos
)
536 // search for attrs with CH_TXTATR
537 if (const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
539 for (sal_uInt16 i
= 0; i
< pTxtAttrs
->Count(); ++i
)
541 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
542 if ( pHt
->HasDummyChar() && (*pHt
->GetStart() == nSwPos
) )
550 bool SwWW8AttrIter::IsDropCap( int nSwPos
)
552 // see if the current position falls on a DropCap
553 int nDropChars
= mrSwFmtDrop
.GetChars();
554 bool bWholeWord
= mrSwFmtDrop
.GetWholeWord();
557 short nWordLen
= rNd
.GetDropLen(0);
558 if(nSwPos
== nWordLen
&& nSwPos
!= 0)
563 if (nSwPos
== nDropChars
&& nSwPos
!= 0)
569 bool SwWW8AttrIter::RequiresImplicitBookmark()
571 SwImplBookmarksIter bkmkIterEnd
= m_rExport
.maImplicitBookmarks
.end();
572 for ( SwImplBookmarksIter aIter
= m_rExport
.maImplicitBookmarks
.begin(); aIter
!= bkmkIterEnd
; ++aIter
)
574 sal_uLong sample
= aIter
->second
;
576 if ( sample
== rNd
.GetIndex() )
582 //HasItem is for the summary of the double attributes: Underline and WordlineMode as TextItems.
583 // OutAttr () calls the output function, which can call HasItem() for other items at the attribute's start position.
584 // Only attributes with end can be queried.
585 // It searches with bDeep
586 const SfxPoolItem
* SwWW8AttrIter::HasTextItem( sal_uInt16 nWhich
) const
588 const SfxPoolItem
* pRet
= 0;
589 const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints();
591 if (pTxtAttrs
&& !m_rExport
.m_aCurrentCharPropStarts
.empty())
593 xub_StrLen nTmpSwPos
= m_rExport
.m_aCurrentCharPropStarts
.top();
594 for (sal_uInt16 i
= 0; i
< pTxtAttrs
->Count(); ++i
)
596 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
597 const SfxPoolItem
* pItem
= &pHt
->GetAttr();
598 const xub_StrLen
* pAtrEnd
= 0;
599 if( 0 != ( pAtrEnd
= pHt
->GetEnd() ) && // only Attr with an end
600 nWhich
== pItem
->Which() &&
601 nTmpSwPos
>= *pHt
->GetStart() && nTmpSwPos
< *pAtrEnd
)
603 pRet
= pItem
; // found it
606 else if (nTmpSwPos
< *pHt
->GetStart())
607 break; // nothing more to come
613 void WW8Export::GetCurrentItems(ww::bytes
&rItems
) const
615 rItems
.insert(rItems
.end(), pO
->begin(), pO
->end());
618 const SfxPoolItem
& SwWW8AttrIter::GetItem(sal_uInt16 nWhich
) const
620 const SfxPoolItem
* pRet
= HasTextItem(nWhich
);
621 return pRet
? *pRet
: rNd
.SwCntntNode::GetAttr(nWhich
);
624 void WW8AttributeOutput::StartRuby( const SwTxtNode
& rNode
, xub_StrLen
/*nPos*/, const SwFmtRuby
& rRuby
)
626 String
aStr( FieldString( ww::eEQ
) );
627 aStr
.AppendAscii( "\\* jc" );
629 sal_Char cDirective
= 0;
630 switch ( rRuby
.GetAdjustment() )
652 OSL_ENSURE( !this,"Unhandled Ruby justication code" );
655 aStr
+= OUString::number( nJC
);
658 MS needs to know the name and size of the font used in the ruby item,
659 but we coud have written it in a mixture of asian and western
660 scripts, and each of these can be a different font and size than the
661 other, so we make a guess based upon the first character of the text,
664 sal_uInt16 nRubyScript
;
665 if( g_pBreakIt
->GetBreakIter().is() )
666 nRubyScript
= g_pBreakIt
->GetBreakIter()->getScriptType( rRuby
.GetText(), 0);
668 nRubyScript
= i18n::ScriptType::ASIAN
;
670 const SwTxtRuby
* pRubyTxt
= rRuby
.GetTxtRuby();
671 const SwCharFmt
* pFmt
= pRubyTxt
? pRubyTxt
->GetCharFmt() : 0;
676 const SvxFontItem
&rFont
= ItemGet
< SvxFontItem
>( *pFmt
,
677 GetWhichOfScript(RES_CHRATR_FONT
,nRubyScript
) );
678 sFamilyName
= rFont
.GetFamilyName();
680 const SvxFontHeightItem
&rHeight
= ItemGet
< SvxFontHeightItem
>( *pFmt
,
681 GetWhichOfScript( RES_CHRATR_FONTSIZE
, nRubyScript
) );
682 nHeight
= rHeight
.GetHeight();
686 /*Get defaults if no formatting on ruby text*/
688 const SfxItemPool
*pPool
= rNode
.GetSwAttrSet().GetPool();
689 pPool
= pPool
? pPool
: &m_rWW8Export
.pDoc
->GetAttrPool();
691 const SvxFontItem
&rFont
= DefaultItemGet
< SvxFontItem
>( *pPool
,
692 GetWhichOfScript( RES_CHRATR_FONT
,nRubyScript
) );
693 sFamilyName
= rFont
.GetFamilyName();
695 const SvxFontHeightItem
&rHeight
= DefaultItemGet
< SvxFontHeightItem
>
696 ( *pPool
, GetWhichOfScript( RES_CHRATR_FONTSIZE
, nRubyScript
) );
697 nHeight
= rHeight
.GetHeight();
699 nHeight
= (nHeight
+ 5)/10;
701 aStr
.AppendAscii( " \\* \"Font:" );
702 aStr
.Append( sFamilyName
);
703 aStr
.AppendAscii( "\" \\* hps" );
704 aStr
+= OUString::number( nHeight
);
705 aStr
.AppendAscii( " \\o" );
708 aStr
.AppendAscii( "\\a" );
709 aStr
.Append( cDirective
);
711 aStr
.AppendAscii( "(\\s\\up " );
714 if ( g_pBreakIt
->GetBreakIter().is() )
715 nRubyScript
= g_pBreakIt
->GetBreakIter()->getScriptType( rNode
.GetTxt(),
716 *( pRubyTxt
->GetStart() ) );
718 nRubyScript
= i18n::ScriptType::ASIAN
;
720 const SwAttrSet
& rSet
= rNode
.GetSwAttrSet();
721 const SvxFontHeightItem
&rHeightItem
=
722 ( const SvxFontHeightItem
& )rSet
.Get(
723 GetWhichOfScript( RES_CHRATR_FONTSIZE
, nRubyScript
) );
724 nHeight
= (rHeightItem
.GetHeight() + 10)/20-1;
725 aStr
+= OUString::number(nHeight
);
727 aStr
+= rRuby
.GetText();
728 aStr
.AppendAscii( ")" );
730 // The parameter separator depends on the FIB.lid
731 if ( m_rWW8Export
.pFib
->getNumDecimalSep() == '.' )
732 aStr
.AppendAscii( "," );
734 aStr
.AppendAscii( ";" );
736 m_rWW8Export
.OutputField( 0, ww::eEQ
, aStr
,
737 WRITEFIELD_START
| WRITEFIELD_CMD_START
);
740 void WW8AttributeOutput::EndRuby()
742 m_rWW8Export
.WriteChar( ')' );
743 m_rWW8Export
.OutputField( 0, ww::eEQ
, aEmptyStr
, WRITEFIELD_END
| WRITEFIELD_CLOSE
);
746 /*#i15387# Better ideas welcome*/
747 String
&TruncateBookmark( String
&rRet
)
749 if ( rRet
.Len() > 40 )
751 OSL_ENSURE( rRet
.Len() <= 40, "Word cannot have bookmarks longer than 40 chars" );
755 bool AttributeOutputBase::AnalyzeURL( const String
& rUrl
, const String
& /*rTarget*/, String
* pLinkURL
, String
* pMark
)
757 bool bBookMarkOnly
= false;
759 INetURLObject
aURL( rUrl
);
763 if ( rUrl
.Len() > 1 && rUrl
.GetChar(0) == INET_MARK_TOKEN
)
765 sMark
= BookmarkToWriter( rUrl
.Copy(1) );
767 xub_StrLen nPos
= sMark
.SearchBackward( cMarkSeparator
);
769 String
sRefType(comphelper::string::remove(sMark
.Copy(nPos
+1), ' '));
771 // #i21465# Only interested in outline references
772 if ( sRefType
.EqualsAscii( pMarkToOutline
) )
774 String sLink
= sMark
.Copy(0, nPos
);
775 SwImplBookmarksIter bkmkIterEnd
= GetExport().maImplicitBookmarks
.end();
776 for ( SwImplBookmarksIter aIter
= GetExport().maImplicitBookmarks
.begin(); aIter
!= bkmkIterEnd
; ++aIter
)
778 String bkmkName
= aIter
->first
;
780 if ( bkmkName
== sLink
)
782 sMark
= String( "_toc" );
783 sMark
+= OUString::number( aIter
->second
);
790 sURL
= aURL
.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS
);
791 sMark
= aURL
.GetMark( INetURLObject::DECODE_UNAMBIGUOUS
);
795 if ( sMark
.Len() && !sURL
.Len() )
796 bBookMarkOnly
= true;
802 return bBookMarkOnly
;
805 bool WW8AttributeOutput::AnalyzeURL( const String
& rUrl
, const String
& rTarget
, String
* pLinkURL
, String
* pMark
)
807 bool bBookMarkOnly
= AttributeOutputBase::AnalyzeURL( rUrl
, rTarget
, pLinkURL
, pMark
);
809 String sURL
= *pLinkURL
;
810 String sMark
= *pMark
;
813 sURL
= URIHelper::simpleNormalizedMakeRelative( m_rWW8Export
.GetWriter().GetBaseURL(), sURL
);
816 sURL
= FieldString( ww::eHYPERLINK
);
819 String
sFld( FieldString( ww::eHYPERLINK
) );
820 sFld
.AppendAscii( "\"" );
821 sURL
.Insert( sFld
, 0 );
826 ( ( sURL
.AppendAscii( " \\l \"" ) ) += sMark
) += '\"';
829 ( sURL
.AppendAscii( " \\n " ) ) += rTarget
;
834 return bBookMarkOnly
;
837 bool WW8AttributeOutput::StartURL( const String
&rUrl
, const String
&rTarget
)
839 // hyperlinks only in WW8
840 if ( !m_rWW8Export
.bWrtWW8
)
843 INetURLObject
aURL( rUrl
);
847 bool bBookMarkOnly
= AnalyzeURL( rUrl
, rTarget
, &sURL
, &sMark
);
850 m_rWW8Export
.OutputField( 0, ww::eHYPERLINK
, sURL
, WRITEFIELD_START
| WRITEFIELD_CMD_START
);
852 // write the refence to the "picture" structure
853 sal_uLong nDataStt
= m_rWW8Export
.pDataStrm
->Tell();
854 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell() );
856 // WinWord 2000 doesn't write this - so its a temp solution by W97 ?
857 m_rWW8Export
.WriteChar( 0x01 );
859 static sal_uInt8 aArr1
[] = {
860 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
862 0x06, 0x08, 0x01, // sprmCFData
863 0x55, 0x08, 0x01, // sprmCFSpec
864 0x02, 0x08, 0x01 // sprmCFFldVanish
866 sal_uInt8
* pDataAdr
= aArr1
+ 2;
867 Set_UInt32( pDataAdr
, nDataStt
);
869 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), sizeof( aArr1
), aArr1
);
871 m_rWW8Export
.OutputField( 0, ww::eHYPERLINK
, sURL
, WRITEFIELD_CMD_END
);
873 // now write the picture structur
874 sURL
= aURL
.GetURLNoMark();
876 // Compare the URL written by AnalyzeURL with the original one to see if
877 // the output URL is absolute or relative.
880 sRelativeURL
= URIHelper::simpleNormalizedMakeRelative( m_rWW8Export
.GetWriter().GetBaseURL(), rUrl
);
881 bool bAbsolute
= sRelativeURL
.Equals( rUrl
);
883 static sal_uInt8 aURLData1
[] = {
884 0,0,0,0, // len of struct
885 0x44,0, // the start of "next" data
886 0,0,0,0,0,0,0,0,0,0, // PIC-Structure!
887 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
888 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
889 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
892 static sal_uInt8 MAGIC_A
[] = {
893 // start of "next" data
894 0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
895 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
898 m_rWW8Export
.pDataStrm
->Write( aURLData1
, sizeof( aURLData1
) );
899 /* Write HFD Structure */
900 sal_uInt8 nAnchor
= 0x00;
903 m_rWW8Export
.pDataStrm
->Write( &nAnchor
, 1 ); // HFDBits
904 m_rWW8Export
.pDataStrm
->Write( MAGIC_A
, sizeof(MAGIC_A
) ); //clsid
906 /* Write Hyperlink Object see [MS-OSHARED] spec*/
907 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 0x00000002);
908 sal_uInt32 nFlag
= bBookMarkOnly
? 0 : 0x01;
913 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, nFlag
);
915 INetProtocol eProto
= aURL
.GetProtocol();
916 if ( eProto
== INET_PROT_FILE
|| eProto
== INET_PROT_SMB
)
918 // version 1 (for a document)
920 static sal_uInt8 MAGIC_C
[] = {
921 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
926 static sal_uInt8 MAGIC_D
[] = {
927 0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
928 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
932 // save the links to files as relative
933 sURL
= URIHelper::simpleNormalizedMakeRelative( m_rWW8Export
.GetWriter().GetBaseURL(), sURL
);
934 if ( eProto
== INET_PROT_FILE
&& sURL
.EqualsAscii( "/", 0, 1 ) )
935 sURL
= aURL
.PathToFileName();
937 // special case for the absolute windows names
938 // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
939 sal_Unicode aDrive
= ( sURL
.Len() > 1 )? sURL
.GetChar( 1 ): 0;
940 if ( sURL
.EqualsAscii( "/", 0, 1 ) &&
941 ( ( aDrive
>= 'A' && aDrive
<= 'Z' ) || ( aDrive
>= 'a' && aDrive
<= 'z' ) ) &&
942 sURL
.EqualsAscii( ":", 2, 1 ) )
945 sURL
.SearchAndReplaceAll( '/', '\\' );
948 // n#261623 convert smb notation to '\\'
949 const char pSmb
[] = "smb://";
950 if ( eProto
== INET_PROT_SMB
&&
951 sURL
.EqualsAscii( pSmb
, 0, sizeof( pSmb
) - 1 ) )
953 sURL
.Erase( 0, sizeof( pSmb
) - 3 );
954 sURL
.SearchAndReplaceAll( '/', '\\' );
957 m_rWW8Export
.pDataStrm
->Write( MAGIC_C
, sizeof(MAGIC_C
) );
958 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, sURL
.Len()+1 );
959 SwWW8Writer::WriteString8( *m_rWW8Export
.pDataStrm
, sURL
, true,
960 RTL_TEXTENCODING_MS_1252
);
961 m_rWW8Export
.pDataStrm
->Write( MAGIC_D
, sizeof( MAGIC_D
) );
963 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 2*sURL
.Len() + 6 );
964 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 2*sURL
.Len() );
965 SwWW8Writer::WriteShort( *m_rWW8Export
.pDataStrm
, 3 );
966 SwWW8Writer::WriteString16( *m_rWW8Export
.pDataStrm
, sURL
, false );
968 else if ( eProto
!= INET_PROT_NOT_VALID
)
970 // version 2 (simple url)
971 // an write some data to the data stream, but dont ask
972 // what the data mean, except for the URL.
973 // The First piece is the WW8_PIC structure.
974 static sal_uInt8 MAGIC_B
[] = {
975 0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
976 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
979 m_rWW8Export
.pDataStrm
->Write( MAGIC_B
, sizeof(MAGIC_B
) );
980 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 2 * ( sURL
.Len() + 1 ) );
981 SwWW8Writer::WriteString16( *m_rWW8Export
.pDataStrm
, sURL
, true );
986 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, sMark
.Len()+1 );
987 SwWW8Writer::WriteString16( *m_rWW8Export
.pDataStrm
, sMark
, true );
989 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, nDataStt
,
990 m_rWW8Export
.pDataStrm
->Tell() - nDataStt
);
995 bool WW8AttributeOutput::EndURL()
997 // hyperlinks only in WW8
998 if ( !m_rWW8Export
.bWrtWW8
)
1001 m_rWW8Export
.OutputField( 0, ww::eHYPERLINK
, aEmptyStr
, WRITEFIELD_CLOSE
);
1006 String
BookmarkToWord(const String
&rBookmark
)
1008 String
sRet(INetURLObject::encode(rBookmark
,
1009 INetURLObject::PART_REL_SEGMENT_EXTRA
, '%',
1010 INetURLObject::ENCODE_ALL
, RTL_TEXTENCODING_ASCII_US
));
1011 return TruncateBookmark(sRet
);
1014 String
BookmarkToWriter(const String
&rBookmark
)
1016 return INetURLObject::decode(rBookmark
, '%',
1017 INetURLObject::DECODE_UNAMBIGUOUS
, RTL_TEXTENCODING_ASCII_US
);
1020 void SwWW8AttrIter::OutSwFmtRefMark(const SwFmtRefMark
& rAttr
, bool)
1022 if ( m_rExport
.HasRefToObject( REF_SETREFATTR
, &rAttr
.GetRefName(), 0 ) )
1023 m_rExport
.AppendBookmark( m_rExport
.GetBookmarkName( REF_SETREFATTR
,
1024 &rAttr
.GetRefName(), 0 ));
1027 void WW8AttributeOutput::FieldVanish( const String
& rTxt
, ww::eField
/*eType*/ )
1030 m_rWW8Export
.GetCurrentItems( aItems
);
1033 if ( m_rWW8Export
.bWrtWW8
)
1034 SwWW8Writer::InsUInt16( aItems
, NS_sprm::LN_CFFldVanish
);
1036 aItems
.push_back( 67 );
1037 aItems
.push_back( 1 );
1039 sal_uInt16 nStt_sprmCFSpec
= aItems
.size();
1041 // sprmCFSpec -- fSpec-Attribut true
1042 if ( m_rWW8Export
.bWrtWW8
)
1043 SwWW8Writer::InsUInt16( aItems
, 0x855 );
1045 aItems
.push_back( 117 );
1046 aItems
.push_back( 1 );
1048 m_rWW8Export
.WriteChar( '\x13' );
1049 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), aItems
.size(),
1051 m_rWW8Export
.OutSwString( rTxt
, 0, rTxt
.Len(), m_rWW8Export
.IsUnicode(),
1052 RTL_TEXTENCODING_MS_1252
);
1053 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), nStt_sprmCFSpec
,
1055 m_rWW8Export
.WriteChar( '\x15' );
1056 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), aItems
.size(),
1060 void AttributeOutputBase::TOXMark( const SwTxtNode
& rNode
, const SwTOXMark
& rAttr
)
1062 // its a field; so get the Text form the Node and build the field
1064 ww::eField eType
= ww::eNONE
;
1066 const SwTxtTOXMark
& rTxtTOXMark
= *rAttr
.GetTxtTOXMark();
1067 const xub_StrLen
* pTxtEnd
= rTxtTOXMark
.GetEnd();
1068 if ( pTxtEnd
) // has range?
1070 sTxt
= rNode
.GetExpandTxt( *rTxtTOXMark
.GetStart(),
1071 *pTxtEnd
- *rTxtTOXMark
.GetStart() );
1074 sTxt
= rAttr
.GetAlternativeText();
1076 switch ( rAttr
.GetTOXType()->GetType() )
1080 if ( rAttr
.GetPrimaryKey().Len() )
1082 if ( rAttr
.GetSecondaryKey().Len() )
1084 sTxt
.Insert( ':', 0 );
1085 sTxt
.Insert( rAttr
.GetSecondaryKey(), 0 );
1088 sTxt
.Insert( ':', 0 );
1089 sTxt
.Insert( rAttr
.GetPrimaryKey(), 0 );
1091 sTxt
.InsertAscii( " XE \"", 0 );
1092 sTxt
.InsertAscii( "\" " );
1096 ( sTxt
.AppendAscii( "\" \\f \"" ) )
1097 += (sal_Char
)( 'A' + GetExport( ).GetId( *rAttr
.GetTOXType() ) );
1098 // fall through - no break;
1102 sTxt
.InsertAscii( " TC \"", 0 );
1103 sal_uInt16 nLvl
= rAttr
.GetLevel();
1104 if (nLvl
> WW8ListManager::nMaxLevel
)
1105 nLvl
= WW8ListManager::nMaxLevel
;
1107 ((sTxt
.AppendAscii( "\" \\l " ))
1108 += OUString::number( nLvl
)) += ' ';
1112 OSL_ENSURE( !this, "Unhandled option for toc export" );
1117 FieldVanish( sTxt
, eType
);
1120 int SwWW8AttrIter::OutAttrWithRange(xub_StrLen nPos
)
1123 if ( const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints() )
1125 m_rExport
.m_aCurrentCharPropStarts
.push( nPos
);
1126 const xub_StrLen
* pEnd
;
1127 for ( sal_uInt16 i
= 0; i
< pTxtAttrs
->Count(); ++i
)
1129 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
1130 const SfxPoolItem
* pItem
= &pHt
->GetAttr();
1131 switch ( pItem
->Which() )
1133 case RES_TXTATR_INETFMT
:
1134 if ( nPos
== *pHt
->GetStart() )
1136 const SwFmtINetFmt
*rINet
= static_cast< const SwFmtINetFmt
* >( pItem
);
1137 if ( m_rExport
.AttrOutput().StartURL( rINet
->GetValue(), rINet
->GetTargetFrame() ) )
1140 if ( 0 != ( pEnd
= pHt
->GetEnd() ) && nPos
== *pEnd
)
1142 if ( m_rExport
.AttrOutput().EndURL() )
1146 case RES_TXTATR_REFMARK
:
1147 if ( nPos
== *pHt
->GetStart() )
1149 OutSwFmtRefMark( *static_cast< const SwFmtRefMark
* >( pItem
), true );
1152 if ( 0 != ( pEnd
= pHt
->GetEnd() ) && nPos
== *pEnd
)
1154 OutSwFmtRefMark( *static_cast< const SwFmtRefMark
* >( pItem
), false );
1158 case RES_TXTATR_TOXMARK
:
1159 if ( nPos
== *pHt
->GetStart() )
1160 m_rExport
.AttrOutput().TOXMark( rNd
, *static_cast< const SwTOXMark
* >( pItem
) );
1162 case RES_TXTATR_CJK_RUBY
:
1163 if ( nPos
== *pHt
->GetStart() )
1165 m_rExport
.AttrOutput().StartRuby( rNd
, nPos
, *static_cast< const SwFmtRuby
* >( pItem
) );
1168 if ( 0 != ( pEnd
= pHt
->GetEnd() ) && nPos
== *pEnd
)
1170 m_rExport
.AttrOutput().EndRuby();
1176 m_rExport
.m_aCurrentCharPropStarts
.pop(); // HasTextItem only allowed in the above range
1181 bool SwWW8AttrIter::IsRedlineAtEnd( xub_StrLen nEnd
) const
1184 // search next Redline
1185 for( sal_uInt16 nPos
= nCurRedlinePos
;
1186 nPos
< m_rExport
.pDoc
->GetRedlineTbl().size(); ++nPos
)
1188 const SwPosition
* pEnd
= m_rExport
.pDoc
->GetRedlineTbl()[ nPos
]->End();
1189 if( pEnd
->nNode
== rNd
)
1191 if( pEnd
->nContent
.GetIndex() == nEnd
)
1203 const SwRedlineData
* SwWW8AttrIter::GetRedline( xub_StrLen nPos
)
1207 const SwPosition
* pEnd
= pCurRedline
->End();
1208 if( pEnd
->nNode
== rNd
&&
1209 pEnd
->nContent
.GetIndex() <= nPos
)
1216 // write data of current redline
1217 return &( pCurRedline
->GetRedlineData() );
1223 // search next Redline
1224 for( ; nCurRedlinePos
< m_rExport
.pDoc
->GetRedlineTbl().size();
1227 const SwRedline
* pRedl
= m_rExport
.pDoc
->GetRedlineTbl()[ nCurRedlinePos
];
1229 const SwPosition
* pStt
= pRedl
->Start();
1230 const SwPosition
* pEnd
= pStt
== pRedl
->GetPoint()
1232 : pRedl
->GetPoint();
1234 if( pStt
->nNode
== rNd
)
1236 if( pStt
->nContent
.GetIndex() >= nPos
)
1238 if( pStt
->nContent
.GetIndex() == nPos
)
1240 // write data of this redline
1241 pCurRedline
= pRedl
;
1242 return &( pCurRedline
->GetRedlineData() );
1250 if( pEnd
->nNode
== rNd
&&
1251 pEnd
->nContent
.GetIndex() < nPos
)
1253 pCurRedline
= pRedl
;
1262 short MSWordExportBase::GetCurrentPageDirection() const
1264 const SwFrmFmt
&rFmt
= pAktPageDesc
1265 ? pAktPageDesc
->GetMaster()
1266 : pDoc
->GetPageDesc( 0 ).GetMaster();
1267 return rFmt
.GetFrmDir().GetValue();
1270 short MSWordExportBase::GetDefaultFrameDirection( ) const
1272 short nDir
= FRMDIR_ENVIRONMENT
;
1274 if ( bOutPageDescs
)
1275 nDir
= GetCurrentPageDirection( );
1276 else if ( pOutFmtNode
)
1278 if ( bOutFlyFrmAttrs
) //frame
1280 nDir
= TrueFrameDirection( *( const SwFrmFmt
* ) pOutFmtNode
);
1282 else if ( pOutFmtNode
->ISA( SwCntntNode
) ) //pagagraph
1284 const SwCntntNode
*pNd
= ( const SwCntntNode
* ) pOutFmtNode
;
1285 SwPosition
aPos( *pNd
);
1286 nDir
= pDoc
->GetTextDirection( aPos
);
1288 else if ( pOutFmtNode
->ISA( SwTxtFmtColl
) )
1289 nDir
= FRMDIR_HORI_LEFT_TOP
; //what else can we do :-(
1292 if ( nDir
== FRMDIR_ENVIRONMENT
)
1293 nDir
= FRMDIR_HORI_LEFT_TOP
; //Set something
1298 short MSWordExportBase::TrueFrameDirection( const SwFrmFmt
&rFlyFmt
) const
1300 const SwFrmFmt
*pFlyFmt
= &rFlyFmt
;
1301 const SvxFrameDirectionItem
* pItem
= 0;
1304 pItem
= &pFlyFmt
->GetFrmDir();
1305 if ( FRMDIR_ENVIRONMENT
== pItem
->GetValue() )
1308 const SwFmtAnchor
* pAnchor
= &pFlyFmt
->GetAnchor();
1309 if ((FLY_AT_PAGE
!= pAnchor
->GetAnchorId()) &&
1310 pAnchor
->GetCntntAnchor() )
1312 pFlyFmt
= pAnchor
->GetCntntAnchor()->nNode
.GetNode().GetFlyFmt();
1323 nRet
= pItem
->GetValue();
1325 nRet
= GetCurrentPageDirection();
1327 OSL_ENSURE( nRet
!= FRMDIR_ENVIRONMENT
, "leaving with environment direction" );
1331 const SvxBrushItem
* WW8Export::GetCurrentPageBgBrush() const
1333 const SwFrmFmt
&rFmt
= pAktPageDesc
1334 ? pAktPageDesc
->GetMaster()
1335 : pDoc
->GetPageDesc(0).GetMaster();
1337 const SfxPoolItem
* pItem
= 0;
1338 //If not set, or "no fill", get real bg
1339 SfxItemState eState
= rFmt
.GetItemState(RES_BACKGROUND
, true, &pItem
);
1341 const SvxBrushItem
* pRet
= (const SvxBrushItem
*)pItem
;
1342 if (SFX_ITEM_SET
!= eState
|| (!pRet
->GetGraphic() &&
1343 pRet
->GetColor() == COL_TRANSPARENT
))
1345 pRet
= &(DefaultItemGet
<SvxBrushItem
>(*pDoc
,RES_BACKGROUND
));
1350 SvxBrushItem
WW8Export::TrueFrameBgBrush(const SwFrmFmt
&rFlyFmt
) const
1352 const SwFrmFmt
*pFlyFmt
= &rFlyFmt
;
1353 const SvxBrushItem
* pRet
= 0;
1357 //If not set, or "no fill", get real bg
1358 const SfxPoolItem
* pItem
= 0;
1359 SfxItemState eState
=
1360 pFlyFmt
->GetItemState(RES_BACKGROUND
, true, &pItem
);
1361 pRet
= (const SvxBrushItem
*)pItem
;
1362 if (SFX_ITEM_SET
!= eState
|| (!pRet
->GetGraphic() &&
1363 pRet
->GetColor() == COL_TRANSPARENT
))
1366 const SwFmtAnchor
* pAnchor
= &pFlyFmt
->GetAnchor();
1367 if ((FLY_AT_PAGE
!= pAnchor
->GetAnchorId()) &&
1368 pAnchor
->GetCntntAnchor())
1371 pAnchor
->GetCntntAnchor()->nNode
.GetNode().GetFlyFmt();
1381 pRet
= GetCurrentPageBgBrush();
1383 const Color
aTmpColor( COL_WHITE
);
1384 SvxBrushItem
aRet( aTmpColor
, RES_BACKGROUND
);
1385 if (pRet
&& (pRet
->GetGraphic() ||( pRet
->GetColor() != COL_TRANSPARENT
)))
1393 Convert characters that need to be converted, the basic replacements and the
1394 ridicously complicated title case attribute mapping to hardcoded upper case
1395 because word doesn't have the feature
1397 String
SwWW8AttrIter::GetSnippet(const String
&rStr
, xub_StrLen nAktPos
,
1398 xub_StrLen nLen
) const
1400 String
aSnippet(rStr
, nAktPos
, nLen
);
1404 // 0x0a ( Hard Line Break ) -> 0x0b
1405 // 0xad ( soft hyphen ) -> 0x1f
1406 // 0x2011 ( hard hyphen ) -> 0x1e
1407 aSnippet
.SearchAndReplaceAll(0x0A, 0x0B);
1408 aSnippet
.SearchAndReplaceAll(CHAR_HARDHYPHEN
, 0x1e);
1409 aSnippet
.SearchAndReplaceAll(CHAR_SOFTHYPHEN
, 0x1f);
1411 m_rExport
.m_aCurrentCharPropStarts
.push( nAktPos
);
1412 const SfxPoolItem
&rItem
= GetItem(RES_CHRATR_CASEMAP
);
1414 if (SVX_CASEMAP_TITEL
== ((const SvxCaseMapItem
&)rItem
).GetValue())
1416 sal_uInt16 nScriptType
= i18n::ScriptType::LATIN
;
1417 if (g_pBreakIt
->GetBreakIter().is())
1418 nScriptType
= g_pBreakIt
->GetBreakIter()->getScriptType(aSnippet
, 0);
1420 LanguageType nLanguage
;
1421 switch (nScriptType
)
1423 case i18n::ScriptType::ASIAN
:
1424 nLanguage
= ((const SvxLanguageItem
&)GetItem(RES_CHRATR_CJK_LANGUAGE
)).GetLanguage();
1426 case i18n::ScriptType::COMPLEX
:
1427 nLanguage
= ((const SvxLanguageItem
&)GetItem(RES_CHRATR_CTL_LANGUAGE
)).GetLanguage();
1429 case i18n::ScriptType::LATIN
:
1431 nLanguage
= ((const SvxLanguageItem
&)GetItem(RES_CHRATR_LANGUAGE
)).GetLanguage();
1435 SvxFont aFontHelper
;
1436 aFontHelper
.SetCaseMap(SVX_CASEMAP_TITEL
);
1437 aFontHelper
.SetLanguage(nLanguage
);
1438 aSnippet
= aFontHelper
.CalcCaseMap(aSnippet
);
1440 //If we weren't at the begin of a word undo the case change.
1441 //not done before doing the casemap because the sequence might start
1443 if (g_pBreakIt
->GetBreakIter().is() && !g_pBreakIt
->GetBreakIter()->isBeginWord(
1444 rStr
, nAktPos
, g_pBreakIt
->GetLocale(nLanguage
),
1445 i18n::WordType::ANYWORD_IGNOREWHITESPACES
) )
1447 aSnippet
.SetChar(0, rStr
.GetChar(nAktPos
));
1450 m_rExport
.m_aCurrentCharPropStarts
.pop();
1455 /** Delivers the right paragraph style
1457 Because of the different style handling for delete operations,
1458 the track changes have to be analysed. A deletion, starting in paragraph A
1459 with style A, ending in paragraph B with style B, needs a hack.
1461 static SwTxtFmtColl
& lcl_getFormatCollection( MSWordExportBase
& rExport
, const SwTxtNode
* pTxtNode
)
1463 sal_uInt16 nPos
= 0;
1464 sal_uInt16 nMax
= rExport
.pDoc
->GetRedlineTbl().size();
1465 while( nPos
< nMax
)
1467 const SwRedline
* pRedl
= rExport
.pDoc
->GetRedlineTbl()[ nPos
++ ];
1468 const SwPosition
* pStt
= pRedl
->Start();
1469 const SwPosition
* pEnd
= pStt
== pRedl
->GetPoint()
1471 : pRedl
->GetPoint();
1472 // Looking for deletions, which ends in current pTxtNode
1473 if( nsRedlineType_t::REDLINE_DELETE
== pRedl
->GetRedlineData().GetType() &&
1474 pEnd
->nNode
== *pTxtNode
&& pStt
->nNode
!= *pTxtNode
&&
1475 pStt
->nNode
.GetNode().IsTxtNode() )
1477 pTxtNode
= pStt
->nNode
.GetNode().GetTxtNode();
1482 return static_cast<SwTxtFmtColl
&>( pTxtNode
->GetAnyFmtColl() );
1485 void WW8AttributeOutput::FormatDrop( const SwTxtNode
& rNode
, const SwFmtDrop
&rSwFmtDrop
, sal_uInt16 nStyle
,
1486 ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo
, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
1488 short nDropLines
= rSwFmtDrop
.GetLines();
1489 short nDistance
= rSwFmtDrop
.GetDistance();
1490 int rFontHeight
, rDropHeight
, rDropDescent
;
1493 ShortToSVBT16( nStyle
, nSty
);
1494 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), (sal_uInt8
*)&nSty
, (sal_uInt8
*)&nSty
+2 ); // Style #
1496 if ( m_rWW8Export
.bWrtWW8
)
1498 m_rWW8Export
.InsUInt16( NS_sprm::LN_PPc
); // Alignment (sprmPPc)
1499 m_rWW8Export
.pO
->push_back( 0x20 );
1501 m_rWW8Export
.InsUInt16( NS_sprm::LN_PWr
); // Wrapping (sprmPWr)
1502 m_rWW8Export
.pO
->push_back( 0x02 );
1504 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDcs
); // Dropcap (sprmPDcs)
1505 int nDCS
= ( nDropLines
<< 3 ) | 0x01;
1506 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( nDCS
) );
1508 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDxaFromText
); // Distance from text (sprmPDxaFromText)
1509 m_rWW8Export
.InsUInt16( nDistance
);
1511 if ( rNode
.GetDropSize( rFontHeight
, rDropHeight
, rDropDescent
) )
1513 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDyaLine
); // Line spacing
1514 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( -rDropHeight
) );
1515 m_rWW8Export
.InsUInt16( 0 );
1520 m_rWW8Export
.pO
->push_back( 29 ); // Alignment (sprmPPc)
1521 m_rWW8Export
.pO
->push_back( 0x20 );
1523 m_rWW8Export
.pO
->push_back( 37 ); // Wrapping (sprmPWr)
1524 m_rWW8Export
.pO
->push_back( 0x02 );
1526 m_rWW8Export
.pO
->push_back( 46 ); // Dropcap (sprmPDcs)
1527 int nDCS
= ( nDropLines
<< 3 ) | 0x01;
1528 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( nDCS
) );
1530 m_rWW8Export
.pO
->push_back( 49 ); // Distance from text (sprmPDxaFromText)
1531 m_rWW8Export
.InsUInt16( nDistance
);
1533 if (rNode
.GetDropSize(rFontHeight
, rDropHeight
, rDropDescent
))
1535 m_rWW8Export
.pO
->push_back( 20 ); // Line spacing
1536 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( -rDropHeight
) );
1537 m_rWW8Export
.InsUInt16( 0 );
1541 m_rWW8Export
.WriteCR( pTextNodeInfoInner
);
1543 if ( pTextNodeInfo
.get() != NULL
)
1546 SAL_INFO( "sw.ww8", pTextNodeInfo
->toString());
1548 TableInfoCell( pTextNodeInfoInner
);
1551 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
1552 m_rWW8Export
.pO
->clear();
1554 if ( rNode
.GetDropSize( rFontHeight
, rDropHeight
, rDropDescent
) )
1556 if ( m_rWW8Export
.bWrtWW8
)
1558 const SwCharFmt
*pSwCharFmt
= rSwFmtDrop
.GetCharFmt();
1561 m_rWW8Export
.InsUInt16( NS_sprm::LN_CIstd
);
1562 m_rWW8Export
.InsUInt16( m_rWW8Export
.GetId( *pSwCharFmt
) );
1565 m_rWW8Export
.InsUInt16( NS_sprm::LN_CHpsPos
); // Lower the chars
1566 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( -((nDropLines
- 1)*rDropDescent
) / 10 ) );
1568 m_rWW8Export
.InsUInt16( NS_sprm::LN_CHps
); // Font Size
1569 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( rFontHeight
/ 10 ) );
1573 const SwCharFmt
*pSwCharFmt
= rSwFmtDrop
.GetCharFmt();
1576 m_rWW8Export
.InsUInt16( 80 );
1577 m_rWW8Export
.InsUInt16( m_rWW8Export
.GetId( *pSwCharFmt
) );
1580 m_rWW8Export
.pO
->push_back( 101 ); // Lower the chars
1581 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( -((nDropLines
- 1)*rDropDescent
) / 10 ) );
1583 m_rWW8Export
.pO
->push_back( 99 ); // Font Size
1584 m_rWW8Export
.InsUInt16( static_cast< sal_uInt16
>( rFontHeight
/ 10 ) );
1588 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
1589 m_rWW8Export
.pO
->clear();
1592 xub_StrLen
MSWordExportBase::GetNextPos( SwWW8AttrIter
* aAttrIter
, const SwTxtNode
& rNode
, xub_StrLen nAktPos
)
1594 // Get the bookmarks for the normal run
1595 xub_StrLen nNextPos
= aAttrIter
->WhereNext();
1596 xub_StrLen nNextBookmark
= nNextPos
;
1598 if( nNextBookmark
> nAktPos
) //no need to search for bookmarks otherwise (checked in UpdatePosition())
1600 GetSortedBookmarks( rNode
, nAktPos
, nNextBookmark
- nAktPos
);
1601 NearestBookmark( nNextBookmark
, nAktPos
, false );
1603 return std::min( nNextPos
, nNextBookmark
);
1606 void MSWordExportBase::UpdatePosition( SwWW8AttrIter
* aAttrIter
, xub_StrLen nAktPos
, xub_StrLen
/*nEnd*/ )
1608 xub_StrLen nNextPos
;
1610 // go to next attribute if no bookmark is found or if the bookmark is behind the next attribute position
1611 // It may happened that the WhereNext() wasn't used in the previous increment because there was a
1612 // bookmark before it. Use that position before trying to find another one.
1613 bool bNextBookmark
= NearestBookmark( nNextPos
, nAktPos
, true );
1614 if( nAktPos
== aAttrIter
->WhereNext() && ( !bNextBookmark
|| nNextPos
> aAttrIter
->WhereNext() ) )
1615 aAttrIter
->NextPos();
1618 bool MSWordExportBase::GetBookmarks( const SwTxtNode
& rNd
, xub_StrLen nStt
,
1619 xub_StrLen nEnd
, IMarkVector
& rArr
)
1621 IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1622 sal_uLong nNd
= rNd
.GetIndex( );
1624 const sal_Int32 nMarks
= pMarkAccess
->getMarksCount();
1625 for ( sal_Int32 i
= 0; i
< nMarks
; i
++ )
1627 IMark
* pMark
= ( pMarkAccess
->getMarksBegin() + i
)->get();
1629 // Only keep the bookmarks starting or ending in this node
1630 if ( pMark
->GetMarkStart().nNode
== nNd
||
1631 pMark
->GetMarkEnd().nNode
== nNd
)
1633 xub_StrLen nBStart
= pMark
->GetMarkStart().nContent
.GetIndex();
1634 xub_StrLen nBEnd
= pMark
->GetMarkEnd().nContent
.GetIndex();
1636 // Keep only the bookmars starting or ending in the snippet
1637 bool bIsStartOk
= ( nBStart
>= nStt
) && ( nBStart
<= nEnd
);
1638 bool bIsEndOk
= ( nBEnd
>= nStt
) && ( nBEnd
<= nEnd
);
1640 IFieldmark
* pFieldmark
= dynamic_cast<IFieldmark
*>(pMark
);
1641 if (pFieldmark
&& pFieldmark
->GetFieldname() == ODF_COMMENTRANGE
)
1644 if ( bIsStartOk
|| bIsEndOk
)
1645 rArr
.push_back( pMark
);
1648 return ( rArr
.size() > 0 );
1651 class CompareMarksEnd
: public std::binary_function
< const IMark
*, const IMark
*, bool >
1654 inline bool operator() ( const IMark
* pOneB
, const IMark
* pTwoB
) const
1656 xub_StrLen nOEnd
= pOneB
->GetMarkEnd().nContent
.GetIndex();
1657 xub_StrLen nTEnd
= pTwoB
->GetMarkEnd().nContent
.GetIndex();
1659 return nOEnd
< nTEnd
;
1663 bool MSWordExportBase::NearestBookmark( xub_StrLen
& rNearest
, const xub_StrLen nAktPos
, bool bNextPositionOnly
)
1665 bool bHasBookmark
= false;
1667 if ( !m_rSortedMarksStart
.empty() )
1669 IMark
* pMarkStart
= m_rSortedMarksStart
.front();
1670 xub_StrLen nNext
= pMarkStart
->GetMarkStart().nContent
.GetIndex();
1671 if( !bNextPositionOnly
|| (nNext
> nAktPos
))
1674 bHasBookmark
= true;
1678 if ( !m_rSortedMarksEnd
.empty() )
1680 IMark
* pMarkEnd
= m_rSortedMarksEnd
[0];
1681 xub_StrLen nNext
= pMarkEnd
->GetMarkEnd().nContent
.GetIndex();
1682 if( !bNextPositionOnly
|| nNext
> nAktPos
)
1684 if ( !bHasBookmark
)
1687 rNearest
= std::min( rNearest
, nNext
);
1688 bHasBookmark
= true;
1692 return bHasBookmark
;
1695 void MSWordExportBase::GetSortedBookmarks( const SwTxtNode
& rNode
, xub_StrLen nAktPos
, xub_StrLen nLen
)
1697 IMarkVector aMarksStart
;
1698 if ( GetBookmarks( rNode
, nAktPos
, nAktPos
+ nLen
, aMarksStart
) )
1700 IMarkVector aSortedEnd
;
1701 IMarkVector aSortedStart
;
1702 for ( IMarkVector::const_iterator it
= aMarksStart
.begin(), end
= aMarksStart
.end();
1705 IMark
* pMark
= (*it
);
1707 // Remove the positions egals to the current pos
1708 xub_StrLen nStart
= pMark
->GetMarkStart().nContent
.GetIndex();
1709 xub_StrLen nEnd
= pMark
->GetMarkEnd().nContent
.GetIndex();
1711 if ( nStart
> nAktPos
&& ( pMark
->GetMarkStart().nNode
== rNode
.GetIndex()) )
1712 aSortedStart
.push_back( pMark
);
1714 if ( nEnd
> nAktPos
&& nEnd
<= ( nAktPos
+ nLen
) && (pMark
->GetMarkEnd().nNode
== rNode
.GetIndex()) )
1715 aSortedEnd
.push_back( pMark
);
1718 // Sort the bookmarks by end position
1719 std::sort( aSortedEnd
.begin(), aSortedEnd
.end(), CompareMarksEnd() );
1721 m_rSortedMarksStart
.swap( aSortedStart
);
1722 m_rSortedMarksEnd
.swap( aSortedEnd
);
1726 m_rSortedMarksStart
.clear( );
1727 m_rSortedMarksEnd
.clear( );
1731 void MSWordExportBase::OutputTextNode( const SwTxtNode
& rNode
)
1733 SAL_INFO( "sw.ww8", "<OutWW8_SwTxtNode>" );
1735 ww8::WW8TableNodeInfo::Pointer_t
pTextNodeInfo( mpTableInfo
->getTableNodeInfo( &rNode
) );
1737 //For i120928,identify the last node
1738 bool bLastCR
= false;
1739 bool bExported
= false;
1741 SwNodeIndex
aNextIdx(rNode
,1);
1742 SwNodeIndex
aLastIdx(rNode
.GetNodes().GetEndOfContent());
1743 if (aNextIdx
== aLastIdx
)
1747 AttrOutput().StartParagraph( pTextNodeInfo
);
1749 bool bFlyInTable
= mpParentFrame
&& IsInTable();
1752 nStyleBeforeFly
= GetId( lcl_getFormatCollection( *this, &rNode
) );
1754 // nStyleBeforeFly may change when we recurse into another node, so we
1755 // have to remember it in nStyle
1756 sal_uInt16 nStyle
= nStyleBeforeFly
;
1758 SwWW8AttrIter
aAttrIter( *this, rNode
);
1759 rtl_TextEncoding eChrSet
= aAttrIter
.GetCharSet();
1763 // ignore TOX header section
1764 const SwSectionNode
* pSectNd
= rNode
.FindSectionNode();
1765 if ( pSectNd
&& TOX_CONTENT_SECTION
== pSectNd
->GetSection().GetType() )
1767 AttrOutput().StartTOX( pSectNd
->GetSection() );
1768 m_aCurrentCharPropStarts
.push( 0 );
1772 const SwSection
* pTOXSect
= 0;
1775 // check for end of TOX
1776 SwNodeIndex
aIdx( rNode
, 1 );
1777 if( !aIdx
.GetNode().IsTxtNode() )
1779 const SwSectionNode
* pTOXSectNd
= rNode
.FindSectionNode();
1782 pTOXSect
= &pTOXSectNd
->GetSection();
1784 const SwNode
* pNxt
= rNode
.GetNodes().GoNext( &aIdx
);
1785 if( pNxt
&& pNxt
->FindSectionNode() == pTOXSectNd
)
1791 if ( aAttrIter
.RequiresImplicitBookmark() )
1793 String sBkmkName
= String( "_toc" );
1794 sBkmkName
+= OUString::number( rNode
.GetIndex() );
1795 AppendWordBookmark( sBkmkName
);
1798 String
aStr( rNode
.GetTxt() );
1800 xub_StrLen nAktPos
= 0;
1801 xub_StrLen
const nEnd
= aStr
.Len();
1802 bool bRedlineAtEnd
= false;
1803 int nOpenAttrWithRange
= 0;
1805 ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
;
1806 if ( pTextNodeInfo
.get() != NULL
)
1807 pTextNodeInfoInner
= pTextNodeInfo
->getFirstInner();
1810 const SwRedlineData
* pRedlineData
= aAttrIter
.GetRedline( nAktPos
);
1812 xub_StrLen nNextAttr
= GetNextPos( &aAttrIter
, rNode
, nAktPos
);
1813 // Is this the only run in this paragraph and it's empty?
1814 bool bSingleEmptyRun
= nAktPos
== 0 && nNextAttr
== 0;
1815 AttrOutput().StartRun( pRedlineData
, bSingleEmptyRun
);
1816 if( nTxtTyp
== TXT_FTN
|| nTxtTyp
== TXT_EDN
)
1817 AttrOutput().FootnoteEndnoteRefTag();
1819 if( nNextAttr
> nEnd
)
1822 aAttrIter
.OutFlys( nAktPos
);
1823 // Append bookmarks in this range after flys, exclusive of final
1824 // position of this range
1825 AppendBookmarks( rNode
, nAktPos
, nNextAttr
- nAktPos
);
1826 bool bTxtAtr
= aAttrIter
.IsTxtAttr( nAktPos
);
1827 nOpenAttrWithRange
+= aAttrIter
.OutAttrWithRange(nAktPos
);
1829 xub_StrLen nLen
= nNextAttr
- nAktPos
;
1830 if ( !bTxtAtr
&& nLen
)
1832 sal_Unicode ch
= aStr
.GetChar( nAktPos
);
1833 int ofs
= ( ch
== CH_TXT_ATR_FIELDSTART
|| ch
== CH_TXT_ATR_FIELDEND
|| ch
== CH_TXT_ATR_FORMELEMENT
? 1: 0 );
1835 IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1836 if ( ch
== CH_TXT_ATR_FIELDSTART
)
1838 SwPosition
aPosition( rNode
, SwIndex( const_cast< SwTxtNode
* >( &rNode
), nAktPos
) );
1839 ::sw::mark::IFieldmark
const * const pFieldmark
= pMarkAccess
->getFieldmarkFor( aPosition
);
1840 OSL_ENSURE( pFieldmark
, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
1842 if ( pFieldmark
&& pFieldmark
->GetFieldname() == ODF_FORMTEXT
)
1843 AppendBookmark( pFieldmark
->GetName(), false );
1844 ww::eField eFieldId
= lcl_getFieldId( pFieldmark
);
1845 String sCode
= lcl_getFieldCode( pFieldmark
);
1846 if ( pFieldmark
&& pFieldmark
->GetFieldname() == ODF_UNHANDLED
)
1848 IFieldmark::parameter_map_t::const_iterator it
= pFieldmark
->GetParameters()->find( ODF_ID_PARAM
);
1849 if ( it
!= pFieldmark
->GetParameters()->end() )
1852 it
->second
>>= sFieldId
;
1853 eFieldId
= (ww::eField
)sFieldId
.toInt32();
1856 it
= pFieldmark
->GetParameters()->find( ODF_CODE_PARAM
);
1857 if ( it
!= pFieldmark
->GetParameters()->end() )
1860 it
->second
>>= sOUCode
;
1865 bool bCommentRange
= pFieldmark
&& pFieldmark
->GetFieldname() == ODF_COMMENTRANGE
;
1867 AttrOutput().WritePostitFieldStart();
1869 OutputField( NULL
, eFieldId
, sCode
, WRITEFIELD_START
| WRITEFIELD_CMD_START
);
1871 if ( pFieldmark
&& pFieldmark
->GetFieldname( ) == ODF_FORMTEXT
)
1872 WriteFormData( *pFieldmark
);
1873 else if ( pFieldmark
&& pFieldmark
->GetFieldname( ) == ODF_HYPERLINK
)
1874 WriteHyperlinkData( *pFieldmark
);
1876 OutputField( NULL
, lcl_getFieldId( pFieldmark
), String(), WRITEFIELD_CMD_END
);
1878 if ( pFieldmark
&& pFieldmark
->GetFieldname() == ODF_UNHANDLED
)
1880 // Check for the presence of a linked OLE object
1881 IFieldmark::parameter_map_t::const_iterator it
= pFieldmark
->GetParameters()->find( ODF_OLE_PARAM
);
1882 if ( it
!= pFieldmark
->GetParameters()->end() )
1885 uno::Any aValue
= it
->second
;
1887 if ( !sOleId
.isEmpty() )
1888 OutputLinkedOLE( sOleId
);
1892 else if ( ch
== CH_TXT_ATR_FIELDEND
)
1894 SwPosition
aPosition( rNode
, SwIndex( const_cast< SwTxtNode
* >( &rNode
), nAktPos
) );
1895 ::sw::mark::IFieldmark
const * const pFieldmark
= pMarkAccess
->getFieldmarkFor( aPosition
);
1897 OSL_ENSURE( pFieldmark
, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" );
1899 ww::eField eFieldId
= lcl_getFieldId( pFieldmark
);
1900 if ( pFieldmark
&& pFieldmark
->GetFieldname() == ODF_UNHANDLED
)
1902 IFieldmark::parameter_map_t::const_iterator it
= pFieldmark
->GetParameters()->find( ODF_ID_PARAM
);
1903 if ( it
!= pFieldmark
->GetParameters()->end() )
1906 it
->second
>>= sFieldId
;
1907 eFieldId
= (ww::eField
)sFieldId
.toInt32();
1911 if (pFieldmark
&& pFieldmark
->GetFieldname() == ODF_COMMENTRANGE
)
1912 AttrOutput().WritePostitFieldEnd();
1914 OutputField( NULL
, eFieldId
, String(), WRITEFIELD_CLOSE
);
1916 if ( pFieldmark
&& pFieldmark
->GetFieldname() == ODF_FORMTEXT
)
1917 AppendBookmark( pFieldmark
->GetName(), false );
1919 else if ( ch
== CH_TXT_ATR_FORMELEMENT
)
1921 SwPosition
aPosition( rNode
, SwIndex( const_cast< SwTxtNode
* >( &rNode
), nAktPos
) );
1922 ::sw::mark::IFieldmark
const * const pFieldmark
= pMarkAccess
->getFieldmarkFor( aPosition
);
1923 OSL_ENSURE( pFieldmark
, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
1925 bool isDropdownOrCheckbox
= pFieldmark
&& (pFieldmark
->GetFieldname( ) == ODF_FORMDROPDOWN
||
1926 pFieldmark
->GetFieldname( ) == ODF_FORMCHECKBOX
);
1928 if ( isDropdownOrCheckbox
)
1929 AppendBookmark( pFieldmark
->GetName(), 0 );
1930 OutputField( NULL
, lcl_getFieldId( pFieldmark
),
1931 lcl_getFieldCode( pFieldmark
),
1932 WRITEFIELD_START
| WRITEFIELD_CMD_START
);
1933 if ( isDropdownOrCheckbox
)
1934 WriteFormData( *pFieldmark
);
1935 OutputField( NULL
, lcl_getFieldId( pFieldmark
), String(), WRITEFIELD_CLOSE
);
1936 if ( isDropdownOrCheckbox
)
1937 AppendBookmark( pFieldmark
->GetName(), false );
1939 nLen
-= static_cast< sal_uInt16
>( ofs
);
1941 String
aSnippet( aAttrIter
.GetSnippet( aStr
, nAktPos
+ static_cast< sal_uInt16
>( ofs
), nLen
) );
1942 if ( ( nTxtTyp
== TXT_EDN
|| nTxtTyp
== TXT_FTN
) && nAktPos
== 0 && nLen
> 0 )
1944 // Insert tab for aesthetic puposes #i24762#
1945 if ( aSnippet
.GetChar( 0 ) != 0x09 )
1946 aSnippet
.Insert( 0x09, 0 );
1948 AttrOutput().RunText( aSnippet
, eChrSet
);
1951 if ( aAttrIter
.IsDropCap( nNextAttr
) )
1952 AttrOutput().FormatDrop( rNode
, aAttrIter
.GetSwFmtDrop(), nStyle
, pTextNodeInfo
, pTextNodeInfoInner
);
1956 // Output the character attributes
1957 // #i51277# do this before writing flys at end of paragraph
1958 AttrOutput().StartRunProperties();
1959 aAttrIter
.OutAttr( nAktPos
);
1960 AttrOutput().EndRunProperties( pRedlineData
);
1963 // At the end of line, output the attributes until the CR.
1964 // Exception: footnotes at the end of line
1965 if ( nNextAttr
== nEnd
)
1967 OSL_ENSURE( nOpenAttrWithRange
>= 0, "odd to see this happening, expected >= 0" );
1968 if ( !bTxtAtr
&& nOpenAttrWithRange
<= 0 )
1970 if ( aAttrIter
.IsRedlineAtEnd( nEnd
) )
1971 bRedlineAtEnd
= true;
1974 // insert final graphic anchors if any before CR
1975 aAttrIter
.OutFlys( nEnd
);
1976 // insert final bookmarks if any before CR and after flys
1977 AppendBookmarks( rNode
, nEnd
, 1 );
1980 m_aCurrentCharPropStarts
.pop();
1981 AttrOutput().EndTOX( *pTOXSect
);
1983 //For i120928,the position of the bullet's graphic is at end of doc
1984 if (bLastCR
&& (!bExported
))
1986 ExportGrfBullet(rNode
);
1990 WriteCR( pTextNodeInfoInner
);
1997 // Output the character attributes
1998 // do it after WriteCR for an empty paragraph (otherwise
1999 // WW8_WrFkp::Append throws SPRMs away...)
2000 AttrOutput().StartRunProperties();
2001 aAttrIter
.OutAttr( nAktPos
);
2002 AttrOutput().EndRunProperties( pRedlineData
);
2005 // Exception: footnotes at the end of line
2006 if ( nNextAttr
== nEnd
)
2008 OSL_ENSURE(nOpenAttrWithRange
>= 0,
2009 "odd to see this happening, expected >= 0");
2010 bool bAttrWithRange
= (nOpenAttrWithRange
> 0);
2011 if ( nAktPos
!= nEnd
)
2013 nOpenAttrWithRange
+= aAttrIter
.OutAttrWithRange(nEnd
);
2014 OSL_ENSURE(nOpenAttrWithRange
== 0,
2015 "odd to see this happening, expected 0");
2018 AttrOutput().OutputFKP();
2020 if ( bTxtAtr
|| bAttrWithRange
|| bRedlineAtEnd
)
2022 // insert final graphic anchors if any before CR
2023 aAttrIter
.OutFlys( nEnd
);
2024 // insert final bookmarks if any before CR and after flys
2025 AppendBookmarks( rNode
, nEnd
, 1 );
2026 // #i120928 - position of the bullet's graphic is at end of doc
2027 if (bLastCR
&& (!bExported
))
2029 ExportGrfBullet(rNode
);
2035 m_aCurrentCharPropStarts
.pop();
2036 AttrOutput().EndTOX( *pTOXSect
);
2039 WriteCR( pTextNodeInfoInner
);
2041 if ( bRedlineAtEnd
)
2043 AttrOutput().Redline( aAttrIter
.GetRedline( nEnd
) );
2044 AttrOutput().OutputFKP();
2049 AttrOutput().WritePostitFieldReference();
2051 AttrOutput().EndRun();
2053 nAktPos
= nNextAttr
;
2054 UpdatePosition( &aAttrIter
, nAktPos
, nEnd
);
2055 eChrSet
= aAttrIter
.GetCharSet();
2057 while ( nAktPos
< nEnd
);
2059 AttrOutput().StartParagraphProperties( rNode
);
2061 AttrOutput().ParagraphStyle( nStyle
);
2063 if ( mpParentFrame
&& IsInTable() ) // Fly-Attrs
2064 OutputFormat( mpParentFrame
->GetFrmFmt(), false, false, true );
2066 if ( pTextNodeInfo
.get() != NULL
)
2069 SAL_INFO( "sw.ww8", pTextNodeInfo
->toString());
2072 AttrOutput().TableInfoCell( pTextNodeInfoInner
);
2073 if (pTextNodeInfoInner
->isFirstInTable())
2075 const SwTable
* pTable
= pTextNodeInfoInner
->getTable();
2077 const SwTableFmt
* pTabFmt
= pTable
->GetTableFmt();
2078 if (pTabFmt
!= NULL
)
2080 if (pTabFmt
->GetBreak().GetBreak() == SVX_BREAK_PAGE_BEFORE
)
2081 AttrOutput().PageBreakBefore(true);
2088 SfxItemSet
* pTmpSet
= 0;
2089 const sal_uInt8 nPrvNxtNd
= rNode
.HasPrevNextLayNode();
2091 if( (ND_HAS_PREV_LAYNODE
|ND_HAS_NEXT_LAYNODE
) != nPrvNxtNd
)
2093 const SfxPoolItem
* pItem
;
2094 if( SFX_ITEM_SET
== rNode
.GetSwAttrSet().GetItemState(
2095 RES_UL_SPACE
, true, &pItem
) &&
2096 ( ( !( ND_HAS_PREV_LAYNODE
& nPrvNxtNd
) &&
2097 ((SvxULSpaceItem
*)pItem
)->GetUpper()) ||
2098 ( !( ND_HAS_NEXT_LAYNODE
& nPrvNxtNd
) &&
2099 ((SvxULSpaceItem
*)pItem
)->GetLower()) ))
2101 pTmpSet
= new SfxItemSet( rNode
.GetSwAttrSet() );
2102 SvxULSpaceItem
aUL( *(SvxULSpaceItem
*)pItem
);
2103 // #i25901#- consider compatibility option
2104 if (!pDoc
->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES
))
2106 if( !(ND_HAS_PREV_LAYNODE
& nPrvNxtNd
))
2109 // #i25901# - consider compatibility option
2110 if (!pDoc
->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS
))
2112 if( !(ND_HAS_NEXT_LAYNODE
& nPrvNxtNd
))
2115 pTmpSet
->Put( aUL
);
2119 bool bParaRTL
= false;
2120 const SvxFrameDirectionItem
* pItem
= (const SvxFrameDirectionItem
*)
2121 rNode
.GetSwAttrSet().GetItem(RES_FRAMEDIR
);
2122 if ( aAttrIter
.IsParaRTL())
2125 if( rNode
.IsNumbered())
2127 const SwNumRule
* pRule
= rNode
.GetNumRule();
2128 sal_uInt8 nLvl
= static_cast< sal_uInt8
>( rNode
.GetActualListLevel() );
2129 const SwNumFmt
* pFmt
= pRule
->GetNumFmt( nLvl
);
2131 pFmt
= &pRule
->Get( nLvl
);
2134 pTmpSet
= new SfxItemSet( rNode
.GetSwAttrSet() );
2136 SvxLRSpaceItem
aLR(ItemGet
<SvxLRSpaceItem
>(*pTmpSet
, RES_LR_SPACE
));
2138 if ( pFmt
->GetPositionAndSpaceMode() ==
2139 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
2141 aLR
.SetTxtLeft( aLR
.GetTxtLeft() + pFmt
->GetAbsLSpace() );
2144 if( rNode
.IsNumbered() && rNode
.IsCountedInList() )
2147 if ( pFmt
->GetPositionAndSpaceMode() ==
2148 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
2151 aLR
.SetTxtFirstLineOfstValue(pFmt
->GetAbsLSpace() - pFmt
->GetFirstLineOffset());
2153 aLR
.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt
));
2156 // correct fix for issue i94187
2158 pTmpSet
->GetItemState(RES_PARATR_NUMRULE
, false) )
2160 // List style set via paragraph style - then put it into the itemset.
2161 // This is needed to get list level and list id exported for
2163 pTmpSet
->Put( SwNumRuleItem( pRule
->GetName() ));
2165 // Put indent values into the itemset in case that the list
2166 // style is applied via paragraph style and the list level
2167 // indent values are not applicable.
2168 if ( pFmt
->GetPositionAndSpaceMode() ==
2169 SvxNumberFormat::LABEL_ALIGNMENT
&&
2170 !rNode
.AreListLevelIndentsApplicable() )
2172 pTmpSet
->Put( aLR
);
2177 pTmpSet
->ClearItem(RES_PARATR_NUMRULE
);
2180 if ( pFmt
->GetPositionAndSpaceMode() ==
2181 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
2186 SvxTabStopItem
aItem(
2187 ItemGet
<SvxTabStopItem
>(*pTmpSet
, RES_PARATR_TABSTOP
));
2188 SvxTabStop
aTabStop(pFmt
->GetAbsLSpace());
2189 aItem
.Insert(aTabStop
);
2190 pTmpSet
->Put(aItem
);
2192 MSWordExportBase::CorrectTabStopInSet(*pTmpSet
, pFmt
->GetAbsLSpace());
2197 If a given para is using the FRMDIR_ENVIRONMENT direction we
2198 cannot export that, its its ltr then that's ok as thats word's
2199 default. Otherwise we must add a RTL attribute to our export list
2201 pItem
= (const SvxFrameDirectionItem
*)
2202 rNode
.GetSwAttrSet().GetItem(RES_FRAMEDIR
);
2204 (!pItem
|| pItem
->GetValue() == FRMDIR_ENVIRONMENT
) &&
2205 aAttrIter
.IsParaRTL()
2209 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2211 pTmpSet
->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP
, RES_FRAMEDIR
));
2213 // move code for handling of numbered,
2214 // but not counted paragraphs to this place. Otherwise, the paragraph
2215 // isn't exported as numbered, but not counted, if no other attribute
2216 // is found in <pTmpSet>
2217 // #i44815# adjust numbering/indents for numbered paragraphs
2218 // without number (NO_NUMLEVEL)
2219 // #i47013# need to check rNode.GetNumRule()!=NULL as well.
2220 if ( ! rNode
.IsCountedInList() && rNode
.GetNumRule()!=NULL
)
2222 // WW8 does not know numbered paragraphs without number
2223 // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
2224 // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
2225 // no numbering. Here, we will adjust the indents to match
2229 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2231 // create new LRSpace item, based on the current (if present)
2232 const SfxPoolItem
* pPoolItem
= NULL
;
2233 pTmpSet
->GetItemState(RES_LR_SPACE
, sal_True
, &pPoolItem
);
2234 SvxLRSpaceItem
aLRSpace(
2235 ( pPoolItem
== NULL
)
2236 ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE
)
2237 : *static_cast<const SvxLRSpaceItem
*>( pPoolItem
) );
2239 // new left margin = old left + label space
2240 const SwNumRule
* pRule
= rNode
.GetNumRule();
2241 const SwNumFmt
& rNumFmt
= pRule
->Get( static_cast< sal_uInt16
>(rNode
.GetActualListLevel()) );
2243 if ( rNumFmt
.GetPositionAndSpaceMode() ==
2244 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
2246 aLRSpace
.SetTxtLeft( aLRSpace
.GetLeft() + rNumFmt
.GetAbsLSpace() );
2248 // new first line indent = 0
2249 // (first line indent is ignored for NO_NUMLEVEL)
2251 aLRSpace
.SetTxtFirstLineOfst( 0 );
2253 // put back the new item
2254 pTmpSet
->Put( aLRSpace
);
2257 // assure that numbering rule is in <pTmpSet>
2258 if (SFX_ITEM_SET
!= pTmpSet
->GetItemState(RES_PARATR_NUMRULE
, false) )
2260 pTmpSet
->Put( SwNumRuleItem( pRule
->GetName() ));
2265 // Export page break after attribute from paragraph style.
2266 // If page break attribute at the text node exist, an existing page
2267 // break after at the paragraph style hasn't got to be considered.
2268 if ( !rNode
.GetpSwAttrSet() ||
2269 SFX_ITEM_SET
!= rNode
.GetpSwAttrSet()->GetItemState(RES_BREAK
, false) )
2271 const SvxFmtBreakItem
* pBreakAtParaStyle
=
2272 &(ItemGet
<SvxFmtBreakItem
>(rNode
.GetSwAttrSet(), RES_BREAK
));
2273 if ( pBreakAtParaStyle
&&
2274 pBreakAtParaStyle
->GetBreak() == SVX_BREAK_PAGE_AFTER
)
2278 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2280 pTmpSet
->Put( *pBreakAtParaStyle
);
2283 { // Even a pagedesc item is set, the break item can be set 'NONE',
2284 // this has to be overruled.
2285 const SwFmtPageDesc
& rPageDescAtParaStyle
=
2286 ItemGet
<SwFmtPageDesc
>( rNode
, RES_PAGEDESC
);
2287 if( rPageDescAtParaStyle
.KnowsPageDesc() )
2288 pTmpSet
->ClearItem( RES_BREAK
);
2292 // #i76520# Emulate non-splitting tables
2295 const SwTableNode
* pTableNode
= rNode
.FindTableNode();
2299 const SwTable
& rTable
= pTableNode
->GetTable();
2300 const SvxFmtKeepItem
& rKeep
= rTable
.GetFrmFmt()->GetKeep();
2301 const bool bKeep
= rKeep
.GetValue();
2302 const bool bDontSplit
= !bKeep
?
2303 !rTable
.GetFrmFmt()->GetLayoutSplit().GetValue() :
2306 if ( bKeep
|| bDontSplit
)
2308 // bKeep: set keep at first paragraphs in all lines
2309 // bDontSplit : set keep at first paragraphs in all lines except from last line
2310 // but only for non-complex tables
2311 const SwTableBox
* pBox
= rNode
.GetTblBox();
2312 const SwTableLine
* pLine
= pBox
? pBox
->GetUpper() : 0;
2314 if ( pLine
&& !pLine
->GetUpper() )
2316 // check if box is first in that line:
2317 if ( 0 == pLine
->GetTabBoxes().GetPos( pBox
) && pBox
->GetSttNd() )
2319 // check if paragraph is first in that line:
2320 if ( 1 == ( rNode
.GetIndex() - pBox
->GetSttNd()->GetIndex() ) )
2322 bool bSetAtPara
= false;
2325 else if ( bDontSplit
)
2327 // check if pLine isn't last line in table
2328 if ( rTable
.GetTabLines().size() - rTable
.GetTabLines().GetPos( pLine
) != 1 )
2335 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2337 const SvxFmtKeepItem
aKeepItem( sal_True
, RES_KEEP
);
2338 pTmpSet
->Put( aKeepItem
);
2347 const SfxItemSet
* pNewSet
= pTmpSet
? pTmpSet
: rNode
.GetpSwAttrSet();
2350 pStyAttr
= &rNode
.GetAnyFmtColl().GetAttrSet();
2352 const SwModify
* pOldMod
= pOutFmtNode
;
2353 pOutFmtNode
= &rNode
;
2355 // Pap-Attrs, so script is not necessary
2356 OutputItemSet( *pNewSet
, true, false, i18n::ScriptType::LATIN
, false);
2359 pOutFmtNode
= pOldMod
;
2361 if( pNewSet
!= rNode
.GetpSwAttrSet() )
2366 AttrOutput().EndParagraphProperties();
2368 AttrOutput().EndParagraph( pTextNodeInfoInner
);
2370 SAL_INFO( "sw.ww8", "</OutWW8_SwTxtNode>" );
2373 void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo
)
2376 ShortToSVBT16( GetExport().nStyleBeforeFly
, nSty
);
2378 ww8::WW8TableNodeInfo::Inners_t::const_iterator
aIt( pNodeInfo
->getInners().begin() );
2379 ww8::WW8TableNodeInfo::Inners_t::const_iterator
aItEnd( pNodeInfo
->getInners().end() );
2381 while (aIt
!= aItEnd
)
2383 ww8::WW8TableNodeInfoInner::Pointer_t pInner
= aIt
->second
;
2384 if ( pInner
->isEndOfCell() )
2386 TableRowEnd( pInner
->getDepth() );
2388 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), (sal_uInt8
*)&nSty
, (sal_uInt8
*)&nSty
+2); // Style #
2389 TableInfoRow( pInner
);
2390 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data());
2391 m_rWW8Export
.pO
->clear();
2394 if ( pInner
->isEndOfLine() )
2404 void WW8AttributeOutput::EmptyParagraph()
2406 m_rWW8Export
.WriteStringAsPara( aEmptyStr
);
2409 bool MSWordExportBase::NoPageBreakSection( const SfxItemSet
* pSet
)
2412 const SfxPoolItem
* pI
;
2415 bool bNoPageBreak
= false;
2416 if ( SFX_ITEM_ON
!= pSet
->GetItemState(RES_PAGEDESC
, true, &pI
)
2417 || 0 == ((SwFmtPageDesc
*)pI
)->GetPageDesc() )
2419 bNoPageBreak
= true;
2424 if (SFX_ITEM_ON
!= pSet
->GetItemState(RES_BREAK
, true, &pI
))
2425 bNoPageBreak
= true;
2428 SvxBreak eBreak
= ((const SvxFmtBreakItem
*)pI
)->GetBreak();
2431 case SVX_BREAK_PAGE_BEFORE
:
2432 case SVX_BREAK_PAGE_AFTER
:
2433 bNoPageBreak
= false;
2440 bRet
= bNoPageBreak
;
2446 void MSWordExportBase::OutputSectionNode( const SwSectionNode
& rSectionNode
)
2448 const SwSection
& rSection
= rSectionNode
.GetSection();
2450 SwNodeIndex
aIdx( rSectionNode
, 1 );
2451 const SwNode
& rNd
= aIdx
.GetNode();
2452 if ( !rNd
.IsSectionNode() && !IsInTable() ) //No sections in table
2454 // if the first Node inside the section has an own
2455 // PageDesc or PageBreak attribut, then dont write
2456 // here the section break
2457 sal_uLong nRstLnNum
= 0;
2458 const SfxItemSet
* pSet
;
2459 if ( rNd
.IsTableNode() )
2460 pSet
= &rNd
.GetTableNode()->GetTable().GetFrmFmt()->GetAttrSet();
2461 else if ( rNd
.IsCntntNode() )
2463 pSet
= &rNd
.GetCntntNode()->GetSwAttrSet();
2464 nRstLnNum
= ((SwFmtLineNumber
&)pSet
->Get(
2465 RES_LINENUMBER
)).GetStartValue();
2470 if ( pSet
&& NoPageBreakSection( pSet
) )
2475 // new Section with no own PageDesc/-Break
2476 // -> write follow section break;
2477 const SwSectionFmt
& rFmt
= *rSection
.GetFmt();
2478 ReplaceCr( msword::PageBreak
); // Indikator fuer Page/Section-Break
2480 // Get the page in use at the top of this section
2481 SwNodeIndex
aIdxTmp(rSectionNode
, 1);
2482 const SwPageDesc
*pCurrent
=
2483 SwPageDesc::GetPageDescOfNode(aIdxTmp
.GetNode());
2485 pCurrent
= pAktPageDesc
;
2487 AppendSection( pCurrent
, &rFmt
, nRstLnNum
);
2490 if ( TOX_CONTENT_SECTION
== rSection
.GetType() )
2495 void WW8Export::AppendSection( const SwPageDesc
*pPageDesc
, const SwSectionFmt
* pFmt
, sal_uLong nLnNum
)
2497 pSepx
->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc
, pFmt
, nLnNum
);
2502 void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode
& rNd
)
2504 OSL_ENSURE(!bWrtWW8
, "I shouldn't be needed for Word >=8");
2508 if (const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
2510 for( sal_uInt16 n
=0; n
< pTxtAttrs
->Count(); ++n
)
2512 const SwTxtAttr
* pAttr
= (*pTxtAttrs
)[ n
];
2513 if( RES_TXTATR_FLYCNT
== pAttr
->Which() )
2515 // attribute bound to a character
2516 const SwFmtFlyCnt
& rFlyCntnt
= pAttr
->GetFlyCnt();
2517 const SwFlyFrmFmt
& rFlyFrmFmt
= *(SwFlyFrmFmt
*)rFlyCntnt
.GetFrmFmt();
2518 const SwNodeIndex
* pNodeIndex
= rFlyFrmFmt
.GetCntnt().GetCntntIdx();
2522 sal_uLong nStt
= pNodeIndex
->GetIndex()+1,
2523 nEnd
= pNodeIndex
->GetNode().EndOfSectionIndex();
2525 if( (nStt
< nEnd
) && !pDoc
->GetNodes()[ nStt
]->IsNoTxtNode() )
2528 // get rectangle (bounding box?) of Fly and paragraph
2529 SwRect
aParentRect(rNd
.FindLayoutRect(false, &aOffset
)),
2530 aFlyRect(rFlyFrmFmt
.FindLayoutRect(false, &aOffset
) );
2532 aOffset
= aFlyRect
.Pos() - aParentRect
.Pos();
2534 // let PaM point to content of Fly-frame format
2535 SaveData( nStt
, nEnd
);
2537 // is analysed in OutputFormat()
2538 pFlyOffset
= &aOffset
;
2539 eNewAnchorType
= rFlyFrmFmt
.GetAnchor().GetAnchorId();
2540 sw::Frame
aFrm(rFlyFrmFmt
, SwPosition(rNd
));
2541 mpParentFrame
= &aFrm
;
2542 // Ok, write it out:
2553 void WW8AttributeOutput::OutputFlyFrame_Impl( const sw::Frame
& rFmt
, const Point
& rNdTopLeft
)
2555 const SwFrmFmt
&rFrmFmt
= rFmt
.GetFrmFmt();
2556 const SwFmtAnchor
& rAnch
= rFrmFmt
.GetAnchor();
2558 bool bUseEscher
= m_rWW8Export
.bWrtWW8
;
2560 if ( m_rWW8Export
.bWrtWW8
&& rFmt
.IsInline() )
2562 sw::Frame::WriterSource eType
= rFmt
.GetWriterType();
2563 if ((eType
== sw::Frame::eGraphic
) || (eType
== sw::Frame::eOle
))
2569 A special case for converting some inline form controls to form fields
2570 when in winword 8+ mode
2572 if ((bUseEscher
== true) && (eType
== sw::Frame::eFormControl
))
2574 if ( m_rWW8Export
.MiserableFormFieldExportHack( rFrmFmt
) )
2581 OSL_ENSURE( m_rWW8Export
.bWrtWW8
, "this has gone horribly wrong" );
2583 m_rWW8Export
.AppendFlyInFlys(rFmt
, rNdTopLeft
);
2589 // Hole vom Node und vom letzten Node die Position in der Section
2590 const SwNodeIndex
* pNodeIndex
= rFrmFmt
.GetCntnt().GetCntntIdx();
2592 sal_uLong nStt
= pNodeIndex
? pNodeIndex
->GetIndex()+1 : 0;
2593 sal_uLong nEnd
= pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : 0;
2595 if( nStt
>= nEnd
) // no range, hence no valid node
2598 if ( !m_rWW8Export
.IsInTable() && rFmt
.IsInline() )
2600 //Test to see if this textbox contains only a single graphic/ole
2601 SwTxtNode
* pParTxtNode
= rAnch
.GetCntntAnchor()->nNode
.GetNode().GetTxtNode();
2602 if ( pParTxtNode
&& !m_rWW8Export
.pDoc
->GetNodes()[ nStt
]->IsNoTxtNode() )
2608 m_rWW8Export
.SaveData( nStt
, nEnd
);
2611 if ( m_rWW8Export
.mpParentFrame
)
2613 /* Munge flys in fly into absolutely positioned elements for word 6 */
2614 const SwTxtNode
* pParTxtNode
= rAnch
.GetCntntAnchor()->nNode
.GetNode().GetTxtNode();
2615 const SwRect aPageRect
= pParTxtNode
->FindPageFrmRect( sal_False
, 0, sal_False
);
2617 aOffset
= rFrmFmt
.FindLayoutRect().Pos();
2618 aOffset
-= aPageRect
.Pos();
2620 m_rWW8Export
.pFlyOffset
= &aOffset
;
2621 m_rWW8Export
.eNewAnchorType
= FLY_AT_PAGE
;
2624 m_rWW8Export
.mpParentFrame
= &rFmt
;
2626 m_rWW8Export
.IsInTable() &&
2627 (FLY_AT_PAGE
!= rAnch
.GetAnchorId()) &&
2628 !m_rWW8Export
.pDoc
->GetNodes()[ nStt
]->IsNoTxtNode()
2631 // note: set Flag bOutTable again,
2632 // because we deliver the normal content of the table cell, and no border
2633 // ( Flag was deleted above in aSaveData() )
2634 m_rWW8Export
.bOutTable
= true;
2635 const String
& rName
= rFrmFmt
.GetName();
2636 m_rWW8Export
.StartCommentOutput(rName
);
2637 m_rWW8Export
.WriteText();
2638 m_rWW8Export
.EndCommentOutput(rName
);
2641 m_rWW8Export
.WriteText();
2643 m_rWW8Export
.RestoreData();
2648 void AttributeOutputBase::OutputFlyFrame( const sw::Frame
& rFmt
)
2650 if ( !rFmt
.GetCntntNode() )
2653 const SwCntntNode
&rNode
= *rFmt
.GetCntntNode();
2654 Point aNdPos
, aPgPos
;
2656 bool bValidNdPos
= false, bValidPgPos
= false;
2658 if (FLY_AT_PAGE
== rFmt
.GetFrmFmt().GetAnchor().GetAnchorId())
2660 // get the Layout Node-Position.
2663 aPgPos
= rNode
.FindPageFrmRect(false, &aPgPos
).Pos();
2670 // get the Layout Node-Position.
2673 aNdPos
= rNode
.FindLayoutRect(false, &aNdPos
).Pos();
2679 OutputFlyFrame_Impl( rFmt
, *pLayPos
);
2682 // write data of any redline
2683 void WW8AttributeOutput::Redline( const SwRedlineData
* pRedline
)
2688 if ( pRedline
->Next() )
2689 Redline( pRedline
->Next() );
2691 static sal_uInt16 aSprmIds
[ 2 * 2 * 3 ] =
2694 NS_sprm::LN_CFRMark
, NS_sprm::LN_CIbstRMark
, NS_sprm::LN_CDttmRMark
, // for WW8
2695 0x0042, 0x0045, 0x0046, // for WW6
2697 NS_sprm::LN_CFRMarkDel
, NS_sprm::LN_CIbstRMarkDel
, NS_sprm::LN_CDttmRMarkDel
, // for WW8
2698 0x0041, 0x0045, 0x0046 // for WW6
2701 const sal_uInt16
* pSprmIds
= 0;
2702 switch( pRedline
->GetType() )
2704 case nsRedlineType_t::REDLINE_INSERT
:
2705 pSprmIds
= aSprmIds
;
2708 case nsRedlineType_t::REDLINE_DELETE
:
2709 pSprmIds
= aSprmIds
+ (2 * 3);
2712 case nsRedlineType_t::REDLINE_FORMAT
:
2713 if( m_rWW8Export
.bWrtWW8
)
2715 m_rWW8Export
.InsUInt16( NS_sprm::LN_CPropRMark
);
2716 m_rWW8Export
.pO
->push_back( 7 ); // len
2717 m_rWW8Export
.pO
->push_back( 1 );
2718 m_rWW8Export
.InsUInt16( m_rWW8Export
.AddRedlineAuthor( pRedline
->GetAuthor() ) );
2719 m_rWW8Export
.InsUInt32( sw::ms::DateTime2DTTM( pRedline
->GetTimeStamp() ));
2723 OSL_ENSURE(!this, "Unhandled redline type for export");
2729 if ( !m_rWW8Export
.bWrtWW8
)
2732 if ( m_rWW8Export
.bWrtWW8
)
2733 m_rWW8Export
.InsUInt16( pSprmIds
[0] );
2735 m_rWW8Export
.pO
->push_back( msword_cast
<sal_uInt8
>(pSprmIds
[0]) );
2736 m_rWW8Export
.pO
->push_back( 1 );
2738 if ( m_rWW8Export
.bWrtWW8
)
2739 m_rWW8Export
.InsUInt16( pSprmIds
[1] );
2741 m_rWW8Export
.pO
->push_back( msword_cast
<sal_uInt8
>(pSprmIds
[1]) );
2742 m_rWW8Export
.InsUInt16( m_rWW8Export
.AddRedlineAuthor( pRedline
->GetAuthor() ) );
2744 if ( m_rWW8Export
.bWrtWW8
)
2745 m_rWW8Export
.InsUInt16( pSprmIds
[2] );
2747 m_rWW8Export
.pO
->push_back( msword_cast
<sal_uInt8
>(pSprmIds
[2]) );
2748 m_rWW8Export
.InsUInt32( sw::ms::DateTime2DTTM( pRedline
->GetTimeStamp() ));
2753 void MSWordExportBase::OutputContentNode( const SwCntntNode
& rNode
)
2755 switch ( rNode
.GetNodeType() )
2759 const SwTxtNode
& rTextNode
= *rNode
.GetTxtNode();
2760 if( !mbOutOutlineOnly
|| rTextNode
.IsOutline() )
2761 OutputTextNode( rTextNode
);
2765 OutputGrfNode( *rNode
.GetGrfNode() );
2768 OutputOLENode( *rNode
.GetOLENode() );
2771 OSL_TRACE("Unhandled node, type == %d", rNode
.GetNodeType() );
2776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */