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