LibreOffice Module sw (master)  1
wrtw8nds.cxx
Go to the documentation of this file.
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 <iostream>
25 
26 #include <oox/core/filterbase.hxx>
27 #include "docxexport.hxx"
28 #include "docxexportfilter.hxx"
29 
30 #include <i18nlangtag/mslangid.hxx>
31 #include <hintids.hxx>
32 #include <tools/urlobj.hxx>
33 #include <editeng/boxitem.hxx>
34 #include <editeng/cmapitem.hxx>
35 #include <editeng/langitem.hxx>
36 #include <editeng/svxfont.hxx>
37 #include <editeng/lrspitem.hxx>
38 #include <editeng/brushitem.hxx>
39 #include <editeng/fontitem.hxx>
40 #include <editeng/keepitem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/ulspitem.hxx>
44 #include <editeng/frmdiritem.hxx>
45 #include <editeng/tstpitem.hxx>
46 #include <svl/grabbagitem.hxx>
47 #include <svl/urihelper.hxx>
48 #include <svl/whiter.hxx>
49 #include <fmtpdsc.hxx>
50 #include <fmtfsize.hxx>
51 #include <fmtornt.hxx>
52 #include <fmtlsplt.hxx>
53 #include <fmtflcnt.hxx>
54 #include <fmtanchr.hxx>
55 #include <fmtcntnt.hxx>
56 #include <frmatr.hxx>
57 #include <paratr.hxx>
58 #include <txatbase.hxx>
59 #include <fmtinfmt.hxx>
60 #include <fmtrfmrk.hxx>
61 #include <fchrfmt.hxx>
62 #include <fmtautofmt.hxx>
63 #include <charfmt.hxx>
64 #include <tox.hxx>
65 #include <ndtxt.hxx>
66 #include <pam.hxx>
67 #include <doc.hxx>
69 #include <IDocumentMarkAccess.hxx>
70 #include <docary.hxx>
71 #include <swtable.hxx>
72 #include <swtblfmt.hxx>
73 #include <section.hxx>
74 #include <pagedesc.hxx>
75 #include <swrect.hxx>
76 #include <reffld.hxx>
77 #include <redline.hxx>
78 #include <wrtswtbl.hxx>
79 #include <htmltbl.hxx>
80 #include <txttxmrk.hxx>
81 #include <fmtline.hxx>
82 #include <fmtruby.hxx>
83 #include <breakit.hxx>
84 #include <txtatr.hxx>
85 #include <fmtsrnd.hxx>
86 #include <fmtrowsplt.hxx>
87 #include <com/sun/star/drawing/XShape.hpp>
88 #include <com/sun/star/i18n/BreakIterator.hpp>
89 #include <com/sun/star/i18n/ScriptType.hpp>
90 #include <com/sun/star/i18n/WordType.hpp>
91 #include <com/sun/star/text/RubyPosition.hpp>
92 #include <oox/export/vmlexport.hxx>
93 #include <sfx2/docfile.hxx>
94 #include <sal/log.hxx>
96 
97 #include "sprmids.hxx"
98 
99 #include "writerhelper.hxx"
100 #include "writerwordglue.hxx"
101 #include <numrule.hxx>
102 #include "wrtww8.hxx"
103 #include "ww8par.hxx"
104 #include <IMark.hxx>
105 #include "ww8attributeoutput.hxx"
106 
107 #include <ndgrf.hxx>
108 #include <ndole.hxx>
109 
110 #include <cstdio>
111 
112 using namespace ::com::sun::star;
113 using namespace ::com::sun::star::i18n;
114 using namespace sw::util;
115 using namespace sw::types;
116 using namespace sw::mark;
117 using namespace ::oox::vml;
118 
119 static OUString lcl_getFieldCode( const IFieldmark* pFieldmark )
120 {
121  OSL_ENSURE(pFieldmark!=nullptr, "where is my fieldmark???");
122 
123  if ( !pFieldmark)
124  return OUString();
125  if ( pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
126  return OUString(" FORMTEXT ");
127  if ( pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN )
128  return OUString(" FORMDROPDOWN ");
129  if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
130  return OUString(" FORMCHECKBOX ");
131  if ( pFieldmark->GetFieldname( ) == ODF_TOC )
132  return OUString(" TOC ");
133  if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
134  return OUString(" HYPERLINK ");
135  if ( pFieldmark->GetFieldname( ) == ODF_PAGEREF )
136  return OUString(" PAGEREF ");
137  return pFieldmark->GetFieldname();
138 }
139 
140 static ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) {
141  OSL_ENSURE(pFieldmark!=nullptr, "where is my fieldmark???");
142  if ( !pFieldmark )
143  return ww::eUNKNOWN;
144  if ( pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
145  return ww::eFORMTEXT;
146  if ( pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN )
147  return ww::eFORMDROPDOWN;
148  if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
149  return ww::eFORMCHECKBOX;
150  if ( pFieldmark->GetFieldname( ) == ODF_TOC )
151  return ww::eTOC;
152  if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
153  return ww::eHYPERLINK;
154  if ( pFieldmark->GetFieldname( ) == ODF_PAGEREF )
155  return ww::ePAGEREF;
156  return ww::eUNKNOWN;
157 }
158 
160  : pOld( rExport.m_pChpIter ), m_rExport( rExport )
161 {
162  m_rExport.m_pChpIter = this;
163 }
164 
166 {
168 }
169 
171 {
172 public:
173  bool operator()(const ww8::Frame &rOne, const ww8::Frame &rTwo) const
174  {
175  return rOne.GetPosition() < rTwo.GetPosition();
176  }
177 };
178 
180 {
181  OSL_ENSURE(maCharRuns.begin() != maCharRuns.end(), "Impossible");
182  mnScript = maCharRunIter->mnScript;
183  meChrSet = maCharRunIter->meCharSet;
184  mbCharIsRTL = maCharRunIter->mbRTL;
185 }
186 
188  MSWordAttrIter(rWr),
189  rNd(rTextNd),
190  maCharRuns(GetPseudoCharRuns(rTextNd)),
191  pCurRedline(nullptr),
192  nCurrentSwPos(0),
193  nCurRedlinePos(SwRedlineTable::npos),
194  mrSwFormatDrop(rTextNd.GetSwAttrSet().GetDrop())
195 {
196 
197  SwPosition aPos(rTextNd);
198  mbParaIsRTL = SvxFrameDirection::Horizontal_RL_TB == rWr.m_pDoc->GetTextDirection(aPos);
199 
200  maCharRunIter = maCharRuns.begin();
201  IterToCurrent();
202 
203  /*
204  #i2916#
205  Get list of any graphics which may be anchored from this paragraph.
206  */
208  std::sort(maFlyFrames.begin(), maFlyFrames.end(), sortswflys());
209 
210  /*
211  #i18480#
212  If we are inside a frame then anything anchored inside this frame can
213  only be supported by word anchored inline ("as character"), so force
214  this in the supportable case.
215  */
216  if (rWr.m_bInWriteEscher)
217  {
218  for ( auto& aFlyFrame : maFlyFrames )
219  aFlyFrame.ForceTreatAsInline();
220  }
221 
222  maFlyIter = maFlyFrames.begin();
223 
225  {
226  SwPosition aPosition( rNd, SwIndex( const_cast<SwTextNode*>(&rNd) ) );
228  }
229 
231 }
232 
233 static sal_Int32 lcl_getMinPos( sal_Int32 pos1, sal_Int32 pos2 )
234 {
235  if ( pos1 >= 0 && pos2 >= 0 )
236  {
237  // both valid: return minimum one
238  return std::min(pos1, pos2);
239  }
240 
241  // return the valid one, if any, or -1
242  return std::max(pos1, pos2);
243 }
244 
245 sal_Int32 SwWW8AttrIter::SearchNext( sal_Int32 nStartPos )
246 {
247  const OUString aText = rNd.GetText();
248  sal_Int32 fieldEndPos = aText.indexOf(CH_TXT_ATR_FIELDEND, nStartPos);
249  sal_Int32 fieldStartPos = aText.indexOf(CH_TXT_ATR_FIELDSTART, nStartPos);
250  sal_Int32 formElementPos = aText.indexOf(CH_TXT_ATR_FORMELEMENT, nStartPos);
251 
252  const sal_Int32 pos = lcl_getMinPos(
253  lcl_getMinPos( fieldEndPos, fieldStartPos ),
254  formElementPos );
255 
256  sal_Int32 nMinPos = (pos>=0) ? pos : SAL_MAX_INT32;
257 
258  // first the redline, then the attributes
259  if( pCurRedline )
260  {
261  const SwPosition* pEnd = pCurRedline->End();
262  if (pEnd->nNode == rNd)
263  {
264  const sal_Int32 i = pEnd->nContent.GetIndex();
265  if ( i >= nStartPos && i < nMinPos )
266  {
267  nMinPos = i;
268  }
269  }
270  }
271 
272  if ( nCurRedlinePos < m_rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable().size() )
273  {
274  // nCurRedlinePos point to the next redline
276  if( pCurRedline )
277  ++nRedLinePos;
278 
279  for ( ; nRedLinePos < m_rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable().size(); ++nRedLinePos )
280  {
281  const SwRangeRedline* pRedl = m_rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable()[ nRedLinePos ];
282 
283  const SwPosition* pStt = pRedl->Start();
284  const SwPosition* pEnd = pStt == pRedl->GetPoint()
285  ? pRedl->GetMark()
286  : pRedl->GetPoint();
287 
288  if( pStt->nNode == rNd )
289  {
290  const sal_Int32 i = pStt->nContent.GetIndex();
291  if( i >= nStartPos && i < nMinPos )
292  nMinPos = i;
293  }
294  else
295  break;
296 
297  if( pEnd->nNode == rNd )
298  {
299  const sal_Int32 i = pEnd->nContent.GetIndex();
300  if( i >= nStartPos && i < nMinPos )
301  {
302  nMinPos = i;
303  }
304  }
305  }
306  }
307 
308  if (mrSwFormatDrop.GetWholeWord() && nStartPos <= rNd.GetDropLen(0))
309  nMinPos = rNd.GetDropLen(0);
310  else if(nStartPos <= mrSwFormatDrop.GetChars())
311  nMinPos = mrSwFormatDrop.GetChars();
312 
313  if(const SwpHints* pTextAttrs = rNd.GetpSwpHints())
314  {
315 
316 // can be optimized if we consider that the TextAttrs are sorted by start position.
317 // but then we'd have to save 2 indices
318  for( size_t i = 0; i < pTextAttrs->Count(); ++i )
319  {
320  const SwTextAttr* pHt = pTextAttrs->Get(i);
321  sal_Int32 nPos = pHt->GetStart(); // first Attr characters
322  if( nPos >= nStartPos && nPos <= nMinPos )
323  nMinPos = nPos;
324 
325  if( pHt->End() ) // Attr with end
326  {
327  nPos = *pHt->End(); // last Attr character + 1
328  if( nPos >= nStartPos && nPos <= nMinPos )
329  nMinPos = nPos;
330  }
331  if (pHt->HasDummyChar())
332  {
333  // pos + 1 because of CH_TXTATR in Text
334  nPos = pHt->GetStart() + 1;
335  if( nPos >= nStartPos && nPos <= nMinPos )
336  nMinPos = nPos;
337  }
338  }
339  }
340 
341  if (maCharRunIter != maCharRuns.end())
342  {
343  if (maCharRunIter->mnEndPos < nMinPos)
344  nMinPos = maCharRunIter->mnEndPos;
345  IterToCurrent();
346  }
347 
348  /*
349  #i2916#
350  Check to see if there are any graphics anchored to characters in this
351  paragraph's text. Set nMinPos to 1 past the placement for anchored to
352  character because anchors in Word appear after the character they are
353  anchored to.
354  */
355  if (maFlyIter != maFlyFrames.end())
356  {
357  const SwPosition &rAnchor = maFlyIter->GetPosition();
358 
359  sal_Int32 nPos = rAnchor.nContent.GetIndex();
360  if (nPos >= nStartPos && nPos <= nMinPos)
361  nMinPos = nPos;
362 
363  if (maFlyIter->GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
364  {
365  ++nPos;
366  if (nPos >= nStartPos && nPos <= nMinPos)
367  nMinPos = nPos;
368  }
369  }
370 
371  //nMinPos found and not going to change at this point
372 
373  if (maCharRunIter != maCharRuns.end())
374  {
375  if (maCharRunIter->mnEndPos == nMinPos)
376  ++maCharRunIter;
377  }
378 
379  return nMinPos;
380 }
381 
382 void SwWW8AttrIter::OutAttr( sal_Int32 nSwPos, bool bWriteCombChars)
383 {
385 
386  /*
387  Depending on whether text is in CTL/CJK or Western, get the id of that
388  script, the idea is that the font that is actually in use to render this
389  range of text ends up in pFont
390  */
391  sal_uInt16 nFontId = GetWhichOfScript( RES_CHRATR_FONT, GetScript() );
392 
393  const SvxFontItem &rParentFont = ItemGet<SvxFontItem>(
394  static_cast<const SwTextFormatColl&>(rNd.GetAnyFormatColl()), nFontId);
395  const SvxFontItem *pFont = &rParentFont;
396  const SfxPoolItem *pGrabBag = nullptr;
397 
398  SfxItemSet aExportSet(*rNd.GetSwAttrSet().GetPool(),
400 
401  //The hard formatting properties that affect the entire paragraph
402  if (rNd.HasSwAttrSet())
403  {
404  // only copy hard attributes - bDeep = false
405  aExportSet.Set(rNd.GetSwAttrSet(), false/*bDeep*/);
406  // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
407  const SvxFontItem &rNdFont = ItemGet<SvxFontItem>(rNd.GetSwAttrSet(), nFontId);
408  pFont = &rNdFont;
409  aExportSet.ClearItem(nFontId);
410  }
411 
412  //The additional hard formatting properties that affect this range in the
413  //paragraph
414  ww8::PoolItems aRangeItems;
415  if (const SwpHints* pTextAttrs = rNd.GetpSwpHints())
416  {
417  for( size_t i = 0; i < pTextAttrs->Count(); ++i )
418  {
419  const SwTextAttr* pHt = pTextAttrs->Get(i);
420  const sal_Int32* pEnd = pHt->End();
421 
422  if (pEnd ? ( nSwPos >= pHt->GetStart() && nSwPos < *pEnd)
423  : nSwPos == pHt->GetStart() )
424  {
425  sal_uInt16 nWhich = pHt->GetAttr().Which();
426  if (nWhich == RES_TXTATR_AUTOFMT)
427  {
428  const SwFormatAutoFormat& rAutoFormat = static_cast<const SwFormatAutoFormat&>(pHt->GetAttr());
429  const std::shared_ptr<SfxItemSet>& pSet = rAutoFormat.GetStyleHandle();
430  SfxWhichIter aIter( *pSet );
431  const SfxPoolItem* pItem;
432  sal_uInt16 nWhichId = aIter.FirstWhich();
433  while( nWhichId )
434  {
435  if( SfxItemState::SET == pSet->GetItemState( nWhichId, false, &pItem ))
436  {
437  if (nWhichId == nFontId)
438  pFont = &(item_cast<SvxFontItem>(*pItem));
439  else if (nWhichId == RES_CHRATR_GRABBAG)
440  pGrabBag = pItem;
441  else
442  aRangeItems[nWhichId] = pItem;
443  }
444  nWhichId = aIter.NextWhich();
445  }
446  }
447  else
448  aRangeItems[nWhich] = (&(pHt->GetAttr()));
449  }
450  else if (nSwPos < pHt->GetStart())
451  break;
452  }
453  }
454 
455  /*
456  For #i24291# we need to explicitly remove any properties from the
457  aExportSet which a SwCharFormat would override, we can't rely on word doing
458  this for us like writer does
459  */
460  const SwFormatCharFormat *pCharFormatItem =
461  HasItem< SwFormatCharFormat >( aRangeItems, RES_TXTATR_CHARFMT );
462  if ( pCharFormatItem )
463  ClearOverridesFromSet( *pCharFormatItem, aExportSet );
464 
465  // tdf#113790: AutoFormat style overwrites char style, so remove all
466  // elements from CHARFMT grab bag which are set in AUTOFMT grab bag
467  if (const SfxGrabBagItem *pAutoFmtGrabBag = dynamic_cast<const SfxGrabBagItem*>(pGrabBag))
468  {
469  if (const SfxGrabBagItem *pCharFmtGrabBag = aExportSet.GetItem<SfxGrabBagItem>(RES_CHRATR_GRABBAG, false))
470  {
471  std::unique_ptr<SfxGrabBagItem> pNewCharFmtGrabBag(static_cast<SfxGrabBagItem*>(pCharFmtGrabBag->Clone()));
472  assert(pNewCharFmtGrabBag);
473  auto & rNewFmtMap = pNewCharFmtGrabBag->GetGrabBag();
474  for (auto const & item : pAutoFmtGrabBag->GetGrabBag())
475  {
476  if (item.second.hasValue())
477  rNewFmtMap.erase(item.first);
478  }
479  aExportSet.Put(std::move(pNewCharFmtGrabBag));
480  }
481  }
482 
483  ww8::PoolItems aExportItems;
484  GetPoolItems( aExportSet, aExportItems, false );
485 
486  if( rNd.GetpSwpHints() == nullptr )
487  m_rExport.SetCurItemSet(&aExportSet);
488 
489  for ( const auto& aRangeItem : aRangeItems )
490  {
491  aExportItems[aRangeItem.first] = aRangeItem.second;
492  }
493 
494  if ( !aExportItems.empty() )
495  {
496  const SwModify* pOldMod = m_rExport.m_pOutFormatNode;
498  m_rExport.m_aCurrentCharPropStarts.push( nSwPos );
499 
500  // tdf#38778 Fix output of the font in DOC run for fields
501  const SvxFontItem * pFontToOutput = ( rParentFont != *pFont )? pFont : nullptr;
502 
503  m_rExport.ExportPoolItemsToCHP( aExportItems, GetScript(), pFontToOutput, bWriteCombChars );
504 
505  // HasTextItem only allowed in the above range
507  m_rExport.m_pOutFormatNode = pOldMod;
508  }
509 
510  if( rNd.GetpSwpHints() == nullptr )
511  m_rExport.SetCurItemSet(nullptr);
512 
513  OSL_ENSURE( pFont, "must be *some* font associated with this txtnode" );
514  if ( pFont )
515  {
516  SvxFontItem aFont( *pFont );
517 
518  if ( rParentFont != aFont )
519  m_rExport.AttrOutput().OutputItem( aFont );
520  }
521 
522  // Output grab bag attributes
523  if (pGrabBag)
524  m_rExport.AttrOutput().OutputItem( *pGrabBag );
525 }
526 
528 {
529  if (maFlyFrames.size() != 1)
530  return false;
531 
532  while ( maFlyIter != maFlyFrames.end() )
533  {
534  const SdrObject* pSdrObj = maFlyIter->GetFrameFormat().FindRealSdrObject();
535 
536  if (pSdrObj)
537  {
538  if (VMLExport::IsWaterMarkShape(pSdrObj->GetName()))
539  return true;
540  }
541  ++maFlyIter;
542  }
543 
544  return false;
545 }
546 
548 {
549  ww8::FrameIter aTmpFlyIter = maFlyIter ;
550 
551  while ( aTmpFlyIter != maFlyFrames.end() )
552  {
553  const SwPosition &rAnchor = maFlyIter->GetPosition();
554  sal_uLong nAnchorPos = rAnchor.nNode.GetIndex();
555  /* if current node position and the anchor position are the same
556  then the frame anchor is linked to this node
557  */
558  if ( nAnchorPos == nNodePos )
559  return true ;
560 
561  ++aTmpFlyIter;
562  }
563  return false ;
564 }
565 
567 {
568  // collection point to first gather info about all of the potentially linked textboxes: to be analyzed later.
569  OUString sLinkChainName;
570  ww8::FrameIter linkedTextboxesIter = maFlyIter;
571  while ( linkedTextboxesIter != maFlyFrames.end() )
572  {
573  uno::Reference< drawing::XShape > xShape;
574  ww8::Frame aFrame = *linkedTextboxesIter;
575  const SdrObject* pSdrObj = aFrame.GetFrameFormat().FindRealSdrObject();
576  if( pSdrObj )
577  xShape.set(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);
578  uno::Reference< beans::XPropertySet > xPropertySet(xShape, uno::UNO_QUERY);
579  uno::Reference< beans::XPropertySetInfo > xPropertySetInfo;
580  if( xPropertySet.is() )
581  xPropertySetInfo = xPropertySet->getPropertySetInfo();
582  if( xPropertySetInfo.is() )
583  {
585 
586  if( xPropertySetInfo->hasPropertyByName("LinkDisplayName") )
587  xPropertySet->getPropertyValue("LinkDisplayName") >>= sLinkChainName;
588  else if( xPropertySetInfo->hasPropertyByName("ChainName") )
589  xPropertySet->getPropertyValue("ChainName") >>= sLinkChainName;
590 
591  if( xPropertySetInfo->hasPropertyByName("ChainNextName") )
592  xPropertySet->getPropertyValue("ChainNextName") >>= aLinkedTextboxInfo.sNextChain;
593  if( xPropertySetInfo->hasPropertyByName("ChainPrevName") )
594  xPropertySet->getPropertyValue("ChainPrevName") >>= aLinkedTextboxInfo.sPrevChain;
595 
596  //collect a list of linked textboxes: those with a NEXT or PREVIOUS link
597  if( !aLinkedTextboxInfo.sNextChain.isEmpty() || !aLinkedTextboxInfo.sPrevChain.isEmpty() )
598  {
599  assert( !sLinkChainName.isEmpty() );
600 
601  //there are many discarded duplicates in documents - no duplicates allowed in the list, so try to find the real one.
602  //if this LinkDisplayName/ChainName already exists on a different shape...
603  // the earlier processed duplicates are thrown out unless this one can be proved as bad. (last processed duplicate usually is stored)
604  auto linkFinder = m_rExport.m_aLinkedTextboxesHelper.find(sLinkChainName);
605  if( linkFinder != m_rExport.m_aLinkedTextboxesHelper.end() )
606  {
607  //If my NEXT/PREV targets have already been discovered, but don't match me, then assume I'm an abandoned remnant
608  // (this logic fails if both me and one of my links are duplicated, and the remnants were added first.)
609  linkFinder = m_rExport.m_aLinkedTextboxesHelper.find(aLinkedTextboxInfo.sNextChain);
610  if( (linkFinder != m_rExport.m_aLinkedTextboxesHelper.end()) && (linkFinder->second.sPrevChain != sLinkChainName) )
611  {
612  ++linkedTextboxesIter;
613  break;
614  }
615 
616  linkFinder = m_rExport.m_aLinkedTextboxesHelper.find(aLinkedTextboxInfo.sPrevChain);
617  if( (linkFinder != m_rExport.m_aLinkedTextboxesHelper.end()) && (linkFinder->second.sNextChain != sLinkChainName) )
618  {
619  ++linkedTextboxesIter;
620  break;
621  }
622  }
624  m_rExport.m_aLinkedTextboxesHelper[sLinkChainName] = aLinkedTextboxInfo;
625  }
626  }
627  ++linkedTextboxesIter;
628  }
629 
630  /*
631  #i2916#
632  May have an anchored graphic to be placed, loop through sorted array
633  and output all at this position
634  */
635  while ( maFlyIter != maFlyFrames.end() )
636  {
637  const SwPosition &rAnchor = maFlyIter->GetPosition();
638  const sal_Int32 nPos = rAnchor.nContent.GetIndex();
639 
640  if ( nPos != nSwPos )
641  return FLY_NOT_PROCESSED ; // We haven't processed the fly
642 
643  const SdrObject* pSdrObj = maFlyIter->GetFrameFormat().FindRealSdrObject();
644 
645  if (pSdrObj)
646  {
647  if (VMLExport::IsWaterMarkShape(pSdrObj->GetName()))
648  {
649  // This is a watermark object. Should be written ONLY in the header
651  {
652  // Should write a watermark in the header
654  }
655  else
656  {
657  // Should not write watermark object in the main body text
658  }
659  }
660  else
661  {
662  // This is not a watermark object - write normally
664  }
665  }
666  else
667  {
668  // This is not a watermark object - write normally
670  }
671  ++maFlyIter;
672  }
674 }
675 
676 bool SwWW8AttrIter::IsTextAttr( sal_Int32 nSwPos ) const
677 {
678  // search for attrs with dummy character or content
679  if (const SwpHints* pTextAttrs = rNd.GetpSwpHints())
680  {
681  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
682  {
683  const SwTextAttr* pHt = pTextAttrs->Get(i);
684  if (nSwPos == pHt->GetStart())
685  {
686  if (pHt->HasDummyChar() || pHt->HasContent() )
687  {
688  return true;
689  }
690  }
691  else if (nSwPos < pHt->GetStart())
692  {
693  break; // sorted by start
694  }
695  }
696  }
697 
698  return false;
699 }
700 
701 bool SwWW8AttrIter::IsExportableAttr(sal_Int32 nSwPos) const
702 {
703  if (const SwpHints* pTextAttrs = rNd.GetpSwpHints())
704  {
705  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
706  {
707  const SwTextAttr* pHt = pTextAttrs->GetSortedByEnd(i);
708  const sal_Int32 nStart = pHt->GetStart();
709  const sal_Int32 nEnd = pHt->End() ? *pHt->End() : INT_MAX;
710  if (nSwPos >= nStart && nSwPos < nEnd)
711  {
712  switch (pHt->GetAttr().Which())
713  {
714  // Metadata fields should be dynamically generated, not dumped as text.
716  return false;
717  }
718  }
719  }
720  }
721 
722  return true;
723 }
724 
725 bool SwWW8AttrIter::IsDropCap( int nSwPos )
726 {
727  // see if the current position falls on a DropCap
728  int nDropChars = mrSwFormatDrop.GetChars();
729  bool bWholeWord = mrSwFormatDrop.GetWholeWord();
730  if (bWholeWord)
731  {
732  const sal_Int32 nWordLen = rNd.GetDropLen(0);
733  if(nSwPos == nWordLen && nSwPos != 0)
734  return true;
735  }
736  else
737  {
738  if (nSwPos == nDropChars && nSwPos != 0)
739  return true;
740  }
741  return false;
742 }
743 
745 {
746  return std::any_of(m_rExport.m_aImplicitBookmarks.begin(), m_rExport.m_aImplicitBookmarks.end(),
747  [this](const aBookmarkPair& rBookmarkPair) { return rBookmarkPair.second == rNd.GetIndex(); });
748 }
749 
750 //HasItem is for the summary of the double attributes: Underline and WordlineMode as TextItems.
751 // OutAttr () calls the output function, which can call HasItem() for other items at the attribute's start position.
752 // Only attributes with end can be queried.
753 // It searches with bDeep
754 const SfxPoolItem* SwWW8AttrIter::HasTextItem( sal_uInt16 nWhich ) const
755 {
756  const SfxPoolItem* pRet = nullptr;
757  const SwpHints* pTextAttrs = rNd.GetpSwpHints();
758  if (pTextAttrs && !m_rExport.m_aCurrentCharPropStarts.empty())
759  {
760  const sal_Int32 nTmpSwPos = m_rExport.m_aCurrentCharPropStarts.top();
761  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
762  {
763  const SwTextAttr* pHt = pTextAttrs->Get(i);
764  const SfxPoolItem* pItem = &pHt->GetAttr();
765  const sal_Int32 * pAtrEnd = nullptr;
766  if( nullptr != ( pAtrEnd = pHt->End() ) && // only Attr with an end
767  nTmpSwPos >= pHt->GetStart() && nTmpSwPos < *pAtrEnd )
768  {
769  if ( nWhich == pItem->Which() )
770  {
771  pRet = pItem; // found it
772  break;
773  }
774  else if( RES_TXTATR_INETFMT == pHt->Which() ||
775  RES_TXTATR_CHARFMT == pHt->Which() ||
776  RES_TXTATR_AUTOFMT == pHt->Which() )
777  {
778  const SfxItemSet* pSet = CharFormat::GetItemSet( pHt->GetAttr() );
779  const SfxPoolItem* pCharItem;
780  if ( pSet &&
781  SfxItemState::SET == pSet->GetItemState( nWhich, pHt->Which() != RES_TXTATR_AUTOFMT, &pCharItem ) )
782  {
783  pRet = pCharItem; // found it
784  break;
785  }
786  }
787  }
788  else if (nTmpSwPos < pHt->GetStart())
789  break; // nothing more to come
790  }
791  }
792  return pRet;
793 }
794 
796 {
797  rItems.insert(rItems.end(), pO->begin(), pO->end());
798 }
799 
800 const SfxPoolItem& SwWW8AttrIter::GetItem(sal_uInt16 nWhich) const
801 {
802  const SfxPoolItem* pRet = HasTextItem(nWhich);
803  return pRet ? *pRet : rNd.SwContentNode::GetAttr(nWhich);
804 }
805 
806 void WW8AttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 /*nPos*/, const SwFormatRuby& rRuby )
807 {
808  WW8Ruby aWW8Ruby(rNode, rRuby, GetExport());
809  OUString aStr( FieldString( ww::eEQ ) );
810  aStr += "\\* jc";
811  aStr += OUString::number(aWW8Ruby.GetJC());
812 
813 
814  aStr += " \\* \"Font:";
815  aStr += aWW8Ruby.GetFontFamily();
816  aStr += "\" \\* hps";
817  aStr += OUString::number((aWW8Ruby.GetRubyHeight() + 5) / 10);
818  aStr += " \\o";
819  if (aWW8Ruby.GetDirective())
820  {
821  aStr += "\\a" + OUString(aWW8Ruby.GetDirective());
822  }
823  aStr += "(\\s\\up ";
824 
825  aStr += OUString::number((aWW8Ruby.GetBaseHeight() + 10) / 20 - 1);
826  aStr += "(";
827  aStr += rRuby.GetText();
828  aStr += ")";
829 
830  // The parameter separator depends on the FIB.lid
831  if ( m_rWW8Export.pFib->getNumDecimalSep() == '.' )
832  aStr += ",";
833  else
834  aStr += ";";
835 
836  m_rWW8Export.OutputField( nullptr, ww::eEQ, aStr,
838 }
839 
840 void WW8AttributeOutput::EndRuby(const SwTextNode& /*rNode*/, sal_Int32 /*nPos*/)
841 {
842  m_rWW8Export.WriteChar( ')' );
844 }
845 
846 /*#i15387# Better ideas welcome*/
847 static OUString &TruncateBookmark( OUString &rRet )
848 {
849  if ( rRet.getLength() > 40 )
850  rRet = rRet.copy( 0, 40 );
851  OSL_ENSURE( rRet.getLength() <= 40, "Word cannot have bookmarks longer than 40 chars" );
852  return rRet;
853 }
854 
855 OUString AttributeOutputBase::ConvertURL( const OUString& rUrl, bool bAbsoluteOut )
856 {
857  OUString sURL = rUrl;
858  OUString sExportedDocumentURL = "";
859  {
860  DocxExport* pDocxExport = dynamic_cast<DocxExport*>(&GetExport());
861  if ( pDocxExport )
862  {
863  // DOCX
864  DocxExportFilter& rFilter = pDocxExport->GetFilter();
865  sExportedDocumentURL = rFilter.getFileUrl();
866  }
867  else
868  {
869  // DOC
870  WW8Export* pWW8Export = dynamic_cast<WW8Export*>(&GetExport());
871  if ( pWW8Export )
872  {
873  SwWW8Writer& rWriter = pWW8Export->GetWriter();
874  sExportedDocumentURL = rWriter.GetMedia()->GetURLObject().GetPath();
875  }
876  }
877  }
878 
879  INetURLObject anAbsoluteParent( sExportedDocumentURL );
880  if ( anAbsoluteParent.GetURLPath().isEmpty() )
881  {
882  // DOC filter returns system path (without file:///)
883  anAbsoluteParent.setFSysPath( sExportedDocumentURL, FSysStyle::Detect );
884  anAbsoluteParent.setFinalSlash();
885  }
886  OUString sConvertedParent = INetURLObject::GetScheme( anAbsoluteParent.GetProtocol() ) + anAbsoluteParent.GetURLPath();
887  OUString sParentPath = sConvertedParent.isEmpty() ? sExportedDocumentURL : sConvertedParent;
888 
889  if ( bAbsoluteOut )
890  {
891  INetURLObject anAbsoluteNew;
892 
893  if ( anAbsoluteParent.GetNewAbsURL( rUrl, &anAbsoluteNew ) )
894  sURL = anAbsoluteNew.GetMainURL( INetURLObject::DecodeMechanism::NONE );
895  else
896  sURL = rUrl;
897  }
898  else
899  {
900  OUString sToConvert = rUrl.replaceAll( "\\", "/" );
901  INetURLObject aURL( sToConvert );
902  sToConvert = INetURLObject::GetScheme( aURL.GetProtocol() ) + aURL.GetURLPath();
904  if ( !sRelative.isEmpty() )
905  sURL = sRelative;
906  }
907 
908  return sURL;
909 }
910 
911 bool AttributeOutputBase::AnalyzeURL( const OUString& rUrl, const OUString& /*rTarget*/, OUString* pLinkURL, OUString* pMark )
912 {
913  bool bBookMarkOnly = false;
914 
915  OUString sMark;
916  OUString sURL;
917 
918  if ( rUrl.getLength() > 1 && rUrl[0] == '#' )
919  {
920  sMark = BookmarkToWriter( rUrl.copy(1) );
921 
922  const sal_Int32 nPos = sMark.lastIndexOf( cMarkSeparator );
923 
924  const OUString sRefType(nPos>=0 && nPos+1<sMark.getLength() ?
925  sMark.copy(nPos+1).replaceAll(" ", "") :
926  OUString());
927 
928  // #i21465# Only interested in outline references
929  if ( sRefType == "outline" )
930  {
931  OUString sLink = sMark.copy(0, nPos);
932  for ( const auto& rBookmarkPair : GetExport().m_aImplicitBookmarks )
933  {
934  if ( rBookmarkPair.first == sLink )
935  {
936  sMark = "_toc" + OUString::number( rBookmarkPair.second );
937  }
938  }
939  }
940  }
941  else
942  {
943  INetURLObject aURL( rUrl, INetProtocol::NotValid );
946  INetProtocol aProtocol = aURL.GetProtocol();
947 
948  if ( aProtocol == INetProtocol::File || aProtocol == INetProtocol::NotValid )
949  {
950  // INetProtocol::NotValid - may be a relative link
951  bool bExportRelative = m_aSaveOpt.IsSaveRelFSys();
952  sURL = ConvertURL( rUrl, !bExportRelative );
953  }
954  }
955 
956  if ( !sMark.isEmpty() && sURL.isEmpty() )
957  bBookMarkOnly = true;
958 
959  *pMark = sMark;
960  *pLinkURL = sURL;
961  return bBookMarkOnly;
962 }
963 
964 bool WW8AttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark )
965 {
966  bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
967 
968  OUString sURL = *pLinkURL;
969 
970  if ( !sURL.isEmpty() )
972 
973  if ( bBookMarkOnly )
974  sURL = FieldString( ww::eHYPERLINK );
975  else
976  sURL = FieldString( ww::eHYPERLINK ) + "\"" + sURL + "\"";
977 
978  if ( !pMark->isEmpty() )
979  sURL += " \\l \"" + *pMark + "\"";
980 
981  if ( !rTarget.isEmpty() )
982  sURL += " \\n " + rTarget;
983 
984  *pLinkURL = sURL;
985 
986  return bBookMarkOnly;
987 }
988 
989 void WW8AttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos )
990 {
991  m_aBookmarksOfParagraphStart.insert(std::pair<sal_Int32, OUString>(nFirstRunPos, rName));
992  m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName));
993 }
994 
995 bool WW8AttributeOutput::StartURL( const OUString &rUrl, const OUString &rTarget )
996 {
997  INetURLObject aURL( rUrl );
998  OUString sURL;
999  OUString sMark;
1000 
1001  bool bBookMarkOnly = AnalyzeURL( rUrl, rTarget, &sURL, &sMark );
1002 
1004 
1005  // write the reference to the "picture" structure
1006  sal_uLong nDataStt = m_rWW8Export.pDataStrm->Tell();
1007  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() );
1008 
1009  // WinWord 2000 doesn't write this - so it's a temp solution by W97 ?
1010  m_rWW8Export.WriteChar( 0x01 );
1011 
1012  static sal_uInt8 aArr1[] = {
1013  0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
1014 
1015  0x06, 0x08, 0x01, // sprmCFData
1016  0x55, 0x08, 0x01, // sprmCFSpec
1017  0x02, 0x08, 0x01 // sprmCFFieldVanish
1018  };
1019  sal_uInt8* pDataAdr = aArr1 + 2;
1020  Set_UInt32( pDataAdr, nDataStt );
1021 
1022  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), sizeof( aArr1 ), aArr1 );
1023 
1025 
1026  // now write the picture structure
1027  sURL = aURL.GetURLNoMark();
1028 
1029  // Compare the URL written by AnalyzeURL with the original one to see if
1030  // the output URL is absolute or relative.
1031  OUString sRelativeURL;
1032  if ( !rUrl.isEmpty() )
1034  bool bAbsolute = sRelativeURL == rUrl;
1035 
1036  static sal_uInt8 aURLData1[] = {
1037  0,0,0,0, // len of struct
1038  0x44,0, // the start of "next" data
1039  0,0,0,0,0,0,0,0,0,0, // PIC-Structure!
1040  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
1041  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
1042  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
1043  0,0,0,0, // /
1044  };
1045  static sal_uInt8 MAGIC_A[] = {
1046  // start of "next" data
1047  0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
1048  0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
1049  };
1050 
1051  m_rWW8Export.pDataStrm->WriteBytes(aURLData1, sizeof(aURLData1));
1052  /* Write HFD Structure */
1053  sal_uInt8 nAnchor = 0x00;
1054  if ( !sMark.isEmpty() )
1055  nAnchor = 0x08;
1056  m_rWW8Export.pDataStrm->WriteUChar(nAnchor); // HFDBits
1057  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_A, sizeof(MAGIC_A)); //clsid
1058 
1059  /* Write Hyperlink Object see [MS-OSHARED] spec*/
1061  sal_uInt32 nFlag = bBookMarkOnly ? 0 : 0x01;
1062  if ( bAbsolute )
1063  nFlag |= 0x02;
1064  if ( !sMark.isEmpty() )
1065  nFlag |= 0x08;
1067 
1068  INetProtocol eProto = aURL.GetProtocol();
1069  if ( eProto == INetProtocol::File || eProto == INetProtocol::Smb )
1070  {
1071  // version 1 (for a document)
1072 
1073  static sal_uInt8 MAGIC_C[] = {
1074  0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
1076  0x00, 0x00
1077  };
1078 
1079  static sal_uInt8 MAGIC_D[] = {
1080  0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
1081  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1083  };
1084 
1085  // save the links to files as relative
1087  if ( eProto == INetProtocol::File && sURL.startsWith( "/" ) )
1088  sURL = aURL.PathToFileName();
1089 
1090  // special case for the absolute windows names
1091  // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
1092  if (sURL.getLength()>=3)
1093  {
1094  const sal_Unicode aDrive = sURL[1];
1095  if ( sURL[0]=='/' && sURL[2]==':' &&
1096  ( (aDrive>='A' && aDrive<='Z' ) || (aDrive>='a' && aDrive<='z') ) )
1097  {
1098  sURL = sURL.copy(1).replaceAll("/", "\\");
1099  }
1100  }
1101 
1102  // n#261623 convert smb notation to '\\'
1103  const char pSmb[] = "smb://";
1104  if ( eProto == INetProtocol::Smb && sURL.startsWith( pSmb ) )
1105  {
1106  sURL = sURL.copy( sizeof(pSmb)-3 ).replaceAll( "/", "\\" );
1107  }
1108 
1109  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_C, sizeof(MAGIC_C));
1110  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sURL.getLength()+1 );
1112  RTL_TEXTENCODING_MS_1252 );
1113  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_D, sizeof(MAGIC_D));
1114 
1115  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.getLength() + 6 );
1116  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.getLength() );
1119  }
1120  else if ( eProto != INetProtocol::NotValid )
1121  {
1122  // version 2 (simple url)
1123  // and write some data to the data stream, but don't ask
1124  // what the data mean, except for the URL.
1125  // The First piece is the WW8_PIC structure.
1126  static sal_uInt8 MAGIC_B[] = {
1127  0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
1128  0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
1129  };
1130 
1131  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_B, sizeof(MAGIC_B));
1132  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2 * ( sURL.getLength() + 1 ) );
1134  }
1135 
1136  if ( !sMark.isEmpty() )
1137  {
1138  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sMark.getLength()+1 );
1140  }
1142  m_rWW8Export.pDataStrm->Tell() - nDataStt );
1143 
1144  return true;
1145 }
1146 
1148 {
1149  m_rWW8Export.OutputField( nullptr, ww::eHYPERLINK, OUString(), FieldFlags::Close );
1150 
1151  return true;
1152 }
1153 
1154 OUString BookmarkToWord(const OUString &rBookmark)
1155 {
1156  OUString sRet(INetURLObject::encode(
1157  rBookmark.replace(' ', '_'), // Spaces are prohibited in bookmark name
1159  INetURLObject::EncodeMechanism::All, RTL_TEXTENCODING_ASCII_US));
1160  // Unicode letters are allowed
1161  sRet = INetURLObject::decode(sRet, INetURLObject::DecodeMechanism::Unambiguous, RTL_TEXTENCODING_UTF8);
1162  return TruncateBookmark(sRet);
1163 }
1164 
1165 OUString BookmarkToWriter(const OUString &rBookmark)
1166 {
1167  return INetURLObject::decode(rBookmark,
1168  INetURLObject::DecodeMechanism::Unambiguous, RTL_TEXTENCODING_ASCII_US);
1169 }
1170 
1172 {
1173  if ( m_rExport.HasRefToObject( REF_SETREFATTR, &rAttr.GetRefName(), 0 ) )
1175  &rAttr.GetRefName(), 0 ));
1176 }
1177 
1178 void SwWW8AttrIter::SplitRun( sal_Int32 nSplitEndPos )
1179 {
1180  auto aIter = std::find_if(maCharRuns.begin(), maCharRuns.end(),
1181  [nSplitEndPos](const CharRunEntry& rCharRun) { return rCharRun.mnEndPos >= nSplitEndPos; });
1182  if (aIter == maCharRuns.end() || aIter->mnEndPos == nSplitEndPos)
1183  return;
1184 
1185  CharRunEntry aNewEntry = *aIter;
1186  aIter->mnEndPos = nSplitEndPos;
1187  maCharRuns.insert( ++aIter, aNewEntry);
1188  maCharRunIter = maCharRuns.begin();
1189  IterToCurrent();
1191 }
1192 
1193 void WW8AttributeOutput::FieldVanish( const OUString& rText, ww::eField /*eType*/ )
1194 {
1195  ww::bytes aItems;
1196  m_rWW8Export.GetCurrentItems( aItems );
1197 
1198  // sprmCFFieldVanish
1200  aItems.push_back( 1 );
1201 
1202  sal_uInt16 nStt_sprmCFSpec = aItems.size();
1203 
1204  // sprmCFSpec -- fSpec-Attribut true
1205  SwWW8Writer::InsUInt16( aItems, 0x855 );
1206  aItems.push_back( 1 );
1207 
1208  m_rWW8Export.WriteChar( '\x13' );
1209  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.size(),
1210  aItems.data() );
1211  m_rWW8Export.OutSwString(rText, 0, rText.getLength());
1212  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), nStt_sprmCFSpec,
1213  aItems.data() );
1214  m_rWW8Export.WriteChar( '\x15' );
1215  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.size(),
1216  aItems.data() );
1217 }
1218 
1219 void AttributeOutputBase::TOXMark( const SwTextNode& rNode, const SwTOXMark& rAttr )
1220 {
1221  // it's a field; so get the Text form the Node and build the field
1222  OUString sText;
1224 
1225  const SwTextTOXMark& rTextTOXMark = *rAttr.GetTextTOXMark();
1226  const sal_Int32* pTextEnd = rTextTOXMark.End();
1227  if ( pTextEnd ) // has range?
1228  {
1229  sText = rNode.GetExpandText(nullptr, rTextTOXMark.GetStart(),
1230  *pTextEnd - rTextTOXMark.GetStart() );
1231  }
1232  else
1233  sText = rAttr.GetAlternativeText();
1234 
1235  switch ( rAttr.GetTOXType()->GetType() )
1236  {
1237  case TOX_INDEX:
1238  eType = ww::eXE;
1239  if ( !rAttr.GetPrimaryKey().isEmpty() )
1240  {
1241  if ( !rAttr.GetSecondaryKey().isEmpty() )
1242  {
1243  sText = rAttr.GetSecondaryKey() + ":" + sText;
1244  }
1245 
1246  sText = rAttr.GetPrimaryKey() + ":" + sText;
1247  }
1248  sText = " XE \"" + sText + "\" ";
1249  break;
1250 
1251  case TOX_USER:
1252  sText += "\" \\f \"" + OUString(static_cast<sal_Char>( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) ));
1253  [[fallthrough]];
1254  case TOX_CONTENT:
1255  {
1256  eType = ww::eTC;
1257  sText = " TC \"" + sText;
1258  sal_uInt16 nLvl = rAttr.GetLevel();
1259  if (nLvl > WW8ListManager::nMaxLevel)
1261 
1262  sText += "\" \\l " + OUString::number(nLvl) + " ";
1263  }
1264  break;
1265  default:
1266  OSL_ENSURE( false, "Unhandled option for toc export" );
1267  break;
1268  }
1269 
1270  if (!sText.isEmpty())
1271  FieldVanish( sText, eType );
1272 }
1273 
1274 int SwWW8AttrIter::OutAttrWithRange(const SwTextNode& rNode, sal_Int32 nPos)
1275 {
1276  int nRet = 0;
1277  if ( const SwpHints* pTextAttrs = rNd.GetpSwpHints() )
1278  {
1279  m_rExport.m_aCurrentCharPropStarts.push( nPos );
1280  const sal_Int32* pEnd;
1281  // first process ends of attributes with extent
1282  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
1283  {
1284  const SwTextAttr* pHt = pTextAttrs->GetSortedByEnd(i);
1285  const SfxPoolItem* pItem = &pHt->GetAttr();
1286  switch ( pItem->Which() )
1287  {
1288  case RES_TXTATR_INETFMT:
1289  pEnd = pHt->End();
1290  if (nPos == *pEnd && nPos != pHt->GetStart())
1291  {
1292  if (m_rExport.AttrOutput().EndURL(nPos == rNd.Len()))
1293  --nRet;
1294  }
1295  break;
1296  case RES_TXTATR_REFMARK:
1297  pEnd = pHt->End();
1298  if (nullptr != pEnd && nPos == *pEnd && nPos != pHt->GetStart())
1299  {
1300  OutSwFormatRefMark(*static_cast<const SwFormatRefMark*>(pItem));
1301  --nRet;
1302  }
1303  break;
1304  case RES_TXTATR_CJK_RUBY:
1305  pEnd = pHt->End();
1306  if (nPos == *pEnd && nPos != pHt->GetStart())
1307  {
1308  m_rExport.AttrOutput().EndRuby(rNode, nPos);
1309  --nRet;
1310  }
1311  break;
1312  }
1313  if (nPos < *pHt->GetAnyEnd())
1314  break; // sorted by end
1315  }
1316  for ( size_t i = 0; i < pTextAttrs->Count(); ++i )
1317  {
1318  const SwTextAttr* pHt = pTextAttrs->Get(i);
1319  const SfxPoolItem* pItem = &pHt->GetAttr();
1320  switch ( pItem->Which() )
1321  {
1322  case RES_TXTATR_INETFMT:
1323  if ( nPos == pHt->GetStart() )
1324  {
1325  const SwFormatINetFormat *rINet = static_cast< const SwFormatINetFormat* >( pItem );
1326  if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) )
1327  ++nRet;
1328  }
1329  pEnd = pHt->End();
1330  if (nPos == *pEnd && nPos == pHt->GetStart())
1331  { // special case: empty must be handled here
1332  if (m_rExport.AttrOutput().EndURL(nPos == rNd.Len()))
1333  --nRet;
1334  }
1335  break;
1336  case RES_TXTATR_REFMARK:
1337  if ( nPos == pHt->GetStart() )
1338  {
1339  OutSwFormatRefMark( *static_cast< const SwFormatRefMark* >( pItem ) );
1340  ++nRet;
1341  }
1342  pEnd = pHt->End();
1343  if (nullptr != pEnd && nPos == *pEnd && nPos == pHt->GetStart())
1344  { // special case: empty TODO: is this possible or would empty one have pEnd null?
1345  OutSwFormatRefMark( *static_cast< const SwFormatRefMark* >( pItem ) );
1346  --nRet;
1347  }
1348  break;
1349  case RES_TXTATR_TOXMARK:
1350  if ( nPos == pHt->GetStart() )
1351  m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) );
1352  break;
1353  case RES_TXTATR_CJK_RUBY:
1354  if ( nPos == pHt->GetStart() )
1355  {
1356  m_rExport.AttrOutput().StartRuby( rNd, nPos, *static_cast< const SwFormatRuby* >( pItem ) );
1357  ++nRet;
1358  }
1359  pEnd = pHt->End();
1360  if (nPos == *pEnd && nPos == pHt->GetStart())
1361  { // special case: empty must be handled here
1362  m_rExport.AttrOutput().EndRuby( rNd, nPos );
1363  --nRet;
1364  }
1365  break;
1366  }
1367  if (nPos < pHt->GetStart())
1368  break; // sorted by start
1369  }
1370  m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem only allowed in the above range
1371  }
1372  return nRet;
1373 }
1374 
1376 {
1377  // search next Redline
1380  {
1382  const SwPosition* pEnd = pRange->End();
1383  const SwPosition* pStart = pRange->Start();
1384  bool bBreak = true;
1385  // In word the paragraph end marker is a real character, in writer it is not.
1386  // Here we find out if the para end marker we will emit is affected by
1387  // redlining, in which case it must be included by the range of character
1388  // attributes that contains the redlining information.
1389  if (pEnd->nNode == rNd)
1390  {
1391  if (pEnd->nContent.GetIndex() == nEnd)
1392  {
1393  // This condition detects if the pseudo-char we will export
1394  // should be explicitly included by the redlining char
1395  // properties on this node because the redlining ends right
1396  // after it
1397  return true;
1398  }
1399  bBreak = false;
1400  }
1401  if (pStart->nNode == rNd)
1402  {
1403  if (pStart->nContent.GetIndex() == nEnd)
1404  {
1405  // This condition detects if the pseudo-char we will export
1406  // should be explicitly included by the redlining char
1407  // properties on this node because the redlining starts right
1408  // before it
1409  return true;
1410  }
1411  bBreak = false;
1412  }
1413  if (pStart->nNode.GetIndex()-1 == rNd.GetIndex())
1414  {
1415  if (pStart->nContent.GetIndex() == 0)
1416  {
1417  // This condition detects if the pseudo-char we will export
1418  // should be implicitly excluded by the redlining char
1419  // properties starting on the next node.
1420  return true;
1421  }
1422  bBreak = false;
1423  }
1424 
1425  if (bBreak)
1426  break;
1427  }
1428  return false;
1429 }
1430 
1432 {
1433  pCurRedline = nullptr;
1434 
1435  // ToDo : this is not the most ideal ... should start maybe from 'nCurRedlinePos'
1437  {
1438  const SwPosition* pCheckedStt = pRedl->Start();
1439 
1440  if( pCheckedStt->nNode == rNd )
1441  {
1442  // Maybe add here a check that also the start & end of the redline is the entire paragraph
1443 
1444  // Only return if this is a paragraph formatting redline
1445  if (pRedl->GetType() == nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT)
1446  {
1447  // write data of this redline
1448  pCurRedline = pRedl;
1449  return &( pCurRedline->GetRedlineData() );
1450  }
1451  }
1452  }
1453  return nullptr;
1454 }
1455 
1457 {
1458  if( pCurRedline )
1459  {
1460  const SwPosition* pEnd = pCurRedline->End();
1461  if (!(pEnd->nNode == rNd && pEnd->nContent.GetIndex() <= nPos))
1462  {
1463  switch( pCurRedline->GetType() )
1464  {
1468  // write data of this redline
1469  return &( pCurRedline->GetRedlineData() );
1470  break;
1471  default:
1472  break;
1473  }
1474  }
1475  pCurRedline = nullptr;
1476  ++nCurRedlinePos;
1477  }
1478 
1479  assert(!pCurRedline);
1480  // search next Redline
1482  ++nCurRedlinePos )
1483  {
1485 
1486  const SwPosition* pStt = pRedl->Start();
1487  const SwPosition* pEnd = pStt == pRedl->GetPoint()
1488  ? pRedl->GetMark()
1489  : pRedl->GetPoint();
1490 
1491  if( pStt->nNode == rNd )
1492  {
1493  if( pStt->nContent.GetIndex() >= nPos )
1494  {
1495  if( pStt->nContent.GetIndex() == nPos )
1496  {
1497  switch( pRedl->GetType() )
1498  {
1502  // write data of this redline
1503  pCurRedline = pRedl;
1504  return &( pCurRedline->GetRedlineData() );
1505  break;
1506  default:
1507  break;
1508  }
1509  }
1510  break;
1511  }
1512  }
1513  else
1514  {
1515  break;
1516  }
1517 
1518  if( pEnd->nNode == rNd &&
1519  pEnd->nContent.GetIndex() < nPos )
1520  {
1521  pCurRedline = pRedl;
1522  break;
1523  }
1524  }
1525  return nullptr;
1526 }
1527 
1529 {
1530  const SwFrameFormat &rFormat = m_pCurrentPageDesc
1532  : m_pDoc->GetPageDesc( 0 ).GetMaster();
1533  return rFormat.GetFrameDir().GetValue();
1534 }
1535 
1537 {
1538  SvxFrameDirection nDir = SvxFrameDirection::Environment;
1539 
1540  if ( m_bOutPageDescs )
1541  nDir = GetCurrentPageDirection( );
1542  else if ( m_pOutFormatNode )
1543  {
1544  if ( m_bOutFlyFrameAttrs ) //frame
1545  {
1546  nDir = TrueFrameDirection( *static_cast< const SwFrameFormat * >(m_pOutFormatNode) );
1547  }
1548  else if ( dynamic_cast< const SwContentNode *>( m_pOutFormatNode ) != nullptr ) //paragraph
1549  {
1550  const SwContentNode *pNd = static_cast<const SwContentNode *>(m_pOutFormatNode);
1551  SwPosition aPos( *pNd );
1552  nDir = m_pDoc->GetTextDirection( aPos );
1553  }
1554  else if ( dynamic_cast< const SwTextFormatColl *>( m_pOutFormatNode ) != nullptr )
1555  {
1557  nDir = SvxFrameDirection::Horizontal_RL_TB;
1558  else
1559  nDir = SvxFrameDirection::Horizontal_LR_TB; //what else can we do :-(
1560  }
1561  }
1562 
1563  if ( nDir == SvxFrameDirection::Environment )
1564  {
1565  // fdo#44029 put direction right when the locale are RTL.
1567  nDir = SvxFrameDirection::Horizontal_RL_TB;
1568  else
1569  nDir = SvxFrameDirection::Horizontal_LR_TB; //Set something
1570  }
1571 
1572  return nDir;
1573 }
1574 
1576 {
1577  const SwFrameFormat *pFlyFormat = &rFlyFormat;
1578  const SvxFrameDirectionItem* pItem = nullptr;
1579  while ( pFlyFormat )
1580  {
1581  pItem = &pFlyFormat->GetFrameDir();
1582  if ( SvxFrameDirection::Environment == pItem->GetValue() )
1583  {
1584  pItem = nullptr;
1585  const SwFormatAnchor* pAnchor = &pFlyFormat->GetAnchor();
1586  if ((RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
1587  pAnchor->GetContentAnchor() )
1588  {
1589  pFlyFormat = pAnchor->GetContentAnchor()->nNode.GetNode().GetFlyFormat();
1590  }
1591  else
1592  pFlyFormat = nullptr;
1593  }
1594  else
1595  pFlyFormat = nullptr;
1596  }
1597 
1598  SvxFrameDirection nRet;
1599  if ( pItem )
1600  nRet = pItem->GetValue();
1601  else
1602  nRet = GetCurrentPageDirection();
1603 
1604  OSL_ENSURE( nRet != SvxFrameDirection::Environment, "leaving with environment direction" );
1605  return nRet;
1606 }
1607 
1609 {
1610  const SwFrameFormat &rFormat = m_pCurrentPageDesc
1612  : m_pDoc->GetPageDesc(0).GetMaster();
1613 
1614  const SfxPoolItem* pItem = nullptr;
1615  //If not set, or "no fill", get real bg
1616  SfxItemState eState = rFormat.GetItemState(RES_BACKGROUND, true, &pItem);
1617 
1618  const SvxBrushItem* pRet = static_cast<const SvxBrushItem*>(pItem);
1619  if (SfxItemState::SET != eState || !pRet || (!pRet->GetGraphic() &&
1620  pRet->GetColor() == COL_TRANSPARENT))
1621  {
1622  pRet = &(DefaultItemGet<SvxBrushItem>(*m_pDoc,RES_BACKGROUND));
1623  }
1624  return pRet;
1625 }
1626 
1627 std::shared_ptr<SvxBrushItem> WW8Export::TrueFrameBgBrush(const SwFrameFormat &rFlyFormat) const
1628 {
1629  const SwFrameFormat *pFlyFormat = &rFlyFormat;
1630  const SvxBrushItem* pRet = nullptr;
1631 
1632  while (pFlyFormat)
1633  {
1634  //If not set, or "no fill", get real bg
1635  const SfxPoolItem* pItem = nullptr;
1636  SfxItemState eState =
1637  pFlyFormat->GetItemState(RES_BACKGROUND, true, &pItem);
1638  pRet = static_cast<const SvxBrushItem*>(pItem);
1639  if (SfxItemState::SET != eState || !pRet || (!pRet->GetGraphic() &&
1640  pRet->GetColor() == COL_TRANSPARENT))
1641  {
1642  pRet = nullptr;
1643  const SwFormatAnchor* pAnchor = &pFlyFormat->GetAnchor();
1644  if ((RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
1645  pAnchor->GetContentAnchor())
1646  {
1647  pFlyFormat =
1648  pAnchor->GetContentAnchor()->nNode.GetNode().GetFlyFormat();
1649  }
1650  else
1651  pFlyFormat = nullptr;
1652  }
1653  else
1654  pFlyFormat = nullptr;
1655  }
1656 
1657  if (!pRet)
1658  pRet = GetCurrentPageBgBrush();
1659 
1660  const Color aTmpColor( COL_WHITE );
1661  std::shared_ptr<SvxBrushItem> aRet(std::make_shared<SvxBrushItem>(aTmpColor, RES_BACKGROUND));
1662 
1663  if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
1664  {
1665  aRet.reset(static_cast<SvxBrushItem*>(pRet->Clone()));
1666  }
1667 
1668  return aRet;
1669 }
1670 
1671 /*
1672 Convert characters that need to be converted, the basic replacements and the
1673 ridiculously complicated title case attribute mapping to hardcoded upper case
1674 because word doesn't have the feature
1675 */
1676 OUString SwWW8AttrIter::GetSnippet(const OUString &rStr, sal_Int32 nCurrentPos,
1677  sal_Int32 nLen) const
1678 {
1679  if (!nLen)
1680  return OUString();
1681 
1682  OUString aSnippet(rStr.copy(nCurrentPos, nLen));
1683  // 0x0a ( Hard Line Break ) -> 0x0b
1684  // 0xad ( soft hyphen ) -> 0x1f
1685  // 0x2011 ( hard hyphen ) -> 0x1e
1686  aSnippet = aSnippet.replace(0x0A, 0x0B);
1687  aSnippet = aSnippet.replace(CHAR_HARDHYPHEN, 0x1e);
1688  aSnippet = aSnippet.replace(CHAR_SOFTHYPHEN, 0x1f);
1689 
1690  m_rExport.m_aCurrentCharPropStarts.push( nCurrentPos );
1691  const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP);
1692 
1693  if (SvxCaseMap::Capitalize == static_cast<const SvxCaseMapItem&>(rItem).GetValue())
1694  {
1695  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
1696  sal_uInt16 nScriptType = g_pBreakIt->GetBreakIter()->getScriptType(aSnippet, 0);
1697 
1698  LanguageType nLanguage;
1699  switch (nScriptType)
1700  {
1701  case i18n::ScriptType::ASIAN:
1702  nLanguage = static_cast<const SvxLanguageItem&>(GetItem(RES_CHRATR_CJK_LANGUAGE)).GetLanguage();
1703  break;
1704  case i18n::ScriptType::COMPLEX:
1705  nLanguage = static_cast<const SvxLanguageItem&>(GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage();
1706  break;
1707  case i18n::ScriptType::LATIN:
1708  default:
1709  nLanguage = static_cast<const SvxLanguageItem&>(GetItem(RES_CHRATR_LANGUAGE)).GetLanguage();
1710  break;
1711  }
1712 
1713  SvxFont aFontHelper;
1714  aFontHelper.SetCaseMap(SvxCaseMap::Capitalize);
1715  aFontHelper.SetLanguage(nLanguage);
1716  aSnippet = aFontHelper.CalcCaseMap(aSnippet);
1717 
1718  //If we weren't at the begin of a word undo the case change.
1719  //not done before doing the casemap because the sequence might start
1720  //with whitespace
1721  if (!g_pBreakIt->GetBreakIter()->isBeginWord(
1722  rStr, nCurrentPos, g_pBreakIt->GetLocale(nLanguage),
1723  i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
1724  {
1725  aSnippet = OUStringLiteral1(rStr[nCurrentPos]) + aSnippet.copy(1);
1726  }
1727  }
1729 
1730  return aSnippet;
1731 }
1732 
1740 {
1743  while( nPos < nMax )
1744  {
1745  const SwRangeRedline* pRedl = rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable()[ nPos++ ];
1746  const SwPosition* pStt = pRedl->Start();
1747  const SwPosition* pEnd = pStt == pRedl->GetPoint()
1748  ? pRedl->GetMark()
1749  : pRedl->GetPoint();
1750  // Looking for deletions, which ends in current pTextNode
1752  pEnd->nNode == *pTextNode && pStt->nNode != *pTextNode &&
1753  pStt->nNode.GetNode().IsTextNode() )
1754  {
1755  pTextNode = pStt->nNode.GetNode().GetTextNode();
1756  nMax = nPos;
1757  nPos = 0;
1758  }
1759  }
1760  return static_cast<SwTextFormatColl&>( pTextNode->GetAnyFormatColl() );
1761 }
1762 
1763 void WW8AttributeOutput::FormatDrop( const SwTextNode& rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle,
1765 {
1766  short nDropLines = rSwFormatDrop.GetLines();
1767  short nDistance = rSwFormatDrop.GetDistance();
1768  int rFontHeight, rDropHeight, rDropDescent;
1769 
1770  SVBT16 nSty;
1771  ShortToSVBT16( nStyle, nSty );
1772  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nSty, nSty+2 ); // Style #
1773 
1774  m_rWW8Export.InsUInt16( NS_sprm::sprmPPc ); // Alignment (sprmPPc)
1775  m_rWW8Export.pO->push_back( 0x20 );
1776 
1777  m_rWW8Export.InsUInt16( NS_sprm::sprmPWr ); // Wrapping (sprmPWr)
1778  m_rWW8Export.pO->push_back( 0x02 );
1779 
1780  m_rWW8Export.InsUInt16( NS_sprm::sprmPDcs ); // Dropcap (sprmPDcs)
1781  int nDCS = ( nDropLines << 3 ) | 0x01;
1782  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
1783 
1784  m_rWW8Export.InsUInt16( NS_sprm::sprmPDxaFromText ); // Distance from text (sprmPDxaFromText)
1785  m_rWW8Export.InsUInt16( nDistance );
1786 
1787  if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
1788  {
1789  m_rWW8Export.InsUInt16( NS_sprm::sprmPDyaLine ); // Line spacing
1790  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
1791  m_rWW8Export.InsUInt16( 0 );
1792  }
1793 
1794  m_rWW8Export.WriteCR( pTextNodeInfoInner );
1795 
1796  if ( pTextNodeInfo.get() != nullptr )
1797  {
1798 #ifdef DBG_UTIL
1799  SAL_INFO( "sw.ww8", pTextNodeInfo->toString());
1800 #endif
1801  TableInfoCell( pTextNodeInfoInner );
1802  }
1803 
1804  m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
1805  m_rWW8Export.pO->clear();
1806 
1807  if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
1808  {
1809  const SwCharFormat *pSwCharFormat = rSwFormatDrop.GetCharFormat();
1810  if ( pSwCharFormat )
1811  {
1813  m_rWW8Export.InsUInt16( m_rWW8Export.GetId( pSwCharFormat ) );
1814  }
1815 
1816  m_rWW8Export.InsUInt16( NS_sprm::sprmCHpsPos ); // Lower the chars
1817  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
1818 
1819  m_rWW8Export.InsUInt16( NS_sprm::sprmCHps ); // Font Size
1820  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
1821  }
1822 
1823  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
1824  m_rWW8Export.pO->clear();
1825 }
1826 
1827 sal_Int32 MSWordExportBase::GetNextPos( SwWW8AttrIter const * aAttrIter, const SwTextNode& rNode, sal_Int32 nCurrentPos )
1828 {
1829  // Get the bookmarks for the normal run
1830  const sal_Int32 nNextPos = aAttrIter->WhereNext();
1831  sal_Int32 nNextBookmark = nNextPos;
1832  sal_Int32 nNextAnnotationMark = nNextPos;
1833 
1834  if( nNextBookmark > nCurrentPos ) //no need to search for bookmarks otherwise (checked in UpdatePosition())
1835  {
1836  GetSortedBookmarks( rNode, nCurrentPos, nNextBookmark - nCurrentPos );
1837  NearestBookmark( nNextBookmark, nCurrentPos, false );
1838  GetSortedAnnotationMarks( rNode, nCurrentPos, nNextAnnotationMark - nCurrentPos );
1839  NearestAnnotationMark( nNextAnnotationMark, nCurrentPos, false );
1840  }
1841  return std::min( nNextPos, std::min( nNextBookmark, nNextAnnotationMark ) );
1842 }
1843 
1844 void MSWordExportBase::UpdatePosition( SwWW8AttrIter* aAttrIter, sal_Int32 nCurrentPos )
1845 {
1846  sal_Int32 nNextPos;
1847 
1848  // go to next attribute if no bookmark is found or if the bookmark is after the next attribute position
1849  // It may happened that the WhereNext() wasn't used in the previous increment because there was a
1850  // bookmark before it. Use that position before trying to find another one.
1851  bool bNextBookmark = NearestBookmark( nNextPos, nCurrentPos, true );
1852  if( nCurrentPos == aAttrIter->WhereNext() && ( !bNextBookmark || nNextPos > aAttrIter->WhereNext() ) )
1853  aAttrIter->NextPos();
1854 }
1855 
1856 bool MSWordExportBase::GetBookmarks( const SwTextNode& rNd, sal_Int32 nStt,
1857  sal_Int32 nEnd, IMarkVector& rArr )
1858 {
1859  IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
1860  sal_uLong nNd = rNd.GetIndex( );
1861 
1862  const sal_Int32 nMarks = pMarkAccess->getAllMarksCount();
1863  for ( sal_Int32 i = 0; i < nMarks; i++ )
1864  {
1865  IMark* pMark = ( pMarkAccess->getAllMarksBegin() + i )->get();
1866 
1868  {
1869  continue;
1870  }
1871 
1872  // Only keep the bookmarks starting or ending in this node
1873  if ( pMark->GetMarkStart().nNode == nNd ||
1874  pMark->GetMarkEnd().nNode == nNd )
1875  {
1876  const sal_Int32 nBStart = pMark->GetMarkStart().nContent.GetIndex();
1877  const sal_Int32 nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
1878 
1879  // Keep only the bookmars starting or ending in the snippet
1880  bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
1881  bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
1882 
1883  if ( bIsStartOk || bIsEndOk )
1884  {
1885  rArr.push_back( pMark );
1886  }
1887  }
1888  }
1889  return ( !rArr.empty() );
1890 }
1891 
1892 bool MSWordExportBase::GetAnnotationMarks( const SwTextNode& rNd, sal_Int32 nStt,
1893  sal_Int32 nEnd, IMarkVector& rArr )
1894 {
1895  IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
1896  sal_uLong nNd = rNd.GetIndex( );
1897 
1898  const sal_Int32 nMarks = pMarkAccess->getAnnotationMarksCount();
1899  for ( sal_Int32 i = 0; i < nMarks; i++ )
1900  {
1901  IMark* pMark = ( pMarkAccess->getAnnotationMarksBegin() + i )->get();
1902 
1903  // Only keep the bookmarks starting or ending in this node
1904  if ( pMark->GetMarkStart().nNode == nNd ||
1905  pMark->GetMarkEnd().nNode == nNd )
1906  {
1907  const sal_Int32 nBStart = pMark->GetMarkStart().nContent.GetIndex();
1908  const sal_Int32 nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
1909 
1910  // Keep only the bookmars starting or ending in the snippet
1911  bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
1912  bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
1913 
1914  // Annotation marks always have at least one character: the anchor
1915  // point of the comment field. In this case Word wants only the
1916  // comment field, so ignore the annotation mark itself.
1917  bool bSingleChar = pMark->GetMarkStart().nNode == pMark->GetMarkEnd().nNode && nBStart + 1 == nBEnd;
1918 
1919  if ( ( bIsStartOk || bIsEndOk ) && !bSingleChar )
1920  {
1921  rArr.push_back( pMark );
1922  }
1923  }
1924  }
1925  return ( !rArr.empty() );
1926 }
1927 
1929 {
1930 public:
1931  bool operator() ( const IMark * pOneB, const IMark * pTwoB ) const
1932  {
1933  const sal_Int32 nOEnd = pOneB->GetMarkEnd().nContent.GetIndex();
1934  const sal_Int32 nTEnd = pTwoB->GetMarkEnd().nContent.GetIndex();
1935 
1936  return nOEnd < nTEnd;
1937  }
1938 };
1939 
1940 bool MSWordExportBase::NearestBookmark( sal_Int32& rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly )
1941 {
1942  bool bHasBookmark = false;
1943 
1944  if ( !m_rSortedBookmarksStart.empty() )
1945  {
1946  IMark* pMarkStart = m_rSortedBookmarksStart.front();
1947  const sal_Int32 nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
1948  if( !bNextPositionOnly || (nNext > nCurrentPos ))
1949  {
1950  rNearest = nNext;
1951  bHasBookmark = true;
1952  }
1953  }
1954 
1955  if ( !m_rSortedBookmarksEnd.empty() )
1956  {
1957  IMark* pMarkEnd = m_rSortedBookmarksEnd[0];
1958  const sal_Int32 nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
1959  if( !bNextPositionOnly || nNext > nCurrentPos )
1960  {
1961  if ( !bHasBookmark )
1962  rNearest = nNext;
1963  else
1964  rNearest = std::min( rNearest, nNext );
1965  bHasBookmark = true;
1966  }
1967  }
1968 
1969  return bHasBookmark;
1970 }
1971 
1972 void MSWordExportBase::NearestAnnotationMark( sal_Int32& rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly )
1973 {
1974  bool bHasAnnotationMark = false;
1975 
1976  if ( !m_rSortedAnnotationMarksStart.empty() )
1977  {
1978  IMark* pMarkStart = m_rSortedAnnotationMarksStart.front();
1979  const sal_Int32 nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
1980  if( !bNextPositionOnly || (nNext > nCurrentPos ))
1981  {
1982  rNearest = nNext;
1983  bHasAnnotationMark = true;
1984  }
1985  }
1986 
1987  if ( !m_rSortedAnnotationMarksEnd.empty() )
1988  {
1989  IMark* pMarkEnd = m_rSortedAnnotationMarksEnd[0];
1990  const sal_Int32 nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
1991  if( !bNextPositionOnly || nNext > nCurrentPos )
1992  {
1993  if ( !bHasAnnotationMark )
1994  rNearest = nNext;
1995  else
1996  rNearest = std::min( rNearest, nNext );
1997  }
1998  }
1999 }
2000 
2001 void MSWordExportBase::GetSortedAnnotationMarks( const SwTextNode& rNode, sal_Int32 nCurrentPos, sal_Int32 nLen )
2002 {
2003  IMarkVector aMarksStart;
2004  if ( GetAnnotationMarks( rNode, nCurrentPos, nCurrentPos + nLen, aMarksStart ) )
2005  {
2006  IMarkVector aSortedEnd;
2007  IMarkVector aSortedStart;
2008  for ( IMark* pMark : aMarksStart )
2009  {
2010  // Remove the positions equal to the current pos
2011  const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
2012  const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
2013 
2014  if ( nStart > nCurrentPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
2015  aSortedStart.push_back( pMark );
2016 
2017  if ( nEnd > nCurrentPos && nEnd <= ( nCurrentPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
2018  aSortedEnd.push_back( pMark );
2019  }
2020 
2021  // Sort the bookmarks by end position
2022  std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
2023 
2024  m_rSortedAnnotationMarksStart.swap( aSortedStart );
2025  m_rSortedAnnotationMarksEnd.swap( aSortedEnd );
2026  }
2027  else
2028  {
2030  m_rSortedAnnotationMarksEnd.clear( );
2031  }
2032 }
2033 
2034 void MSWordExportBase::GetSortedBookmarks( const SwTextNode& rNode, sal_Int32 nCurrentPos, sal_Int32 nLen )
2035 {
2036  IMarkVector aMarksStart;
2037  if ( GetBookmarks( rNode, nCurrentPos, nCurrentPos + nLen, aMarksStart ) )
2038  {
2039  IMarkVector aSortedEnd;
2040  IMarkVector aSortedStart;
2041  for ( IMark* pMark : aMarksStart )
2042  {
2043  // Remove the positions equal to the current pos
2044  const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
2045  const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
2046 
2047  if ( nStart > nCurrentPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
2048  aSortedStart.push_back( pMark );
2049 
2050  if ( nEnd > nCurrentPos && nEnd <= ( nCurrentPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
2051  aSortedEnd.push_back( pMark );
2052  }
2053 
2054  // Sort the bookmarks by end position
2055  std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
2056 
2057  m_rSortedBookmarksStart.swap( aSortedStart );
2058  m_rSortedBookmarksEnd.swap( aSortedEnd );
2059  }
2060  else
2061  {
2062  m_rSortedBookmarksStart.clear( );
2063  m_rSortedBookmarksEnd.clear( );
2064  }
2065 }
2066 
2068 {
2070  return false;
2071 
2072  const SwPageDesc * pPageDesc = rNd.FindPageDesc()->GetFollow();
2073 
2074  if (m_pCurrentPageDesc != pPageDesc)
2075  {
2077  {
2078  return true;
2079  }
2080  }
2081 
2082  return false;
2083 }
2084 
2086 {
2087  rNd.fillSoftPageBreakList( pList );
2088  pList.insert(0);
2089  pList.insert( rNd.GetText().getLength() );
2090  return pList.size() > 2 && NeedSectionBreak( rNd );
2091 }
2092 
2094 {
2095  SAL_INFO( "sw.ww8", "<OutWW8_SwTextNode>" );
2096 
2097  ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( m_pTableInfo->getTableNodeInfo( &rNode ) );
2098 
2099  //For i120928,identify the last node
2100  bool bLastCR = false;
2101  bool bExported = false;
2102  {
2103  SwNodeIndex aNextIdx(rNode,1);
2104  SwNodeIndex aLastIdx(rNode.GetNodes().GetEndOfContent());
2105  if (aNextIdx == aLastIdx)
2106  bLastCR = true;
2107  }
2108 
2109  // In order to make sure watermark is stored in 'header.xml', check nTextTyp.
2110  // if it is document.xml, don't write the tags (watermark should be only in the 'header')
2111  SwWW8AttrIter aWatermarkAttrIter( *this, rNode );
2112  if (( TXT_HDFT != m_nTextTyp) && aWatermarkAttrIter.IsWatermarkFrame())
2113  {
2114  return;
2115  }
2116 
2117  bool bFlyInTable = m_pParentFrame && IsInTable();
2118 
2119  SwTextFormatColl& rTextColl = lcl_getFormatCollection( *this, &rNode );
2120  if ( !bFlyInTable )
2121  m_nStyleBeforeFly = GetId( rTextColl );
2122 
2123  // nStyleBeforeFly may change when we recurse into another node, so we
2124  // have to remember it in nStyle
2125  sal_uInt16 nStyle = m_nStyleBeforeFly;
2126 
2127  SwWW8AttrIter aAttrIter( *this, rNode );
2128  rtl_TextEncoding eChrSet = aAttrIter.GetCharSet();
2129 
2130  if ( m_bStartTOX )
2131  {
2132  // ignore TOX header section
2133  const SwSectionNode* pSectNd = rNode.FindSectionNode();
2134  if ( pSectNd && TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
2135  {
2136  AttrOutput().StartTOX( pSectNd->GetSection() );
2137  m_aCurrentCharPropStarts.push( 0 );
2138  }
2139  }
2140 
2141  // Emulate: If 1-row table is marked as don't split, then set the row as don't split.
2142  if ( IsInTable() )
2143  {
2144  const SwTableNode* pTableNode = rNode.FindTableNode();
2145  if ( pTableNode )
2146  {
2147  const SwTable& rTable = pTableNode->GetTable();
2148  const bool bKeep = rTable.GetFrameFormat()->GetKeep().GetValue();
2149  const bool bDontSplit = !rTable.GetFrameFormat()->GetLayoutSplit().GetValue();
2150  // bKeep handles this a different way later on, so ignore now
2151  if ( !bKeep && bDontSplit && rTable.GetTabLines().size() == 1 )
2152  {
2153  // bDontSplit : set don't split once for the row
2154  // but only for non-complex tables
2155  const SwTableBox* pBox = rNode.GetTableBox();
2156  const SwTableLine* pLine = pBox ? pBox->GetUpper() : nullptr;
2157  if ( pLine && !pLine->GetUpper() )
2158  {
2159  // check if box is first in that line:
2160  if ( 0 == pLine->GetBoxPos( pBox ) && pBox->GetSttNd() )
2161  {
2162  // check if paragraph is first in that line:
2163  if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
2164  pLine->GetFrameFormat()->SetFormatAttr(SwFormatRowSplit(!bDontSplit));
2165  }
2166  }
2167  }
2168  }
2169  }
2170 
2171  SwSoftPageBreakList softBreakList;
2172  // Let's decide if we need to split the paragraph because of a section break
2173  bool bNeedParaSplit = NeedTextNodeSplit( rNode, softBreakList )
2174  && !IsInTable();
2175 
2176  auto aBreakIt = softBreakList.begin();
2177  // iterate through portions on different pages
2178  do
2179  {
2180  sal_Int32 nCurrentPos = *aBreakIt;
2181 
2182  if( softBreakList.size() > 1 ) // not for empty paragraph
2183  ++aBreakIt;
2184 
2185  AttrOutput().StartParagraph( pTextNodeInfo );
2186 
2187  const SwSection* pTOXSect = nullptr;
2188  if( m_bInWriteTOX )
2189  {
2190  // check for end of TOX
2191  SwNodeIndex aIdx( rNode, 1 );
2192  if( !aIdx.GetNode().IsTextNode() )
2193  {
2194  const SwSectionNode* pTOXSectNd = rNode.FindSectionNode();
2195  if ( pTOXSectNd )
2196  {
2197  pTOXSect = &pTOXSectNd->GetSection();
2198 
2199  const SwNode* pNxt = rNode.GetNodes().GoNext( &aIdx );
2200  if( pNxt && pNxt->FindSectionNode() == pTOXSectNd )
2201  pTOXSect = nullptr;
2202  }
2203  }
2204  }
2205 
2206  if ( aAttrIter.RequiresImplicitBookmark() )
2207  {
2208  OUString sBkmkName = "_toc" + OUString::number( rNode.GetIndex() );
2209  // Add a bookmark converted to a Word name.
2210  AppendBookmark( BookmarkToWord( sBkmkName ) );
2211  }
2212 
2213  // Call this before write out fields and runs
2214  AttrOutput().GenerateBookmarksForSequenceField(rNode, aAttrIter);
2215 
2216  const OUString& aStr( rNode.GetText() );
2217 
2218  sal_Int32 const nEnd = bNeedParaSplit ? *aBreakIt : aStr.getLength();
2219  bool bIncludeEndOfParaCRInRedlineProperties = false;
2220  sal_Int32 nOpenAttrWithRange = 0;
2221 
2222  ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner;
2223  if ( pTextNodeInfo.get() != nullptr )
2224  {
2225  pTextNodeInfoInner = pTextNodeInfo->getFirstInner();
2226  }
2227 
2228  do {
2229 
2230  const SwRedlineData* pRedlineData = aAttrIter.GetRunLevelRedline( nCurrentPos );
2231  FlyProcessingState nStateOfFlyFrame = FLY_PROCESSED;
2232  bool bPostponeWritingText = false ;
2233  OUString aSavedSnippet ;
2234 
2235  sal_Int32 nNextAttr = GetNextPos( &aAttrIter, rNode, nCurrentPos );
2236 
2237  // Skip un-exportable attributes.
2238  if (!aAttrIter.IsExportableAttr(nCurrentPos))
2239  {
2240  nCurrentPos = nNextAttr;
2241  UpdatePosition(&aAttrIter, nCurrentPos);
2242  eChrSet = aAttrIter.GetCharSet();
2243  continue;
2244  }
2245 
2246  // Is this the only run in this paragraph and it's empty?
2247  bool bSingleEmptyRun = nCurrentPos == 0 && nNextAttr == 0;
2248  AttrOutput().StartRun( pRedlineData, nCurrentPos, bSingleEmptyRun );
2249 
2250  if( nNextAttr > nEnd )
2251  nNextAttr = nEnd;
2252 
2253  if( m_nTextTyp == TXT_FTN || m_nTextTyp == TXT_EDN )
2254  {
2255  if( AttrOutput().FootnoteEndnoteRefTag() )
2256  {
2257  AttrOutput().EndRun( &rNode, nCurrentPos, nNextAttr == nEnd );
2258  AttrOutput().StartRun( pRedlineData, nCurrentPos, bSingleEmptyRun );
2259  }
2260  }
2261 
2262  /*
2263  1) If there is a text node and an overlapping anchor, then write them in two different
2264  runs and not as part of the same run.
2265  2) Ensure that it is a text node and not in a fly.
2266  3) If the anchor is associated with a text node with empty text then we ignore.
2267  */
2268  if( rNode.IsTextNode()
2269  && aStr != "\001" && !aStr.isEmpty()
2270  && !rNode.GetFlyFormat()
2271  && !(IsInTable() && !AllowPostponedTextInTable())
2272  && aAttrIter.IsAnchorLinkedToThisNode(rNode.GetIndex()) )
2273  {
2274  bPostponeWritingText = true ;
2275  }
2276 
2277  nStateOfFlyFrame = aAttrIter.OutFlys( nCurrentPos );
2278  AttrOutput().SetStateOfFlyFrame( nStateOfFlyFrame );
2279  AttrOutput().SetAnchorIsLinkedToNode( bPostponeWritingText && (FLY_POSTPONED != nStateOfFlyFrame) );
2280  // Append bookmarks in this range after flys, exclusive of final
2281  // position of this range
2282  AppendBookmarks( rNode, nCurrentPos, nNextAttr - nCurrentPos );
2283  AppendAnnotationMarks( rNode, nCurrentPos, nNextAttr - nCurrentPos );
2284 
2285  // At the moment smarttags are only written for paragraphs, at the
2286  // beginning of the paragraph.
2287  if (nCurrentPos == 0)
2288  AppendSmartTags(rNode);
2289 
2290  bool bTextAtr = aAttrIter.IsTextAttr( nCurrentPos );
2291  nOpenAttrWithRange += aAttrIter.OutAttrWithRange( rNode, nCurrentPos );
2292 
2293  sal_Int32 nLen = nNextAttr - nCurrentPos;
2294  if ( !bTextAtr && nLen )
2295  {
2296  sal_Unicode ch = aStr[nCurrentPos];
2297  const sal_Int32 ofs = ( ch == CH_TXT_ATR_FIELDSTART || ch == CH_TXT_ATR_FIELDEND || ch == CH_TXT_ATR_FORMELEMENT? 1 : 0 );
2298 
2299  IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
2300  if ( ch == CH_TXT_ATR_FIELDSTART )
2301  {
2302  SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
2303  ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
2304  OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
2305 
2306  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
2307  && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
2308  {
2309  AppendBookmark( pFieldmark->GetName() );
2310  }
2311  ww::eField eFieldId = lcl_getFieldId( pFieldmark );
2312  OUString sCode = lcl_getFieldCode( pFieldmark );
2313  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
2314  {
2315  IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
2316  if ( it != pFieldmark->GetParameters()->end() )
2317  {
2318  OUString sFieldId;
2319  it->second >>= sFieldId;
2320  eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
2321  }
2322 
2323  it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM );
2324  if ( it != pFieldmark->GetParameters()->end() )
2325  {
2326  it->second >>= sCode;
2327  }
2328  }
2329 
2330  OutputField( nullptr, eFieldId, sCode, FieldFlags::Start | FieldFlags::CmdStart );
2331 
2332  if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
2333  WriteFormData( *pFieldmark );
2334  else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
2335  WriteHyperlinkData( *pFieldmark );
2336  OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::CmdEnd );
2337 
2338  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
2339  {
2340  // Check for the presence of a linked OLE object
2341  IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM );
2342  if ( it != pFieldmark->GetParameters()->end() )
2343  {
2344  OUString sOleId;
2345  uno::Any aValue = it->second;
2346  aValue >>= sOleId;
2347  if ( !sOleId.isEmpty() )
2348  OutputLinkedOLE( sOleId );
2349  }
2350  }
2351  }
2352  else if ( ch == CH_TXT_ATR_FIELDEND )
2353  {
2354  SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
2355  ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
2356 
2357  OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" );
2358 
2359  ww::eField eFieldId = lcl_getFieldId( pFieldmark );
2360  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
2361  {
2362  IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
2363  if ( it != pFieldmark->GetParameters()->end() )
2364  {
2365  OUString sFieldId;
2366  it->second >>= sFieldId;
2367  eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
2368  }
2369  }
2370 
2371  OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close );
2372 
2373  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
2374  && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
2375  {
2376  AppendBookmark( pFieldmark->GetName() );
2377  }
2378  }
2379  else if ( ch == CH_TXT_ATR_FORMELEMENT )
2380  {
2381  SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
2382  ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
2383  OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
2384 
2385  bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
2386  pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
2387 
2388  if ( isDropdownOrCheckbox )
2389  AppendBookmark( pFieldmark->GetName() );
2390  OutputField( nullptr, lcl_getFieldId( pFieldmark ),
2391  lcl_getFieldCode( pFieldmark ),
2393  if ( isDropdownOrCheckbox )
2394  WriteFormData( *pFieldmark );
2395  OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close );
2396  if ( isDropdownOrCheckbox )
2397  AppendBookmark( pFieldmark->GetName() );
2398  }
2399  nLen -= ofs;
2400 
2401  // if paragraph needs to be split, write only until split position
2402  assert(!bNeedParaSplit || nCurrentPos <= *aBreakIt);
2403  if( bNeedParaSplit && nCurrentPos + ofs + nLen > *aBreakIt)
2404  nLen = *aBreakIt - nCurrentPos - ofs;
2405  assert(0 <= nLen);
2406 
2407  OUString aSnippet( aAttrIter.GetSnippet( aStr, nCurrentPos + ofs, nLen ) );
2408  if ( ( m_nTextTyp == TXT_EDN || m_nTextTyp == TXT_FTN ) && nCurrentPos == 0 && nLen > 0 )
2409  {
2410  // Allow MSO to emulate LO footnote text starting at left margin - only meaningful with hanging indent
2411  sal_Int32 nFirstLineIndent=0;
2413  const SwTextNode* pTextNode( rNode.GetTextNode() );
2414  if ( pTextNode && pTextNode->GetAttr(aSet) )
2415  {
2416  const SvxLRSpaceItem* pLRSpace = aSet.GetItem<SvxLRSpaceItem>(RES_LR_SPACE);
2417  if ( pLRSpace )
2418  nFirstLineIndent = pLRSpace->GetTextFirstLineOfst();
2419  }
2420 
2421  // Insert tab for aesthetic purposes #i24762#
2422  if ( m_bAddFootnoteTab && nFirstLineIndent < 0 && aSnippet[0] != 0x09 )
2423  aSnippet = "\x09" + aSnippet;
2424  m_bAddFootnoteTab = false;
2425  }
2426 
2427  if ( bPostponeWritingText && ( FLY_POSTPONED != nStateOfFlyFrame ) )
2428  {
2429  bPostponeWritingText = true ;
2430  aSavedSnippet = aSnippet ;
2431  }
2432  else
2433  {
2434  bPostponeWritingText = false ;
2435  AttrOutput().RunText( aSnippet, eChrSet );
2436  }
2437  }
2438 
2439  if ( aAttrIter.IsDropCap( nNextAttr ) )
2440  AttrOutput().FormatDrop( rNode, aAttrIter.GetSwFormatDrop(), nStyle, pTextNodeInfo, pTextNodeInfoInner );
2441 
2442  // Only output character attributes if this is not a postponed text run.
2443  if (0 != nEnd && !(bPostponeWritingText && FLY_PROCESSED == nStateOfFlyFrame))
2444  {
2445  // Output the character attributes
2446  // #i51277# do this before writing flys at end of paragraph
2448  aAttrIter.OutAttr( nCurrentPos, false );
2449  AttrOutput().EndRunProperties( pRedlineData );
2450  }
2451 
2452  // At the end of line, output the attributes until the CR.
2453  // Exception: footnotes at the end of line
2454  if ( nNextAttr == nEnd )
2455  {
2456  OSL_ENSURE( nOpenAttrWithRange >= 0, "odd to see this happening, expected >= 0" );
2457  if ( !bTextAtr && nOpenAttrWithRange <= 0 )
2458  {
2459  if ( aAttrIter.IncludeEndOfParaCRInRedlineProperties( nEnd ) )
2460  bIncludeEndOfParaCRInRedlineProperties = true;
2461  else
2462  {
2463  // insert final graphic anchors if any before CR
2464  nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
2465  // insert final bookmarks if any before CR and after flys
2466  AppendBookmarks( rNode, nEnd, 1 );
2467  AppendAnnotationMarks( rNode, nEnd, 1 );
2468  if ( pTOXSect )
2469  {
2471  AttrOutput().EndTOX( *pTOXSect ,false);
2472  }
2473  //For i120928,the position of the bullet's graphic is at end of doc
2474  if (bLastCR && (!bExported))
2475  {
2476  ExportGrfBullet(rNode);
2477  bExported = true;
2478  }
2479 
2480  WriteCR( pTextNodeInfoInner );
2481  }
2482  }
2483  }
2484 
2485  if (0 == nEnd)
2486  {
2487  // Output the character attributes
2488  // do it after WriteCR for an empty paragraph (otherwise
2489  // WW8_WrFkp::Append throws SPRMs away...)
2491  aAttrIter.OutAttr( nCurrentPos, false );
2492  AttrOutput().EndRunProperties( pRedlineData );
2493  }
2494 
2495  // Exception: footnotes at the end of line
2496  if ( nNextAttr == nEnd )
2497  {
2498  OSL_ENSURE(nOpenAttrWithRange >= 0,
2499  "odd to see this happening, expected >= 0");
2500  bool bAttrWithRange = (nOpenAttrWithRange > 0);
2501  if ( nCurrentPos != nEnd )
2502  {
2503  nOpenAttrWithRange += aAttrIter.OutAttrWithRange( rNode, nEnd );
2504  OSL_ENSURE(nOpenAttrWithRange == 0,
2505  "odd to see this happening, expected 0");
2506  }
2507 
2508  // !bIncludeEndOfParaCRInRedlineProperties implies we have just
2509  // emitted a CR, in which case we want to pass force=true to
2510  // OutputFKP to ensure that an FKP entry for direct character
2511  // formatting is written even if empty, so that the next one will
2512  // start after the CR.
2513  AttrOutput().OutputFKP(!bIncludeEndOfParaCRInRedlineProperties);
2514 
2515  if (bTextAtr || bAttrWithRange || bIncludeEndOfParaCRInRedlineProperties)
2516  {
2517  // insert final graphic anchors if any before CR
2518  nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
2519  // insert final bookmarks if any before CR and after flys
2520  AppendBookmarks( rNode, nEnd, 1 );
2521  AppendAnnotationMarks( rNode, nEnd, 1 );
2522  WriteCR( pTextNodeInfoInner );
2523  // #i120928 - position of the bullet's graphic is at end of doc
2524  if (bLastCR && (!bExported))
2525  {
2526  ExportGrfBullet(rNode);
2527  bExported = true;
2528  }
2529 
2530  if ( pTOXSect )
2531  {
2533  AttrOutput().EndTOX( *pTOXSect );
2534  }
2535 
2536  if (bIncludeEndOfParaCRInRedlineProperties)
2537  {
2538  AttrOutput().Redline( aAttrIter.GetRunLevelRedline( nEnd ) );
2539  //If there was no redline property emitted, force adding
2540  //another entry for the CR so that in the case that this
2541  //has no redline, but the next para does, then this one is
2542  //not merged with the next
2543  AttrOutput().OutputFKP(true);
2544  }
2545  }
2546  }
2547 
2549 
2550  if( bPostponeWritingText && FLY_PROCESSED == nStateOfFlyFrame )
2551  {
2552  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2553  //write the postponed text run
2554  AttrOutput().StartRun( pRedlineData, nCurrentPos, bSingleEmptyRun );
2557  if (0 != nEnd)
2558  {
2560  aAttrIter.OutAttr( nCurrentPos, false );
2561  AttrOutput().EndRunProperties( pRedlineData );
2562  }
2563  AttrOutput().RunText( aSavedSnippet, eChrSet );
2564  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2565  }
2566  else if( bPostponeWritingText && !aSavedSnippet.isEmpty() )
2567  {
2568  //write the postponed text run
2569  AttrOutput().RunText( aSavedSnippet, eChrSet );
2570  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2571  }
2572  else
2573  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2574 
2575  nCurrentPos = nNextAttr;
2576  UpdatePosition( &aAttrIter, nCurrentPos );
2577  eChrSet = aAttrIter.GetCharSet();
2578  }
2579  while ( nCurrentPos < nEnd );
2580 
2581  // if paragraph is split, put the section break between the parts
2582  if( bNeedParaSplit && *aBreakIt != rNode.GetText().getLength() )
2583  {
2584  SwNodeIndex aNextIndex( rNode, 1 );
2585  const SwNode& pNextNode = aNextIndex.GetNode();
2586  // if there is a next node, use its attributes to create the new
2587  // section
2588  if( pNextNode.IsTextNode() )
2589  {
2590  const SwTextNode& rNextNode = *static_cast<SwTextNode*>(
2591  &aNextIndex.GetNode() );
2592  OutputSectionBreaks(rNextNode.GetpSwAttrSet(), rNextNode);
2593  }
2594  else if (pNextNode.IsEndNode() )
2595  {
2596  // In this case the same paragraph holds the next page style
2597  // too.
2598  const SwPageDesc* pNextPageDesc = m_pCurrentPageDesc->GetFollow();
2599  assert(pNextPageDesc);
2600  PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc);
2601  }
2602  }
2603  else if (!bNeedParaSplit)
2604  {
2605  // else check if section break needed after the paragraph
2606  AttrOutput().SectionBreaks(rNode);
2607  }
2608 
2610 
2611  AttrOutput().ParagraphStyle( nStyle );
2612 
2613  if ( m_pParentFrame && IsInTable() ) // Fly-Attrs
2614  OutputFormat( m_pParentFrame->GetFrameFormat(), false, false, true );
2615 
2616  if ( pTextNodeInfo.get() != nullptr )
2617  {
2618 #ifdef DBG_UTIL
2619  SAL_INFO( "sw.ww8", pTextNodeInfo->toString());
2620 #endif
2621 
2622  AttrOutput().TableInfoCell( pTextNodeInfoInner );
2623  if (pTextNodeInfoInner->isFirstInTable())
2624  {
2625  const SwTable * pTable = pTextNodeInfoInner->getTable();
2626 
2627  const SwTableFormat* pTabFormat = pTable->GetFrameFormat();
2628  if (pTabFormat != nullptr)
2629  {
2630  if (pTabFormat->GetBreak().GetBreak() == SvxBreak::PageBefore)
2631  AttrOutput().PageBreakBefore(true);
2632  }
2633  }
2634  }
2635 
2636  if ( !bFlyInTable )
2637  {
2638  SfxItemSet* pTmpSet = nullptr;
2639  const sal_uInt8 nPrvNxtNd = rNode.HasPrevNextLayNode();
2640 
2641  if( (ND_HAS_PREV_LAYNODE|ND_HAS_NEXT_LAYNODE ) != nPrvNxtNd )
2642  {
2643  const SfxPoolItem* pItem;
2644  if( SfxItemState::SET == rNode.GetSwAttrSet().GetItemState(
2645  RES_UL_SPACE, true, &pItem ) &&
2646  ( ( !( ND_HAS_PREV_LAYNODE & nPrvNxtNd ) &&
2647  static_cast<const SvxULSpaceItem*>(pItem)->GetUpper()) ||
2648  ( !( ND_HAS_NEXT_LAYNODE & nPrvNxtNd ) &&
2649  static_cast<const SvxULSpaceItem*>(pItem)->GetLower()) ))
2650  {
2651  pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
2652  SvxULSpaceItem aUL( *static_cast<const SvxULSpaceItem*>(pItem) );
2653  // #i25901#- consider compatibility option
2655  {
2656  if( !(ND_HAS_PREV_LAYNODE & nPrvNxtNd ))
2657  aUL.SetUpper( 0 );
2658  }
2659  // #i25901# - consider compatibility option
2661  {
2662  if( !(ND_HAS_NEXT_LAYNODE & nPrvNxtNd ))
2663  aUL.SetLower( 0 );
2664  }
2665  pTmpSet->Put( aUL );
2666  }
2667  }
2668 
2669  const bool bParaRTL = aAttrIter.IsParaRTL();
2670 
2671  int nNumberLevel = -1;
2672  if (rNode.IsNumbered())
2673  nNumberLevel = rNode.GetActualListLevel();
2674  if (nNumberLevel >= 0 && nNumberLevel < MAXLEVEL)
2675  {
2676  const SwNumRule* pRule = rNode.GetNumRule();
2677  sal_uInt8 nLvl = static_cast< sal_uInt8 >(nNumberLevel);
2678  const SwNumFormat* pFormat = pRule->GetNumFormat( nLvl );
2679  if( !pFormat )
2680  pFormat = &pRule->Get( nLvl );
2681 
2682  if( !pTmpSet )
2683  pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
2684 
2685  SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*pTmpSet, RES_LR_SPACE));
2686  // #i86652#
2687  if ( pFormat->GetPositionAndSpaceMode() ==
2689  {
2690  aLR.SetTextLeft( aLR.GetTextLeft() + pFormat->GetAbsLSpace() );
2691  }
2692 
2693  if( rNode.IsNumbered() && rNode.IsCountedInList() )
2694  {
2695  // #i86652#
2696  if ( pFormat->GetPositionAndSpaceMode() ==
2698  {
2699  if (bParaRTL)
2700  aLR.SetTextFirstLineOfstValue(pFormat->GetAbsLSpace() - pFormat->GetFirstLineOffset()); //TODO: overflow
2701  else
2702  aLR.SetTextFirstLineOfst(GetWordFirstLineOffset(*pFormat));
2703  }
2704 
2705  // correct fix for issue i94187
2706  if (SfxItemState::SET !=
2707  pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
2708  {
2709  // List style set via paragraph style - then put it into the itemset.
2710  // This is needed to get list level and list id exported for
2711  // the paragraph.
2712  pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
2713 
2714  // Put indent values into the itemset in case that the list
2715  // style is applied via paragraph style and the list level
2716  // indent values are not applicable.
2717  if ( pFormat->GetPositionAndSpaceMode() ==
2720  {
2721  pTmpSet->Put( aLR );
2722  }
2723  }
2724  }
2725  else
2726  pTmpSet->ClearItem(RES_PARATR_NUMRULE);
2727 
2728  // #i86652#
2729  if ( pFormat->GetPositionAndSpaceMode() ==
2731  {
2732  pTmpSet->Put(aLR);
2733 
2734  //#i21847#
2735  SvxTabStopItem aItem(
2736  ItemGet<SvxTabStopItem>(*pTmpSet, RES_PARATR_TABSTOP));
2737  SvxTabStop aTabStop(pFormat->GetAbsLSpace());
2738  aItem.Insert(aTabStop);
2739  pTmpSet->Put(aItem);
2740 
2742  }
2743  }
2744 
2745  /*
2746  If a given para is using the SvxFrameDirection::Environment direction we
2747  cannot export that, if it's ltr then that's ok as that is word's
2748  default. Otherwise we must add a RTL attribute to our export list
2749  Only necessary if the ParaStyle doesn't define the direction.
2750  */
2751  const SvxFrameDirectionItem* pItem =
2753  if (
2754  (!pItem || pItem->GetValue() == SvxFrameDirection::Environment) &&
2755  rTextColl.GetFrameDir().GetValue() == SvxFrameDirection::Environment
2756  )
2757  {
2758  if ( !pTmpSet )
2759  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2760 
2761  if ( bParaRTL )
2762  pTmpSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_RL_TB, RES_FRAMEDIR));
2763  else
2764  pTmpSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, RES_FRAMEDIR));
2765 
2766  const SvxAdjustItem* pAdjust = rNode.GetSwAttrSet().GetItem(RES_PARATR_ADJUST);
2767  if ( pAdjust && (pAdjust->GetAdjust() == SvxAdjust::Left || pAdjust->GetAdjust() == SvxAdjust::Right ) )
2768  pTmpSet->Put( *pAdjust, RES_PARATR_ADJUST );
2769  }
2770  // move code for handling of numbered,
2771  // but not counted paragraphs to this place. Otherwise, the paragraph
2772  // isn't exported as numbered, but not counted, if no other attribute
2773  // is found in <pTmpSet>
2774  // #i44815# adjust numbering/indents for numbered paragraphs
2775  // without number (NO_NUMLEVEL)
2776  // #i47013# need to check rNode.GetNumRule()!=NULL as well.
2777  if ( ! rNode.IsCountedInList() && rNode.GetNumRule()!=nullptr )
2778  {
2779  // WW8 does not know numbered paragraphs without number
2780  // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
2781  // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
2782  // no numbering. Here, we will adjust the indents to match
2783  // visually.
2784 
2785  if ( !pTmpSet )
2786  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2787 
2788  // create new LRSpace item, based on the current (if present)
2789  const SfxPoolItem* pPoolItem = nullptr;
2790  pTmpSet->GetItemState(RES_LR_SPACE, true, &pPoolItem);
2791  SvxLRSpaceItem aLRSpace(
2792  ( pPoolItem == nullptr )
2793  ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE)
2794  : *static_cast<const SvxLRSpaceItem*>( pPoolItem ) );
2795 
2796  // new left margin = old left + label space
2797  const SwNumRule* pRule = rNode.GetNumRule();
2798  int nLevel = rNode.GetActualListLevel();
2799 
2800  if (nLevel < 0)
2801  nLevel = 0;
2802 
2803  if (nLevel >= MAXLEVEL)
2804  nLevel = MAXLEVEL - 1;
2805 
2806  const SwNumFormat& rNumFormat = pRule->Get( static_cast< sal_uInt16 >(nLevel) );
2807 
2808  // #i86652#
2809  if ( rNumFormat.GetPositionAndSpaceMode() ==
2811  {
2812  aLRSpace.SetTextLeft( aLRSpace.GetLeft() + rNumFormat.GetAbsLSpace() );
2813  }
2814  else
2815  {
2816  aLRSpace.SetTextLeft( aLRSpace.GetLeft() + rNumFormat.GetIndentAt() );
2817  }
2818 
2819  // new first line indent = 0
2820  // (first line indent is ignored for NO_NUMLEVEL)
2821  if (!bParaRTL)
2822  aLRSpace.SetTextFirstLineOfst( 0 );
2823 
2824  // put back the new item
2825  pTmpSet->Put( aLRSpace );
2826 
2827  // assure that numbering rule is in <pTmpSet>
2828  if (SfxItemState::SET != pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
2829  {
2830  pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
2831  }
2832  }
2833 
2834  // #i75457#
2835  // Export page break after attribute from paragraph style.
2836  // If page break attribute at the text node exist, an existing page
2837  // break after at the paragraph style hasn't got to be considered.
2838  if ( !rNode.GetpSwAttrSet() ||
2839  SfxItemState::SET != rNode.GetpSwAttrSet()->GetItemState(RES_BREAK, false) )
2840  {
2841  const SvxFormatBreakItem& rBreakAtParaStyle
2842  = ItemGet<SvxFormatBreakItem>(rNode.GetSwAttrSet(), RES_BREAK);
2843  if (rBreakAtParaStyle.GetBreak() == SvxBreak::PageAfter)
2844  {
2845  if ( !pTmpSet )
2846  {
2847  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2848  }
2849  pTmpSet->Put(rBreakAtParaStyle);
2850  }
2851  else if( pTmpSet )
2852  { // Even a pagedesc item is set, the break item can be set 'NONE',
2853  // this has to be overruled.
2854  const SwFormatPageDesc& rPageDescAtParaStyle =
2855  ItemGet<SwFormatPageDesc>( rNode, RES_PAGEDESC );
2856  if( rPageDescAtParaStyle.KnowsPageDesc() )
2857  pTmpSet->ClearItem( RES_BREAK );
2858  }
2859  }
2860 
2861  // #i76520# Emulate non-splitting tables
2862  if ( IsInTable() )
2863  {
2864  const SwTableNode* pTableNode = rNode.FindTableNode();
2865 
2866  if ( pTableNode )
2867  {
2868  const SwTable& rTable = pTableNode->GetTable();
2869  const SvxFormatKeepItem& rKeep = rTable.GetFrameFormat()->GetKeep();
2870  const bool bKeep = rKeep.GetValue();
2871  const bool bDontSplit = !(bKeep ||
2872  rTable.GetFrameFormat()->GetLayoutSplit().GetValue());
2873 
2874  if ( bKeep || bDontSplit )
2875  {
2876  // bKeep: set keep at first paragraphs in all lines
2877  // bDontSplit : set keep at first paragraphs in all lines except from last line
2878  // but only for non-complex tables
2879  const SwTableBox* pBox = rNode.GetTableBox();
2880  const SwTableLine* pLine = pBox ? pBox->GetUpper() : nullptr;
2881 
2882  if ( pLine && !pLine->GetUpper() )
2883  {
2884  // check if box is first in that line:
2885  if ( 0 == pLine->GetBoxPos( pBox ) && pBox->GetSttNd() )
2886  {
2887  // check if paragraph is first in that line:
2888  if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
2889  {
2890  bool bSetAtPara = false;
2891  if ( bKeep )
2892  bSetAtPara = true;
2893  else if ( bDontSplit )
2894  {
2895  // check if pLine isn't last line in table
2896  if ( rTable.GetTabLines().size() - rTable.GetTabLines().GetPos( pLine ) != 1 )
2897  bSetAtPara = true;
2898  }
2899 
2900  if ( bSetAtPara )
2901  {
2902  if ( !pTmpSet )
2903  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2904 
2905  const SvxFormatKeepItem aKeepItem( true, RES_KEEP );
2906  pTmpSet->Put( aKeepItem );
2907  }
2908  }
2909  }
2910  }
2911  }
2912  }
2913  }
2914 
2915  const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet();
2916  if( pNewSet )
2917  { // Para-Attrs
2918  m_pStyAttr = &rNode.GetAnyFormatColl().GetAttrSet();
2919 
2920  const SwModify* pOldMod = m_pOutFormatNode;
2921  m_pOutFormatNode = &rNode;
2922 
2923  // Pap-Attrs, so script is not necessary
2924  OutputItemSet( *pNewSet, true, false, i18n::ScriptType::LATIN, false);
2925 
2926  m_pStyAttr = nullptr;
2927  m_pOutFormatNode = pOldMod;
2928 
2929  if( pNewSet != rNode.GetpSwAttrSet() )
2930  delete pNewSet;
2931  }
2932  }
2933 
2934  // The formatting of the paragraph marker has two sources:
2935  // 1) If there are hints at the end of the paragraph, then use that.
2936  // 2) Else use the RES_CHRATR_BEGIN..RES_TXTATR_END range of the paragraph
2937  // properties.
2938  //
2939  // Exception: if there is a character style hint at the end of the
2940  // paragraph only, then still go with 2), as RES_TXTATR_CHARFMT is always
2941  // set as a hint.
2943  bool bCharFormatOnly = true;
2944  if(const SwpHints* pTextAttrs = rNode.GetpSwpHints())
2945  {
2946  for( size_t i = 0; i < pTextAttrs->Count(); ++i )
2947  {
2948  const SwTextAttr* pHt = pTextAttrs->Get(i);
2949  const sal_Int32 startPos = pHt->GetStart(); // first Attr characters
2950  const sal_Int32* endPos = pHt->End(); // end Attr characters
2951  // Check if these attributes are for the last character in the paragraph
2952  // - which means the paragraph marker. If a paragraph has 7 characters,
2953  // then properties on character 8 are for the paragraph marker
2954  if( endPos && (startPos == *endPos ) && (*endPos == rNode.GetText().getLength()) )
2955  {
2956  SAL_INFO( "sw.ww8", startPos << "startPos == endPos" << *endPos);
2957  sal_uInt16 nWhich = pHt->GetAttr().Which();
2958  SAL_INFO( "sw.ww8", "nWhich" << nWhich);
2959  if (nWhich == RES_TXTATR_AUTOFMT || nWhich == RES_TXTATR_CHARFMT)
2960  aParagraphMarkerProperties.Put(pHt->GetAttr());
2961  if (nWhich != RES_TXTATR_CHARFMT)
2962  bCharFormatOnly = false;
2963  }
2964  }
2965  }
2966  if (rNode.GetpSwAttrSet() && bCharFormatOnly)
2967  {
2968  aParagraphMarkerProperties.Put(*rNode.GetpSwAttrSet());
2969  }
2970  const SwRedlineData* pRedlineParagraphMarkerDelete = AttrOutput().GetParagraphMarkerRedline( rNode, nsRedlineType_t::REDLINE_DELETE );
2971  const SwRedlineData* pRedlineParagraphMarkerInsert = AttrOutput().GetParagraphMarkerRedline( rNode, nsRedlineType_t::REDLINE_INSERT );
2972  const SwRedlineData* pParagraphRedlineData = aAttrIter.GetParagraphLevelRedline( );
2973  AttrOutput().EndParagraphProperties(aParagraphMarkerProperties, pParagraphRedlineData, pRedlineParagraphMarkerDelete, pRedlineParagraphMarkerInsert);
2974 
2975  AttrOutput().EndParagraph( pTextNodeInfoInner );
2976  }while(*aBreakIt != rNode.GetText().getLength() && bNeedParaSplit );
2977 
2978  SAL_INFO( "sw.ww8", "</OutWW8_SwTextNode>" );
2979 }
2980 
2981 // Tables
2982 
2984 {
2985  m_rWW8Export.WriteStringAsPara( OUString() );
2986 }
2987 
2989 {
2990  bool bRet = false;
2991  const SfxPoolItem* pI;
2992  if( pSet)
2993  {
2994  bool bNoPageBreak = false;
2995  if ( SfxItemState::SET != pSet->GetItemState(RES_PAGEDESC, true, &pI)
2996  || nullptr == static_cast<const SwFormatPageDesc*>(pI)->GetPageDesc() )
2997  {
2998  bNoPageBreak = true;
2999  }
3000 
3001  if (bNoPageBreak)
3002  {
3003  if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, true, &pI))
3004  {
3005  SvxBreak eBreak = static_cast<const SvxFormatBreakItem*>(pI)->GetBreak();
3006  switch (eBreak)
3007  {
3008  case SvxBreak::PageBefore:
3009  case SvxBreak::PageAfter:
3010  bNoPageBreak = false;
3011  break;
3012  default:
3013  break;
3014  }
3015  }
3016  }
3017  bRet = bNoPageBreak;
3018  }
3019  return bRet;
3020 }
3021 
3023 {
3024  const SwSection& rSection = rSectionNode.GetSection();
3025 
3026  SwNodeIndex aIdx( rSectionNode, 1 );
3027  const SwNode& rNd = aIdx.GetNode();
3028  if ( !rNd.IsSectionNode() && !IsInTable()
3029  && rSection.GetType() != TOX_CONTENT_SECTION && rSection.GetType() != TOX_HEADER_SECTION) //No sections in table
3030  {
3031  // if the first Node inside the section has an own
3032  // PageDesc or PageBreak attribute, then don't write
3033  // here the section break
3034  sal_uLong nRstLnNum = 0;
3035  const SfxItemSet* pSet;
3036  if ( rNd.IsContentNode() )
3037  {
3038  pSet = &rNd.GetContentNode()->GetSwAttrSet();
3039  nRstLnNum = pSet->Get( RES_LINENUMBER ).GetStartValue();
3040  }
3041  else
3042  pSet = nullptr;
3043 
3044  if ( pSet && NoPageBreakSection( pSet ) )
3045  pSet = nullptr;
3046  else
3047  AttrOutput().SectionBreaks( rSectionNode );
3048 
3049  if ( !pSet )
3050  {
3051  // new Section with no own PageDesc/-Break
3052  // -> write follow section break;
3053  const SwSectionFormat* pFormat = rSection.GetFormat();
3054  ReplaceCr( msword::PageBreak ); // Indicator for Page/Section-Break
3055 
3056  // Get the page in use at the top of this section
3057  const SwPageDesc *pCurrent = SwPageDesc::GetPageDescOfNode(rNd);
3058  if (!pCurrent)
3059  pCurrent = m_pCurrentPageDesc;
3060 
3061  AppendSection( pCurrent, pFormat, nRstLnNum );
3062  }
3063  }
3064  if ( TOX_CONTENT_SECTION == rSection.GetType() )
3065  {
3066  m_bStartTOX = true;
3067  UpdateTocSectionNodeProperties(rSectionNode);
3068  }
3069 }
3070 
3071 // tdf#121561: During export of the ODT file with TOC inside into DOCX format,
3072 // the TOC title is being exported as regular paragraph. We should surround it
3073 // with <w:sdt><w:sdtPr><w:sdtContent> to make it (TOC title) recognizable
3074 // by MS Word as part of the TOC.
3076 {
3077  // check section type
3078  {
3079  const SwSection& rSection = rSectionNode.GetSection();
3080  if (TOX_CONTENT_SECTION != rSection.GetType())
3081  return;
3082 
3083  const SwTOXBase* pTOX = rSection.GetTOXBase();
3084  if (pTOX)
3085  {
3086  TOXTypes type = pTOX->GetType();
3087  if (type != TOXTypes::TOX_CONTENT)
3088  return;
3089  }
3090  }
3091 
3092  // get section node, skip toc-header node
3093  const SwSectionNode* pSectNd = &rSectionNode;
3094  {
3095  SwNodeIndex aIdxNext( *pSectNd, 1 );
3096  const SwNode& rNdNext = aIdxNext.GetNode();
3097 
3098  if (rNdNext.IsSectionNode())
3099  {
3100  const SwSectionNode* pSectNdNext = static_cast<const SwSectionNode*>(&rNdNext);
3101  if (TOX_HEADER_SECTION == pSectNdNext->GetSection().GetType() &&
3102  pSectNdNext->StartOfSectionNode()->IsSectionNode())
3103  {
3104  pSectNd = pSectNdNext;
3105  }
3106  }
3107  }
3108 
3109  // get node of the first paragraph inside TOC
3110  SwNodeIndex aIdxNext( *pSectNd, 1 );
3111  const SwNode& rNdTocPara = aIdxNext.GetNode();
3112  const SwContentNode* pNode = rNdTocPara.GetContentNode();
3113  if (!pNode)
3114  return;
3115 
3116  // put required flags into grab bag of the first node in TOC
3117  {
3118  uno::Sequence<beans::PropertyValue> aDocPropertyValues(comphelper::InitPropertySequence(
3119  {
3120  {"ooxml:CT_SdtDocPart_docPartGallery", uno::makeAny(OUString("Table of Contents"))},
3121  {"ooxml:CT_SdtDocPart_docPartUnique", uno::makeAny(OUString("true"))},
3122  }));
3123 
3124  uno::Sequence<beans::PropertyValue> aSdtPrPropertyValues(comphelper::InitPropertySequence(
3125  {
3126  {"ooxml:CT_SdtPr_docPartObj", uno::makeAny(aDocPropertyValues)},
3127  }));
3128 
3130  aGrabBag.GetGrabBag()["SdtPr"] <<= aSdtPrPropertyValues;
3131 
3132  // create temp attr set
3133  SwAttrSet aSet(pNode->GetSwAttrSet());
3134  aSet.Put(aGrabBag);
3135 
3136  // set new attr to node
3137  const_cast<SwContentNode*>(pNode)->SetAttr(aSet);
3138  }
3139 
3140  // set flag for the next node after TOC
3141  // in order to indicate that std area has been finished
3142  // see, DomainMapper::lcl_startParagraphGroup() for the same functionality during load
3143  {
3144  SwNodeIndex aEndTocNext( *rSectionNode.EndOfSectionNode(), 1 );
3145  const SwNode& rEndTocNextNode = aEndTocNext.GetNode();
3146  const SwContentNode* pNodeAfterToc = rEndTocNextNode.GetContentNode();
3147  if (pNodeAfterToc)
3148  {
3150  aGrabBag.GetGrabBag()["ParaSdtEndBefore"] <<= true;
3151 
3152  // create temp attr set
3153  SwAttrSet aSet(pNodeAfterToc->GetSwAttrSet());
3154  aSet.Put(aGrabBag);
3155 
3156  // set new attr to node
3157  const_cast<SwContentNode*>(pNodeAfterToc)->SetAttr(aSet);
3158  }
3159  }
3160 }
3161 
3162 void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum )
3163 {
3164  pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFormat, nLnNum);
3165 }
3166 
3167 // Flys
3168 
3169 void WW8AttributeOutput::OutputFlyFrame_Impl( const ww8::Frame& rFormat, const Point& rNdTopLeft )
3170 {
3171  const SwFrameFormat &rFrameFormat = rFormat.GetFrameFormat();
3172  const SwFormatAnchor& rAnch = rFrameFormat.GetAnchor();
3173 
3174  bool bUseEscher = true;
3175 
3176  if (rFormat.IsInline())
3177  {
3179  bUseEscher = eType != ww8::Frame::eGraphic && eType != ww8::Frame::eOle;
3180 
3181  /*
3182  A special case for converting some inline form controls to form fields
3183  when in winword 8+ mode
3184  */
3185  if (bUseEscher && (eType == ww8::Frame::eFormControl))
3186  {
3187  if ( m_rWW8Export.MiserableFormFieldExportHack( rFrameFormat ) )
3188  return ;
3189  }
3190  }
3191 
3192  if (bUseEscher)
3193  {
3194  // write as escher
3195  m_rWW8Export.AppendFlyInFlys(rFormat, rNdTopLeft);
3196  }
3197  else
3198  {
3199  bool bDone = false;
3200 
3201  // Fetch from node and last node the position in the section
3202  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
3203 
3204  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
3205  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
3206 
3207  if( nStt >= nEnd ) // no range, hence no valid node
3208  return;
3209 
3210  if ( !m_rWW8Export.IsInTable() && rFormat.IsInline() )
3211  {
3212  //Test to see if this textbox contains only a single graphic/ole
3213  SwTextNode* pParTextNode = rAnch.GetContentAnchor()->nNode.GetNode().GetTextNode();
3214  if ( pParTextNode && !m_rWW8Export.m_pDoc->GetNodes()[ nStt ]->IsNoTextNode() )
3215  bDone = true;
3216  }
3217  if( !bDone )
3218  {
3219 
3220  m_rWW8Export.SaveData( nStt, nEnd );
3221 
3222  Point aOffset;
3224  {
3225  /* Munge flys in fly into absolutely positioned elements for word 6 */
3226  const SwTextNode* pParTextNode = rAnch.GetContentAnchor()->nNode.GetNode().GetTextNode();
3227  const SwRect aPageRect = pParTextNode->FindPageFrameRect();
3228 
3229  aOffset = rFrameFormat.FindLayoutRect().Pos();
3230  aOffset -= aPageRect.Pos();
3231 
3232  m_rWW8Export.m_pFlyOffset = &aOffset;
3233  m_rWW8Export.m_eNewAnchorType = RndStdIds::FLY_AT_PAGE;
3234  }
3235 
3236  m_rWW8Export.m_pParentFrame = &rFormat;
3237  if (
3238  m_rWW8Export.IsInTable() &&
3239  (RndStdIds::FLY_AT_PAGE != rAnch.GetAnchorId()) &&
3240  !m_rWW8Export.m_pDoc->GetNodes()[ nStt ]->IsNoTextNode()
3241  )
3242  {
3243  // note: set Flag bOutTable again,
3244  // because we deliver the normal content of the table cell, and no border
3245  // ( Flag was deleted above in aSaveData() )
3246  m_rWW8Export.m_bOutTable = true;
3247  const OUString& aName = rFrameFormat.GetName();
3251  }
3252  else
3254 
3256  }
3257  }
3258 }
3259 
3261 {
3262  if ( !rFormat.GetContentNode() )
3263  return;
3264 
3265  const SwContentNode &rNode = *rFormat.GetContentNode();
3266  Point aLayPos;
3267 
3268  // get the Layout Node-Position
3269  if (RndStdIds::FLY_AT_PAGE == rFormat.GetFrameFormat().GetAnchor().GetAnchorId())
3270  aLayPos = rNode.FindPageFrameRect().Pos();
3271  else
3272  aLayPos = rNode.FindLayoutRect().Pos();
3273 
3274  OutputFlyFrame_Impl( rFormat, aLayPos );
3275 }
3276 
3277 // write data of any redline
3279 {
3280  if ( !pRedline )
3281  return;
3282 
3283  if ( pRedline->Next() )
3284  Redline( pRedline->Next() );
3285 
3286  static const sal_uInt16 insSprmIds[ 3 ] =
3287  {
3288  // Ids for insert // for WW8
3290  };
3291  static const sal_uInt16 delSprmIds[ 3 ] =
3292  {
3293  // Ids for delete // for WW8
3295  };
3296 
3297  const sal_uInt16* pSprmIds = nullptr;
3298  switch( pRedline->GetType() )
3299  {
3301  pSprmIds = insSprmIds;
3302  break;
3303 
3305  pSprmIds = delSprmIds;
3306  break;
3307 
3310  m_rWW8Export.pO->push_back( 7 ); // len
3311  m_rWW8Export.pO->push_back( 1 );
3314  break;
3315  default:
3316  OSL_ENSURE(false, "Unhandled redline type for export");
3317  break;
3318  }
3319 
3320  if ( pSprmIds )
3321  {
3322  m_rWW8Export.InsUInt16( pSprmIds[0] );
3323  m_rWW8Export.pO->push_back( 1 );
3324 
3325  m_rWW8Export.InsUInt16( pSprmIds[1] );
3327 
3328  m_rWW8Export.InsUInt16( pSprmIds[2] );
3330  }
3331 }
3332 
3334 {
3335  switch ( rNode.GetNodeType() )
3336  {
3337  case SwNodeType::Text:
3338  OutputTextNode( *rNode.GetTextNode() );
3339  break;
3340  case SwNodeType::Grf:
3341  OutputGrfNode( *rNode.GetGrfNode() );
3342  break;
3343  case SwNodeType::Ole:
3344  OutputOLENode( *rNode.GetOLENode() );
3345  break;
3346  default:
3347  SAL_WARN("sw.ww8", "Unhandled node, type == " << static_cast<int>(rNode.GetNodeType()) );
3348  break;
3349  }
3350 }
3351 
3352 
3353 WW8Ruby::WW8Ruby(const SwTextNode& rNode, const SwFormatRuby& rRuby, const MSWordExportBase& rExport ):
3354  m_nJC(0),
3355  m_cDirective(0),
3356  m_nRubyHeight(0),
3357  m_nBaseHeight(0)
3358 {
3359  switch ( rRuby.GetAdjustment() )
3360  {
3361  case css::text::RubyAdjust_LEFT:
3362  m_nJC = 3;
3363  m_cDirective = 'l';
3364  break;
3365  case css::text::RubyAdjust_CENTER:
3366  //defaults to 0
3367  break;
3368  case css::text::RubyAdjust_RIGHT:
3369  m_nJC = 4;
3370  m_cDirective = 'r';
3371  break;
3372  case css::text::RubyAdjust_BLOCK:
3373  m_nJC = 1;
3374  m_cDirective = 'd';
3375  break;
3376  case css::text::RubyAdjust_INDENT_BLOCK:
3377  m_nJC = 2;
3378  m_cDirective = 'd';
3379  break;
3380  default:
3381  OSL_ENSURE( false,"Unhandled Ruby justification code" );
3382  break;
3383  }
3384 
3385  if ( rRuby.GetPosition() == css::text::RubyPosition::INTER_CHARACTER )
3386  {
3387  m_nJC = 5;
3388  m_cDirective = 0;
3389  }
3390 
3391  /*
3392  MS needs to know the name and size of the font used in the ruby item,
3393  but we could have written it in a mixture of asian and western
3394  scripts, and each of these can be a different font and size than the
3395  other, so we make a guess based upon the first character of the text,
3396  defaulting to asian.
3397  */
3398  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
3399  sal_uInt16 nRubyScript = g_pBreakIt->GetBreakIter()->getScriptType(rRuby.GetText(), 0);
3400 
3401  const SwTextRuby* pRubyText = rRuby.GetTextRuby();
3402  const SwCharFormat* pFormat = pRubyText ? pRubyText->GetCharFormat() : nullptr;
3403 
3404  if (pFormat)
3405  {
3406  const auto& rFont
3407  = ItemGet<SvxFontItem>(*pFormat, GetWhichOfScript(RES_CHRATR_FONT, nRubyScript));
3408  m_sFontFamily = rFont.GetFamilyName();
3409 
3410  const auto& rHeight = ItemGet<SvxFontHeightItem>(
3411  *pFormat, GetWhichOfScript(RES_CHRATR_FONTSIZE, nRubyScript));
3412  m_nRubyHeight = rHeight.GetHeight();
3413  }
3414  else
3415  {
3416  /*Get defaults if no formatting on ruby text*/
3417 
3418  const SfxItemPool* pPool = rNode.GetSwAttrSet().GetPool();
3419  pPool = pPool ? pPool : &rExport.m_pDoc->GetAttrPool();
3420 
3421 
3422  const auto& rFont
3423  = DefaultItemGet<SvxFontItem>(*pPool, GetWhichOfScript(RES_CHRATR_FONT, nRubyScript));
3424  m_sFontFamily = rFont.GetFamilyName();
3425 
3426  const auto& rHeight = DefaultItemGet<SvxFontHeightItem>(
3427  *pPool, GetWhichOfScript(RES_CHRATR_FONTSIZE, nRubyScript));
3428  m_nRubyHeight = rHeight.GetHeight();
3429  }
3430 
3431  if (pRubyText)
3432  nRubyScript
3433  = g_pBreakIt->GetBreakIter()->getScriptType(rNode.GetText(), pRubyText->GetStart());
3434  else
3435  nRubyScript = i18n::ScriptType::ASIAN;
3436 
3437  const OUString &rText = rNode.GetText();
3438  sal_uInt16 nScript = i18n::ScriptType::LATIN;
3439 
3440  if (!rText.isEmpty())
3441  nScript = g_pBreakIt->GetBreakIter()->getScriptType(rText, 0);
3442 
3443  sal_uInt16 nWhich = GetWhichOfScript(RES_CHRATR_FONTSIZE, nScript);
3444  auto& rHeightItem = static_cast<const SvxFontHeightItem&>(rExport.GetItem(nWhich));
3445  m_nBaseHeight = rHeightItem.GetHeight();
3446 }
3447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long GetLeft() const
bool GetValue() const
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:960
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
virtual void WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner=ww8::WW8TableNodeInfoInner::Pointer_t())=0
SvxBreak
sal_Int32 & GetStart()
start position
Definition: txatbase.hxx:77
OUString GetSnippet(const OUString &rStr, sal_Int32 nCurrentPos, sal_Int32 nLen) const
Definition: wrtw8nds.cxx:1676
TOXTypes
Definition: toxe.hxx:39
Exporter of the binary Word file formats.
Definition: wrtww8.hxx:963
virtual AttributeOutputBase & AttrOutput() const =0
Access to the attribute output class.
virtual void OutputOLENode(const SwOLENode &)=0
Output SwOLENode.
bool Insert(const SvxTabStop &rTab)
sal_uLong GetIndex() const
Definition: node.hxx:282
const OUString & GetBaseURL() const
Definition: shellio.hxx:440
virtual void AppendSmartTags(SwTextNode &)
Definition: wrtww8.hxx:693
virtual const OUString & GetName() const =0
std::unique_ptr< ww::bytes > pO
Buffer.
Definition: wrtww8.hxx:966
void GetCurrentItems(ww::bytes &rItems) const
Definition: wrtw8nds.cxx:795
bool m_bLinkedTextboxesHelperInitialized
Definition: wrtww8.hxx:508
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
sal_uInt16 AddRedlineAuthor(std::size_t nId)
Definition: wrtww8.cxx:1680
bool IsSaveRelFSys() const
virtual void FormatDrop(const SwTextNode &rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner)=0
const SwFormatLayoutSplit & GetLayoutSplit(bool=true) const
Definition: fmtlsplt.hxx:46
Marks a position in the document model.
Definition: pam.hxx:35
void OutSwString(const OUString &, sal_Int32 nStt, sal_Int32 nLen)
Definition: wrtww8.cxx:1859
bool GetWholeWord() const
Definition: paratr.hxx:92
bool IsSectionNode() const
Definition: node.hxx:644
#define RES_CHRATR_CJK_LANGUAGE
Definition: hintids.hxx:92
std::unique_ptr< WW8Fib > pFib
File Information Block.
Definition: wrtww8.hxx:970
virtual void SectionBreaks(const SwNode &rNode)=0
Called in order to output section breaks.
ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
Get the Frames anchored to a given node.
const SfxPoolItem & GetItem(sal_uInt16 nWhich) const
Definition: wrtww8.cxx:802
static const SwPageDesc * GetPageDescOfNode(const SwNode &rNd)
Given a SwNode return the pagedesc in use at that location.
Definition: pagedesc.cxx:311
const RedlineType_t REDLINE_FORMAT
OUString & GetRefName()
Definition: fmtrfmrk.hxx:66
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SvxAdjust GetAdjust() const
sal_uInt8 SVBT16[2]
virtual void EndParagraphProperties(const SfxItemSet &rParagraphMarkerProperties, const SwRedlineData *pRedlineData, const SwRedlineData *pRedlineParagraphMarkerDeleted, const SwRedlineData *pRedlineParagraphMarkerInserted)=0
Called after we end outputting the attributes.
#define ODF_OLE_PARAM
sal_Char GetDirective()
#define RES_CHRATR_FONTSIZE
Definition: hintids.hxx:76
SwOLENode * GetOLENode()
Inline methods from Node.hxx.
Definition: ndole.hxx:157
void WriteStringAsPara(const OUString &rText)
Definition: wrtww8.cxx:1802
SwTableBox * GetTableBox() const
If node is in a table return the respective table box.
Definition: node.cxx:745
const sal_uInt16 sprmPWr
Definition: sprmids.hxx:381
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:78
#define RES_TXTATR_CJK_RUBY
Definition: hintids.hxx:143
RndStdIds m_eNewAnchorType
Definition: wrtww8.hxx:515
bool m_bAddFootnoteTab
Definition: wrtww8.hxx:565
const OUString & GetText() const
Definition: ndtxt.hxx:211
OUString const & GetPrimaryKey() const
Definition: tox.hxx:604
#define RES_PARATR_GRABBAG
Definition: hintids.hxx:179
#define ODF_PAGEREF
#define RES_TXTATR_METAFIELD
Definition: hintids.hxx:139
const SwFormatDrop & mrSwFormatDrop
Definition: wrtww8.hxx:1490
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:219
std::string GetValue
const SwRedlineData * Next() const
Definition: redline.hxx:148
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: node.cxx:1158
short GetTextFirstLineOfst() const
const sal_uInt16 sprmCDttmRMarkDel
Definition: sprmids.hxx:328
std::multimap< sal_Int32, OUString > m_aBookmarksOfParagraphEnd
const SwNumFormat * GetNumFormat(sal_uInt16 i) const
Definition: number.cxx:93
OUString GetURLPath(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
SwNodeIndex nNode
Definition: pam.hxx:37
virtual bool AnalyzeURL(const OUString &rURL, const OUString &rTarget, OUString *pLinkURL, OUString *pMark) override
Definition: wrtw8nds.cxx:964
std::size_t GetAuthor() const
Definition: redline.hxx:145
const sal_uInt16 sprmPDxaFromText
Definition: sprmids.hxx:393
SvxBreak GetBreak() const
virtual void Redline(const SwRedlineData *pRedline) override
Output redlining.
Definition: wrtw8nds.cxx:3278
const SwRedlineData * GetParagraphLevelRedline()
Definition: wrtw8nds.cxx:1431
std::vector< sal_uInt8 > bytes
Definition: types.hxx:27
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:284
sal_uInt8 GetLines() const
Definition: paratr.hxx:86
sal_uIntPtr sal_uLong
virtual void EndRuby(const SwTextNode &rNode, sal_Int32 nPos)=0
Output ruby end.
static void WriteString8(SvStream &rStrm, const OUString &rStr, bool bAddZero, rtl_TextEncoding eCodeSet)
Definition: wrtww8.cxx:1789
#define RES_FRAMEDIR
Definition: hintids.hxx:225
const SwRedlineData * GetParagraphMarkerRedline(const SwTextNode &rNode, RedlineType_t aRedlineType)
Definition: ww8atr.cxx:5466
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:322
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2633
const SwPosition * GetMark() const
Definition: pam.hxx:209
const SwAttrSet * m_pStyAttr
Definition: wrtww8.hxx:529
const SvxFrameDirectionItem & GetFrameDir(bool=true) const
Definition: frmatr.hxx:94
const SwPageDesc * FindPageDesc(size_t *pPgDescNdIdx=nullptr) const
Search PageDesc with which this node is formatted.
Definition: node.cxx:466
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:402
rtl_TextEncoding meChrSet
Definition: wrtww8.hxx:1480
SwFrameFormat & GetFirstMaster()
Definition: pagedesc.hxx:218
bool MiserableFormFieldExportHack(const SwFrameFormat &rFrameFormat)
Definition: wrtw8esh.cxx:363
Provides access to the marks of a document.
bool m_bOutPageDescs
PageDescs (section properties) are being written.
Definition: wrtww8.hxx:546
#define ODF_FORMCHECKBOX
bool mbCharIsRTL
Definition: wrtww8.hxx:1482
const sal_uInt16 sprmCHps
Definition: sprmids.hxx:302
virtual void StartRuby(const SwTextNode &rNode, sal_Int32 nPos, const SwFormatRuby &rRuby)=0
Output ruby start.
virtual void OutputLinkedOLE(const OUString &)=0
sal_uInt16 FirstWhich()
#define ODF_CODE_PARAM
std::stack< sal_Int32 > m_aCurrentCharPropStarts
To remember the position in a run.
Definition: wrtww8.hxx:465
#define RES_CHRATR_FONT
Definition: hintids.hxx:75
bool NeedSectionBreak(const SwNode &rNd) const
Definition: wrtw8nds.cxx:2067
bool HasDummyChar() const
Definition: txatbase.hxx:96
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
void SetTextLeft(const long nL, const sal_uInt16 nProp=100)
SwNode & GetNode() const
Definition: ndindex.hxx:118
const OUString & GetName() const
Definition: numrule.hxx:221
bool GetNewAbsURL(OUString const &rTheRelURIRef, INetURLObject *pTheAbsURIRef) const
Point * m_pFlyOffset
Definition: wrtww8.hxx:514
const std::shared_ptr< SfxItemSet > & GetStyleHandle() const
Definition: fmtautofmt.hxx:48
SvxFrameDirection
static OUString GetRelURL(OUString const &rTheBaseURIRef, OUString const &rTheAbsURIRef, EncodeMechanism eEncodeMechanism=EncodeMechanism::WasEncoded, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
SwSectionFormat * GetFormat()
Definition: section.hxx:337
SvxFrameDirection GetTextDirection(const SwPosition &rPos, const Point *pPt=nullptr) const
Definition: doclay.cxx:1614
sal_uInt16 m_nStyleBeforeFly
style number of the node
Definition: wrtww8.hxx:476
void Pos(const Point &rNew)
Definition: swrect.hxx:167
bool AreListLevelIndentsApplicable() const
Determines, if the list level indent attributes can be applied to the paragraph.
Definition: ndtxt.cxx:4412
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1348
virtual void StartRunProperties()=0
Called before we start outputting the attributes.
WW8_CP Fc2Cp(sal_uLong nFc) const
Definition: wrtww8.hxx:1080
const SwTOXType * GetTOXType() const
Definition: tox.hxx:542
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
#define RES_TXTATR_CHARFMT
Definition: hintids.hxx:142
sal_uInt16 Which() const
Definition: txatbase.hxx:105
void Set_UInt32(sal_uInt8 *&p, sal_uInt32 n)
Definition: ww8struc.hxx:51
virtual sal_Int32 getAnnotationMarksCount() const =0
void OutputItemSet(const SfxItemSet &rSet, bool bPapFormat, bool bChpFormat, sal_uInt16 nScript, bool bExportParentItemSet)
Use OutputItem() on an item set according to the parameters.
Definition: ww8atr.cxx:256
void AppendFlyInFlys(const ww8::Frame &rFrameFormat, const Point &rNdTopLeft)
Definition: wrtw8esh.cxx:980
bool operator()(const ww8::Frame &rOne, const ww8::Frame &rTwo) const
Definition: wrtw8nds.cxx:173
The class that does all the actual DOCX export-related work.
Definition: docxexport.hxx:67
SfxMedium * GetMedia()
Definition: wrtww8.hxx:955
#define RES_TXTATR_END
Definition: hintids.hxx:158
SVL_DLLPUBLIC OUString simpleNormalizedMakeRelative(OUString const &baseUriReference, OUString const &uriReference)
virtual const SfxPoolItem * HasTextItem(sal_uInt16 nWhich) const override
Definition: wrtw8nds.cxx:754
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:50
OUString FieldString(ww::eField eIndex)
Definition: ww8atr.cxx:2579
virtual ExportFormat GetExportFormat() const =0
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4097
std::shared_ptr< SvxBrushItem > TrueFrameBgBrush(const SwFrameFormat &rFlyFormat) const
Definition: wrtw8nds.cxx:1627
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
sal_uInt32 m_nBaseHeight
size_type size() const
Definition: swtable.hxx:74
sal_uInt16 NextWhich()
IMarkVector m_rSortedAnnotationMarksEnd
Definition: wrtww8.hxx:579
const sal_uInt16 sprmPDyaLine
Definition: sprmids.hxx:371
void GetPoolItems(const SfxItemSet &rSet, ww8::PoolItems &rItems, bool bExportParentItemSet)
Get the SfxPoolItems of a SfxItemSet.
virtual void SetAnchorIsLinkedToNode(bool)
If the node has an anchor linked.
ww8::FrameIter maFlyIter
Definition: wrtww8.hxx:1493
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:174
OUString PathToFileName() const
size_type size() const
Definition: docary.hxx:370
OUString BookmarkToWord(const OUString &rBookmark)
Definition: wrtw8nds.cxx:1154
const SwSection & GetSection() const
Definition: node.hxx:541
sal_Int32 WhereNext() const
Definition: wrtww8.hxx:1522
sal_uInt16 GetScript() const
Definition: wrtww8.hxx:1523
void GenerateBookmarksForSequenceField(const SwTextNode &rNode, SwWW8AttrIter &rAttrIter)
MSO uses bookmarks to reference sequence fields, so we need to generate these additional bookmarks du...
Definition: ww8atr.cxx:1987
#define ODF_HYPERLINK
const sal_uInt16 sprmCDttmRMark
Definition: sprmids.hxx:275
bool setFSysPath(OUString const &rFSysPath, FSysStyle eStyle)
void WriteText()
Iterate through the nodes and call the appropriate OutputNode() on them.
Definition: wrtww8.cxx:2710
sal_uInt16 sal_Unicode
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
const OUString & GetValue() const
Definition: fmtinfmt.hxx:75
const SwTextRuby * GetTextRuby() const
Definition: fmtruby.hxx:59
virtual void PageBreakBefore(bool bBreak)=0
Page break As a paragraph property - the paragraph should be on the next page.
bool setFinalSlash()
virtual void AppendBookmarks(const SwTextNode &rNd, sal_Int32 nCurrentPos, sal_Int32 nLen)=0
virtual void OutputField(const SwField *pField, ww::eField eFieldType, const OUString &rFieldCmd, FieldFlags nMode=FieldFlags::All) override
Write the field.
Definition: ww8atr.cxx:1734
SwWW8AttrIter(const SwWW8AttrIter &)=delete
SwNodeType GetNodeType() const
Definition: node.hxx:144
MSWordExportBase & m_rExport
Definition: wrtww8.hxx:1414
std::map< OUString, LinkedTextboxInfo > m_aLinkedTextboxesHelper
Definition: wrtww8.hxx:507
SwIndex nContent
Definition: pam.hxx:38
bool empty() const
Definition: docary.hxx:369
virtual ::sw::mark::IFieldmark * getFieldmarkFor(const SwPosition &pos) const =0
void OutputFormat(const SwFormat &rFormat, bool bPapFormat, bool bChpFormat, bool bFlyFormat=false)
Output attributes.
Definition: ww8atr.cxx:753
virtual bool StartURL(const OUString &rUrl, const OUString &rTarget) override
Output URL start.
Definition: wrtw8nds.cxx:995
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const override
#define RES_PARATR_TABSTOP
Definition: hintids.hxx:166
const OUString & GetName() const
Definition: format.hxx:111
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:34
void StartTOX(const SwSection &rSect)
Definition: ww8atr.cxx:2156
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
const sal_uInt16 sprmCFRMarkDel
Definition: sprmids.hxx:270
eField
Definition: fields.hxx:26
virtual void StartRun(const SwRedlineData *pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun=false)=0
Start of the text run.
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
const SvxBrushItem * GetCurrentPageBgBrush() const
Definition: wrtw8nds.cxx:1608
MSWordAttrIter * m_pChpIter
Definition: wrtww8.hxx:493
bool m_bInWriteEscher
Definition: wrtww8.hxx:551
bool GetAnnotationMarks(const SwTextNode &rNd, sal_Int32 nStt, sal_Int32 nEnd, IMarkVector &rArr)
Definition: wrtw8nds.cxx:1892
virtual void SetStateOfFlyFrame(FlyProcessingState)
Set the state of the Fly at current position.
virtual void StartParagraphProperties()=0
Called before we start outputting the attributes.
#define RES_UL_SPACE
Definition: hintids.hxx:197
virtual bool IsFlyProcessingPostponed()
Is processing of fly postponed ?
const SwTable & GetTable() const
Definition: node.hxx:497
virtual void ResetFlyProcessingFlag()
Reset the flag for FlyProcessing.
virtual parameter_map_t * GetParameters()=0
sal_uInt16 GetDistance() const
Definition: paratr.hxx:95
const SvxFormatKeepItem & GetKeep(bool=true) const
Definition: frmatr.hxx:86
bool HasRefToObject(sal_uInt16 nTyp, const OUString *pName, sal_uInt16 nSeqNo)
Find the reference.
Definition: ww8atr.cxx:889
const Graphic * GetGraphic(OUString const &referer=OUString()) const
#define RES_PARATR_NUMRULE
Definition: hintids.hxx:170
void WriteChar(sal_Unicode c) override
Definition: wrtww8.cxx:1896
RedlineType_t GetType() const
Definition: redline.hxx:142
INetProtocol
ww8::Frames maFlyFrames
Definition: wrtww8.hxx:1492
#define RES_CHRATR_CASEMAP
Definition: hintids.hxx:69
const sal_uInt16 sprmCIbstRMarkDel
Definition: sprmids.hxx:327
static void UpdateTocSectionNodeProperties(const SwSectionNode &rSectionNode)
Definition: wrtw8nds.cxx:3075
const RedlineType_t REDLINE_DELETE
ww8::WW8TableInfo::Pointer_t m_pTableInfo
Definition: wrtww8.hxx:472
void OutputItem(const SfxPoolItem &rHt)
Call the right virtual function according to the type of the item.
Definition: ww8atr.cxx:5130
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
SwAttrPool * GetPool() const
Definition: swatrset.hxx:190
rtl_TextEncoding GetCharSet() const
Definition: wrtww8.hxx:1525
const SwFrameFormat & GetFrameFormat() const
Get the writer SwFrameFormat that this object describes.
const SwRedlineData & GetRedlineData(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1797
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:716
const sal_uInt16 sprmPPc
Definition: sprmids.hxx:380
const T & item_cast(const SfxPoolItem &rItem)
Provide a dynamic_cast style cast for SfxPoolItems.
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:164
const OUString & GetText() const
Definition: fmtruby.hxx:61
#define RES_BACKGROUND
Definition: hintids.hxx:210
static void WriteString16(SvStream &rStrm, const OUString &rStr, bool bAddZero)
Definition: wrtww8.cxx:1766
void IterToCurrent()
Definition: wrtw8nds.cxx:179
virtual const_iterator_t getAllMarksBegin() const =0
returns a STL-like random access iterator to the begin of the sequence of marks.
const Color & GetColor() const
virtual sal_uLong ReplaceCr(sal_uInt8 nChar)=0
const OUString & GetAlternativeText() const
Definition: tox.hxx:533
bool IsContentNode() const
Definition: node.hxx:628
const sal_uInt16 sprmCIstd
Definition: sprmids.hxx:287
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:443
void NextPos()
Definition: wrtww8.hxx:1512
virtual bool AnalyzeURL(const OUString &rUrl, const OUString &rTarget, OUString *pLinkURL, OUString *pMark)
Definition: wrtw8nds.cxx:911
std::unique_ptr< WW8_WrPlcPn > m_pPapPlc
Definition: wrtww8.hxx:491
sal_uInt16 GetPosition() const
Definition: fmtruby.hxx:70
const RedlineType_t REDLINE_PARAGRAPH_FORMAT
WW8Export & m_rWW8Export
Reference to the export, where to get the data from.
void OutputSectionNode(const SwSectionNode &)
Output SwSectionNode.
Definition: wrtw8nds.cxx:3022
RedlineType_t GetType(sal_uInt16 nPos=0) const
Definition: redline.hxx:225
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
Style of a layout element.
Definition: frmfmt.hxx:57
size_t Count() const
Definition: ndhints.hxx:152
#define SAL_MAX_INT32
virtual void RunText(const OUString &rText, rtl_TextEncoding eCharSet=RTL_TEXTENCODING_UTF8)=0
Output text (inside a run).
static bool isRightToLeft(LanguageType nLang)
sal_Int32 GetNextPos(SwWW8AttrIter const *pAttrIter, const SwTextNode &rNode, sal_Int32 nCurrentPos)
Get the next position in the text node to output.
Definition: wrtw8nds.cxx:1827
const sal_uInt8 ND_HAS_PREV_LAYNODE
Definition: ndtyp.hxx:63
void SplitRun(sal_Int32 nSplitEndPos)
Definition: wrtw8nds.cxx:1178
virtual ~MSWordAttrIter()
Definition: wrtw8nds.cxx:165
virtual void FormatDrop(const SwTextNode &rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner) override
Definition: wrtw8nds.cxx:1763
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:154
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void SetCurItemSet(const SfxItemSet *pS)
Setter for pISet.
Definition: wrtww8.hxx:712
std::map< sal_uInt16, const SfxPoolItem *, sw::util::ItemSort > PoolItems
STL container of SfxPoolItems (Attributes)
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
std::vector< Frame >::iterator FrameIter
STL iterator for Frames.
std::unique_ptr< WW8_WrPlcSepx > pSepx
Sections/headers/footers.
Definition: wrtww8.hxx:974
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
sal_Int32 GetAbsLSpace() const
WW8Ruby(const SwTextNode &rNode, const SwFormatRuby &rRuby, const MSWordExportBase &rExport)
Definition: wrtw8nds.cxx:3353
void NearestAnnotationMark(sal_Int32 &rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly)
Find the nearest annotation mark from the current position.
Definition: wrtw8nds.cxx:1972
void UpdatePosition(SwWW8AttrIter *pAttrIter, sal_Int32 nCurrentPos)
Update the information for GetNextPos().
Definition: wrtw8nds.cxx:1844
const SwPosition * GetPoint() const
Definition: pam.hxx:207
OUString GetURLNoMark(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
sal_uInt16 mnScript
Definition: wrtww8.hxx:1481
FlyProcessingState OutFlys(sal_Int32 nSwPos)
Definition: wrtw8nds.cxx:566
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:875
const SwTOXBase * GetTOXBase() const
Definition: section.cxx:620
const sal_uInt16 sprmCIbstRMark
Definition: sprmids.hxx:274
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
sal_uInt16 GetId(const SwNumRule &rNumRule)
Return the numeric id of the numbering rule.
Definition: wrtw8num.cxx:73
bool IsParaRTL() const
Definition: wrtww8.hxx:1524
sal_Int32 GetJC()
const SwModify * m_pOutFormatNode
Definition: wrtww8.hxx:530
virtual void OutputTextNode(SwTextNode &)
Output SwTextNode.
Definition: wrtw8nds.cxx:2093
sw::util::CharRuns maCharRuns
Definition: wrtww8.hxx:1477
void OutputContentNode(SwContentNode &)
Call the right (virtual) function according to the type of the item.
Definition: wrtw8nds.cxx:3333
bool HasContent() const
Definition: txatbase.hxx:101
virtual void ExportGrfBullet(const SwTextNode &rNd)=0
int i
void OutputSectionBreaks(const SfxItemSet *pSet, const SwNode &rNd, bool isCellOpen=false, bool isTextNodeEmpty=false)
Start new section.
Definition: ww8atr.cxx:407
SwContentNode * GetContentNode()
Definition: node.hxx:615
sal_uInt8 HasPrevNextLayNode() const
Definition: node.cxx:841
vector_type::size_type size_type
Definition: docary.hxx:331
FlyAnchors.
Definition: fmtanchr.hxx:34
sal_uInt16 GetLevel() const
Definition: tox.hxx:598
static void WriteShort(SvStream &rStrm, sal_Int16 nVal)
Definition: wrtww8.hxx:937
const ww8::Frame * m_pParentFrame
Definition: wrtww8.hxx:511
virtual WW8Export & GetExport() override
Return the right export class.
MSWordAttrIter *const pOld
Definition: wrtww8.hxx:1410
static sal_Int32 lcl_getMinPos(sal_Int32 pos1, sal_Int32 pos2)
Definition: wrtw8nds.cxx:233
The writer class that gets called for the WW8 filter.
Definition: wrtww8.hxx:906
std::size_t WriteBytes(const void *pData, std::size_t nSize)
sal_uInt32 GetRubyHeight()
virtual void StartParagraph(ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo)=0
Start of the paragraph.
Marks a character position inside a document model node.
Definition: index.hxx:37
const SfxItemSet * GetItemSet(const SfxPoolItem &rAttr)
Returns the item set associated with an character/inet/auto style.
Definition: atrstck.cxx:135
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:52
const SwRedlineData * GetRunLevelRedline(sal_Int32 nPos)
Definition: wrtw8nds.cxx:1456
#define RES_CHRATR_BEGIN
Definition: hintids.hxx:68
sal_uInt16 GetWhichOfScript(sal_uInt16 nWhich, sal_uInt16 nScript)
Definition: hints.cxx:195
const DateTime & GetTimeStamp() const
Definition: redline.hxx:147
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2814
SvxFrameDirection GetDefaultFrameDirection() const
Definition: wrtw8nds.cxx:1536
const std::map< OUString, css::uno::Any > & GetGrabBag() const
static OUString GetScheme(INetProtocol eTheScheme)
virtual void OutputField(const SwField *pField, ww::eField eFieldType, const OUString &rFieldCmd, FieldFlags nMode=FieldFlags::All)=0
Write the field.
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:366
virtual const_iterator_t getAnnotationMarksBegin() const =0
bool KnowsPageDesc() const
Definition: atrfrm.cxx:616
void OutputFlyFrame(const ww8::Frame &rFormat)
Output frames.
Definition: wrtw8nds.cxx:3260
virtual void EndRuby(const SwTextNode &rNode, sal_Int32 nPos) override
Output ruby end.
Definition: wrtw8nds.cxx:840
size
virtual void WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner=ww8::WW8TableNodeInfoInner::Pointer_t()) override
Definition: wrtww8.cxx:1886
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:398
#define RES_TXTATR_TOXMARK
Definition: hintids.hxx:137
Marks a node in the document model.
Definition: ndindex.hxx:31
#define RES_LINENUMBER
Definition: hintids.hxx:221
SwWW8Writer & GetWriter() const
Definition: wrtww8.hxx:1155
bool IsEndNode() const
Definition: node.hxx:632
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:693
void StartCommentOutput(const OUString &rName)
Definition: ww8atr.cxx:1872
static void CorrectTabStopInSet(SfxItemSet &rSet, sal_Int32 nAbsLeft)
Definition: ww8atr.cxx:665
const sal_uInt16 sprmCPropRMark90
Definition: sprmids.hxx:316
const SvxFormatBreakItem & GetBreak(bool=true) const
Definition: frmatr.hxx:90
bool HasSwAttrSet() const
Definition: node.hxx:444
void InsUInt16(sal_uInt16 n)
Definition: wrtww8.hxx:1127
sal_Char m_cDirective
sal_uInt8 GetChars() const
Definition: paratr.hxx:89
DocumentType const eType
virtual void OutputGrfNode(const SwGrfNode &)=0
Output SwGrfNode.
virtual void TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo)=0
const sal_Unicode cMarkSeparator
Definition: swtypes.hxx:137
const SwRangeRedline * pCurRedline
Definition: wrtww8.hxx:1484
SvxNumPositionAndSpaceMode GetPositionAndSpaceMode() const
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:356
void InsUInt32(sal_uInt32 n)
Definition: wrtww8.hxx:1129
#define RES_TXTATR_INETFMT
Definition: hintids.hxx:141
void EndTOX(const SwSection &rSect, bool bCareEnd=true)
Definition: ww8atr.cxx:2476
SwTableLines & GetTabLines()
Definition: swtable.hxx:198
OUString GetName() const
IMarkVector m_rSortedAnnotationMarksStart
Definition: wrtww8.hxx:578
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:110
sal_Int16 GetWordFirstLineOffset(const SwNumFormat &rFormat)
Definition: wrtw8num.cxx:121
const SwPosition * Start() const
Definition: pam.hxx:212
sal_uInt32 GetBaseHeight()
void GetSortedBookmarks(const SwTextNode &rNd, sal_Int32 nCurrentPos, sal_Int32 nLen)
Definition: wrtw8nds.cxx:2034
OUString const & GetFontFamily()
#define RES_LR_SPACE
Definition: hintids.hxx:196
const SwPageDesc * GetFollow() const
Definition: pagedesc.hxx:245
virtual void EndRunProperties(const SwRedlineData *pRedlineData)=0
Called after we end outputting the attributes.
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
virtual void AppendAnnotationMarks(const SwTextNode &rNd, sal_Int32 nCurrentPos, sal_Int32 nLen)=0
DocxExportFilter & GetFilter()
Definition: docxexport.hxx:121
static ww::eField lcl_getFieldId(const IFieldmark *pFieldmark)
Definition: wrtw8nds.cxx:140
CharRuns GetPseudoCharRuns(const SwTextNode &rTextNd)
Collect the ranges of Text which share.
long GetIndentAt() const
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:460
bool operator()(const IMark *pOneB, const IMark *pTwoB) const
Definition: wrtw8nds.cxx:1931
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
void fillSoftPageBreakList(SwSoftPageBreakList &rBreak) const
const SwTextNode & rNd
Definition: wrtww8.hxx:1475
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:83
virtual void RTLAndCJKState(bool bIsRTL, sal_uInt16 nScript)=0
Export the state of RTL/CJK.
const RedlineType_t REDLINE_INSERT
const OUString & getFileUrl() const
#define ODF_UNHANDLED
const css::lang::Locale & GetLocale(const LanguageType aLang)
Definition: breakit.hxx:67
SwFrameFormat & GetMaster()
Definition: pagedesc.hxx:216
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
void OutSwFormatRefMark(const SwFormatRefMark &rAttr)
Definition: wrtw8nds.cxx:1171
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
sal_Int32 GetDropLen(sal_Int32 nWishLen) const
nWishLen = 0 indicates that we want a whole word
Definition: txtdrop.cxx:124
void SetCaseMap(const SvxCaseMap eNew)
virtual void WriteBookmarkInActParagraph(const OUString &rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos) override
Insert a bookmark inside the currently processed paragraph.
Definition: wrtw8nds.cxx:989
sal_uInt32 m_nRubyHeight
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:173
const sal_uInt16 sprmCFFldVanish
Definition: sprmids.hxx:272
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:367
IMarkVector m_rSortedBookmarksEnd
Definition: wrtww8.hxx:577
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:439
#define RES_TXTATR_AUTOFMT
Definition: hintids.hxx:140
OUString BookmarkToWriter(const OUString &rBookmark)
Definition: wrtw8nds.cxx:1165
#define ODF_TOC
const SwPageDesc * m_pCurrentPageDesc
Definition: wrtww8.hxx:488
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:76
SfxItemState
OUString GetExpandText(SwRootFrame const *pLayout, const sal_Int32 nIdx=0, const sal_Int32 nLen=-1, const bool bWithNum=false, const bool bAddSpaceAfterListLabelStr=false, const bool bWithSpacesForLevel=false, const ExpandMode eAdditionalMode=ExpandMode::ExpandFootnote) const
add 4th optional parameter indicating, when that a spa...
Definition: ndtxt.cxx:3384
void SetTextFirstLineOfst(const short nF, const sal_uInt16 nProp=100)
virtual void StartRuby(const SwTextNode &rNode, sal_Int32 nPos, const SwFormatRuby &rRuby) override
Output ruby start.
Definition: wrtw8nds.cxx:806
virtual const SfxPoolItem & GetItem(sal_uInt16 nWhich) const override
Definition: wrtw8nds.cxx:800
static OUString & TruncateBookmark(OUString &rRet)
Definition: wrtw8nds.cxx:847
bool GetDropSize(int &rFontHeight, int &rDropHeight, int &rDropDescent) const
Passes back info needed on the dropcap dimensions.
Definition: txtdrop.cxx:230
virtual sal_Int32 getAllMarksCount() const =0
returns the number of marks.
SvStream & Strm() const
Definition: wrtww8.hxx:1156
OUString GetPath() const
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
OUString const & GetSecondaryKey() const
Definition: tox.hxx:610
virtual bool AllowPostponedTextInTable() const
Text in tables can be postponed except for .doc.
Definition: wrtww8.hxx:673
std::set< sal_Int32 > SwSoftPageBreakList
Definition: wrtww8.hxx:138
FlyProcessingState
enum to state the present state of the fly
Definition: wrtww8.hxx:170
#define RES_CHRATR_CTL_LANGUAGE
Definition: hintids.hxx:97
unsigned char sal_uInt8
const sal_uInt16 sprmCFRMarkIns
Definition: sprmids.hxx:271
const OUString & GetTargetFrame() const
Definition: fmtinfmt.hxx:89
Make exporting a Writer Frame easy.
bool IsDropCap(int nSwPos)
Definition: wrtw8nds.cxx:725
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2889
const SwContentNode * GetContentNode() const
Get the node this frame is anchored into.
bool IncludeEndOfParaCRInRedlineProperties(sal_Int32 nPos) const
Definition: wrtw8nds.cxx:1375
bool IsWatermarkFrame()
Definition: wrtw8nds.cxx:527
TOXTypes GetType() const
Definition: tox.hxx:695
sal_uInt32 DateTime2DTTM(const DateTime &rDT)
Convert from DTTM to Writer's DateTime.
#define SAL_INFO(area, stream)
SvStream & WriteUChar(unsigned char nChar)
sal_Int32 GetIndex() const
Definition: index.hxx:95
SvStream * pDataStrm
Streams for WW97 Export.
Definition: wrtww8.hxx:968
bool IsCountedInList() const
Definition: ndtxt.cxx:4240
INetProtocol GetProtocol() const
#define ODF_FORMTEXT
LanguageType GetAppLanguage()
Definition: init.cxx:760
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:208
SwNodes & GetNodes()
Definition: doc.hxx:403
const sal_uInt8 PageBreak
std::pair< OUString, sal_uLong > aBookmarkPair
Definition: wrtww8.hxx:414
sw::util::CharRuns::const_iterator maCharRunIter
Definition: wrtww8.hxx:1478
const SwPosition * End() const
Definition: pam.hxx:217
OUString CalcCaseMap(const OUString &rTxt) const
#define RES_KEEP
Definition: hintids.hxx:215
std::multimap< sal_Int32, OUString > m_aBookmarksOfParagraphStart
Bookmarks of the current paragraph.
virtual void SaveData(sal_uLong nStt, sal_uLong nEnd) override
Remember some of the members so that we can recurse in WriteText().
Definition: wrtww8.cxx:1974
The physical access to the DOCX document (for writing).
sal_uInt8 m_nTextTyp
Definition: wrtww8.hxx:540
ww8::Frames m_aFrames
Definition: wrtww8.hxx:487
const sal_Int32 * End() const
Definition: txatbase.hxx:142
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
const INetURLObject & GetURLObject() const
bool m_bOutFlyFrameAttrs
Definition: wrtww8.hxx:545
bool NearestBookmark(sal_Int32 &rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly)
Find the nearest bookmark from the current position.
Definition: wrtw8nds.cxx:1940
virtual void FieldVanish(const OUString &rText, ww::eField eType)=0
virtual bool EndURL(bool isAtEndOfParagraph)=0
Output URL end.
sal_uInt64 Tell() const
#define RES_PARATR_ADJUST
Definition: hintids.hxx:162
std::shared_ptr< WW8TableNodeInfoInner > Pointer_t
void GetSortedAnnotationMarks(const SwTextNode &rNd, sal_Int32 nCurrentPos, sal_Int32 nLen)
Definition: wrtw8nds.cxx:2001
bool m_bInWriteTOX
Definition: wrtww8.hxx:553
virtual void AppendSection(const SwPageDesc *pPageDesc, const SwSectionFormat *pFormat, sal_uLong nLnNum) override
Definition: wrtw8nds.cxx:3162
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
bool IsPlausableSingleWordSection(const SwFrameFormat &rTitleFormat, const SwFrameFormat &rFollowFormat)
See if two page formats can be expressed as a single word section.
virtual void ParagraphStyle(sal_uInt16 nStyle)=0
Output style.
bool GetBookmarks(const SwTextNode &rNd, sal_Int32 nStt, sal_Int32 nEnd, IMarkVector &rArr)
Definition: wrtw8nds.cxx:1856
sal_Int32 GetFirstLineOffset() const
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
#define RES_TXTATR_REFMARK
Definition: hintids.hxx:136
virtual const SwPosition & GetMarkEnd() const =0
static void InsUInt16(ww::bytes &rO, sal_uInt16 n)
Definition: wrtww8.cxx:1730
virtual void TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2007
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:53
TOXTypes GetType() const
Definition: tox.hxx:663
SvtSaveOptions const m_aSaveOpt
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:723
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:351
SwTableBox * GetUpper()
Definition: swtable.hxx:362
virtual bool StartURL(const OUString &rUrl, const OUString &rTarget)=0
Output URL start.
css::text::RubyAdjust GetAdjustment() const
Definition: fmtruby.hxx:73
virtual void PrepareNewPageDesc(const SfxItemSet *pSet, const SwNode &rNd, const SwFormatPageDesc *pNewPgDescFormat, const SwPageDesc *pNewPgDesc)=0
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter()
Definition: breakit.hxx:62
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:153
OString const aName
void ExportPoolItemsToCHP(ww8::PoolItems &rItems, sal_uInt16 nScript, const SvxFontItem *pFont, bool bWriteCombChars=false)
Export the pool items to attributes (through an attribute output class).
Definition: ww8atr.cxx:209
virtual OUString GetFieldname() const =0
virtual void Redline(const SwRedlineData *pRedline)=0
Output redlining.
sal_Int32 nCurrentSwPos
Definition: wrtww8.hxx:1485
#define SAL_WARN(area, stream)
const SwCharFormat * GetCharFormat() const
Definition: paratr.hxx:98
Base class for WW8Export and DocxExport.
Definition: wrtww8.hxx:453
OUString GetMark(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static OUString lcl_getFieldCode(const IFieldmark *pFieldmark)
Definition: wrtw8nds.cxx:119
sal_Int32 SearchNext(sal_Int32 nStartPos)
Definition: wrtw8nds.cxx:245
SwRedlineTable::size_type nCurRedlinePos
Definition: wrtww8.hxx:1486
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:96
bool IsExportableAttr(sal_Int32 nSwPos) const
Definition: wrtw8nds.cxx:701
SvxFrameDirection GetCurrentPageDirection() const
Right to left?
Definition: wrtw8nds.cxx:1528
const SwFormatDrop & GetSwFormatDrop() const
Definition: wrtww8.hxx:1528
virtual const SwPosition & GetMarkStart() const =0
static OUString GetBookmarkName(sal_uInt16 nTyp, const OUString *pName, sal_uInt16 nSeqNo)
Find the bookmark name.
Definition: ww8atr.cxx:925
virtual void EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner)=0
End of the paragraph.
const SwTextTOXMark * GetTextTOXMark() const
Definition: tox.hxx:137
bool mbParaIsRTL
Definition: wrtww8.hxx:1488
bool IsInline() const
Is this frame inline (as character)
WriterSource GetWriterType() const
Get the type of frame that this wraps.
SectionType GetType() const
Definition: section.hxx:171
SwGrfNode * GetGrfNode()
Definition: ndgrf.hxx:155
MSWordAttrIter(const MSWordAttrIter &)=delete
static SwTextFormatColl & lcl_getFormatCollection(MSWordExportBase &rExport, const SwTextNode *pTextNode)
Delivers the right paragraph style.
Definition: wrtw8nds.cxx:1739
virtual void WriteHyperlinkData(const ::sw::mark::IFieldmark &rFieldmark)=0
static bool NoPageBreakSection(const SfxItemSet *pSet)
Definition: wrtw8nds.cxx:2988
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
If SwFormatDrop is a Client, it is the CharFormat that describes the font for the DropCaps...
Definition: paratr.hxx:50
const sal_uInt16 sprmPDcs
Definition: sprmids.hxx:390
virtual const SwRedlineTable & GetRedlineTable() const =0
void TOXMark(const SwTextNode &rNode, const SwTOXMark &rAttr)
Definition: wrtw8nds.cxx:1219
std::vector< ::sw::mark::IMark * > IMarkVector
Used to split the runs according to the bookmarks start and ends.
Definition: wrtww8.hxx:575
virtual void AppendBookmark(const OUString &rName)=0
void EndCommentOutput(const OUString &rName)
Definition: ww8atr.cxx:1878
void ClearOverridesFromSet(const SwFormatCharFormat &rFormat, SfxItemSet &rSet)
Remove properties from an SfxItemSet which a SwFormatCharFormat overrides.
#define RES_PAGEDESC
Definition: hintids.hxx:198
#define RES_BREAK
Definition: hintids.hxx:199
void OutAttr(sal_Int32 nSwPos, bool bWriteCombinedChars)
Definition: wrtw8nds.cxx:382
virtual void RestoreData() override
Restore what was saved in SaveData().
Definition: wrtww8.cxx:1992
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
bool IsTextAttr(sal_Int32 nSwPos) const
Definition: wrtw8nds.cxx:676
void OutputFlyFrame_Impl(const ww8::Frame &rFormat, const Point &rNdTopLeft) override
Output frames - the implementation.
Definition: wrtw8nds.cxx:3169
virtual bool EndURL(bool) override
Output URL end.
Definition: wrtw8nds.cxx:1147
virtual void WriteFormData(const ::sw::mark::IFieldmark &rFieldmark)=0
Write the data of the form field.
int OutAttrWithRange(const SwTextNode &rNode, sal_Int32 nPos)
Definition: wrtw8nds.cxx:1274
SwTableLine * GetUpper()
Definition: swtable.hxx:421
sal_Int32 nPos
bool IsTextNode() const
Definition: node.hxx:636
#define RES_CHRATR_GRABBAG
Definition: hintids.hxx:111
The class MSWordAttrIter is a helper class to build the Fkp.chpx.
Definition: wrtww8.hxx:1407
std::shared_ptr< WW8TableNodeInfo > Pointer_t
static void WriteLong(SvStream &rStrm, sal_Int32 nVal)
Definition: wrtww8.hxx:940
const SwPosition & GetPosition() const
Get the position this frame is anchored at.
bool IsInTable() const
Return whether currently exported node is in table.
Definition: wrtww8.cxx:2882
bool NeedTextNodeSplit(const SwTextNode &rNd, SwSoftPageBreakList &pList) const
Definition: wrtw8nds.cxx:2085
SwFrameFormat * GetFlyFormat() const
If node is in a fly return the respective format.
Definition: node.cxx:710
aStr
SwCharFormat * GetCharFormat()
Definition: txtatr2.cxx:230
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1273
const sal_uInt16 sprmCHpsPos
Definition: sprmids.hxx:303
virtual void AppendSection(const SwPageDesc *pPageDesc, const SwSectionFormat *pFormat, sal_uLong nLnNum)=0
const sal_uInt8 ND_HAS_NEXT_LAYNODE
Definition: ndtyp.hxx:64
virtual void EndRun(const SwTextNode *pNode, sal_Int32 nPos, bool bLastRun=false)=0
End of the text run.
SwRect FindPageFrameRect() const
Definition: node.cxx:1174
virtual void EmptyParagraph() override
Empty paragraph.
Definition: wrtw8nds.cxx:2983
std::unique_ptr< WW8_WrPlcPn > m_pChpPlc
Definition: wrtww8.hxx:492
sal_uInt16 Which() const
SvxFrameDirection TrueFrameDirection(const SwFrameFormat &rFlyFormat) const
Right to left?
Definition: wrtw8nds.cxx:1575
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2686
OUString ConvertURL(const OUString &rUrl, bool bAbsoluteOut)
Definition: wrtw8nds.cxx:855
IMarkVector m_rSortedBookmarksStart
Definition: wrtww8.hxx:576
SwDoc * m_pDoc
Definition: wrtww8.hxx:567
#define ODF_ID_PARAM
virtual MSWordExportBase & GetExport()=0
Return the right export class.
static OUString encode(OUString const &rText, Part ePart, EncodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1307
std::vector< aBookmarkPair > m_aImplicitBookmarks
Definition: wrtww8.hxx:486
virtual void OutputFlyFrame_Impl(const ww8::Frame &rFormat, const Point &rNdTopLeft)=0
Output frames - the implementation.
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
#define ODF_FORMDROPDOWN
bool IsAnchorLinkedToThisNode(sal_uLong nNodePos)
Definition: wrtw8nds.cxx:547
virtual void WritePostitFieldReference()
for docx w:commentReference
virtual void FieldVanish(const OUString &rText, ww::eField eType) override
Definition: wrtw8nds.cxx:1193
OUString m_sFontFamily
virtual void OutputFKP(bool)
Output FKP (Formatted disK Page) - necessary for binary formats only.
bool RequiresImplicitBookmark()
Definition: wrtw8nds.cxx:744
Base class of the Writer document model elements.
Definition: node.hxx:79
static OUString decode(OUString const &rText, DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)