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