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