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