Update ooo320-m1
[ooovba.git] / sw / source / filter / ww8 / wrtw8nds.cxx
bloba9bbf790a94acf1cd9f932035b069c1da07cf589
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 -*- */
35 #include <vector>
36 #include <list>
37 #include <utility>
38 #include <algorithm>
39 #include <functional>
40 #include <iostream>
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>
65 #include <frmatr.hxx>
66 #include <paratr.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>
73 #include <tox.hxx>
74 #include <ndtxt.hxx>
75 #include <pam.hxx>
76 #include <doc.hxx>
77 #include <docary.hxx>
78 #include <swtable.hxx>
79 #include <section.hxx>
80 #include <pagedesc.hxx>
81 #include <swrect.hxx>
82 #include <reffld.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>
90 #include <txtatr.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"
103 #include <IMark.hxx>
104 #include "ww8attributeoutput.hxx"
106 #include <ndgrf.hxx>
107 #include <ndole.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 ");
131 } else {
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 ) ) {
145 return ww::eTOC;
146 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ECMA_HYPERLINK ) ) {
147 return ww::eHYPERLINK;
148 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ECMA_PAGEREF ) ) {
149 return ww::ePAGEREF;
150 } else {
151 return ww::eUNKNOWN;
155 /* \f */
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
176 // ausgegeben.
178 class SwAttrIter : public MSWordAttrIter
180 private:
181 const SwTxtNode& rNd;
183 CharRuns maCharRuns;
184 cCharRunIter maCharRunIter;
186 rtl_TextEncoding meChrSet;
187 sal_uInt16 mnScript;
188 bool mbCharIsRTL;
190 const SwRedline* pCurRedline;
191 xub_StrLen nAktSwPos;
192 USHORT nCurRedlinePos;
194 bool mbParaIsRTL;
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();
208 //No copying
209 SwAttrIter(const SwAttrIter&);
210 SwAttrIter& operator=(const SwAttrIter&);
211 public:
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; }
238 class sortswflys :
239 public std::binary_function<const sw::Frame&, const sw::Frame&, bool>
241 public:
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) :
257 MSWordAttrIter(rWr),
258 rNd(rTxtNd),
259 maCharRuns(GetPseudoCharRuns(rTxtNd, 0, !rWr.HackIsWW8OrHigher())),
260 pCurRedline(0),
261 nAktSwPos(0),
262 nCurRedlinePos(USHRT_MAX),
263 mrSwFmtDrop(rTxtNd.GetSwAttrSet().GetDrop())
266 SwPosition aPos(rTxtNd);
267 if (FRMDIR_HORI_RIGHT_TOP == rWr.pDoc->GetTextDirection(aPos))
268 mbParaIsRTL = true;
269 else
270 mbParaIsRTL = false;
272 maCharRunIter = maCharRuns.begin();
273 IterToCurrent();
276 #i2916#
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());
283 #i18480#
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 )
307 xub_StrLen nPos;
308 xub_StrLen nMinPos = STRING_MAXLEN;
309 xub_StrLen i=0;
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)
318 nMinPos=pos;
320 // first the redline, then the attributes
321 if( pCurRedline )
323 const SwPosition* pEnd = pCurRedline->End();
324 if (pEnd->nNode == rNd && ((i = pEnd->nContent.GetIndex()) >= nStartPos) && i < nMinPos )
325 nMinPos = i;
328 if ( nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count() )
330 // nCurRedlinePos point to the next redline
331 nPos = nCurRedlinePos;
332 if( pCurRedline )
333 ++nPos;
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()
341 ? pRedl->GetMark()
342 : pRedl->GetPoint();
344 if( pStt->nNode == rNd )
346 if( ( i = pStt->nContent.GetIndex() ) >= nStartPos &&
347 i < nMinPos )
348 nMinPos = i;
350 else
351 break;
353 if( pEnd->nNode == rNd &&
354 ( i = pEnd->nContent.GetIndex() ) < nMinPos &&
355 i >= nStartPos )
356 nMinPos = i;
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 )
377 nMinPos = nPos;
379 if( pHt->GetEnd() ) // Attr mit Ende
381 nPos = *pHt->GetEnd(); // gibt letztes Attr-Zeichen + 1
382 if( nPos >= nStartPos && nPos <= nMinPos )
383 nMinPos = nPos;
385 if (pHt->HasDummyChar())
387 // pos + 1 because of CH_TXTATR in Text
388 nPos = *pHt->GetStart() + 1;
389 if( nPos >= nStartPos && nPos <= nMinPos )
390 nMinPos = nPos;
395 if (maCharRunIter != maCharRuns.end())
397 if (maCharRunIter->mnEndPos < nMinPos)
398 nMinPos = maCharRunIter->mnEndPos;
399 IterToCurrent();
403 #i2916#
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
407 anchored to.
409 if (maFlyIter != maFlyFrms.end())
411 const SwPosition &rAnchor = maFlyIter->GetPosition();
413 nPos = rAnchor.nContent.GetIndex();
414 if (nPos >= nStartPos && nPos <= nMinPos)
415 nMinPos = nPos;
417 if (maFlyIter->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AUTO_CNTNT)
419 ++nPos;
420 if (nPos >= nStartPos && nPos <= nMinPos)
421 nMinPos = nPos;
425 //nMinPos found and not going to change at this point
427 if (maCharRunIter != maCharRuns.end())
429 if (maCharRunIter->mnEndPos == nMinPos)
430 ++maCharRunIter;
433 return 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())
457 BOOL bDeep = FALSE;
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);
462 pFont = &rNdFont;
463 aExportSet.ClearItem(nFontId);
466 //The additional hard formatting properties that affect this range in the
467 //paragraph
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();
489 while( nWhichId )
491 if( SFX_ITEM_SET == pSet->GetItemState( nWhichId, FALSE, &pItem ))
493 if (nWhichId == nFontId)
494 pFont = &(item_cast<SvxFontItem>(*pItem));
495 else
496 aRangeItems[nWhichId] = pItem;
498 nWhichId = aIter.NextWhich();
501 else
502 aRangeItems[nWhich] = (&(pHt->GetAttr()));
504 else if (nSwPos < *pHt->GetStart())
505 break;
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 );
516 if ( pCharFmtItem )
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" );
540 if ( pFont )
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
552 characters.
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)
565 #i2916#
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 )
575 break;
576 else
578 m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter );
579 ++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) )
593 return true;
597 return false;
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();
605 if (bWholeWord)
607 short nWordLen = rNd.GetDropLen(0);
608 if(nSwPos == nWordLen && nSwPos != 0)
609 return true;
611 else
613 if (nSwPos == nDropChars && nSwPos != 0)
614 return true;
616 return false;
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() )
627 return true;
629 return false;
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();
643 if (pTxtAttrs)
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
655 break;
657 else if (nTmpSwPos < *pHt->GetStart())
658 break; // dann kommt da nichts mehr
661 return pRet;
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" );
681 sal_Int32 nJC = 0;
682 sal_Char cDirective = 0;
683 switch ( rRuby.GetAdjustment() )
685 case 0:
686 nJC = 3;
687 cDirective = 'l';
688 break;
689 case 1:
690 //defaults to 0
691 break;
692 case 2:
693 nJC = 4;
694 cDirective = 'r';
695 break;
696 case 3:
697 nJC = 1;
698 cDirective = 'd';
699 break;
700 case 4:
701 nJC = 2;
702 cDirective = 'd';
703 break;
704 default:
705 ASSERT( !this,"Unhandled Ruby justication code" );
706 break;
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,
715 defaulting to asian.
717 USHORT nRubyScript;
718 if( pBreakIt->GetBreakIter().is() )
719 nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rRuby.GetText(), 0);
720 else
721 nRubyScript = i18n::ScriptType::ASIAN;
723 const SwTxtRuby* pRubyTxt = rRuby.GetTxtRuby();
724 const SwCharFmt* pFmt = pRubyTxt ? pRubyTxt->GetCharFmt() : 0;
725 String sFamilyName;
726 long nHeight;
727 if ( pFmt )
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();
737 else
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" );
759 if ( cDirective )
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() ) );
770 else
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);
779 aStr += '(';
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 )
796 rRet.Erase( 40 );
797 ASSERT( rRet.Len() <= 40, "Word cannot have bookmarks longer than 40 chars" );
798 return rRet;
801 bool AttributeOutputBase::AnalyzeURL( const String& rUrl, const String& /*rTarget*/, String* pLinkURL, String* pMark )
803 bool bBookMarkOnly = false;
805 INetURLObject aURL( rUrl );
806 String sMark;
807 String sURL;
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 );
835 else
837 sURL = aURL.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS );
838 sMark = aURL.GetMark( INetURLObject::DECODE_UNAMBIGUOUS );
842 if ( sMark.Len() && !sURL.Len() )
843 bBookMarkOnly = true;
847 *pMark = sMark;
848 *pLinkURL = sURL;
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;
859 if ( sURL.Len() )
860 sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
862 if ( bBookMarkOnly )
863 sURL = FieldString( ww::eHYPERLINK );
864 else
866 String sFld( FieldString( ww::eHYPERLINK ) );
867 sFld.APPEND_CONST_ASC( "\"" );
868 sURL.Insert( sFld, 0 );
869 sURL += '\"';
872 if ( sMark.Len() )
873 ( ( sURL.APPEND_CONST_ASC( " \\l \"" ) ) += sMark ) += '\"';
875 if ( rTarget.Len() )
876 ( sURL.APPEND_CONST_ASC( " \\n " ) ) += rTarget;
878 *pLinkURL = sURL;
879 *pMark = sMark;
881 return bBookMarkOnly;
884 bool WW8AttributeOutput::StartURL( const String &rUrl, const String &rTarget )
886 // hyperlinks only in WW8
887 if ( !m_rWW8Export.bWrtWW8 )
888 return false;
890 INetURLObject aURL( rUrl );
891 String sURL;
892 String sMark;
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, // |
933 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 ) );
942 BYTE nAnchor = 0x00;
943 if ( sMark.Len() )
944 nAnchor = 0x08;
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;
949 if ( bAbsolute )
950 nFlag |= 0x02;
951 if ( sMark.Len() )
952 nFlag |= 0x08;
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,
963 0x00, 0x00
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 ) )
984 sURL.Erase( 0, 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 );
1025 if ( sMark.Len() )
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 );
1033 return true;
1036 bool WW8AttributeOutput::EndURL()
1038 // hyperlinks only in WW8
1039 if ( !m_rWW8Export.bWrtWW8 )
1040 return false;
1042 m_rWW8Export.OutputField( 0, ww::eHYPERLINK, aEmptyStr, WRITEFIELD_CLOSE );
1044 return true;
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*/ )
1070 WW8Bytes aItems;
1071 m_rWW8Export.GetCurrentItems( aItems );
1073 // sprmCFFldVanish
1074 if ( m_rWW8Export.bWrtWW8 )
1075 SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish );
1076 else
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 );
1085 else
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(),
1091 aItems.GetData() );
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,
1095 aItems.GetData() );
1096 m_rWW8Export.WriteChar( '\x15' );
1097 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(),
1098 aItems.GetData() );
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
1104 String sTxt;
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() );
1114 else
1115 sTxt = rAttr.GetAlternativeText();
1117 switch ( rAttr.GetTOXType()->GetType() )
1119 case TOX_INDEX:
1120 eType = ww::eXE;
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( "\" " );
1134 break;
1136 case TOX_USER:
1137 ( sTxt.APPEND_CONST_ASC( "\" \\f \"" ) )
1138 += (sal_Char)( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) );
1139 // fall through - no break;
1140 case TOX_CONTENT:
1142 eType = ww::eTC;
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 )) += ' ';
1151 break;
1152 default:
1153 ASSERT( !this, "Unhandled option for toc export" );
1154 break;
1157 if ( sTxt.Len() )
1158 FieldVanish( sTxt, eType );
1161 int SwAttrIter::OutAttrWithRange(xub_StrLen nPos)
1163 int nRet = 0;
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() ) )
1179 ++nRet;
1181 if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd )
1183 if ( m_rExport.AttrOutput().EndURL() )
1184 --nRet;
1186 break;
1187 case RES_TXTATR_REFMARK:
1188 if ( nPos == *pHt->GetStart() )
1190 OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), true );
1191 ++nRet;
1193 if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd )
1195 OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), false );
1196 --nRet;
1198 break;
1199 case RES_TXTATR_TOXMARK:
1200 if ( nPos == *pHt->GetStart() )
1201 m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) );
1202 break;
1203 case RES_TXTATR_CJK_RUBY:
1204 if ( nPos == *pHt->GetStart() )
1206 m_rExport.AttrOutput().StartRuby( rNd, *static_cast< const SwFmtRuby* >( pItem ) );
1207 ++nRet;
1209 if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd )
1211 m_rExport.AttrOutput().EndRuby();
1212 --nRet;
1214 break;
1217 m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem nur in dem obigen Bereich erlaubt
1219 return nRet;
1222 bool SwAttrIter::IsRedlineAtEnd( xub_StrLen nEnd ) const
1224 bool bRet = false;
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 )
1234 bRet = true;
1235 break;
1238 else
1239 break;
1241 return bRet;
1244 const SwRedlineData* SwAttrIter::GetRedline( xub_StrLen nPos )
1246 if( pCurRedline )
1248 const SwPosition* pEnd = pCurRedline->End();
1249 if( pEnd->nNode == rNd &&
1250 pEnd->nContent.GetIndex() <= nPos )
1252 pCurRedline = 0;
1253 ++nCurRedlinePos;
1255 else
1257 // write data of current redline
1258 return &( pCurRedline->GetRedlineData() );
1262 if( !pCurRedline )
1264 // search next Redline
1265 for( ; nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count();
1266 ++nCurRedlinePos )
1268 const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nCurRedlinePos ];
1270 const SwPosition* pStt = pRedl->Start();
1271 const SwPosition* pEnd = pStt == pRedl->GetPoint()
1272 ? pRedl->GetMark()
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() );
1285 break;
1288 else
1289 break;
1291 if( pEnd->nNode == rNd &&
1292 pEnd->nContent.GetIndex() < nPos )
1294 pCurRedline = pRedl;
1295 break;
1299 return NULL;
1302 /* \f */
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
1337 return nDir;
1340 short MSWordExportBase::TrueFrameDirection( const SwFrmFmt &rFlyFmt ) const
1342 const SwFrmFmt *pFlyFmt = &rFlyFmt;
1343 const SvxFrameDirectionItem* pItem = 0;
1344 while ( pFlyFmt )
1346 pItem = &pFlyFmt->GetFrmDir();
1347 if ( FRMDIR_ENVIRONMENT == pItem->GetValue() )
1349 pItem = 0;
1350 const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
1351 if ( FLY_PAGE != pAnchor->GetAnchorId() &&
1352 pAnchor->GetCntntAnchor() )
1354 pFlyFmt = pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
1356 else
1357 pFlyFmt = 0;
1359 else
1360 pFlyFmt = 0;
1363 short nRet;
1364 if ( pItem )
1365 nRet = pItem->GetValue();
1366 else
1367 nRet = GetCurrentPageDirection();
1369 ASSERT( nRet != FRMDIR_ENVIRONMENT, "leaving with environment direction" );
1370 return nRet;
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));
1389 return pRet;
1392 SvxBrushItem WW8Export::TrueFrameBgBrush(const SwFrmFmt &rFlyFmt) const
1394 const SwFrmFmt *pFlyFmt = &rFlyFmt;
1395 const SvxBrushItem* pRet = 0;
1397 while (pFlyFmt)
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))
1407 pRet = 0;
1408 const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
1409 if (FLY_PAGE != pAnchor->GetAnchorId() &&
1410 pAnchor->GetCntntAnchor())
1412 pFlyFmt =
1413 pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
1415 else
1416 pFlyFmt = 0;
1418 else
1419 pFlyFmt = 0;
1422 if (!pRet)
1423 pRet = GetCurrentPageBgBrush();
1425 const Color aTmpColor( COL_WHITE );
1426 SvxBrushItem aRet( aTmpColor, RES_BACKGROUND );
1427 if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
1428 aRet = *pRet;
1430 return aRet;
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);
1443 if (!nLen)
1444 return aSnippet;
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();
1467 break;
1468 case i18n::ScriptType::COMPLEX:
1469 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage();
1470 break;
1471 case i18n::ScriptType::LATIN:
1472 default:
1473 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_LANGUAGE)).GetLanguage();
1474 break;
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
1484 //with whitespace
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();
1494 return aSnippet;
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 )
1505 USHORT nPos = 0;
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()
1512 ? pRedl->GetMark()
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();
1520 nMax = nPos;
1521 nPos = 0;
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;
1534 SVBT16 nSty;
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 );
1560 else
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 )
1587 #ifdef DEBUG
1588 ::std::clog << pTextNodeInfo->toString() << ::std::endl;
1589 #endif
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();
1602 if ( pSwCharFmt )
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 ) );
1614 else
1616 const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
1617 if ( pSwCharFmt )
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 )
1647 #ifdef DEBUG
1648 ::std::clog << "<OutWW8_SwTxtNode>" << ::std::endl;
1649 #endif
1651 ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( mpTableInfo->getTableNodeInfo( &rNode ) );
1653 AttrOutput().StartParagraph( pTextNodeInfo );
1655 bool bFlyInTable = mpParentFrame && bIsInTable;
1657 if ( !bFlyInTable )
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();
1667 if ( bStartTOX )
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;
1679 if( bInWriteTOX )
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 )
1690 pTOXSect = 0;
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();
1715 do {
1716 const SwRedlineData* pRedlineData = aAttrIter.GetRedline( nAktPos );
1718 AttrOutput().StartRun( pRedlineData );
1720 xub_StrLen nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos );
1722 if( nNextAttr > nEnd )
1723 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 );
1773 if ( isEcma )
1774 AppendBookmark( pFieldmark->GetName(), 0 );
1775 OutputField( NULL, lcl_getFieldId( pFieldmark ),
1776 lcl_getFieldCode( pFieldmark ),
1777 WRITEFIELD_START | WRITEFIELD_CMD_START );
1778 if ( isEcma )
1779 WriteFormData( *pFieldmark );
1780 OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CMD_END | WRITEFIELD_CLOSE );
1781 if ( isEcma )
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;
1808 else
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 );
1814 if ( pTOXSect )
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 );
1851 if ( pTOXSect )
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 )
1884 #ifdef DEBUG
1885 ::std::clog << pTextNodeInfo->toString() << ::std::endl;
1886 #endif
1888 AttrOutput().TableInfoCell( pTextNodeInfoInner );
1891 if ( !bFlyInTable )
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 ))
1912 aUL.SetUpper( 0 );
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 ))
1918 aUL.SetLower( 0 );
1920 pTmpSet->Put( aUL );
1924 BOOL bParaRTL = FALSE;
1925 const SvxFrameDirectionItem* pItem = (const SvxFrameDirectionItem*)
1926 rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR);
1927 if ( aAttrIter.IsParaRTL())
1928 bParaRTL = TRUE;
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 );
1935 if( !pFmt )
1936 pFmt = &pRule->Get( nLvl );
1938 if( !pTmpSet )
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() );
1948 // <--
1950 if( rNode.IsNumbered() && rNode.IsCountedInList() )
1952 // --> OD 2008-06-03 #i86652#
1953 if ( pFmt->GetPositionAndSpaceMode() ==
1954 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1956 if (bParaRTL)
1957 aLR.SetTxtFirstLineOfstValue(pFmt->GetAbsLSpace() - pFmt->GetFirstLineOffset());
1958 else
1959 aLR.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt));
1961 // <--
1963 // --> OD 2009-03-09 #100020#
1964 // correct fix for issue i94187
1965 if (SFX_ITEM_SET !=
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
1970 // the paragraph.
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 );
1984 else
1985 pTmpSet->ClearItem(RES_PARATR_NUMRULE);
1987 // --> OD 2008-06-03 #i86652#
1988 if ( pFmt->GetPositionAndSpaceMode() ==
1989 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1991 pTmpSet->Put(aLR);
1993 //#i21847#
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);
2011 if (
2012 (!pItem || pItem->GetValue() == FRMDIR_ENVIRONMENT) &&
2013 aAttrIter.IsParaRTL()
2016 if ( !pTmpSet )
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
2034 // visually.
2036 if ( !pTmpSet )
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)
2058 if (!bParaRTL)
2059 aLRSpace.SetTxtFirstLineOfst( 0 );
2061 // put back the new item
2062 pTmpSet->Put( aLRSpace );
2064 // <--
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 )
2085 if ( !pTmpSet )
2087 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2089 pTmpSet->Put( *pBreakAtParaStyle );
2091 else if( pTmpSet )
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
2102 if ( bOutTable )
2104 const SwTableNode* pTableNode = rNode.FindTableNode();
2106 if ( pTableNode )
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() :
2113 false;
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;
2132 if ( bKeep )
2133 bSetAtPara = true;
2134 else if ( bDontSplit )
2136 // check if pLine isn't last line in table
2137 if ( rTable.GetTabLines().Count() - rTable.GetTabLines().GetPos( pLine ) != 1 )
2138 bSetAtPara = true;
2141 if ( bSetAtPara )
2143 if ( !pTmpSet )
2144 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2146 const SvxFmtKeepItem aKeepItem( TRUE, RES_KEEP );
2147 pTmpSet->Put( aKeepItem );
2155 // <--
2157 const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet();
2158 if( pNewSet )
2159 { // Para-Attrs
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);
2168 pStyAttr = 0;
2169 pOutFmtNode = pOldMod;
2171 if( pNewSet != rNode.GetpSwAttrSet() )
2172 delete pNewSet;
2176 AttrOutput().EndParagraphProperties();
2178 AttrOutput().EndParagraph( pTextNodeInfoInner );
2180 #ifdef DEBUG
2181 ::std::clog << "</OutWW8_SwTxtNode>" << ::std::endl;
2182 #endif
2185 void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )
2187 SVBT16 nSty;
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() )
2211 aIt++;
2215 #if 0
2216 /* \f */
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
2226 if( bWrtWW8 )
2228 static BYTE __READONLY_DATA aTabLineAttr[] = {
2229 0, 0, // Sty # 0
2230 0x16, 0x24, 1, // sprmPFInTable
2231 0x17, 0x24, 1 }; // sprmPFTtp
2232 rAt.Insert( aTabLineAttr, sizeof( aTabLineAttr ), rAt.Count() );
2234 else
2236 static BYTE __READONLY_DATA aTabLineAttr[] = {
2237 0, 0, // Sty # 0
2238 24, 1, // sprmPFInTable
2239 25, 1 }; // sprmPFTtp
2240 rAt.Insert( aTabLineAttr, sizeof( aTabLineAttr ), rAt.Count() );
2243 ASSERT( pFmt, "No pFmt!" );
2244 if ( pFmt )
2246 const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
2247 const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
2248 if (
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();
2257 switch (eHOri)
2259 case text::HoriOrientation::CENTER:
2260 case text::HoriOrientation::RIGHT:
2261 if( bWrtWW8 )
2262 SwWW8Writer::InsUInt16( rAt, NS_sprm::LN_TJc );
2263 else
2264 rAt.Insert( 182, rAt.Count() );
2265 SwWW8Writer::InsUInt16( rAt, (text::HoriOrientation::RIGHT == eHOri ? 2 : 1 ));
2266 break;
2267 default:
2268 break;
2272 return rAt.Count();
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 )
2283 return false;
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 )
2294 bHasGraphic = true;
2295 break;
2298 return bHasGraphic;
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 ) )
2309 bHasGraphic = true;
2310 break;
2313 return bHasGraphic;
2315 #endif
2316 //---------------------------------------------------------------------------
2317 // Tabellen
2318 //---------------------------------------------------------------------------
2320 void WW8AttributeOutput::EmptyParagraph()
2322 m_rWW8Export.WriteStringAsPara( aEmptyStr );
2325 bool MSWordExportBase::NoPageBreakSection( const SfxItemSet* pSet )
2327 bool bRet = false;
2328 const SfxPoolItem* pI;
2329 if( pSet)
2331 bool bNoPageBreak = false;
2332 if ( SFX_ITEM_ON != pSet->GetItemState(RES_PAGEDESC, true, &pI)
2333 || 0 == ((SwFmtPageDesc*)pI)->GetPageDesc() )
2335 bNoPageBreak = true;
2338 if (bNoPageBreak)
2340 if (SFX_ITEM_ON != pSet->GetItemState(RES_BREAK, true, &pI))
2341 bNoPageBreak = true;
2342 else
2344 SvxBreak eBreak = ((const SvxFmtBreakItem*)pI)->GetBreak();
2345 switch (eBreak)
2347 case SVX_BREAK_PAGE_BEFORE:
2348 case SVX_BREAK_PAGE_AFTER:
2349 bNoPageBreak = false;
2350 break;
2351 default:
2352 break;
2356 bRet = bNoPageBreak;
2358 return bRet;
2361 /* \f */
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();
2384 else
2385 pSet = 0;
2387 if ( pSet && NoPageBreakSection( pSet ) )
2388 pSet = 0;
2390 if ( !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());
2401 if (!pCurrent)
2402 pCurrent = pAktPageDesc;
2404 AppendSection( pCurrent, &rFmt, nRstLnNum );
2407 if ( TOX_CONTENT_SECTION == rSection.GetType() )
2408 bStartTOX = true;
2412 void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, ULONG nLnNum )
2414 pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFmt, nLnNum);
2417 /* \f */
2419 //---------------------------------------------------------------------------
2420 // Flys
2421 //---------------------------------------------------------------------------
2423 void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode& rNd )
2425 ASSERT(!bWrtWW8, "I shouldn't be needed for Word >=8");
2426 if ( bWrtWW8 )
2427 return;
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();
2441 if( pNodeIndex )
2443 ULONG nStt = pNodeIndex->GetIndex()+1,
2444 nEnd = pNodeIndex->GetNode().EndOfSectionIndex();
2446 if( (nStt < nEnd) && !pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
2448 Point aOffset;
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:
2464 WriteText();
2466 RestoreData();
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))
2485 bUseEscher = false;
2486 else
2487 bUseEscher = true;
2490 #110185#
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 ) )
2497 return ;
2501 if (bUseEscher)
2503 ASSERT( m_rWW8Export.bWrtWW8, "this has gone horribly wrong" );
2504 // write as escher
2505 m_rWW8Export.AppendFlyInFlys(rFmt, rNdTopLeft);
2507 else
2509 bool bDone = false;
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
2518 return;
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() )
2525 bDone = true;
2527 if( !bDone )
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();
2535 // <--
2537 m_rWW8Export.SaveData( nStt, nEnd );
2539 Point aOffset;
2540 if ( m_rWW8Export.mpParentFrame )
2543 #90804#
2544 Munge flys in fly into absolutely positioned elements for
2545 word 6
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;
2558 if (
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);
2573 else
2574 m_rWW8Export.WriteText();
2576 m_rWW8Export.RestoreData();
2581 void AttributeOutputBase::OutputFlyFrame( const sw::Frame& rFmt )
2583 if ( !rFmt.GetCntntNode() )
2584 return;
2586 const SwCntntNode &rNode = *rFmt.GetCntntNode();
2587 Point aNdPos, aPgPos;
2588 Point* pLayPos;
2589 bool bValidNdPos = false, bValidPgPos = false;
2591 if ( FLY_PAGE == rFmt.GetFrmFmt().GetAnchor().GetAnchorId() )
2593 // get the Layout Node-Position.
2594 if ( !bValidPgPos )
2596 aPgPos = rNode.FindPageFrmRect(false, &aPgPos).Pos();
2597 bValidPgPos = true;
2599 pLayPos = &aPgPos;
2601 else
2603 // get the Layout Node-Position.
2604 if ( !bValidNdPos )
2606 aNdPos = rNode.FindLayoutRect(false, &aNdPos).Pos();
2607 bValidNdPos = true;
2609 pLayPos = &aNdPos;
2612 OutputFlyFrame_Impl( rFmt, *pLayPos );
2615 // write data of any redline
2616 void WW8AttributeOutput::Redline( const SwRedlineData* pRedline )
2618 if ( !pRedline )
2619 return;
2621 if ( pRedline->Next() )
2622 Redline( pRedline->Next() );
2624 static USHORT __READONLY_DATA aSprmIds[ 2 * 2 * 3 ] =
2626 // Ids for insert
2627 NS_sprm::LN_CFRMark, NS_sprm::LN_CIbstRMark, NS_sprm::LN_CDttmRMark, // for WW8
2628 0x0042, 0x0045, 0x0046, // for WW6
2629 // Ids for delete
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;
2639 break;
2641 case nsRedlineType_t::REDLINE_DELETE:
2642 pSprmIds = aSprmIds + (2 * 3);
2643 break;
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() ));
2654 break;
2655 default:
2656 ASSERT(!this, "Unhandled redline type for export");
2657 break;
2660 if ( pSprmIds )
2662 if ( !m_rWW8Export.bWrtWW8 )
2663 pSprmIds += 3;
2665 if ( m_rWW8Export.bWrtWW8 )
2666 m_rWW8Export.InsUInt16( pSprmIds[0] );
2667 else
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] );
2673 else
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] );
2679 else
2680 m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[2]), m_rWW8Export.pO->Count() );
2681 m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
2685 /* \f */
2687 void MSWordExportBase::OutputContentNode( const SwCntntNode& rNode )
2689 switch ( rNode.GetNodeType() )
2691 case ND_TEXTNODE:
2692 OutputTextNode( *rNode.GetTxtNode() );
2693 break;
2694 case ND_GRFNODE:
2695 OutputGrfNode( *rNode.GetGrfNode() );
2696 break;
2697 case ND_OLENODE:
2698 OutputOLENode( *rNode.GetOLENode() );
2699 break;
2700 default:
2701 #if OSL_DEBUG_LEVEL > 0
2702 fprintf( stderr, "Unhandled node, type == %d\n", rNode.GetNodeType() );
2703 #endif
2704 break;
2708 /* vi:set tabstop=4 shiftwidth=4 expandtab: */