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