1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtw8nds.cxx,v $
10 * $Revision: 1.109.40.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
41 #include <hintids.hxx>
42 #include <tools/urlobj.hxx>
43 #include <svx/boxitem.hxx>
44 #include <svx/cmapitem.hxx>
45 #include <svx/langitem.hxx>
46 #include <svx/svxfont.hxx>
47 #include <svx/lrspitem.hxx>
48 #include <svx/brshitem.hxx>
49 #include <svx/fontitem.hxx>
50 #include <svx/keepitem.hxx>
51 #include <svx/fhgtitem.hxx>
52 #include <svx/ulspitem.hxx>
53 #include <svx/brkitem.hxx>
54 #include <svx/frmdiritem.hxx>
55 #include <svx/tstpitem.hxx>
56 #include "svtools/urihelper.hxx"
57 #include <svtools/whiter.hxx>
58 #include <fmtpdsc.hxx>
59 #include <fmtfsize.hxx>
60 #include <fmtornt.hxx>
61 #include <fmtlsplt.hxx>
62 #include <fmtflcnt.hxx>
63 #include <fmtanchr.hxx>
64 #include <fmtcntnt.hxx>
67 #include <txatbase.hxx>
68 #include <fmtinfmt.hxx>
69 #include <fmtrfmrk.hxx>
70 #include <fchrfmt.hxx>
71 #include <fmtautofmt.hxx>
72 #include <charfmt.hxx>
78 #include <swtable.hxx>
79 #include <section.hxx>
80 #include <pagedesc.hxx>
83 #include <redline.hxx>
84 #include <wrtswtbl.hxx>
85 #include <htmltbl.hxx>
86 #include <txttxmrk.hxx>
87 #include <fmtline.hxx>
88 #include <fmtruby.hxx>
89 #include <breakit.hxx>
91 #include <fmtsrnd.hxx>
92 #include <fmtrowsplt.hxx>
93 #include <com/sun/star/i18n/ScriptType.hdl>
94 #include <com/sun/star/i18n/WordType.hpp>
96 #include <writerfilter/doctok/sprmids.hxx>
98 #include "writerhelper.hxx"
99 #include "writerwordglue.hxx"
100 #include <numrule.hxx>
101 #include "wrtww8.hxx"
102 #include "ww8par.hxx"
104 #include "ww8attributeoutput.hxx"
109 using namespace ::com::sun::star
;
110 using namespace ::com::sun::star::i18n
;
111 using namespace sw::util
;
112 using namespace sw::types
;
113 using namespace sw::mark
;
114 using namespace nsFieldFlags
;
117 static String
lcl_getFieldCode( const IFieldmark
* pFieldmark
) {
118 ASSERT(pFieldmark
!=NULL
, "where is my fieldmark???");
119 if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMTEXT
) ) {
120 return String::CreateFromAscii(" FORMTEXT ");
121 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMDROPDOWN
) ) {
122 return String::CreateFromAscii(" FORMDROPDOWN ");
123 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMCHECKBOX
) ) {
124 return String::CreateFromAscii(" FORMCHECKBOX ");
125 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_TOC
) ) {
126 return String::CreateFromAscii(" TOC ");
127 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_HYPERLINK
) ) {
128 return String::CreateFromAscii(" HYPERLINK ");
129 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_PAGEREF
) ) {
130 return String::CreateFromAscii(" PAGEREF ");
132 return pFieldmark
->GetFieldname();
136 ww::eField
lcl_getFieldId( const IFieldmark
* pFieldmark
) {
137 ASSERT(pFieldmark
!=NULL
, "where is my fieldmark???");
138 if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMTEXT
) ) {
139 return ww::eFORMTEXT
;
140 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMDROPDOWN
) ) {
141 return ww::eFORMDROPDOWN
;
142 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMCHECKBOX
) ) {
143 return ww::eFORMCHECKBOX
;
144 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_TOC
) ) {
146 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_HYPERLINK
) ) {
147 return ww::eHYPERLINK
;
148 } else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_PAGEREF
) ) {
157 MSWordAttrIter::MSWordAttrIter( MSWordExportBase
& rExport
)
158 : pOld( rExport
.pChpIter
), m_rExport( rExport
)
160 m_rExport
.pChpIter
= this;
163 MSWordAttrIter::~MSWordAttrIter()
165 m_rExport
.pChpIter
= pOld
;
168 // Die Klasse SwAttrIter ist eine Hilfe zum Aufbauen der Fkp.chpx.
169 // Dabei werden nur Zeichen-Attribute beachtet; Absatz-Attribute brauchen
170 // diese Behandlung nicht.
171 // Die Absatz- und Textattribute des Writers kommen rein, und es wird
172 // mit Where() die naechste Position geliefert, an der sich die Attribute
173 // aendern. IsTxtAtr() sagt, ob sich an der mit Where() gelieferten Position
174 // ein Attribut ohne Ende und mit \xff im Text befindet.
175 // Mit OutAttr() werden die Attribute an der angegebenen SwPos
178 class SwAttrIter
: public MSWordAttrIter
181 const SwTxtNode
& rNd
;
184 cCharRunIter maCharRunIter
;
186 rtl_TextEncoding meChrSet
;
190 const SwRedline
* pCurRedline
;
191 xub_StrLen nAktSwPos
;
192 USHORT nCurRedlinePos
;
196 const SwFmtDrop
&mrSwFmtDrop
;
198 sw::Frames maFlyFrms
; // #i2916#
199 sw::FrameIter maFlyIter
;
201 xub_StrLen
SearchNext( xub_StrLen nStartPos
);
202 void FieldVanish( const String
& rTxt
);
204 void OutSwFmtRefMark(const SwFmtRefMark
& rAttr
, bool bStart
);
206 void IterToCurrent();
209 SwAttrIter(const SwAttrIter
&);
210 SwAttrIter
& operator=(const SwAttrIter
&);
212 SwAttrIter( MSWordExportBase
& rWr
, const SwTxtNode
& rNd
);
214 bool IsTxtAttr( xub_StrLen nSwPos
);
215 bool IsRedlineAtEnd( xub_StrLen nPos
) const;
216 bool IsDropCap( int nSwPos
);
217 bool RequiresImplicitBookmark();
219 void NextPos() { nAktSwPos
= SearchNext( nAktSwPos
+ 1 ); }
221 void OutAttr( xub_StrLen nSwPos
);
222 virtual const SfxPoolItem
* HasTextItem( USHORT nWhich
) const;
223 virtual const SfxPoolItem
& GetItem( USHORT nWhich
) const;
224 int OutAttrWithRange(xub_StrLen nPos
);
225 const SwRedlineData
* GetRedline( xub_StrLen nPos
);
226 void OutFlys(xub_StrLen nSwPos
);
228 xub_StrLen
WhereNext() const { return nAktSwPos
; }
229 sal_uInt16
GetScript() const { return mnScript
; }
230 bool IsCharRTL() const { return mbCharIsRTL
; }
231 bool IsParaRTL() const { return mbParaIsRTL
; }
232 rtl_TextEncoding
GetCharSet() const { return meChrSet
; }
233 String
GetSnippet(const String
&rStr
, xub_StrLen nAktPos
,
234 xub_StrLen nLen
) const;
235 const SwFmtDrop
& GetSwFmtDrop() const { return mrSwFmtDrop
; }
239 public std::binary_function
<const sw::Frame
&, const sw::Frame
&, bool>
242 bool operator()(const sw::Frame
&rOne
, const sw::Frame
&rTwo
) const
244 return rOne
.GetPosition() < rTwo
.GetPosition();
248 void SwAttrIter::IterToCurrent()
250 ASSERT(maCharRuns
.begin() != maCharRuns
.end(), "Impossible");
251 mnScript
= maCharRunIter
->mnScript
;
252 meChrSet
= maCharRunIter
->meCharSet
;
253 mbCharIsRTL
= maCharRunIter
->mbRTL
;
256 SwAttrIter::SwAttrIter(MSWordExportBase
& rWr
, const SwTxtNode
& rTxtNd
) :
259 maCharRuns(GetPseudoCharRuns(rTxtNd
, 0, !rWr
.HackIsWW8OrHigher())),
262 nCurRedlinePos(USHRT_MAX
),
263 mrSwFmtDrop(rTxtNd
.GetSwAttrSet().GetDrop())
266 SwPosition
aPos(rTxtNd
);
267 if (FRMDIR_HORI_RIGHT_TOP
== rWr
.pDoc
->GetTextDirection(aPos
))
272 maCharRunIter
= maCharRuns
.begin();
277 Get list of any graphics which may be anchored from this paragraph.
279 maFlyFrms
= GetFramesInNode(rWr
.maFrames
, rNd
);
280 std::sort(maFlyFrms
.begin(), maFlyFrms
.end(), sortswflys());
284 If we are inside a frame then anything anchored inside this frame can
285 only be supported by word anchored inline ("as character"), so force
286 this in the supportable case.
288 if (rWr
.HackIsWW8OrHigher() && rWr
.bInWriteEscher
)
290 std::for_each(maFlyFrms
.begin(), maFlyFrms
.end(),
291 std::mem_fun_ref(&sw::Frame::ForceTreatAsInline
));
294 maFlyIter
= maFlyFrms
.begin();
296 if ( m_rExport
.pDoc
->GetRedlineTbl().Count() )
298 SwPosition
aPosition( rNd
, SwIndex( (SwTxtNode
*)&rNd
) );
299 pCurRedline
= m_rExport
.pDoc
->GetRedline( aPosition
, &nCurRedlinePos
);
302 nAktSwPos
= SearchNext(1);
305 xub_StrLen
SwAttrIter::SearchNext( xub_StrLen nStartPos
)
308 xub_StrLen nMinPos
= STRING_MAXLEN
;
311 const String aTxt
= rNd
.GetTxt();
312 xub_StrLen pos
= aTxt
.Search(CH_TXT_ATR_FIELDSTART
, nStartPos
);
313 if (pos
==STRING_NOTFOUND
)
314 pos
=aTxt
.Search(CH_TXT_ATR_FIELDEND
, nStartPos
);
315 if (pos
==STRING_NOTFOUND
)
316 pos
=aTxt
.Search(CH_TXT_ATR_FORMELEMENT
, nStartPos
);
317 if (pos
!=STRING_NOTFOUND
)
320 // first the redline, then the attributes
323 const SwPosition
* pEnd
= pCurRedline
->End();
324 if (pEnd
->nNode
== rNd
&& ((i
= pEnd
->nContent
.GetIndex()) >= nStartPos
) && i
< nMinPos
)
328 if ( nCurRedlinePos
< m_rExport
.pDoc
->GetRedlineTbl().Count() )
330 // nCurRedlinePos point to the next redline
331 nPos
= nCurRedlinePos
;
335 for ( ; nPos
< m_rExport
.pDoc
->GetRedlineTbl().Count(); ++nPos
)
337 const SwRedline
* pRedl
= m_rExport
.pDoc
->GetRedlineTbl()[ nPos
];
339 const SwPosition
* pStt
= pRedl
->Start();
340 const SwPosition
* pEnd
= pStt
== pRedl
->GetPoint()
344 if( pStt
->nNode
== rNd
)
346 if( ( i
= pStt
->nContent
.GetIndex() ) >= nStartPos
&&
353 if( pEnd
->nNode
== rNd
&&
354 ( i
= pEnd
->nContent
.GetIndex() ) < nMinPos
&&
361 if (mrSwFmtDrop
.GetWholeWord() && nStartPos
<= rNd
.GetDropLen(0))
362 nMinPos
= rNd
.GetDropLen(0);
363 else if(nStartPos
<= mrSwFmtDrop
.GetChars())
364 nMinPos
= mrSwFmtDrop
.GetChars();
366 if(const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
369 // kann noch optimiert werden, wenn ausgenutzt wird, dass die TxtAttrs
370 // nach der Anfangsposition geordnet sind. Dann muessten
371 // allerdings noch 2 Indices gemerkt werden
372 for( i
= 0; i
< pTxtAttrs
->Count(); i
++ )
374 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
375 nPos
= *pHt
->GetStart(); // gibt erstes Attr-Zeichen
376 if( nPos
>= nStartPos
&& nPos
<= nMinPos
)
379 if( pHt
->GetEnd() ) // Attr mit Ende
381 nPos
= *pHt
->GetEnd(); // gibt letztes Attr-Zeichen + 1
382 if( nPos
>= nStartPos
&& nPos
<= nMinPos
)
385 if (pHt
->HasDummyChar())
387 // pos + 1 because of CH_TXTATR in Text
388 nPos
= *pHt
->GetStart() + 1;
389 if( nPos
>= nStartPos
&& nPos
<= nMinPos
)
395 if (maCharRunIter
!= maCharRuns
.end())
397 if (maCharRunIter
->mnEndPos
< nMinPos
)
398 nMinPos
= maCharRunIter
->mnEndPos
;
404 Check to see if there are any graphics anchored to characters in this
405 paragraph's text. Set nMinPos to 1 past the placement for anchored to
406 character because anchors in Word appear after the character they are
409 if (maFlyIter
!= maFlyFrms
.end())
411 const SwPosition
&rAnchor
= maFlyIter
->GetPosition();
413 nPos
= rAnchor
.nContent
.GetIndex();
414 if (nPos
>= nStartPos
&& nPos
<= nMinPos
)
417 if (maFlyIter
->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AUTO_CNTNT
)
420 if (nPos
>= nStartPos
&& nPos
<= nMinPos
)
425 //nMinPos found and not going to change at this point
427 if (maCharRunIter
!= maCharRuns
.end())
429 if (maCharRunIter
->mnEndPos
== nMinPos
)
436 void SwAttrIter::OutAttr( xub_StrLen nSwPos
)
438 m_rExport
.AttrOutput().RTLAndCJKState( IsCharRTL(), GetScript() );
441 Depending on whether text is in CTL/CJK or Western, get the id of that
442 script, the idea is that the font that is actually in use to render this
443 range of text ends up in pFont
445 sal_uInt16 nFontId
= GetWhichOfScript( RES_CHRATR_FONT
, GetScript() );
447 const SvxFontItem
&rParentFont
= ItemGet
<SvxFontItem
>(
448 (const SwTxtFmtColl
&)rNd
.GetAnyFmtColl(), nFontId
);
449 const SvxFontItem
*pFont
= &rParentFont
;
451 SfxItemSet
aExportSet(*rNd
.GetSwAttrSet().GetPool(),
452 RES_CHRATR_BEGIN
, RES_TXTATR_END
- 1);
454 //The hard formatting properties that affect the entire paragraph
455 if (rNd
.HasSwAttrSet())
458 // only copy hard attributes - bDeep = false
459 aExportSet
.Set(rNd
.GetSwAttrSet(), bDeep
);
460 // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
461 const SvxFontItem
&rNdFont
= ItemGet
<SvxFontItem
>(rNd
.GetSwAttrSet(), nFontId
);
463 aExportSet
.ClearItem(nFontId
);
466 //The additional hard formatting properties that affect this range in the
468 sw::PoolItems aRangeItems
;
469 if (const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
471 for (xub_StrLen i
= 0; i
< pTxtAttrs
->Count(); ++i
)
473 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
474 const xub_StrLen
* pEnd
= pHt
->GetEnd();
476 if (pEnd
? ( nSwPos
>= *pHt
->GetStart() && nSwPos
< *pEnd
)
477 : nSwPos
== *pHt
->GetStart() )
479 sal_uInt16 nWhich
= pHt
->GetAttr().Which();
480 if (nWhich
== nFontId
)
481 pFont
= &(item_cast
<SvxFontItem
>(pHt
->GetAttr()));
482 else if( nWhich
== RES_TXTATR_AUTOFMT
)
484 const SwFmtAutoFmt
& rAutoFmt
= static_cast<const SwFmtAutoFmt
&>(pHt
->GetAttr());
485 const boost::shared_ptr
<SfxItemSet
> pSet
= rAutoFmt
.GetStyleHandle();
486 SfxWhichIter
aIter( *pSet
);
487 const SfxPoolItem
* pItem
;
488 sal_uInt16 nWhichId
= aIter
.FirstWhich();
491 if( SFX_ITEM_SET
== pSet
->GetItemState( nWhichId
, FALSE
, &pItem
))
493 if (nWhichId
== nFontId
)
494 pFont
= &(item_cast
<SvxFontItem
>(*pItem
));
496 aRangeItems
[nWhichId
] = pItem
;
498 nWhichId
= aIter
.NextWhich();
502 aRangeItems
[nWhich
] = (&(pHt
->GetAttr()));
504 else if (nSwPos
< *pHt
->GetStart())
510 For #i24291# we need to explictly remove any properties from the
511 aExportSet which a SwCharFmt would override, we can't rely on word doing
512 this for us like writer does
514 const SwFmtCharFmt
*pCharFmtItem
=
515 HasItem
< SwFmtCharFmt
>( aRangeItems
, RES_TXTATR_CHARFMT
);
517 ClearOverridesFromSet( *pCharFmtItem
, aExportSet
);
519 sw::PoolItems aExportItems
;
520 GetPoolItems( aExportSet
, aExportItems
);
522 sw::cPoolItemIter aEnd
= aRangeItems
.end();
523 for ( sw::cPoolItemIter aI
= aRangeItems
.begin(); aI
!= aEnd
; ++aI
)
524 aExportItems
[aI
->first
] = aI
->second
;
526 if ( !aExportItems
.empty() )
528 const SwModify
* pOldMod
= m_rExport
.pOutFmtNode
;
529 m_rExport
.pOutFmtNode
= &rNd
;
530 m_rExport
.m_aCurrentCharPropStarts
.push( nSwPos
);
532 m_rExport
.ExportPoolItemsToCHP( aExportItems
, GetScript() );
534 // HasTextItem nur in dem obigen Bereich erlaubt
535 m_rExport
.m_aCurrentCharPropStarts
.pop();
536 m_rExport
.pOutFmtNode
= pOldMod
;
539 ASSERT( pFont
, "must be *some* font associated with this txtnode" );
542 SvxFontItem
aFont( *pFont
);
545 If we are a nonunicode aware format then we set the charset we want to
546 use for export of this range. If necessary this will generate a pseudo
547 font to use for this range.
549 So now we are guaranteed to have a font with the correct charset set
550 for WW6/95 which will match the script we have exported this range in,
551 this makes older nonunicode aware versions of word display the correct
554 if ( !m_rExport
.HackIsWW8OrHigher() )
555 aFont
.GetCharSet() = GetCharSet();
557 if ( rParentFont
!= aFont
)
558 m_rExport
.AttrOutput().OutputItem( aFont
);
562 void SwAttrIter::OutFlys(xub_StrLen nSwPos
)
566 May have an anchored graphic to be placed, loop through sorted array
567 and output all at this position
569 while ( maFlyIter
!= maFlyFrms
.end() )
571 const SwPosition
&rAnchor
= maFlyIter
->GetPosition();
572 xub_StrLen nPos
= rAnchor
.nContent
.GetIndex();
574 if ( nPos
!= nSwPos
)
578 m_rExport
.AttrOutput().OutputFlyFrame( *maFlyIter
);
584 bool SwAttrIter::IsTxtAttr( xub_StrLen nSwPos
)
586 // search for attrs with CH_TXTATR
587 if (const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
589 for (USHORT i
= 0; i
< pTxtAttrs
->Count(); ++i
)
591 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
592 if ( pHt
->HasDummyChar() && (*pHt
->GetStart() == nSwPos
) )
600 bool SwAttrIter::IsDropCap( int nSwPos
)
602 // see if the current position falls on a DropCap
603 int nDropChars
= mrSwFmtDrop
.GetChars();
604 bool bWholeWord
= mrSwFmtDrop
.GetWholeWord();
607 short nWordLen
= rNd
.GetDropLen(0);
608 if(nSwPos
== nWordLen
&& nSwPos
!= 0)
613 if (nSwPos
== nDropChars
&& nSwPos
!= 0)
619 bool SwAttrIter::RequiresImplicitBookmark()
621 SwImplBookmarksIter bkmkIterEnd
= m_rExport
.maImplicitBookmarks
.end();
622 for ( SwImplBookmarksIter aIter
= m_rExport
.maImplicitBookmarks
.begin(); aIter
!= bkmkIterEnd
; ++aIter
)
624 ULONG sample
= aIter
->second
;
626 if ( sample
== rNd
.GetIndex() )
632 // HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
633 // und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
634 // die dann ueber HasItem() nach anderen Items an der
635 // Attribut-Anfangposition fragen kann.
636 // Es koennen nur Attribute mit Ende abgefragt werden.
637 // Es wird mit bDeep gesucht
638 const SfxPoolItem
* SwAttrIter::HasTextItem( USHORT nWhich
) const
640 const SfxPoolItem
* pRet
= 0;
641 const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints();
642 xub_StrLen nTmpSwPos
= m_rExport
.m_aCurrentCharPropStarts
.top();
645 for (USHORT i
= 0; i
< pTxtAttrs
->Count(); ++i
)
647 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
648 const SfxPoolItem
* pItem
= &pHt
->GetAttr();
649 const xub_StrLen
* pAtrEnd
= 0;
650 if( 0 != ( pAtrEnd
= pHt
->GetEnd() ) && // nur Attr mit Ende
651 nWhich
== pItem
->Which() && //
652 nTmpSwPos
>= *pHt
->GetStart() && nTmpSwPos
< *pAtrEnd
)
654 pRet
= pItem
; // gefunden
657 else if (nTmpSwPos
< *pHt
->GetStart())
658 break; // dann kommt da nichts mehr
664 void WW8Export::GetCurrentItems(WW8Bytes
& rItems
) const
666 USHORT nEnd
= pO
? pO
->Count() : 0;
667 for (USHORT nI
= 0; nI
< nEnd
; ++nI
)
668 rItems
.Insert((*pO
)[nI
], rItems
.Count());
671 const SfxPoolItem
& SwAttrIter::GetItem(USHORT nWhich
) const
673 const SfxPoolItem
* pRet
= HasTextItem(nWhich
);
674 return pRet
? *pRet
: rNd
.SwCntntNode::GetAttr(nWhich
);
677 void WW8AttributeOutput::StartRuby( const SwTxtNode
& rNode
, const SwFmtRuby
& rRuby
)
679 String
aStr( FieldString( ww::eEQ
) );
680 aStr
.APPEND_CONST_ASC( "\\* jc" );
682 sal_Char cDirective
= 0;
683 switch ( rRuby
.GetAdjustment() )
705 ASSERT( !this,"Unhandled Ruby justication code" );
708 aStr
+= String::CreateFromInt32( nJC
);
711 MS needs to know the name and size of the font used in the ruby item,
712 but we coud have written it in a mixture of asian and western
713 scripts, and each of these can be a different font and size than the
714 other, so we make a guess based upon the first character of the text,
718 if( pBreakIt
->GetBreakIter().is() )
719 nRubyScript
= pBreakIt
->GetBreakIter()->getScriptType( rRuby
.GetText(), 0);
721 nRubyScript
= i18n::ScriptType::ASIAN
;
723 const SwTxtRuby
* pRubyTxt
= rRuby
.GetTxtRuby();
724 const SwCharFmt
* pFmt
= pRubyTxt
? pRubyTxt
->GetCharFmt() : 0;
729 const SvxFontItem
&rFont
= ItemGet
< SvxFontItem
>( *pFmt
,
730 GetWhichOfScript(RES_CHRATR_FONT
,nRubyScript
) );
731 sFamilyName
= rFont
.GetFamilyName();
733 const SvxFontHeightItem
&rHeight
= ItemGet
< SvxFontHeightItem
>( *pFmt
,
734 GetWhichOfScript( RES_CHRATR_FONTSIZE
, nRubyScript
) );
735 nHeight
= rHeight
.GetHeight();
739 /*Get defaults if no formatting on ruby text*/
741 const SfxItemPool
*pPool
= rNode
.GetSwAttrSet().GetPool();
742 const SfxItemPool
&rPool
= pPool
? *pPool
: m_rWW8Export
.pDoc
->GetAttrPool();
744 const SvxFontItem
&rFont
= DefaultItemGet
< SvxFontItem
>( rPool
,
745 GetWhichOfScript( RES_CHRATR_FONT
,nRubyScript
) );
746 sFamilyName
= rFont
.GetFamilyName();
748 const SvxFontHeightItem
&rHeight
= DefaultItemGet
< SvxFontHeightItem
>
749 ( rPool
, GetWhichOfScript( RES_CHRATR_FONTSIZE
, nRubyScript
) );
750 nHeight
= rHeight
.GetHeight();
752 nHeight
= (nHeight
+ 5)/10;
754 aStr
.APPEND_CONST_ASC( " \\* \"Font:" );
755 aStr
.Append( sFamilyName
);
756 aStr
.APPEND_CONST_ASC( "\" \\* hps" );
757 aStr
+= String::CreateFromInt32( nHeight
);
758 aStr
.APPEND_CONST_ASC( " \\o" );
761 aStr
.APPEND_CONST_ASC( "\\a" );
762 aStr
.Append( cDirective
);
764 aStr
.APPEND_CONST_ASC( "(\\s\\up " );
767 if ( pBreakIt
->GetBreakIter().is() )
768 nRubyScript
= pBreakIt
->GetBreakIter()->getScriptType( rNode
.GetTxt(),
769 *( pRubyTxt
->GetStart() ) );
771 nRubyScript
= i18n::ScriptType::ASIAN
;
773 const SwAttrSet
& rSet
= rNode
.GetSwAttrSet();
774 const SvxFontHeightItem
&rHeightItem
=
775 ( const SvxFontHeightItem
& )rSet
.Get(
776 GetWhichOfScript( RES_CHRATR_FONTSIZE
, nRubyScript
) );
777 nHeight
= (rHeightItem
.GetHeight() + 10)/20-1;
778 aStr
+= String::CreateFromInt32(nHeight
);
780 aStr
+= rRuby
.GetText();
781 aStr
.APPEND_CONST_ASC( ");" );
782 m_rWW8Export
.OutputField( 0, ww::eEQ
, aStr
,
783 WRITEFIELD_START
| WRITEFIELD_CMD_START
);
786 void WW8AttributeOutput::EndRuby()
788 m_rWW8Export
.WriteChar( ')' );
789 m_rWW8Export
.OutputField( 0, ww::eEQ
, aEmptyStr
, WRITEFIELD_END
| WRITEFIELD_CLOSE
);
792 /*#i15387# Better ideas welcome*/
793 String
&TruncateBookmark( String
&rRet
)
795 if ( rRet
.Len() > 40 )
797 ASSERT( rRet
.Len() <= 40, "Word cannot have bookmarks longer than 40 chars" );
801 bool AttributeOutputBase::AnalyzeURL( const String
& rUrl
, const String
& /*rTarget*/, String
* pLinkURL
, String
* pMark
)
803 bool bBookMarkOnly
= false;
805 INetURLObject
aURL( rUrl
);
809 if ( rUrl
.Len() > 1 && rUrl
.GetChar(0) == INET_MARK_TOKEN
)
811 sMark
= BookmarkToWriter( rUrl
.Copy(1) );
813 xub_StrLen nPos
= sMark
.SearchBackward( cMarkSeperator
);
815 String
sRefType( sMark
.Copy( nPos
+1 ) );
816 sRefType
.EraseAllChars();
818 // i21465 Only interested in outline references
819 if ( sRefType
.EqualsAscii( pMarkToOutline
) )
821 String sLink
= sMark
.Copy(0, nPos
);
822 SwImplBookmarksIter bkmkIterEnd
= GetExport().maImplicitBookmarks
.end();
823 for ( SwImplBookmarksIter aIter
= GetExport().maImplicitBookmarks
.begin(); aIter
!= bkmkIterEnd
; ++aIter
)
825 String bkmkName
= aIter
->first
;
827 if ( bkmkName
== sLink
)
829 sMark
= String( RTL_CONSTASCII_STRINGPARAM( "_toc" ) );
830 sMark
+= String::CreateFromInt32( aIter
->second
);
837 sURL
= aURL
.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS
);
838 sMark
= aURL
.GetMark( INetURLObject::DECODE_UNAMBIGUOUS
);
842 if ( sMark
.Len() && !sURL
.Len() )
843 bBookMarkOnly
= true;
849 return bBookMarkOnly
;
852 bool WW8AttributeOutput::AnalyzeURL( const String
& rUrl
, const String
& rTarget
, String
* pLinkURL
, String
* pMark
)
854 bool bBookMarkOnly
= AttributeOutputBase::AnalyzeURL( rUrl
, rTarget
, pLinkURL
, pMark
);
856 String sURL
= *pLinkURL
;
857 String sMark
= *pMark
;
860 sURL
= URIHelper::simpleNormalizedMakeRelative( m_rWW8Export
.GetWriter().GetBaseURL(), sURL
);
863 sURL
= FieldString( ww::eHYPERLINK
);
866 String
sFld( FieldString( ww::eHYPERLINK
) );
867 sFld
.APPEND_CONST_ASC( "\"" );
868 sURL
.Insert( sFld
, 0 );
873 ( ( sURL
.APPEND_CONST_ASC( " \\l \"" ) ) += sMark
) += '\"';
876 ( sURL
.APPEND_CONST_ASC( " \\n " ) ) += rTarget
;
881 return bBookMarkOnly
;
884 bool WW8AttributeOutput::StartURL( const String
&rUrl
, const String
&rTarget
)
886 // hyperlinks only in WW8
887 if ( !m_rWW8Export
.bWrtWW8
)
890 INetURLObject
aURL( rUrl
);
894 bool bBookMarkOnly
= AnalyzeURL( rUrl
, rTarget
, &sURL
, &sMark
);
897 m_rWW8Export
.OutputField( 0, ww::eHYPERLINK
, sURL
, WRITEFIELD_START
| WRITEFIELD_CMD_START
);
899 // write the refence to the "picture" structure
900 ULONG nDataStt
= m_rWW8Export
.pDataStrm
->Tell();
901 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell() );
903 // WinWord 2000 doesn't write this - so its a temp solution by W97 ?
904 m_rWW8Export
.WriteChar( 0x01 );
906 static BYTE aArr1
[] = {
907 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
909 0x06, 0x08, 0x01, // sprmCFData
910 0x55, 0x08, 0x01, // sprmCFSpec
911 0x02, 0x08, 0x01 // sprmCFFldVanish
913 BYTE
* pDataAdr
= aArr1
+ 2;
914 Set_UInt32( pDataAdr
, nDataStt
);
916 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), sizeof( aArr1
), aArr1
);
918 m_rWW8Export
.OutputField( 0, ww::eHYPERLINK
, sURL
, WRITEFIELD_CMD_END
);
920 // now write the picture structur
921 sURL
= aURL
.GetURLNoMark();
923 //all links end up in the data stream as absolute references.
924 bool bAbsolute
= !bBookMarkOnly
;
926 static BYTE __READONLY_DATA aURLData1
[] = {
927 0,0,0,0, // len of struct
928 0x44,0, // the start of "next" data
929 0,0,0,0,0,0,0,0,0,0, // PIC-Structure!
930 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
931 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
932 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
935 static BYTE __READONLY_DATA MAGIC_A
[] = {
936 // start of "next" data
937 0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
938 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
941 m_rWW8Export
.pDataStrm
->Write( aURLData1
, sizeof( aURLData1
) );
945 m_rWW8Export
.pDataStrm
->Write( &nAnchor
, 1 );
946 m_rWW8Export
.pDataStrm
->Write( MAGIC_A
, sizeof(MAGIC_A
) );
947 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 0x00000002);
948 UINT32 nFlag
= bBookMarkOnly
? 0 : 0x01;
953 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, nFlag
);
955 INetProtocol eProto
= aURL
.GetProtocol();
956 if ( eProto
== INET_PROT_FILE
|| eProto
== INET_PROT_SMB
)
958 // version 1 (for a document)
960 static BYTE __READONLY_DATA MAGIC_C
[] = {
961 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
966 static BYTE __READONLY_DATA MAGIC_D
[] = {
967 0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
972 // save the links to files as relative
973 sURL
= URIHelper::simpleNormalizedMakeRelative( m_rWW8Export
.GetWriter().GetBaseURL(), sURL
);
974 if ( eProto
== INET_PROT_FILE
&& sURL
.EqualsAscii( "/", 0, 1 ) )
975 sURL
= aURL
.PathToFileName();
977 // special case for the absolute windows names
978 // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
979 sal_Unicode aDrive
= ( sURL
.Len() > 1 )? sURL
.GetChar( 1 ): 0;
980 if ( sURL
.EqualsAscii( "/", 0, 1 ) &&
981 ( ( aDrive
>= 'A' && aDrive
<= 'Z' ) || ( aDrive
>= 'a' && aDrive
<= 'z' ) ) &&
982 sURL
.EqualsAscii( ":", 2, 1 ) )
985 sURL
.SearchAndReplaceAll( '/', '\\' );
988 // n#261623 convert smb notation to '\\'
989 const char pSmb
[] = "smb://";
990 if ( eProto
== INET_PROT_SMB
&&
991 sURL
.EqualsAscii( pSmb
, 0, sizeof( pSmb
) - 1 ) )
993 sURL
.Erase( 0, sizeof( pSmb
) - 3 );
994 sURL
.SearchAndReplaceAll( '/', '\\' );
997 m_rWW8Export
.pDataStrm
->Write( MAGIC_C
, sizeof(MAGIC_C
) );
998 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, sURL
.Len()+1 );
999 SwWW8Writer::WriteString8( *m_rWW8Export
.pDataStrm
, sURL
, true,
1000 RTL_TEXTENCODING_MS_1252
);
1001 m_rWW8Export
.pDataStrm
->Write( MAGIC_D
, sizeof( MAGIC_D
) );
1003 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 2*sURL
.Len() + 6 );
1004 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 2*sURL
.Len() );
1005 SwWW8Writer::WriteShort( *m_rWW8Export
.pDataStrm
, 3 );
1006 SwWW8Writer::WriteString16( *m_rWW8Export
.pDataStrm
, sURL
, false );
1008 else if ( eProto
!= INET_PROT_NOT_VALID
)
1010 // version 2 (simple url)
1011 // an write some data to the data stream, but dont ask
1012 // what the data mean, except for the URL.
1013 // The First piece is the WW8_PIC structure.
1015 static BYTE __READONLY_DATA MAGIC_B
[] = {
1016 0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
1017 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
1020 m_rWW8Export
.pDataStrm
->Write( MAGIC_B
, sizeof(MAGIC_B
) );
1021 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, 2 * ( sURL
.Len() + 1 ) );
1022 SwWW8Writer::WriteString16( *m_rWW8Export
.pDataStrm
, sURL
, true );
1027 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, sMark
.Len()+1 );
1028 SwWW8Writer::WriteString16( *m_rWW8Export
.pDataStrm
, sMark
, true );
1030 SwWW8Writer::WriteLong( *m_rWW8Export
.pDataStrm
, nDataStt
,
1031 m_rWW8Export
.pDataStrm
->Tell() - nDataStt
);
1036 bool WW8AttributeOutput::EndURL()
1038 // hyperlinks only in WW8
1039 if ( !m_rWW8Export
.bWrtWW8
)
1042 m_rWW8Export
.OutputField( 0, ww::eHYPERLINK
, aEmptyStr
, WRITEFIELD_CLOSE
);
1047 String
BookmarkToWord(const String
&rBookmark
)
1049 String
sRet(INetURLObject::encode(rBookmark
,
1050 INetURLObject::PART_REL_SEGMENT_EXTRA
, '%',
1051 INetURLObject::ENCODE_ALL
, RTL_TEXTENCODING_ASCII_US
));
1052 return TruncateBookmark(sRet
);
1055 String
BookmarkToWriter(const String
&rBookmark
)
1057 return INetURLObject::decode(rBookmark
, '%',
1058 INetURLObject::DECODE_UNAMBIGUOUS
, RTL_TEXTENCODING_ASCII_US
);
1061 void SwAttrIter::OutSwFmtRefMark(const SwFmtRefMark
& rAttr
, bool)
1063 if ( m_rExport
.HasRefToObject( REF_SETREFATTR
, &rAttr
.GetRefName(), 0 ) )
1064 m_rExport
.AppendBookmark( m_rExport
.GetBookmarkName( REF_SETREFATTR
,
1065 &rAttr
.GetRefName(), 0 ));
1068 void WW8AttributeOutput::FieldVanish( const String
& rTxt
, ww::eField
/*eType*/ )
1071 m_rWW8Export
.GetCurrentItems( aItems
);
1074 if ( m_rWW8Export
.bWrtWW8
)
1075 SwWW8Writer::InsUInt16( aItems
, NS_sprm::LN_CFFldVanish
);
1077 aItems
.Insert( 67, aItems
.Count() );
1078 aItems
.Insert( 1, aItems
.Count() );
1080 USHORT nStt_sprmCFSpec
= aItems
.Count();
1082 // sprmCFSpec -- fSpec-Attribut true
1083 if ( m_rWW8Export
.bWrtWW8
)
1084 SwWW8Writer::InsUInt16( aItems
, 0x855 );
1086 aItems
.Insert( 117, aItems
.Count() );
1087 aItems
.Insert( 1, aItems
.Count() );
1089 m_rWW8Export
.WriteChar( '\x13' );
1090 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), aItems
.Count(),
1092 m_rWW8Export
.OutSwString( rTxt
, 0, rTxt
.Len(), m_rWW8Export
.IsUnicode(),
1093 RTL_TEXTENCODING_MS_1252
);
1094 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), nStt_sprmCFSpec
,
1096 m_rWW8Export
.WriteChar( '\x15' );
1097 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), aItems
.Count(),
1101 void AttributeOutputBase::TOXMark( const SwTxtNode
& rNode
, const SwTOXMark
& rAttr
)
1103 // its a field; so get the Text form the Node and build the field
1105 ww::eField eType
= ww::eNONE
;
1107 const SwTxtTOXMark
& rTxtTOXMark
= *rAttr
.GetTxtTOXMark();
1108 const xub_StrLen
* pTxtEnd
= rTxtTOXMark
.GetEnd();
1109 if ( pTxtEnd
) // has range?
1111 sTxt
= rNode
.GetExpandTxt( *rTxtTOXMark
.GetStart(),
1112 *pTxtEnd
- *rTxtTOXMark
.GetStart() );
1115 sTxt
= rAttr
.GetAlternativeText();
1117 switch ( rAttr
.GetTOXType()->GetType() )
1121 if ( rAttr
.GetPrimaryKey().Len() )
1123 if ( rAttr
.GetSecondaryKey().Len() )
1125 sTxt
.Insert( ':', 0 );
1126 sTxt
.Insert( rAttr
.GetSecondaryKey(), 0 );
1129 sTxt
.Insert( ':', 0 );
1130 sTxt
.Insert( rAttr
.GetPrimaryKey(), 0 );
1132 sTxt
.InsertAscii( " XE \"", 0 );
1133 sTxt
.InsertAscii( "\" " );
1137 ( sTxt
.APPEND_CONST_ASC( "\" \\f \"" ) )
1138 += (sal_Char
)( 'A' + GetExport( ).GetId( *rAttr
.GetTOXType() ) );
1139 // fall through - no break;
1143 sTxt
.InsertAscii( " TC \"", 0 );
1144 USHORT nLvl
= rAttr
.GetLevel();
1145 if (nLvl
> WW8ListManager::nMaxLevel
)
1146 nLvl
= WW8ListManager::nMaxLevel
;
1148 ((sTxt
.APPEND_CONST_ASC( "\" \\l " ))
1149 += String::CreateFromInt32( nLvl
)) += ' ';
1153 ASSERT( !this, "Unhandled option for toc export" );
1158 FieldVanish( sTxt
, eType
);
1161 int SwAttrIter::OutAttrWithRange(xub_StrLen nPos
)
1164 if ( const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints() )
1166 m_rExport
.m_aCurrentCharPropStarts
.push( nPos
);
1167 const xub_StrLen
* pEnd
;
1168 for ( USHORT i
= 0; i
< pTxtAttrs
->Count(); ++i
)
1170 const SwTxtAttr
* pHt
= (*pTxtAttrs
)[i
];
1171 const SfxPoolItem
* pItem
= &pHt
->GetAttr();
1172 switch ( pItem
->Which() )
1174 case RES_TXTATR_INETFMT
:
1175 if ( nPos
== *pHt
->GetStart() )
1177 const SwFmtINetFmt
*rINet
= static_cast< const SwFmtINetFmt
* >( pItem
);
1178 if ( m_rExport
.AttrOutput().StartURL( rINet
->GetValue(), rINet
->GetTargetFrame() ) )
1181 if ( 0 != ( pEnd
= pHt
->GetEnd() ) && nPos
== *pEnd
)
1183 if ( m_rExport
.AttrOutput().EndURL() )
1187 case RES_TXTATR_REFMARK
:
1188 if ( nPos
== *pHt
->GetStart() )
1190 OutSwFmtRefMark( *static_cast< const SwFmtRefMark
* >( pItem
), true );
1193 if ( 0 != ( pEnd
= pHt
->GetEnd() ) && nPos
== *pEnd
)
1195 OutSwFmtRefMark( *static_cast< const SwFmtRefMark
* >( pItem
), false );
1199 case RES_TXTATR_TOXMARK
:
1200 if ( nPos
== *pHt
->GetStart() )
1201 m_rExport
.AttrOutput().TOXMark( rNd
, *static_cast< const SwTOXMark
* >( pItem
) );
1203 case RES_TXTATR_CJK_RUBY
:
1204 if ( nPos
== *pHt
->GetStart() )
1206 m_rExport
.AttrOutput().StartRuby( rNd
, *static_cast< const SwFmtRuby
* >( pItem
) );
1209 if ( 0 != ( pEnd
= pHt
->GetEnd() ) && nPos
== *pEnd
)
1211 m_rExport
.AttrOutput().EndRuby();
1217 m_rExport
.m_aCurrentCharPropStarts
.pop(); // HasTextItem nur in dem obigen Bereich erlaubt
1222 bool SwAttrIter::IsRedlineAtEnd( xub_StrLen nEnd
) const
1225 // search next Redline
1226 for( USHORT nPos
= nCurRedlinePos
;
1227 nPos
< m_rExport
.pDoc
->GetRedlineTbl().Count(); ++nPos
)
1229 const SwPosition
* pEnd
= m_rExport
.pDoc
->GetRedlineTbl()[ nPos
]->End();
1230 if( pEnd
->nNode
== rNd
)
1232 if( pEnd
->nContent
.GetIndex() == nEnd
)
1244 const SwRedlineData
* SwAttrIter::GetRedline( xub_StrLen nPos
)
1248 const SwPosition
* pEnd
= pCurRedline
->End();
1249 if( pEnd
->nNode
== rNd
&&
1250 pEnd
->nContent
.GetIndex() <= nPos
)
1257 // write data of current redline
1258 return &( pCurRedline
->GetRedlineData() );
1264 // search next Redline
1265 for( ; nCurRedlinePos
< m_rExport
.pDoc
->GetRedlineTbl().Count();
1268 const SwRedline
* pRedl
= m_rExport
.pDoc
->GetRedlineTbl()[ nCurRedlinePos
];
1270 const SwPosition
* pStt
= pRedl
->Start();
1271 const SwPosition
* pEnd
= pStt
== pRedl
->GetPoint()
1273 : pRedl
->GetPoint();
1275 if( pStt
->nNode
== rNd
)
1277 if( pStt
->nContent
.GetIndex() >= nPos
)
1279 if( pStt
->nContent
.GetIndex() == nPos
)
1281 // write data of this redline
1282 pCurRedline
= pRedl
;
1283 return &( pCurRedline
->GetRedlineData() );
1291 if( pEnd
->nNode
== rNd
&&
1292 pEnd
->nContent
.GetIndex() < nPos
)
1294 pCurRedline
= pRedl
;
1304 short MSWordExportBase::GetCurrentPageDirection() const
1306 const SwFrmFmt
&rFmt
= pAktPageDesc
1307 ? pAktPageDesc
->GetMaster()
1308 : const_cast<const SwDoc
*>( pDoc
)->GetPageDesc( 0 ).GetMaster();
1309 return rFmt
.GetFrmDir().GetValue();
1312 short MSWordExportBase::GetDefaultFrameDirection( ) const
1314 short nDir
= FRMDIR_ENVIRONMENT
;
1316 if ( bOutPageDescs
)
1317 nDir
= GetCurrentPageDirection( );
1318 else if ( pOutFmtNode
)
1320 if ( bOutFlyFrmAttrs
) //frame
1322 nDir
= TrueFrameDirection( *( const SwFrmFmt
* ) pOutFmtNode
);
1324 else if ( pOutFmtNode
->ISA( SwCntntNode
) ) //pagagraph
1326 const SwCntntNode
*pNd
= ( const SwCntntNode
* ) pOutFmtNode
;
1327 SwPosition
aPos( *pNd
);
1328 nDir
= pDoc
->GetTextDirection( aPos
);
1330 else if ( pOutFmtNode
->ISA( SwTxtFmtColl
) )
1331 nDir
= FRMDIR_HORI_LEFT_TOP
; //what else can we do :-(
1334 if ( nDir
== FRMDIR_ENVIRONMENT
)
1335 nDir
= FRMDIR_HORI_LEFT_TOP
; //Set something
1340 short MSWordExportBase::TrueFrameDirection( const SwFrmFmt
&rFlyFmt
) const
1342 const SwFrmFmt
*pFlyFmt
= &rFlyFmt
;
1343 const SvxFrameDirectionItem
* pItem
= 0;
1346 pItem
= &pFlyFmt
->GetFrmDir();
1347 if ( FRMDIR_ENVIRONMENT
== pItem
->GetValue() )
1350 const SwFmtAnchor
* pAnchor
= &pFlyFmt
->GetAnchor();
1351 if ( FLY_PAGE
!= pAnchor
->GetAnchorId() &&
1352 pAnchor
->GetCntntAnchor() )
1354 pFlyFmt
= pAnchor
->GetCntntAnchor()->nNode
.GetNode().GetFlyFmt();
1365 nRet
= pItem
->GetValue();
1367 nRet
= GetCurrentPageDirection();
1369 ASSERT( nRet
!= FRMDIR_ENVIRONMENT
, "leaving with environment direction" );
1373 const SvxBrushItem
* WW8Export::GetCurrentPageBgBrush() const
1375 const SwFrmFmt
&rFmt
= pAktPageDesc
1376 ? pAktPageDesc
->GetMaster()
1377 : const_cast<const SwDoc
*>(pDoc
)->GetPageDesc(0).GetMaster();
1379 const SfxPoolItem
* pItem
= 0;
1380 //If not set, or "no fill", get real bg
1381 SfxItemState eState
= rFmt
.GetItemState(RES_BACKGROUND
, true, &pItem
);
1383 const SvxBrushItem
* pRet
= (const SvxBrushItem
*)pItem
;
1384 if (SFX_ITEM_SET
!= eState
|| (!pRet
->GetGraphic() &&
1385 pRet
->GetColor() == COL_TRANSPARENT
))
1387 pRet
= &(DefaultItemGet
<SvxBrushItem
>(*pDoc
,RES_BACKGROUND
));
1392 SvxBrushItem
WW8Export::TrueFrameBgBrush(const SwFrmFmt
&rFlyFmt
) const
1394 const SwFrmFmt
*pFlyFmt
= &rFlyFmt
;
1395 const SvxBrushItem
* pRet
= 0;
1399 //If not set, or "no fill", get real bg
1400 const SfxPoolItem
* pItem
= 0;
1401 SfxItemState eState
=
1402 pFlyFmt
->GetItemState(RES_BACKGROUND
, true, &pItem
);
1403 pRet
= (const SvxBrushItem
*)pItem
;
1404 if (SFX_ITEM_SET
!= eState
|| (!pRet
->GetGraphic() &&
1405 pRet
->GetColor() == COL_TRANSPARENT
))
1408 const SwFmtAnchor
* pAnchor
= &pFlyFmt
->GetAnchor();
1409 if (FLY_PAGE
!= pAnchor
->GetAnchorId() &&
1410 pAnchor
->GetCntntAnchor())
1413 pAnchor
->GetCntntAnchor()->nNode
.GetNode().GetFlyFmt();
1423 pRet
= GetCurrentPageBgBrush();
1425 const Color
aTmpColor( COL_WHITE
);
1426 SvxBrushItem
aRet( aTmpColor
, RES_BACKGROUND
);
1427 if (pRet
&& (pRet
->GetGraphic() ||( pRet
->GetColor() != COL_TRANSPARENT
)))
1435 Convert characters that need to be converted, the basic replacements and the
1436 ridicously complicated title case attribute mapping to hardcoded upper case
1437 because word doesn't have the feature
1439 String
SwAttrIter::GetSnippet(const String
&rStr
, xub_StrLen nAktPos
,
1440 xub_StrLen nLen
) const
1442 String
aSnippet(rStr
, nAktPos
, nLen
);
1446 // 0x0a ( Hard Line Break ) -> 0x0b
1447 // 0xad ( soft hyphen ) -> 0x1f
1448 // 0x2011 ( hard hyphen ) -> 0x1e
1449 aSnippet
.SearchAndReplaceAll(0x0A, 0x0B);
1450 aSnippet
.SearchAndReplaceAll(CHAR_HARDHYPHEN
, 0x1e);
1451 aSnippet
.SearchAndReplaceAll(CHAR_SOFTHYPHEN
, 0x1f);
1453 m_rExport
.m_aCurrentCharPropStarts
.push( nAktPos
);
1454 const SfxPoolItem
&rItem
= GetItem(RES_CHRATR_CASEMAP
);
1456 if (SVX_CASEMAP_TITEL
== ((const SvxCaseMapItem
&)rItem
).GetValue())
1458 sal_uInt16 nScriptType
= i18n::ScriptType::LATIN
;
1459 if (pBreakIt
->GetBreakIter().is())
1460 nScriptType
= pBreakIt
->GetBreakIter()->getScriptType(aSnippet
, 0);
1462 LanguageType nLanguage
;
1463 switch (nScriptType
)
1465 case i18n::ScriptType::ASIAN
:
1466 nLanguage
= ((const SvxLanguageItem
&)GetItem(RES_CHRATR_CJK_LANGUAGE
)).GetLanguage();
1468 case i18n::ScriptType::COMPLEX
:
1469 nLanguage
= ((const SvxLanguageItem
&)GetItem(RES_CHRATR_CTL_LANGUAGE
)).GetLanguage();
1471 case i18n::ScriptType::LATIN
:
1473 nLanguage
= ((const SvxLanguageItem
&)GetItem(RES_CHRATR_LANGUAGE
)).GetLanguage();
1477 SvxFont aFontHelper
;
1478 aFontHelper
.SetCaseMap(SVX_CASEMAP_TITEL
);
1479 aFontHelper
.SetLanguage(nLanguage
);
1480 aSnippet
= aFontHelper
.CalcCaseMap(aSnippet
);
1482 //If we weren't at the begin of a word undo the case change.
1483 //not done before doing the casemap because the sequence might start
1485 if (pBreakIt
->GetBreakIter().is() && !pBreakIt
->GetBreakIter()->isBeginWord(
1486 rStr
, nAktPos
, pBreakIt
->GetLocale(nLanguage
),
1487 i18n::WordType::ANYWORD_IGNOREWHITESPACES
) )
1489 aSnippet
.SetChar(0, rStr
.GetChar(nAktPos
));
1492 m_rExport
.m_aCurrentCharPropStarts
.pop();
1497 /** Delivers the right paragraph style
1499 Because of the different style handling for delete operations,
1500 the track changes have to be analysed. A deletion, starting in paragraph A
1501 with style A, ending in paragraph B with style B, needs a hack.
1503 static SwTxtFmtColl
& lcl_getFormatCollection( MSWordExportBase
& rExport
, const SwTxtNode
* pTxtNode
)
1506 USHORT nMax
= rExport
.pDoc
->GetRedlineTbl().Count();
1507 while( nPos
< nMax
)
1509 const SwRedline
* pRedl
= rExport
.pDoc
->GetRedlineTbl()[ nPos
++ ];
1510 const SwPosition
* pStt
= pRedl
->Start();
1511 const SwPosition
* pEnd
= pStt
== pRedl
->GetPoint()
1513 : pRedl
->GetPoint();
1514 // Looking for deletions, which ends in current pTxtNode
1515 if( nsRedlineType_t::REDLINE_DELETE
== pRedl
->GetRedlineData().GetType() &&
1516 pEnd
->nNode
== *pTxtNode
&& pStt
->nNode
!= *pTxtNode
&&
1517 pStt
->nNode
.GetNode().IsTxtNode() )
1519 pTxtNode
= pStt
->nNode
.GetNode().GetTxtNode();
1524 return static_cast<SwTxtFmtColl
&>( pTxtNode
->GetAnyFmtColl() );
1527 void WW8AttributeOutput::FormatDrop( const SwTxtNode
& rNode
, const SwFmtDrop
&rSwFmtDrop
, USHORT nStyle
,
1528 ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo
, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
1530 short nDropLines
= rSwFmtDrop
.GetLines();
1531 short nDistance
= rSwFmtDrop
.GetDistance();
1532 int rFontHeight
, rDropHeight
, rDropDescent
;
1535 ShortToSVBT16( nStyle
, nSty
);
1536 m_rWW8Export
.pO
->Insert( (BYTE
*)&nSty
, 2, m_rWW8Export
.pO
->Count() ); // Style #
1538 if ( m_rWW8Export
.bWrtWW8
)
1540 m_rWW8Export
.InsUInt16( NS_sprm::LN_PPc
); // Alignment (sprmPPc)
1541 m_rWW8Export
.pO
->Insert( 0x20, m_rWW8Export
.pO
->Count() );
1543 m_rWW8Export
.InsUInt16( NS_sprm::LN_PWr
); // Wrapping (sprmPWr)
1544 m_rWW8Export
.pO
->Insert( 0x02, m_rWW8Export
.pO
->Count() );
1546 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDcs
); // Dropcap (sprmPDcs)
1547 int nDCS
= ( nDropLines
<< 3 ) | 0x01;
1548 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( nDCS
) );
1550 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDxaFromText
); // Distance from text (sprmPDxaFromText)
1551 m_rWW8Export
.InsUInt16( nDistance
);
1553 if ( rNode
.GetDropSize( rFontHeight
, rDropHeight
, rDropDescent
) )
1555 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDyaLine
); // Line spacing
1556 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( -rDropHeight
) );
1557 m_rWW8Export
.InsUInt16( 0 );
1562 m_rWW8Export
.pO
->Insert( 29, m_rWW8Export
.pO
->Count() ); // Alignment (sprmPPc)
1563 m_rWW8Export
.pO
->Insert( 0x20, m_rWW8Export
.pO
->Count() );
1565 m_rWW8Export
.pO
->Insert( 37, m_rWW8Export
.pO
->Count() ); // Wrapping (sprmPWr)
1566 m_rWW8Export
.pO
->Insert( 0x02, m_rWW8Export
.pO
->Count() );
1568 m_rWW8Export
.pO
->Insert( 46, m_rWW8Export
.pO
->Count() ); // Dropcap (sprmPDcs)
1569 int nDCS
= ( nDropLines
<< 3 ) | 0x01;
1570 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( nDCS
) );
1572 m_rWW8Export
.pO
->Insert( 49, m_rWW8Export
.pO
->Count() ); // Distance from text (sprmPDxaFromText)
1573 m_rWW8Export
.InsUInt16( nDistance
);
1575 if (rNode
.GetDropSize(rFontHeight
, rDropHeight
, rDropDescent
))
1577 m_rWW8Export
.pO
->Insert( 20, m_rWW8Export
.pO
->Count() ); // Line spacing
1578 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( -rDropHeight
) );
1579 m_rWW8Export
.InsUInt16( 0 );
1583 m_rWW8Export
.WriteCR( pTextNodeInfoInner
);
1585 if ( pTextNodeInfo
.get() != NULL
)
1588 ::std::clog
<< pTextNodeInfo
->toString() << ::std::endl
;
1591 TableInfoCell( pTextNodeInfoInner
);
1594 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->Count(), m_rWW8Export
.pO
->GetData() );
1595 m_rWW8Export
.pO
->Remove( 0, m_rWW8Export
.pO
->Count() );
1597 if ( rNode
.GetDropSize( rFontHeight
, rDropHeight
, rDropDescent
) )
1599 if ( m_rWW8Export
.bWrtWW8
)
1601 const SwCharFmt
*pSwCharFmt
= rSwFmtDrop
.GetCharFmt();
1604 m_rWW8Export
.InsUInt16( NS_sprm::LN_CIstd
);
1605 m_rWW8Export
.InsUInt16( m_rWW8Export
.GetId( *pSwCharFmt
) );
1608 m_rWW8Export
.InsUInt16( NS_sprm::LN_CHpsPos
); // Lower the chars
1609 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( -((nDropLines
- 1)*rDropDescent
) / 10 ) );
1611 m_rWW8Export
.InsUInt16( NS_sprm::LN_CHps
); // Font Size
1612 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( rFontHeight
/ 10 ) );
1616 const SwCharFmt
*pSwCharFmt
= rSwFmtDrop
.GetCharFmt();
1619 m_rWW8Export
.InsUInt16( 80 );
1620 m_rWW8Export
.InsUInt16( m_rWW8Export
.GetId( *pSwCharFmt
) );
1623 m_rWW8Export
.pO
->Insert( 101, m_rWW8Export
.pO
->Count() ); // Lower the chars
1624 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( -((nDropLines
- 1)*rDropDescent
) / 10 ) );
1626 m_rWW8Export
.pO
->Insert( 99, m_rWW8Export
.pO
->Count() ); // Font Size
1627 m_rWW8Export
.InsUInt16( static_cast< UINT16
>( rFontHeight
/ 10 ) );
1631 m_rWW8Export
.pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->Count(), m_rWW8Export
.pO
->GetData() );
1632 m_rWW8Export
.pO
->Remove( 0, m_rWW8Export
.pO
->Count() );
1635 xub_StrLen
MSWordExportBase::GetNextPos( SwAttrIter
* aAttrIter
, const SwTxtNode
& /*rNode*/, xub_StrLen
/*nAktPos*/ )
1637 return aAttrIter
->WhereNext();
1640 void MSWordExportBase::UpdatePosition( SwAttrIter
* aAttrIter
, xub_StrLen
/*nAktPos*/, xub_StrLen
/*nEnd*/ )
1642 aAttrIter
->NextPos();
1645 void MSWordExportBase::OutputTextNode( const SwTxtNode
& rNode
)
1648 ::std::clog
<< "<OutWW8_SwTxtNode>" << ::std::endl
;
1651 ww8::WW8TableNodeInfo::Pointer_t
pTextNodeInfo( mpTableInfo
->getTableNodeInfo( &rNode
) );
1653 AttrOutput().StartParagraph( pTextNodeInfo
);
1655 bool bFlyInTable
= mpParentFrame
&& bIsInTable
;
1658 nStyleBeforeFly
= GetId( lcl_getFormatCollection( *this, &rNode
) );
1660 // nStyleBeforeFly may change when we recurse into another node, so we
1661 // have to remember it in nStyle
1662 USHORT nStyle
= nStyleBeforeFly
;
1664 SwAttrIter
aAttrIter( *this, rNode
);
1665 rtl_TextEncoding eChrSet
= aAttrIter
.GetCharSet();
1669 // ignore TOX header section
1670 const SwSectionNode
* pSectNd
= rNode
.FindSectionNode();
1671 if ( pSectNd
&& TOX_CONTENT_SECTION
== pSectNd
->GetSection().GetType() )
1673 AttrOutput().StartTOX( pSectNd
->GetSection() );
1674 m_aCurrentCharPropStarts
.push( 0 );
1678 const SwSection
* pTOXSect
= 0;
1681 // check for end of TOX
1682 SwNodeIndex
aIdx( rNode
, 1 );
1683 if( !aIdx
.GetNode().IsTxtNode() )
1685 const SwSectionNode
* pTOXSectNd
= rNode
.FindSectionNode();
1686 pTOXSect
= &pTOXSectNd
->GetSection();
1688 const SwNode
* pNxt
= rNode
.GetNodes().GoNext( &aIdx
);
1689 if( pNxt
&& pNxt
->FindSectionNode() == pTOXSectNd
)
1694 if ( aAttrIter
.RequiresImplicitBookmark() )
1696 String sBkmkName
= String( RTL_CONSTASCII_STRINGPARAM( "_toc" ) );
1697 sBkmkName
+= String::CreateFromInt32( rNode
.GetIndex() );
1698 AppendWordBookmark( sBkmkName
);
1701 //Would need to move into WW8Export, probably not worth it
1702 //ASSERT( pO->Count(), " pO ist am Zeilenanfang nicht leer" );
1704 String
aStr( rNode
.GetTxt() );
1706 xub_StrLen nAktPos
= 0;
1707 xub_StrLen nEnd
= aStr
.Len();
1708 bool bRedlineAtEnd
= false;
1709 int nOpenAttrWithRange
= 0;
1711 ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
;
1712 if ( pTextNodeInfo
.get() != NULL
)
1713 pTextNodeInfoInner
= pTextNodeInfo
->getFirstInner();
1716 const SwRedlineData
* pRedlineData
= aAttrIter
.GetRedline( nAktPos
);
1718 AttrOutput().StartRun( pRedlineData
);
1720 xub_StrLen nNextAttr
= GetNextPos( &aAttrIter
, rNode
, nAktPos
);
1722 if( nNextAttr
> nEnd
)
1725 aAttrIter
.OutFlys( nAktPos
);
1726 //Append bookmarks in this range after flys, exclusive of final
1727 //position of this range
1728 AppendBookmarks( rNode
, nAktPos
, nNextAttr
- nAktPos
);
1729 bool bTxtAtr
= aAttrIter
.IsTxtAttr( nAktPos
);
1730 nOpenAttrWithRange
+= aAttrIter
.OutAttrWithRange(nAktPos
);
1732 xub_StrLen nLen
= nNextAttr
- nAktPos
;
1733 if ( !bTxtAtr
&& nLen
)
1735 sal_Unicode ch
= aStr
.GetChar( nAktPos
);
1736 int ofs
= ( ch
== CH_TXT_ATR_FIELDSTART
|| ch
== CH_TXT_ATR_FIELDEND
|| ch
== CH_TXT_ATR_FORMELEMENT
? 1: 0 );
1738 IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1739 if ( ch
== CH_TXT_ATR_FIELDSTART
)
1741 SwPosition
aPosition( rNode
, SwIndex( const_cast< SwTxtNode
* >( &rNode
), nAktPos
+ 1 ) );
1742 ::sw::mark::IFieldmark
const * const pFieldmark
= pMarkAccess
->getFieldmarkFor( aPosition
);
1743 OSL_ENSURE( pFieldmark
, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
1745 if ( pFieldmark
->GetFieldname().equalsAscii( ECMA_FORMTEXT
) )
1746 AppendBookmark( pFieldmark
->GetName(), false );
1747 OutputField( NULL
, lcl_getFieldId( pFieldmark
), lcl_getFieldCode( pFieldmark
), WRITEFIELD_START
| WRITEFIELD_CMD_START
);
1748 if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMTEXT
) )
1749 WriteFormData( *pFieldmark
);
1750 else if ( pFieldmark
->GetFieldname( ).equalsAscii( ECMA_HYPERLINK
) )
1751 WriteHyperlinkData( *pFieldmark
);
1752 OutputField( NULL
, lcl_getFieldId( pFieldmark
), String(), WRITEFIELD_CMD_END
);
1754 else if ( ch
== CH_TXT_ATR_FIELDEND
)
1756 SwPosition
aPosition( rNode
, SwIndex( const_cast< SwTxtNode
* >( &rNode
), nAktPos
) );
1757 ::sw::mark::IFieldmark
const * const pFieldmark
= pMarkAccess
->getFieldmarkFor( aPosition
);
1758 OSL_ENSURE( pFieldmark
, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
1760 OutputField( NULL
, lcl_getFieldId( pFieldmark
), String(), WRITEFIELD_CLOSE
);
1761 if ( pFieldmark
->GetFieldname().equalsAscii( ECMA_FORMTEXT
) )
1762 AppendBookmark( pFieldmark
->GetName(), false );
1764 else if ( ch
== CH_TXT_ATR_FORMELEMENT
)
1766 SwPosition
aPosition( rNode
, SwIndex( const_cast< SwTxtNode
* >( &rNode
), nAktPos
) );
1767 ::sw::mark::IFieldmark
const * const pFieldmark
= pMarkAccess
->getFieldmarkFor( aPosition
);
1768 OSL_ENSURE( pFieldmark
, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
1770 bool isEcma
= pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMDROPDOWN
) ||
1771 pFieldmark
->GetFieldname( ).equalsAscii( ECMA_FORMCHECKBOX
);
1774 AppendBookmark( pFieldmark
->GetName(), 0 );
1775 OutputField( NULL
, lcl_getFieldId( pFieldmark
),
1776 lcl_getFieldCode( pFieldmark
),
1777 WRITEFIELD_START
| WRITEFIELD_CMD_START
);
1779 WriteFormData( *pFieldmark
);
1780 OutputField( NULL
, lcl_getFieldId( pFieldmark
), String(), WRITEFIELD_CMD_END
| WRITEFIELD_CLOSE
);
1782 AppendBookmark( pFieldmark
->GetName(), false );
1784 nLen
-= static_cast< USHORT
>( ofs
);
1786 String
aSnippet( aAttrIter
.GetSnippet( aStr
, nAktPos
+ static_cast< USHORT
>( ofs
), nLen
) );
1787 if ( ( nTxtTyp
== TXT_EDN
|| nTxtTyp
== TXT_FTN
) && nAktPos
== 0 && nLen
> 0 )
1789 // Insert tab for aesthetic puposes #i24762#
1790 if ( aSnippet
.GetChar( 0 ) != 0x09 )
1791 aSnippet
.Insert( 0x09, 0 );
1793 AttrOutput().RunText( aSnippet
, eChrSet
);
1796 if ( aAttrIter
.IsDropCap( nNextAttr
) )
1797 AttrOutput().FormatDrop( rNode
, aAttrIter
.GetSwFmtDrop(), nStyle
, pTextNodeInfo
, pTextNodeInfoInner
);
1799 // At the end of line, output the attributes until the CR.
1800 // Exception: footnotes at the end of line
1801 if ( nNextAttr
== nEnd
)
1803 ASSERT( nOpenAttrWithRange
>= 0, "odd to see this happening, expected >= 0" );
1804 if ( !bTxtAtr
&& nOpenAttrWithRange
<= 0 )
1806 if ( aAttrIter
.IsRedlineAtEnd( nEnd
) )
1807 bRedlineAtEnd
= true;
1810 // insert final graphic anchors if any before CR
1811 aAttrIter
.OutFlys( nEnd
);
1812 // insert final bookmarks if any before CR and after flys
1813 AppendBookmarks( rNode
, nEnd
, 1 );
1816 m_aCurrentCharPropStarts
.pop();
1817 AttrOutput().EndTOX( *pTOXSect
);
1819 WriteCR( pTextNodeInfoInner
);
1824 // Output the character attributes
1825 AttrOutput().StartRunProperties();
1826 aAttrIter
.OutAttr( nAktPos
); // nAktPos - 1 ??
1827 AttrOutput().EndRunProperties( pRedlineData
);
1829 // Exception: footnotes at the end of line
1830 if ( nNextAttr
== nEnd
)
1832 ASSERT(nOpenAttrWithRange
>= 0,
1833 "odd to see this happening, expected >= 0");
1834 bool bAttrWithRange
= (nOpenAttrWithRange
> 0);
1835 if ( nAktPos
!= nEnd
)
1837 nOpenAttrWithRange
+= aAttrIter
.OutAttrWithRange(nEnd
);
1838 ASSERT(nOpenAttrWithRange
== 0,
1839 "odd to see this happening, expected 0");
1842 AttrOutput().OutputFKP();
1844 if ( bTxtAtr
|| bAttrWithRange
|| bRedlineAtEnd
)
1846 // insert final graphic anchors if any before CR
1847 aAttrIter
.OutFlys( nEnd
);
1848 // insert final bookmarks if any before CR and after flys
1849 AppendBookmarks( rNode
, nEnd
, 1 );
1853 m_aCurrentCharPropStarts
.pop();
1854 AttrOutput().EndTOX( *pTOXSect
);
1857 WriteCR( pTextNodeInfoInner
);
1859 if ( bRedlineAtEnd
)
1861 AttrOutput().Redline( aAttrIter
.GetRedline( nEnd
) );
1862 AttrOutput().OutputFKP();
1867 AttrOutput().EndRun();
1869 nAktPos
= nNextAttr
;
1870 UpdatePosition( &aAttrIter
, nAktPos
, nEnd
);
1871 eChrSet
= aAttrIter
.GetCharSet();
1873 while ( nAktPos
< nEnd
);
1875 AttrOutput().StartParagraphProperties( rNode
);
1877 AttrOutput().ParagraphStyle( nStyle
);
1879 if ( mpParentFrame
&& !bIsInTable
) // Fly-Attrs
1880 OutputFormat( mpParentFrame
->GetFrmFmt(), false, false, true );
1882 if ( pTextNodeInfo
.get() != NULL
)
1885 ::std::clog
<< pTextNodeInfo
->toString() << ::std::endl
;
1888 AttrOutput().TableInfoCell( pTextNodeInfoInner
);
1893 SfxItemSet
* pTmpSet
= 0;
1894 const BYTE nPrvNxtNd
= rNode
.HasPrevNextLayNode();
1896 if( (ND_HAS_PREV_LAYNODE
|ND_HAS_NEXT_LAYNODE
) != nPrvNxtNd
)
1898 const SfxPoolItem
* pItem
;
1899 if( SFX_ITEM_SET
== rNode
.GetSwAttrSet().GetItemState(
1900 RES_UL_SPACE
, true, &pItem
) &&
1901 ( ( !( ND_HAS_PREV_LAYNODE
& nPrvNxtNd
) &&
1902 ((SvxULSpaceItem
*)pItem
)->GetUpper()) ||
1903 ( !( ND_HAS_NEXT_LAYNODE
& nPrvNxtNd
) &&
1904 ((SvxULSpaceItem
*)pItem
)->GetLower()) ))
1906 pTmpSet
= new SfxItemSet( rNode
.GetSwAttrSet() );
1907 SvxULSpaceItem
aUL( *(SvxULSpaceItem
*)pItem
);
1908 // OD, MMAHER 2004-03-01 #i25901#- consider compatibility option
1909 if (!pDoc
->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES
))
1911 if( !(ND_HAS_PREV_LAYNODE
& nPrvNxtNd
))
1914 // OD, MMAHER 2004-03-01 #i25901# - consider compatibility option
1915 if (!pDoc
->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS
))
1917 if( !(ND_HAS_NEXT_LAYNODE
& nPrvNxtNd
))
1920 pTmpSet
->Put( aUL
);
1924 BOOL bParaRTL
= FALSE
;
1925 const SvxFrameDirectionItem
* pItem
= (const SvxFrameDirectionItem
*)
1926 rNode
.GetSwAttrSet().GetItem(RES_FRAMEDIR
);
1927 if ( aAttrIter
.IsParaRTL())
1930 if( rNode
.IsNumbered())
1932 const SwNumRule
* pRule
= rNode
.GetNumRule();
1933 BYTE nLvl
= static_cast< BYTE
>( rNode
.GetActualListLevel() );
1934 const SwNumFmt
* pFmt
= pRule
->GetNumFmt( nLvl
);
1936 pFmt
= &pRule
->Get( nLvl
);
1939 pTmpSet
= new SfxItemSet( rNode
.GetSwAttrSet() );
1941 SvxLRSpaceItem
aLR(ItemGet
<SvxLRSpaceItem
>(*pTmpSet
, RES_LR_SPACE
));
1942 // --> OD 2008-06-03 #i86652#
1943 if ( pFmt
->GetPositionAndSpaceMode() ==
1944 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1946 aLR
.SetTxtLeft( aLR
.GetTxtLeft() + pFmt
->GetAbsLSpace() );
1950 if( rNode
.IsNumbered() && rNode
.IsCountedInList() )
1952 // --> OD 2008-06-03 #i86652#
1953 if ( pFmt
->GetPositionAndSpaceMode() ==
1954 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1957 aLR
.SetTxtFirstLineOfstValue(pFmt
->GetAbsLSpace() - pFmt
->GetFirstLineOffset());
1959 aLR
.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt
));
1963 // --> OD 2009-03-09 #100020#
1964 // correct fix for issue i94187
1966 pTmpSet
->GetItemState(RES_PARATR_NUMRULE
, false) )
1968 // List style set via paragraph style - then put it into the itemset.
1969 // This is needed to get list level and list id exported for
1971 pTmpSet
->Put( SwNumRuleItem( pRule
->GetName() ));
1973 // Put indent values into the itemset in case that the list
1974 // style is applied via paragraph style and the list level
1975 // indent values are not applicable.
1976 if ( pFmt
->GetPositionAndSpaceMode() ==
1977 SvxNumberFormat::LABEL_ALIGNMENT
&&
1978 !rNode
.AreListLevelIndentsApplicable() )
1980 pTmpSet
->Put( aLR
);
1985 pTmpSet
->ClearItem(RES_PARATR_NUMRULE
);
1987 // --> OD 2008-06-03 #i86652#
1988 if ( pFmt
->GetPositionAndSpaceMode() ==
1989 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1994 SvxTabStopItem
aItem(
1995 ItemGet
<SvxTabStopItem
>(*pTmpSet
, RES_PARATR_TABSTOP
));
1996 SvxTabStop
aTabStop(pFmt
->GetAbsLSpace());
1997 aItem
.Insert(aTabStop
);
1998 pTmpSet
->Put(aItem
);
2000 MSWordExportBase::CorrectTabStopInSet(*pTmpSet
, pFmt
->GetAbsLSpace());
2005 If a given para is using the FRMDIR_ENVIRONMENT direction we
2006 cannot export that, its its ltr then that's ok as thats word's
2007 default. Otherwise we must add a RTL attribute to our export list
2009 pItem
= (const SvxFrameDirectionItem
*)
2010 rNode
.GetSwAttrSet().GetItem(RES_FRAMEDIR
);
2012 (!pItem
|| pItem
->GetValue() == FRMDIR_ENVIRONMENT
) &&
2013 aAttrIter
.IsParaRTL()
2017 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2019 pTmpSet
->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP
, RES_FRAMEDIR
));
2021 // --> OD 2005-10-18 #126238# - move code for handling of numbered,
2022 // but not counted paragraphs to this place. Otherwise, the paragraph
2023 // isn't exported as numbered, but not counted, if no other attribute
2024 // is found in <pTmpSet>
2025 // #i44815# adjust numbering/indents for numbered paragraphs
2026 // without number (NO_NUMLEVEL)
2027 // #i47013# need to check rNode.GetNumRule()!=NULL as well.
2028 if ( ! rNode
.IsCountedInList() && rNode
.GetNumRule()!=NULL
)
2030 // WW8 does not know numbered paragraphs without number
2031 // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
2032 // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
2033 // no numbering. Here, we will adjust the indents to match
2037 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2039 // create new LRSpace item, based on the current (if present)
2040 const SfxPoolItem
* pPoolItem
= NULL
;
2041 pTmpSet
->GetItemState(RES_LR_SPACE
, TRUE
, &pPoolItem
);
2042 SvxLRSpaceItem
aLRSpace(
2043 ( pPoolItem
== NULL
)
2044 ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE
)
2045 : *static_cast<const SvxLRSpaceItem
*>( pPoolItem
) );
2047 // new left margin = old left + label space
2048 const SwNumRule
* pRule
= rNode
.GetNumRule();
2049 const SwNumFmt
& rNumFmt
= pRule
->Get( static_cast< USHORT
>(rNode
.GetActualListLevel()) );
2050 // --> OD 2008-06-03 #i86652#
2051 if ( rNumFmt
.GetPositionAndSpaceMode() ==
2052 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
2054 aLRSpace
.SetTxtLeft( aLRSpace
.GetLeft() + rNumFmt
.GetAbsLSpace() );
2056 // new first line indent = 0
2057 // (first line indent is ignored for NO_NUMLEVEL)
2059 aLRSpace
.SetTxtFirstLineOfst( 0 );
2061 // put back the new item
2062 pTmpSet
->Put( aLRSpace
);
2066 // assure that numbering rule is in <pTmpSet>
2067 if (SFX_ITEM_SET
!= pTmpSet
->GetItemState(RES_PARATR_NUMRULE
, false) )
2069 pTmpSet
->Put( SwNumRuleItem( pRule
->GetName() ));
2073 // --> OD 2007-04-24 #i75457#
2074 // Export page break after attribute from paragraph style.
2075 // If page break attribute at the text node exist, an existing page
2076 // break after at the paragraph style hasn't got to be considered.
2077 if ( !rNode
.GetpSwAttrSet() ||
2078 SFX_ITEM_SET
!= rNode
.GetpSwAttrSet()->GetItemState(RES_BREAK
, false) )
2080 const SvxFmtBreakItem
* pBreakAtParaStyle
=
2081 &(ItemGet
<SvxFmtBreakItem
>(rNode
.GetSwAttrSet(), RES_BREAK
));
2082 if ( pBreakAtParaStyle
&&
2083 pBreakAtParaStyle
->GetBreak() == SVX_BREAK_PAGE_AFTER
)
2087 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2089 pTmpSet
->Put( *pBreakAtParaStyle
);
2092 { // Even a pagedesc item is set, the break item can be set 'NONE',
2093 // this has to be overruled.
2094 const SwFmtPageDesc
& rPageDescAtParaStyle
=
2095 ItemGet
<SwFmtPageDesc
>( rNode
, RES_PAGEDESC
);
2096 if( rPageDescAtParaStyle
.GetRegisteredIn() )
2097 pTmpSet
->ClearItem( RES_BREAK
);
2101 // --> FME 2007-05-30 #i76520# Emulate non-splitting tables
2104 const SwTableNode
* pTableNode
= rNode
.FindTableNode();
2108 const SwTable
& rTable
= pTableNode
->GetTable();
2109 const SvxFmtKeepItem
& rKeep
= rTable
.GetFrmFmt()->GetKeep();
2110 const bool bKeep
= rKeep
.GetValue();
2111 const bool bDontSplit
= !bKeep
?
2112 !rTable
.GetFrmFmt()->GetLayoutSplit().GetValue() :
2115 if ( bKeep
|| bDontSplit
)
2117 // bKeep: set keep at first paragraphs in all lines
2118 // bDontSplit : set keep at first paragraphs in all lines except from last line
2119 // but only for non-complex tables
2120 const SwTableBox
* pBox
= rNode
.GetTblBox();
2121 const SwTableLine
* pLine
= pBox
? pBox
->GetUpper() : 0;
2123 if ( pLine
&& !pLine
->GetUpper() )
2125 // check if box is first in that line:
2126 if ( 0 == pLine
->GetTabBoxes().GetPos( pBox
) && pBox
->GetSttNd() )
2128 // check if paragraph is first in that line:
2129 if ( 1 == ( rNode
.GetIndex() - pBox
->GetSttNd()->GetIndex() ) )
2131 bool bSetAtPara
= false;
2134 else if ( bDontSplit
)
2136 // check if pLine isn't last line in table
2137 if ( rTable
.GetTabLines().Count() - rTable
.GetTabLines().GetPos( pLine
) != 1 )
2144 pTmpSet
= new SfxItemSet(rNode
.GetSwAttrSet());
2146 const SvxFmtKeepItem
aKeepItem( TRUE
, RES_KEEP
);
2147 pTmpSet
->Put( aKeepItem
);
2157 const SfxItemSet
* pNewSet
= pTmpSet
? pTmpSet
: rNode
.GetpSwAttrSet();
2160 pStyAttr
= &rNode
.GetAnyFmtColl().GetAttrSet();
2162 const SwModify
* pOldMod
= pOutFmtNode
;
2163 pOutFmtNode
= &rNode
;
2165 // Pap-Attrs, so script is not necessary
2166 OutputItemSet( *pNewSet
, true, false, i18n::ScriptType::LATIN
);
2169 pOutFmtNode
= pOldMod
;
2171 if( pNewSet
!= rNode
.GetpSwAttrSet() )
2176 AttrOutput().EndParagraphProperties();
2178 AttrOutput().EndParagraph( pTextNodeInfoInner
);
2181 ::std::clog
<< "</OutWW8_SwTxtNode>" << ::std::endl
;
2185 void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo
)
2188 ShortToSVBT16( GetExport().nStyleBeforeFly
, nSty
);
2190 ww8::WW8TableNodeInfo::Inners_t::const_iterator
aIt( pNodeInfo
->getInners().begin() );
2191 ww8::WW8TableNodeInfo::Inners_t::const_iterator
aItEnd( pNodeInfo
->getInners().end() );
2193 while (aIt
!= aItEnd
)
2195 ww8::WW8TableNodeInfoInner::Pointer_t pInner
= aIt
->second
;
2196 if ( pInner
->isEndOfCell() )
2198 TableRowEnd( pInner
->getDepth() );
2200 m_rWW8Export
.pO
->Insert( (BYTE
*)&nSty
, 2, m_rWW8Export
.pO
->Count() ); // Style #
2201 TableInfoRow( pInner
);
2202 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->Count(),
2203 m_rWW8Export
.pO
->GetData() );
2204 m_rWW8Export
.pO
->Remove( 0, m_rWW8Export
.pO
->Count() ); // leeren
2207 if ( pInner
->isEndOfLine() )
2218 USHORT
WW8Export::StartTableFromFrmFmt( WW8Bytes
&rAt
, const SwFrmFmt
*pFmt
)
2220 // Tell the undocumented table hack that everything between here and
2221 // the last table position is nontable text
2222 if ( WW8_CP nPos
= Fc2Cp( Strm().Tell() ) )
2223 pMagicTable
->Append(nPos
,0);
2225 // sprmPDxaFromText10
2228 static BYTE __READONLY_DATA aTabLineAttr
[] = {
2230 0x16, 0x24, 1, // sprmPFInTable
2231 0x17, 0x24, 1 }; // sprmPFTtp
2232 rAt
.Insert( aTabLineAttr
, sizeof( aTabLineAttr
), rAt
.Count() );
2236 static BYTE __READONLY_DATA aTabLineAttr
[] = {
2238 24, 1, // sprmPFInTable
2239 25, 1 }; // sprmPFTtp
2240 rAt
.Insert( aTabLineAttr
, sizeof( aTabLineAttr
), rAt
.Count() );
2243 ASSERT( pFmt
, "No pFmt!" );
2246 const SwFmtHoriOrient
&rHori
= pFmt
->GetHoriOrient();
2247 const SwFmtVertOrient
&rVert
= pFmt
->GetVertOrient();
2249 (text::RelOrientation::PRINT_AREA
== rHori
.GetRelationOrient() ||
2250 text::RelOrientation::FRAME
== rHori
.GetRelationOrient())
2252 (text::RelOrientation::PRINT_AREA
== rVert
.GetRelationOrient() ||
2253 text::RelOrientation::FRAME
== rVert
.GetRelationOrient())
2256 sal_Int16 eHOri
= rHori
.GetHoriOrient();
2259 case text::HoriOrientation::CENTER
:
2260 case text::HoriOrientation::RIGHT
:
2262 SwWW8Writer::InsUInt16( rAt
, NS_sprm::LN_TJc
);
2264 rAt
.Insert( 182, rAt
.Count() );
2265 SwWW8Writer::InsUInt16( rAt
, (text::HoriOrientation::RIGHT
== eHOri
? 2 : 1 ));
2275 //See #i19484# for why we need this
2276 static bool CellContainsProblematicGraphic( const SwWriteTableCell
*pCell
,
2277 const MSWordExportBase
&rExport
)
2279 const SwNode
*pStart
= pCell
? pCell
->GetBox()->GetSttNd() : 0;
2280 const SwNode
*pEnd
= pStart
? pStart
->EndOfSectionNode() : 0;
2281 ASSERT( pStart
&& pEnd
, "No start or end?" );
2282 if ( !pStart
|| !pEnd
)
2285 bool bHasGraphic
= false;
2287 sw::Frames
aFrames( GetFramesBetweenNodes( rExport
.maFrames
, *pStart
, *pEnd
) );
2288 sw::FrameIter aEnd
= aFrames
.end();
2289 for ( sw::FrameIter aIter
= aFrames
.begin(); aIter
!= aEnd
; ++aIter
)
2291 const SwFrmFmt
&rEntry
= aIter
->GetFrmFmt();
2292 if ( rEntry
.GetSurround().GetSurround() == SURROUND_THROUGHT
)
2301 static bool RowContainsProblematicGraphic( const SwWriteTableCellPtr
*pRow
,
2302 USHORT nCols
, const MSWordExportBase
&rExport
)
2304 bool bHasGraphic
= false;
2305 for ( USHORT nI
= 0; nI
< nCols
; ++nI
)
2307 if ( CellContainsProblematicGraphic( pRow
[nI
], rExport
) )
2316 //---------------------------------------------------------------------------
2318 //---------------------------------------------------------------------------
2320 void WW8AttributeOutput::EmptyParagraph()
2322 m_rWW8Export
.WriteStringAsPara( aEmptyStr
);
2325 bool MSWordExportBase::NoPageBreakSection( const SfxItemSet
* pSet
)
2328 const SfxPoolItem
* pI
;
2331 bool bNoPageBreak
= false;
2332 if ( SFX_ITEM_ON
!= pSet
->GetItemState(RES_PAGEDESC
, true, &pI
)
2333 || 0 == ((SwFmtPageDesc
*)pI
)->GetPageDesc() )
2335 bNoPageBreak
= true;
2340 if (SFX_ITEM_ON
!= pSet
->GetItemState(RES_BREAK
, true, &pI
))
2341 bNoPageBreak
= true;
2344 SvxBreak eBreak
= ((const SvxFmtBreakItem
*)pI
)->GetBreak();
2347 case SVX_BREAK_PAGE_BEFORE
:
2348 case SVX_BREAK_PAGE_AFTER
:
2349 bNoPageBreak
= false;
2356 bRet
= bNoPageBreak
;
2363 void MSWordExportBase::OutputSectionNode( const SwSectionNode
& rSectionNode
)
2365 const SwSection
& rSection
= rSectionNode
.GetSection();
2367 SwNodeIndex
aIdx( rSectionNode
, 1 );
2368 const SwNode
& rNd
= aIdx
.GetNode();
2369 if ( !rNd
.IsSectionNode() && !bIsInTable
) //No sections in table
2371 // Bug 74245 - if the first Node inside the section has an own
2372 // PageDesc or PageBreak attribut, then dont write
2373 // here the section break
2374 ULONG nRstLnNum
= 0;
2375 const SfxItemSet
* pSet
;
2376 if ( rNd
.IsTableNode() )
2377 pSet
= &rNd
.GetTableNode()->GetTable().GetFrmFmt()->GetAttrSet();
2378 else if ( rNd
.IsCntntNode() )
2380 pSet
= &rNd
.GetCntntNode()->GetSwAttrSet();
2381 nRstLnNum
= ((SwFmtLineNumber
&)pSet
->Get(
2382 RES_LINENUMBER
)).GetStartValue();
2387 if ( pSet
&& NoPageBreakSection( pSet
) )
2392 // new Section with no own PageDesc/-Break
2393 // -> write follow section break;
2394 const SwSectionFmt
& rFmt
= *rSection
.GetFmt();
2395 ReplaceCr( msword::PageBreak
); // Indikator fuer Page/Section-Break
2397 //Get the page in use at the top of this section
2398 SwNodeIndex
aIdxTmp(rSectionNode
, 1);
2399 const SwPageDesc
*pCurrent
=
2400 SwPageDesc::GetPageDescOfNode(aIdxTmp
.GetNode());
2402 pCurrent
= pAktPageDesc
;
2404 AppendSection( pCurrent
, &rFmt
, nRstLnNum
);
2407 if ( TOX_CONTENT_SECTION
== rSection
.GetType() )
2412 void WW8Export::AppendSection( const SwPageDesc
*pPageDesc
, const SwSectionFmt
* pFmt
, ULONG nLnNum
)
2414 pSepx
->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc
, pFmt
, nLnNum
);
2419 //---------------------------------------------------------------------------
2421 //---------------------------------------------------------------------------
2423 void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode
& rNd
)
2425 ASSERT(!bWrtWW8
, "I shouldn't be needed for Word >=8");
2429 if (const SwpHints
* pTxtAttrs
= rNd
.GetpSwpHints())
2431 for( USHORT n
=0; n
< pTxtAttrs
->Count(); ++n
)
2433 const SwTxtAttr
* pAttr
= (*pTxtAttrs
)[ n
];
2434 if( RES_TXTATR_FLYCNT
== pAttr
->Which() )
2436 // zeichengebundenes Attribut
2437 const SwFmtFlyCnt
& rFlyCntnt
= pAttr
->GetFlyCnt();
2438 const SwFlyFrmFmt
& rFlyFrmFmt
= *(SwFlyFrmFmt
*)rFlyCntnt
.GetFrmFmt();
2439 const SwNodeIndex
* pNodeIndex
= rFlyFrmFmt
.GetCntnt().GetCntntIdx();
2443 ULONG nStt
= pNodeIndex
->GetIndex()+1,
2444 nEnd
= pNodeIndex
->GetNode().EndOfSectionIndex();
2446 if( (nStt
< nEnd
) && !pDoc
->GetNodes()[ nStt
]->IsNoTxtNode() )
2449 // Rechtecke des Flys und des Absatzes besorgen
2450 SwRect
aParentRect(rNd
.FindLayoutRect(false, &aOffset
)),
2451 aFlyRect(rFlyFrmFmt
.FindLayoutRect(false, &aOffset
) );
2453 aOffset
= aFlyRect
.Pos() - aParentRect
.Pos();
2455 // PaM umsetzen: auf Inhalt des Fly-Frameformats
2456 SaveData( nStt
, nEnd
);
2458 // wird in OutputFormat() ausgewertet
2459 pFlyOffset
= &aOffset
;
2460 eNewAnchorType
= rFlyFrmFmt
.GetAnchor().GetAnchorId();
2461 sw::Frame
aFrm(rFlyFrmFmt
, SwPosition(rNd
));
2462 mpParentFrame
= &aFrm
;
2463 // Ok, rausschreiben:
2474 void WW8AttributeOutput::OutputFlyFrame_Impl( const sw::Frame
& rFmt
, const Point
& rNdTopLeft
)
2476 const SwFrmFmt
&rFrmFmt
= rFmt
.GetFrmFmt();
2477 const SwFmtAnchor
& rAnch
= rFrmFmt
.GetAnchor();
2479 bool bUseEscher
= m_rWW8Export
.bWrtWW8
;
2481 if ( m_rWW8Export
.bWrtWW8
&& rFmt
.IsInline() )
2483 sw::Frame::WriterSource eType
= rFmt
.GetWriterType();
2484 if ((eType
== sw::Frame::eGraphic
) || (eType
== sw::Frame::eOle
))
2491 A special case for converting some inline form controls to form fields
2492 when in winword 8+ mode
2494 if ((bUseEscher
== true) && (eType
== sw::Frame::eFormControl
))
2496 if ( m_rWW8Export
.MiserableFormFieldExportHack( rFrmFmt
) )
2503 ASSERT( m_rWW8Export
.bWrtWW8
, "this has gone horribly wrong" );
2505 m_rWW8Export
.AppendFlyInFlys(rFmt
, rNdTopLeft
);
2511 // Hole vom Node und vom letzten Node die Position in der Section
2512 const SwNodeIndex
* pNodeIndex
= rFrmFmt
.GetCntnt().GetCntntIdx();
2514 ULONG nStt
= pNodeIndex
? pNodeIndex
->GetIndex()+1 : 0;
2515 ULONG nEnd
= pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : 0;
2517 if( nStt
>= nEnd
) // kein Bereich, also kein gueltiger Node
2520 if ( !m_rWW8Export
.bIsInTable
&& rFmt
.IsInline() )
2522 //Test to see if this textbox contains only a single graphic/ole
2523 SwTxtNode
* pParTxtNode
= rAnch
.GetCntntAnchor()->nNode
.GetNode().GetTxtNode();
2524 if ( pParTxtNode
&& !m_rWW8Export
.pDoc
->GetNodes()[ nStt
]->IsNoTxtNode() )
2529 // ein NICHT zeichengebundener Rahmen liegt vor
2531 // --> OD 2007-04-19 #i43447# - removed
2532 // const SwFmtFrmSize& rS = rFrmFmt.GetFrmSize();
2533 // nFlyWidth = rS.GetWidth(); // Fuer Anpassung Graphic-Groesse
2534 // nFlyHeight = rS.GetHeight();
2537 m_rWW8Export
.SaveData( nStt
, nEnd
);
2540 if ( m_rWW8Export
.mpParentFrame
)
2544 Munge flys in fly into absolutely positioned elements for
2547 const SwTxtNode
* pParTxtNode
= rAnch
.GetCntntAnchor()->nNode
.GetNode().GetTxtNode();
2548 const SwRect aPageRect
= pParTxtNode
->FindPageFrmRect( FALSE
, 0, FALSE
);
2550 aOffset
= rFrmFmt
.FindLayoutRect().Pos();
2551 aOffset
-= aPageRect
.Pos();
2553 m_rWW8Export
.pFlyOffset
= &aOffset
;
2554 m_rWW8Export
.eNewAnchorType
= FLY_PAGE
;
2557 m_rWW8Export
.mpParentFrame
= &rFmt
;
2559 m_rWW8Export
.bIsInTable
&& (FLY_PAGE
!= rAnch
.GetAnchorId()) &&
2560 !m_rWW8Export
.pDoc
->GetNodes()[ nStt
]->IsNoTxtNode()
2563 // Beachten: Flag bOutTable wieder setzen,
2564 // denn wir geben ja ganz normalen Content der
2565 // Tabelenzelle aus und keinen Rahmen
2566 // (Flag wurde oben in aSaveData() geloescht)
2567 m_rWW8Export
.bOutTable
= true;
2568 const String
& rName
= rFrmFmt
.GetName();
2569 m_rWW8Export
.StartCommentOutput(rName
);
2570 m_rWW8Export
.WriteText();
2571 m_rWW8Export
.EndCommentOutput(rName
);
2574 m_rWW8Export
.WriteText();
2576 m_rWW8Export
.RestoreData();
2581 void AttributeOutputBase::OutputFlyFrame( const sw::Frame
& rFmt
)
2583 if ( !rFmt
.GetCntntNode() )
2586 const SwCntntNode
&rNode
= *rFmt
.GetCntntNode();
2587 Point aNdPos
, aPgPos
;
2589 bool bValidNdPos
= false, bValidPgPos
= false;
2591 if ( FLY_PAGE
== rFmt
.GetFrmFmt().GetAnchor().GetAnchorId() )
2593 // get the Layout Node-Position.
2596 aPgPos
= rNode
.FindPageFrmRect(false, &aPgPos
).Pos();
2603 // get the Layout Node-Position.
2606 aNdPos
= rNode
.FindLayoutRect(false, &aNdPos
).Pos();
2612 OutputFlyFrame_Impl( rFmt
, *pLayPos
);
2615 // write data of any redline
2616 void WW8AttributeOutput::Redline( const SwRedlineData
* pRedline
)
2621 if ( pRedline
->Next() )
2622 Redline( pRedline
->Next() );
2624 static USHORT __READONLY_DATA aSprmIds
[ 2 * 2 * 3 ] =
2627 NS_sprm::LN_CFRMark
, NS_sprm::LN_CIbstRMark
, NS_sprm::LN_CDttmRMark
, // for WW8
2628 0x0042, 0x0045, 0x0046, // for WW6
2630 NS_sprm::LN_CFRMarkDel
, NS_sprm::LN_CIbstRMarkDel
, NS_sprm::LN_CDttmRMarkDel
, // for WW8
2631 0x0041, 0x0045, 0x0046 // for WW6
2634 const USHORT
* pSprmIds
= 0;
2635 switch( pRedline
->GetType() )
2637 case nsRedlineType_t::REDLINE_INSERT
:
2638 pSprmIds
= aSprmIds
;
2641 case nsRedlineType_t::REDLINE_DELETE
:
2642 pSprmIds
= aSprmIds
+ (2 * 3);
2645 case nsRedlineType_t::REDLINE_FORMAT
:
2646 if( m_rWW8Export
.bWrtWW8
)
2648 m_rWW8Export
.InsUInt16( NS_sprm::LN_CPropRMark
);
2649 m_rWW8Export
.pO
->Insert( 7, m_rWW8Export
.pO
->Count() ); // len
2650 m_rWW8Export
.pO
->Insert( 1, m_rWW8Export
.pO
->Count() );
2651 m_rWW8Export
.InsUInt16( m_rWW8Export
.AddRedlineAuthor( pRedline
->GetAuthor() ) );
2652 m_rWW8Export
.InsUInt32( sw::ms::DateTime2DTTM( pRedline
->GetTimeStamp() ));
2656 ASSERT(!this, "Unhandled redline type for export");
2662 if ( !m_rWW8Export
.bWrtWW8
)
2665 if ( m_rWW8Export
.bWrtWW8
)
2666 m_rWW8Export
.InsUInt16( pSprmIds
[0] );
2668 m_rWW8Export
.pO
->Insert( msword_cast
<sal_uInt8
>(pSprmIds
[0]), m_rWW8Export
.pO
->Count() );
2669 m_rWW8Export
.pO
->Insert( 1, m_rWW8Export
.pO
->Count() );
2671 if ( m_rWW8Export
.bWrtWW8
)
2672 m_rWW8Export
.InsUInt16( pSprmIds
[1] );
2674 m_rWW8Export
.pO
->Insert( msword_cast
<sal_uInt8
>(pSprmIds
[1]), m_rWW8Export
.pO
->Count() );
2675 m_rWW8Export
.InsUInt16( m_rWW8Export
.AddRedlineAuthor( pRedline
->GetAuthor() ) );
2677 if ( m_rWW8Export
.bWrtWW8
)
2678 m_rWW8Export
.InsUInt16( pSprmIds
[2] );
2680 m_rWW8Export
.pO
->Insert( msword_cast
<sal_uInt8
>(pSprmIds
[2]), m_rWW8Export
.pO
->Count() );
2681 m_rWW8Export
.InsUInt32( sw::ms::DateTime2DTTM( pRedline
->GetTimeStamp() ));
2687 void MSWordExportBase::OutputContentNode( const SwCntntNode
& rNode
)
2689 switch ( rNode
.GetNodeType() )
2692 OutputTextNode( *rNode
.GetTxtNode() );
2695 OutputGrfNode( *rNode
.GetGrfNode() );
2698 OutputOLENode( *rNode
.GetOLENode() );
2701 #if OSL_DEBUG_LEVEL > 0
2702 fprintf( stderr
, "Unhandled node, type == %d\n", rNode
.GetNodeType() );
2708 /* vi:set tabstop=4 shiftwidth=4 expandtab: */