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