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