LibreOffice Module sw (master)  1
core/crsr/bookmark.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 <memory>
21 #include <bookmark.hxx>
22 #include <IDocumentUndoRedo.hxx>
24 #include <IDocumentState.hxx>
25 #include <doc.hxx>
26 #include <ndtxt.hxx>
27 #include <pam.hxx>
28 #include <swserv.hxx>
29 #include <sfx2/linkmgr.hxx>
30 #include <sfx2/viewsh.hxx>
31 #include <UndoBookmark.hxx>
32 #include <unobookmark.hxx>
33 #include <xmloff/odffields.hxx>
34 #include <libxml/xmlwriter.h>
35 #include <comphelper/random.hxx>
37 #include <sal/log.hxx>
38 #include <svl/numformat.hxx>
39 #include <svl/zforlist.hxx>
40 #include <edtwin.hxx>
41 #include <DateFormFieldButton.hxx>
44 #include <comphelper/lok.hxx>
45 #include <txtfrm.hxx>
46 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
47 #include <rtl/strbuf.hxx>
48 #include <strings.hrc>
49 
50 using namespace ::sw::mark;
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::uno;
53 
54 namespace sw::mark
55 {
56 
58  {
59  SwPosition const& rStartPos(rMark.GetMarkStart());
60  SwPosition const& rEndPos(rMark.GetMarkEnd());
61  SwNodes const& rNodes(rStartPos.nNode.GetNodes());
62  SwNodeOffset const nStartNode(rStartPos.nNode.GetIndex());
63  SwNodeOffset const nEndNode(rEndPos.nNode.GetIndex());
64  int nFields(0);
65  std::optional<SwPosition> ret;
66  for (SwNodeOffset n = nEndNode; nStartNode <= n; --n)
67  {
68  SwNode *const pNode(rNodes[n]);
69  if (pNode->IsTextNode())
70  {
71  SwTextNode & rTextNode(*pNode->GetTextNode());
72  sal_Int32 const nStart(n == nStartNode
73  ? rStartPos.nContent.GetIndex() + 1
74  : 0);
75  sal_Int32 const nEnd(n == nEndNode
76  // subtract 1 to ignore the end char
77  ? rEndPos.nContent.GetIndex() - 1
78  : rTextNode.Len());
79  for (sal_Int32 i = nEnd; nStart < i; --i)
80  {
81  const sal_Unicode c(rTextNode.GetText()[i - 1]);
82  switch (c)
83  {
85  --nFields;
86  assert(0 <= nFields);
87  break;
89  ++nFields;
90  // fields in field result could happen by manual
91  // editing, although the field update deletes them
92  break;
94  if (nFields == 0)
95  {
96  assert(!ret); // one per field
97  ret = SwPosition(rTextNode, i - 1);
98 #ifndef DBG_UTIL
99  return *ret;
100 #endif
101  }
102  break;
103  }
104  }
105  }
106  else if (pNode->IsEndNode() && !pNode->StartOfSectionNode()->IsSectionNode())
107  {
108  assert(nStartNode <= pNode->StartOfSectionIndex());
109  // fieldmark cannot overlap node section, unless it's a section
110  n = pNode->StartOfSectionIndex();
111  }
112  else
113  {
114  assert(pNode->IsNoTextNode() || pNode->IsSectionNode());
115  }
116  }
117  assert(ret); // must have found it
118  return *ret;
119  }
120 } // namespace sw::mark
121 
122 namespace
123 {
124  void lcl_FixPosition(SwPosition& rPos)
125  {
126  // make sure the position has 1) the proper node, and 2) a proper index
127  SwTextNode* pTextNode = rPos.nNode.GetNode().GetTextNode();
128  if(pTextNode == nullptr && rPos.nContent.GetIndex() > 0)
129  {
130  SAL_INFO(
131  "sw.core",
132  "illegal position: " << rPos.nContent.GetIndex()
133  << " without proper TextNode");
134  rPos.nContent.Assign(nullptr, 0);
135  }
136  else if(pTextNode != nullptr && rPos.nContent.GetIndex() > pTextNode->Len())
137  {
138  SAL_INFO(
139  "sw.core",
140  "illegal position: " << rPos.nContent.GetIndex()
141  << " is beyond " << pTextNode->Len());
142  rPos.nContent.Assign(pTextNode, pTextNode->Len());
143  }
144  }
145 
146  void lcl_AssertFieldMarksSet(const Fieldmark& rField,
147  const sal_Unicode aStartMark,
148  const sal_Unicode aEndMark)
149  {
150  if (aEndMark != CH_TXT_ATR_FORMELEMENT)
151  {
152  SwPosition const& rStart(rField.GetMarkStart());
153  assert(rStart.nNode.GetNode().GetTextNode()->GetText()[rStart.nContent.GetIndex()] == aStartMark); (void) rStart; (void) aStartMark;
154  SwPosition const sepPos(sw::mark::FindFieldSep(rField));
155  assert(sepPos.nNode.GetNode().GetTextNode()->GetText()[sepPos.nContent.GetIndex()] == CH_TXT_ATR_FIELDSEP); (void) sepPos;
156  }
157  else
158  { // must be m_pPos1 < m_pPos2 because of asymmetric SplitNode update
159  assert(rField.GetMarkPos().nContent.GetIndex() + 1 == rField.GetOtherMarkPos().nContent.GetIndex());
160  }
161  SwPosition const& rEnd(rField.GetMarkEnd());
162  assert(rEnd.nNode.GetNode().GetTextNode()->GetText()[rEnd.nContent.GetIndex() - 1] == aEndMark); (void) rEnd;
163  }
164 
165  void lcl_SetFieldMarks(Fieldmark& rField,
166  SwDoc& io_rDoc,
167  const sal_Unicode aStartMark,
168  const sal_Unicode aEndMark,
169  SwPosition const*const pSepPos)
170  {
172  OUString startChar(aStartMark);
173  if (aEndMark != CH_TXT_ATR_FORMELEMENT
174  && rField.GetMarkStart() == rField.GetMarkEnd())
175  {
176  // do only 1 InsertString call - to expand existing bookmarks at the
177  // position over the whole field instead of just aStartMark
178  startChar += OUStringChar(CH_TXT_ATR_FIELDSEP) + OUStringChar(aEndMark);
179  }
180 
181  SwPosition start = rField.GetMarkStart();
182  if (aEndMark != CH_TXT_ATR_FORMELEMENT)
183  {
184  SwPaM aStartPaM(start);
185  io_rDoc.getIDocumentContentOperations().InsertString(aStartPaM, startChar);
186  start.nContent -= startChar.getLength(); // restore, it was moved by InsertString
187  // do not manipulate via reference directly but call SetMarkStartPos
188  // which works even if start and end pos were the same
189  rField.SetMarkStartPos( start );
190  SwPosition& rEnd = rField.GetMarkEnd(); // note: retrieve after
191  // setting start, because if start==end it can go stale, see SetMarkPos()
192  assert(pSepPos == nullptr || (start < *pSepPos && *pSepPos <= rEnd));
193  if (startChar.getLength() == 1)
194  {
195  *aStartPaM.GetPoint() = pSepPos ? *pSepPos : rEnd;
196  io_rDoc.getIDocumentContentOperations().InsertString(aStartPaM, OUString(CH_TXT_ATR_FIELDSEP));
197  if (!pSepPos || rEnd < *pSepPos)
198  { // rEnd is not moved automatically if it's same as insert pos
199  ++rEnd.nContent;
200  }
201  }
202  assert(pSepPos == nullptr || (start < *pSepPos && *pSepPos <= rEnd));
203  }
204  else
205  {
206  assert(pSepPos == nullptr);
207  }
208 
209  SwPosition& rEnd = rField.GetMarkEnd();
210  if (aEndMark && startChar.getLength() == 1)
211  {
212  SwPaM aEndPaM(rEnd);
213  io_rDoc.getIDocumentContentOperations().InsertString(aEndPaM, OUString(aEndMark));
214  if (aEndMark != CH_TXT_ATR_FORMELEMENT)
215  {
216  ++rEnd.nContent; // InsertString didn't move non-empty mark
217  }
218  else
219  { // InsertString moved the mark's end, not its start
220  assert(rField.GetMarkPos().nContent.GetIndex() + 1 == rField.GetOtherMarkPos().nContent.GetIndex());
221  }
222  }
223  lcl_AssertFieldMarksSet(rField, aStartMark, aEndMark);
224 
226  }
227 
228  void lcl_RemoveFieldMarks(const Fieldmark& rField,
229  SwDoc& io_rDoc,
230  const sal_Unicode aStartMark,
231  const sal_Unicode aEndMark)
232  {
234 
235  const SwPosition& rStart = rField.GetMarkStart();
236  SwTextNode const*const pStartTextNode = rStart.nNode.GetNode().GetTextNode();
237  assert(pStartTextNode);
238  if (aEndMark != CH_TXT_ATR_FORMELEMENT)
239  {
240  (void) pStartTextNode;
241  // check this before start / end because of the +1 / -1 ...
242  SwPosition const sepPos(sw::mark::FindFieldSep(rField));
243  io_rDoc.GetDocumentContentOperationsManager().DeleteDummyChar(rStart, aStartMark);
245  }
246 
247  const SwPosition& rEnd = rField.GetMarkEnd();
248  SwTextNode *const pEndTextNode = rEnd.nNode.GetNode().GetTextNode();
249  assert(pEndTextNode);
250  const sal_Int32 nEndPos = (rEnd == rStart)
251  ? rEnd.nContent.GetIndex()
252  : rEnd.nContent.GetIndex() - 1;
253  assert(pEndTextNode->GetText()[nEndPos] == aEndMark);
254  SwPosition const aEnd(*pEndTextNode, nEndPos);
255  io_rDoc.GetDocumentContentOperationsManager().DeleteDummyChar(aEnd, aEndMark);
256 
258  }
259 
260  auto InvalidatePosition(SwPosition const& rPos) -> void
261  {
262  SwUpdateAttr const aHint(rPos.nContent.GetIndex(), rPos.nContent.GetIndex(), 0);
264  }
265 }
266 
267 namespace sw::mark
268 {
270  const OUString& rName)
271  : m_pPos1(new SwPosition(*(aPaM.GetPoint())))
272  , m_aName(rName)
273  {
274  m_pPos1->nContent.SetMark(this);
275  lcl_FixPosition(*m_pPos1);
276  if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint()))
277  {
279  lcl_FixPosition(*m_pPos2);
280  }
281  }
282 
283  // For fieldmarks, the CH_TXT_ATR_FIELDSTART and CH_TXT_ATR_FIELDEND
284  // themselves are part of the covered range. This is guaranteed by
285  // TextFieldmark::InitDoc/lcl_AssureFieldMarksSet.
286  bool MarkBase::IsCoveringPosition(const SwPosition& rPos) const
287  {
288  return GetMarkStart() <= rPos && rPos < GetMarkEnd();
289  }
290 
291  void MarkBase::SetMarkPos(const SwPosition& rNewPos)
292  {
293  std::make_unique<SwPosition>(rNewPos).swap(m_pPos1);
294  m_pPos1->nContent.SetMark(this);
295  }
296 
298  {
299  std::make_unique<SwPosition>(rNewPos).swap(m_pPos2);
300  m_pPos2->nContent.SetMark(this);
301  }
302 
303  OUString MarkBase::ToString( ) const
304  {
305  return "Mark: ( Name, [ Node1, Index1 ] ): ( " + m_aName + ", [ "
306  + OUString::number( sal_Int32(GetMarkPos().nNode.GetIndex()) ) + ", "
307  + OUString::number( GetMarkPos().nContent.GetIndex( ) ) + " ] )";
308  }
309 
311  {
312  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("MarkBase"));
313  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(m_aName.toUtf8().getStr()));
314  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("markPos"));
315  GetMarkPos().dumpAsXml(pWriter);
316  (void)xmlTextWriterEndElement(pWriter);
317  if (IsExpanded())
318  {
319  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("otherMarkPos"));
320  GetOtherMarkPos().dumpAsXml(pWriter);
321  (void)xmlTextWriterEndElement(pWriter);
322  }
323  (void)xmlTextWriterEndElement(pWriter);
324  }
325 
327  { }
328 
329  OUString MarkBase::GenerateNewName(std::u16string_view rPrefix)
330  {
331  static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
332 
333  if (bHack)
334  {
335  static sal_Int64 nIdCounter = SAL_CONST_INT64(6000000000);
336  return rPrefix + OUString::number(nIdCounter++);
337  }
338  else
339  {
340  static OUString sUniquePostfix;
341  static sal_Int32 nCount = SAL_MAX_INT32;
342  if(nCount == SAL_MAX_INT32)
343  {
344  unsigned int const n(comphelper::rng::uniform_uint_distribution(0,
345  std::numeric_limits<unsigned int>::max()));
346  sUniquePostfix = "_" + OUString::number(n);
347  nCount = 0;
348  }
349  // putting the counter in front of the random parts will speed up string comparisons
350  return rPrefix + OUString::number(nCount++) + sUniquePostfix;
351  }
352  }
353 
354  void MarkBase::SwClientNotify(const SwModify&, const SfxHint& rHint)
355  {
356  CallSwClientNotify(rHint);
357  if (rHint.GetId() != SfxHintId::SwLegacyModify)
358  return;
359  auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
360  if(RES_REMOVE_UNO_OBJECT == pLegacy->GetWhich())
361  { // invalidate cached uno object
362  SetXBookmark(uno::Reference<text::XTextContent>(nullptr));
363  }
364  }
365 
367  {
368  }
369 
371  : MarkBase(rPaM, MarkBase::GenerateNewName(u"__NavigatorReminder__"))
372  { }
373 
374  UnoMark::UnoMark(const SwPaM& aPaM)
375  : MarkBase(aPaM, MarkBase::GenerateNewName(u"__UnoMark__"))
376  { }
377 
379  : MarkBase(aPaM, MarkBase::GenerateNewName(u"__DdeLink__"))
380  { }
381 
383  {
384  m_aRefObj = pObj;
385  }
386 
388  {
389  if(m_aRefObj.is())
391  }
392 
394  {
395  if( m_aRefObj.is() )
396  {
397  if(m_aRefObj->HasDataLinks())
398  {
400  p->SendDataChanged();
401  }
403  }
404  }
405 
407  const vcl::KeyCode& rCode,
408  const OUString& rName)
409  : DdeBookmark(aPaM)
410  , m_aCode(rCode)
411  , m_bHidden(false)
412  {
413  m_aName = rName;
414  }
415 
416  void Bookmark::InitDoc(SwDoc& io_rDoc,
417  sw::mark::InsertMode const, SwPosition const*const)
418  {
419  if (io_rDoc.GetIDocumentUndoRedo().DoesUndo())
420  {
422  std::make_unique<SwUndoInsBookmark>(*this));
423  }
424  io_rDoc.getIDocumentState().SetModified();
426  }
427 
429  {
431 
432  if (io_rDoc.GetIDocumentUndoRedo().DoesUndo())
433  {
435  std::make_unique<SwUndoDeleteBookmark>(*this));
436  }
437  io_rDoc.getIDocumentState().SetModified();
439  }
440 
441  // invalidate text frames in case it's hidden or Formatting Marks enabled
443  {
444  InvalidatePosition(GetMarkPos());
445  if (IsExpanded())
446  {
447  InvalidatePosition(GetOtherMarkPos());
448  }
449  }
450 
451  void Bookmark::Hide(bool const isHide)
452  {
453  if (isHide != m_bHidden)
454  {
455  m_bHidden = isHide;
457  }
458  }
459 
460  void Bookmark::SetHideCondition(OUString const& rHideCondition)
461  {
462  if (m_sHideCondition != rHideCondition)
463  {
464  m_sHideCondition = rHideCondition;
465  // don't eval condition here yet - probably only needed for
466  // UI editing condition and that doesn't exist yet
467  }
468  }
469 
471  {
472  SwDoc& rDoc( GetMarkPos().GetDoc() );
473  return rDoc.GetXmlIdRegistry();
474  }
475 
477  {
478  SwDoc& rDoc( GetMarkPos().GetDoc() );
479  return rDoc.IsClipBoard();
480  }
481 
482  bool Bookmark::IsInUndo() const
483  {
484  return false;
485  }
486 
488  {
489  SwDoc& rDoc( GetMarkPos().GetDoc() );
490  return !rDoc.IsInHeaderFooter( GetMarkPos().nNode );
491  }
492 
493  uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject()
494  {
495  SwDoc& rDoc( GetMarkPos().GetDoc() );
496  const uno::Reference< rdf::XMetadatable> xMeta(
497  SwXBookmark::CreateXBookmark(rDoc, this), uno::UNO_QUERY);
498  return xMeta;
499  }
500 
502  : MarkBase(rPaM, MarkBase::GenerateNewName(u"__Fieldmark__"))
503  {
504  if(!IsExpanded())
506  }
507 
508  void Fieldmark::SetMarkStartPos( const SwPosition& rNewStartPos )
509  {
510  if ( GetMarkPos( ) <= GetOtherMarkPos( ) )
511  return SetMarkPos( rNewStartPos );
512  else
513  return SetOtherMarkPos( rNewStartPos );
514  }
515 
516  OUString Fieldmark::ToString( ) const
517  {
518  return "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " + m_aName + ", "
519  + m_aFieldname + ", [ " + OUString::number( sal_Int32(GetMarkPos().nNode.GetIndex( )) )
520  + ", " + OUString::number( GetMarkPos( ).nContent.GetIndex( ) ) + " ], ["
521  + OUString::number( sal_Int32(GetOtherMarkPos().nNode.GetIndex( )) ) + ", "
522  + OUString::number( GetOtherMarkPos( ).nContent.GetIndex( ) ) + " ] ) ";
523  }
524 
526  {
527  // TODO: Does exist a better solution to trigger a format of the
528  // fieldmark portion? If yes, please use it.
529  SwPaM aPaM( GetMarkPos(), GetOtherMarkPos() );
530  aPaM.InvalidatePaM();
531  }
532 
534  {
535  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("Fieldmark"));
536  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fieldname"), BAD_CAST(m_aFieldname.toUtf8().getStr()));
537  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fieldHelptext"), BAD_CAST(m_aFieldHelptext.toUtf8().getStr()));
538  MarkBase::dumpAsXml(pWriter);
539  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("parameters"));
540  for (auto& rParam : m_vParams)
541  {
542  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("parameter"));
543  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(rParam.first.toUtf8().getStr()));
544  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(comphelper::anyToString(rParam.second).toUtf8().getStr()));
545  (void)xmlTextWriterEndElement(pWriter);
546  }
547  (void)xmlTextWriterEndElement(pWriter);
548  (void)xmlTextWriterEndElement(pWriter);
549  }
550 
551  TextFieldmark::TextFieldmark(const SwPaM& rPaM, const OUString& rName)
552  : Fieldmark(rPaM)
553  {
554  if ( !rName.isEmpty() )
555  m_aName = rName;
556  }
557 
559  sw::mark::InsertMode const eMode, SwPosition const*const pSepPos)
560  {
561  if (eMode == sw::mark::InsertMode::New)
562  {
563  lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, pSepPos);
564  }
565  else
566  {
567  lcl_AssertFieldMarksSet(*this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
568  }
569  }
570 
572  {
573  IDocumentUndoRedo & rIDUR(rDoc.GetIDocumentUndoRedo());
574  if (rIDUR.DoesUndo())
575  {
576  rIDUR.AppendUndo(std::make_unique<SwUndoDelTextFieldmark>(*this));
577  }
578  ::sw::UndoGuard const ug(rIDUR); // prevent SwUndoDeletes
579  lcl_RemoveFieldMarks(*this, rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
580  // notify layouts to unhide - for the entire fieldmark, as in InitDoc()
581  SwPaM const tmp(GetMarkPos(), GetOtherMarkPos());
583  }
584 
586  : Fieldmark(rPaM)
587  { }
588 
590  sw::mark::InsertMode const eMode, SwPosition const*const pSepPos)
591  {
592  assert(pSepPos == nullptr);
593  if (eMode == sw::mark::InsertMode::New)
594  {
595  lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT, pSepPos);
596  }
597  else
598  {
599  lcl_AssertFieldMarksSet(*this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
600  }
601  }
602 
604  {
605  IDocumentUndoRedo & rIDUR(rDoc.GetIDocumentUndoRedo());
606  if (rIDUR.DoesUndo())
607  {
608  rIDUR.AppendUndo(std::make_unique<SwUndoDelNoTextFieldmark>(*this));
609  }
610  ::sw::UndoGuard const ug(rIDUR); // prevent SwUndoDeletes
611  lcl_RemoveFieldMarks(*this, rDoc,
613  }
614 
615 
617  : NonTextFieldmark(rPaM)
618  { }
619 
620  void CheckboxFieldmark::SetChecked(bool checked)
621  {
622  if ( IsChecked() != checked )
623  {
624  (*GetParameters())[OUString(ODF_FORMCHECKBOX_RESULT)] <<= checked;
625  // mark document as modified
626  SwDoc& rDoc( GetMarkPos().GetDoc() );
628  }
629  }
630 
632  {
633  bool bResult = false;
634  parameter_map_t::const_iterator pResult = GetParameters()->find(OUString(ODF_FORMCHECKBOX_RESULT));
635  if(pResult != GetParameters()->end())
636  pResult->second >>= bResult;
637  return bResult;
638  }
639 
641  : NonTextFieldmark(rPaM)
642  , m_pButton(nullptr)
643  {
644  }
645 
647  {
649  }
650 
652  {
653  if(m_pButton)
655  }
656 
659  {
660  }
661 
663  {
664  }
665 
667  {
668  if(pEditWin)
669  {
670  if(!m_pButton)
673  m_pButton->Show();
674  }
675  }
676 
678  {
680  }
681 
682  void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea)
683  {
684  m_aPortionPaintArea = rPortionPaintArea;
685  if(m_pButton)
686  {
687  m_pButton->Show();
689  }
690  }
691 
693  {
695  return;
696 
697  if (!pViewShell || pViewShell->isLOKMobilePhone())
698  return;
699 
701  return;
702 
703  OStringBuffer sPayload;
704  sPayload = OString::Concat("{\"action\": \"show\","
705  " \"type\": \"drop-down\", \"textArea\": \"") +
706  m_aPortionPaintArea.SVRect().toString() + "\",";
707  // Add field params to the message
708  sPayload.append(" \"params\": { \"items\": [");
709 
710  // List items
711  auto pParameters = this->GetParameters();
712  auto pListEntriesIter = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
713  css::uno::Sequence<OUString> vListEntries;
714  if (pListEntriesIter != pParameters->end())
715  {
716  pListEntriesIter->second >>= vListEntries;
717  for (const OUString& sItem : std::as_const(vListEntries))
718  sPayload.append("\"" + OUStringToOString(sItem, RTL_TEXTENCODING_UTF8) + "\", ");
719  sPayload.setLength(sPayload.getLength() - 2);
720  }
721  sPayload.append("], ");
722 
723  // Selected item
724  auto pSelectedItemIter = pParameters->find(ODF_FORMDROPDOWN_RESULT);
725  sal_Int32 nSelection = -1;
726  if (pSelectedItemIter != pParameters->end())
727  {
728  pSelectedItemIter->second >>= nSelection;
729  }
730  sPayload.append("\"selected\": \"" + OString::number(nSelection) + "\", ");
731 
732  // Placeholder text
733  sPayload.append("\"placeholderText\": \"" + OUStringToOString(SwResId(STR_DROP_DOWN_EMPTY_LIST), RTL_TEXTENCODING_UTF8) + "\"}}");
734  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.toString().getStr());
735  }
736 
738  {
739  OString sPayload = "{\"action\": \"hide\", \"type\": \"drop-down\"}";
740  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.getStr());
741  }
742 
745  , m_pNumberFormatter(nullptr)
746  , m_pDocumentContentOperationsManager(nullptr)
747  {
748  }
749 
751  {
752  }
753 
755  sw::mark::InsertMode eMode, SwPosition const*const pSepPos)
756  {
759  if (eMode == sw::mark::InsertMode::New)
760  {
761  lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, pSepPos);
762  }
763  else
764  {
765  lcl_AssertFieldMarksSet(*this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
766  }
767  }
768 
770  {
771  IDocumentUndoRedo & rIDUR(rDoc.GetIDocumentUndoRedo());
772  if (rIDUR.DoesUndo())
773  {
774  // TODO does this need a 3rd Undo class?
775  rIDUR.AppendUndo(std::make_unique<SwUndoDelTextFieldmark>(*this));
776  }
777  ::sw::UndoGuard const ug(rIDUR); // prevent SwUndoDeletes
778  lcl_RemoveFieldMarks(*this, rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
779  // notify layouts to unhide - for the entire fieldmark, as in InitDoc()
780  SwPaM const tmp(GetMarkPos(), GetOtherMarkPos());
782  }
783 
785  {
786  if(pEditWin)
787  {
788  if(!m_pButton)
791  m_pButton->CalcPosAndSize(aPaintArea);
792  m_pButton->Show();
793  }
794  }
795 
796  void DateFieldmark::SetPortionPaintAreaStart(const SwRect& rPortionPaintArea)
797  {
798  if (rPortionPaintArea.IsEmpty())
799  return;
800 
801  m_aPaintAreaStart = rPortionPaintArea;
803  }
804 
805  void DateFieldmark::SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea)
806  {
807  if (rPortionPaintArea.IsEmpty())
808  return;
809 
810  if(m_aPaintAreaEnd == rPortionPaintArea &&
812  return;
813 
814  m_aPaintAreaEnd = rPortionPaintArea;
815  if(m_pButton)
816  {
817  m_pButton->Show();
819  m_pButton->CalcPosAndSize(aPaintArea);
821  }
823  }
824 
825  OUString DateFieldmark::GetContent() const
826  {
827  const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode();
828  SwPosition const sepPos(sw::mark::FindFieldSep(*this));
829  const sal_Int32 nStart(sepPos.nContent.GetIndex());
830  const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex());
831 
832  OUString sContent;
833  if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() &&
834  nEnd > nStart + 2)
835  sContent = pTextNode->GetText().copy(nStart + 1, nEnd - nStart - 2);
836  return sContent;
837  }
838 
839  void DateFieldmark::ReplaceContent(const OUString& sNewContent)
840  {
842  return;
843 
844  const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode();
845  SwPosition const sepPos(sw::mark::FindFieldSep(*this));
846  const sal_Int32 nStart(sepPos.nContent.GetIndex());
847  const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex());
848 
849  if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() &&
850  nEnd > nStart + 2)
851  {
852  SwPaM aFieldPam(GetMarkStart().nNode, nStart + 1,
853  GetMarkStart().nNode, nEnd - 1);
854  m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false);
855  }
856  else
857  {
858  SwPaM aFieldStartPam(GetMarkStart().nNode, nStart + 1);
859  m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent);
860  }
861 
862  }
863 
864  std::pair<bool, double> DateFieldmark::GetCurrentDate() const
865  {
866  // Check current date param first
867  std::pair<bool, double> aResult = ParseCurrentDateParam();
868  if(aResult.first)
869  return aResult;
870 
872  bool bFoundValidDate = false;
873  double dCurrentDate = 0;
874  OUString sDateFormat;
875  auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
876  if (pResult != pParameters->end())
877  {
878  pResult->second >>= sDateFormat;
879  }
880 
881  OUString sLang;
882  pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
883  if (pResult != pParameters->end())
884  {
885  pResult->second >>= sLang;
886  }
887 
888  // Get current content of the field
889  OUString sContent = GetContent();
890 
891  sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
892  if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
893  {
894  sal_Int32 nCheckPos = 0;
896  m_pNumberFormatter->PutEntry(sDateFormat,
897  nCheckPos,
898  nType,
899  nFormat,
900  LanguageTag(sLang).getLanguageType());
901  }
902 
903  if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
904  {
905  bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sContent, nFormat, dCurrentDate);
906  }
907  return std::pair<bool, double>(bFoundValidDate, dCurrentDate);
908  }
909 
910  void DateFieldmark::SetCurrentDate(double fDate)
911  {
912  // Replace current content with the selected date
914 
915  // Also save the current date in a standard format
917  (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= GetDateInStandardDateFormat(fDate);
918  }
919 
920  OUString DateFieldmark::GetDateInStandardDateFormat(double fDate) const
921  {
922  OUString sCurrentDate;
924  if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
925  {
926  sal_Int32 nCheckPos = 0;
928  OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
929  m_pNumberFormatter->PutEntry(sFormat,
930  nCheckPos,
931  nType,
932  nFormat,
934  }
935 
936  if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
937  {
938  const Color* pCol = nullptr;
939  m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentDate, &pCol, false);
940  }
941  return sCurrentDate;
942  }
943 
944  std::pair<bool, double> DateFieldmark::ParseCurrentDateParam() const
945  {
946  bool bFoundValidDate = false;
947  double dCurrentDate = 0;
948 
950  auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
951  OUString sCurrentDate;
952  if (pResult != pParameters->end())
953  {
954  pResult->second >>= sCurrentDate;
955  }
956  if(!sCurrentDate.isEmpty())
957  {
959  if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
960  {
961  sal_Int32 nCheckPos = 0;
963  OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
964  m_pNumberFormatter->PutEntry(sFormat,
965  nCheckPos,
966  nType,
967  nFormat,
969  }
970 
971  if(nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
972  {
973  bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate);
974  }
975  }
976  return std::pair<bool, double>(bFoundValidDate, dCurrentDate);
977  }
978 
979 
980  OUString DateFieldmark::GetDateInCurrentDateFormat(double fDate) const
981  {
982  // Get current date format and language
983  OUString sDateFormat;
985  auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
986  if (pResult != pParameters->end())
987  {
988  pResult->second >>= sDateFormat;
989  }
990 
991  OUString sLang;
992  pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
993  if (pResult != pParameters->end())
994  {
995  pResult->second >>= sLang;
996  }
997 
998  // Fill the content with the specified format
999  OUString sCurrentContent;
1000  sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
1001  if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
1002  {
1003  sal_Int32 nCheckPos = 0;
1005  OUString sFormat = sDateFormat;
1006  m_pNumberFormatter->PutEntry(sFormat,
1007  nCheckPos,
1008  nType,
1009  nFormat,
1010  LanguageTag(sLang).getLanguageType());
1011  }
1012 
1013  if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
1014  {
1015  const Color* pCol = nullptr;
1016  m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentContent, &pCol, false);
1017  }
1018  return sCurrentContent;
1019  }
1020 
1022  {
1023  std::pair<bool, double> aResult = ParseCurrentDateParam();
1024  if(!aResult.first)
1025  return;
1026 
1027  // Current date became invalid
1028  if(GetDateInCurrentDateFormat(aResult.second) != GetContent())
1029  {
1031  (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString();
1032  }
1033  }
1034 }
1035 
1036 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetMarkStartPos(const SwPosition &rNewStartPos)
virtual void Hide(bool rHide) override
virtual std::pair< bool, double > GetCurrentDate() const override
bool is() const
virtual void InitDoc(SwDoc &io_rDoc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
DateFieldmark(const SwPaM &rPaM)
static void SendLOKHideMessage(const SfxViewShell *pViewShell)
std::map< OUString, css::uno::Any > parameter_map_t
Definition: IMark.hxx:94
Marks a position in the document model.
Definition: pam.hxx:36
bool IsSectionNode() const
Definition: node.hxx:654
bool isLOKMobilePhone() const
bool IsChecked() const override
OUString m_aName
virtual void ShowButton(SwEditWin *pEditWin) override
const OUString & GetText() const
Definition: ndtxt.hxx:218
virtual bool IsInUndo() const override
virtual void ReplaceContent(const OUString &sNewContent) override
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1410
constexpr OUStringLiteral ODF_FORMCHECKBOX_RESULT
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_REMOVE_UNO_OBJECT(181)
SwNodeOffset StartOfSectionIndex() const
Definition: node.hxx:683
SwNodeIndex nNode
Definition: pam.hxx:38
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:277
virtual void SetModified()=0
Must be called manually at changes of format.
void disposeAndClear()
const SwPosition * GetMark() const
Definition: pam.hxx:210
sal_Int64 n
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override
virtual void InitDoc(SwDoc &io_rDoc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
Definition: doc.hxx:187
virtual SwPosition & GetMarkStart() const override
IDocumentLinksAdministration const & getIDocumentLinksAdministration() const
Definition: doc.cxx:260
sw::DocumentContentOperationsManager * m_pDocumentContentOperationsManager
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
virtual auto InvalidateFrames() -> void override
virtual const SwPosition & GetMarkPos() const =0
SwPosition FindFieldSep(IFieldmark const &rMark)
return position of the CH_TXT_ATR_FIELDSEP for rMark
void SetChecked(bool checked) override
virtual OUString ToString() const override
SwNode & GetNode() const
Definition: ndindex.hxx:119
UnoMark(const SwPaM &rPaM)
virtual ::sfx2::IXmlIdRegistry & GetRegistry() override
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
void SetPortionPaintAreaEnd(const SwRect &rPortionPaintArea)
virtual bool IsCoveringPosition(const SwPosition &rPos) const override
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:180
virtual ~DdeBookmark() override
bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND) override
Insert string into existing text node at position rRg.Point().
SfxHintId GetId() const
TextFieldmark(const SwPaM &rPaM, const OUString &rName)
bool IsInHeaderFooter(const SwNodeIndex &rIdx) const
Definition: doclay.cxx:1550
Fieldmark with a drop down button (e.g. this button opens the date picker for a date field) ...
unsigned int uniform_uint_distribution(unsigned int a, unsigned int b)
void InvalidatePaM()
Definition: pam.cxx:1127
std::unique_ptr< SwPosition > m_pPos1
virtual bool IsExpanded() const override
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:164
Point TopLeft() const
Definition: swrect.hxx:254
virtual void InitDoc(SwDoc &io_Doc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
#define ODF_FORMDATE_CURRENTDATE_LANGUAGE
virtual SwPosition & GetMarkEnd() const override
constexpr OUStringLiteral ODF_FORMDROPDOWN_RESULT
sal_uInt16 sal_Unicode
SwIndex nContent
Definition: pam.hxx:39
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
std::unique_ptr< SwPosition > m_pPos2
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
virtual ~DropDownFieldmark() override
int nCount
void RemoveServer(SvLinkSource *rObj)
virtual void libreOfficeKitViewCallback(int nType, const char *pPayload) const override
std::pair< bool, double > ParseCurrentDateParam() const
constexpr OUStringLiteral ODF_FORMDATE_CURRENTDATE_FORMAT
::sfx2::IXmlIdRegistry & GetXmlIdRegistry()
Definition: docnew.cxx:814
OUString GetDateInCurrentDateFormat(double fDate) const
virtual parameter_map_t * GetParameters()=0
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
void DeleteDummyChar(SwPosition const &rPos, sal_Unicode cDummy)
virtual void DeregisterFromDoc(SwDoc &rDoc)
bool IsEmpty() const
Definition: swrect.hxx:304
virtual bool DoesUndo() const =0
Is Undo enabled?
Bookmark(const SwPaM &rPaM, const vcl::KeyCode &rCode, const OUString &rName)
virtual void ShowButton(SwEditWin *pEditWin) override
void SetRefObject(SwServerObject *pObj)
Point BottomRight() const
Definition: swrect.hxx:266
constexpr OUStringLiteral ODF_FORMDROPDOWN_LISTENTRY
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
static css::uno::Reference< css::text::XTextContent > CreateXBookmark(SwDoc &rDoc,::sw::mark::IMark *pBookmark)
Definition: unobkm.cxx:157
T * get() const
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
virtual void AppendUndo(std::unique_ptr< SwUndo > pUndo)=0
Add new Undo action.
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
#define SAL_MAX_INT32
int i
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:133
virtual void ReleaseDoc(SwDoc &rDoc) override
const SwPosition * GetPoint() const
Definition: pam.hxx:208
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:59
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override
virtual void DeregisterFromDoc(SwDoc &io_rDoc) override
::sw::DocumentContentOperationsManager const & GetDocumentContentOperationsManager() const
Definition: doc.cxx:325
virtual void ReleaseDoc(SwDoc &rDoc) override
void CalcPosAndSize(const SwRect &rPortionPaintArea)
virtual void ReleaseDoc(SwDoc &rDoc) override
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
void SetNoServer()
Definition: swserv.cxx:249
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:206
virtual auto InvalidateFrames() -> void
virtual ~MarkBase() override
float u
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:182
SvNumberFormatter * m_pNumberFormatter
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:394
DdeBookmark(const SwPaM &rPaM)
virtual css::uno::Reference< css::rdf::XMetadatable > MakeUnoObject() override
bool IsNoTextNode() const
Definition: node.hxx:658
SvNumFormatType
bool IsEndNode() const
Definition: node.hxx:642
sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge=LANGUAGE_DONTKNOW)
void SetPortionPaintAreaStart(const SwRect &rPortionPaintArea)
static OUString GenerateNewName(std::u16string_view rPrefix)
DropDownFieldmark(const SwPaM &rPaM)
CheckboxFieldmark(const SwPaM &rPaM)
constexpr OUStringLiteral ODF_FORMDATE_DATEFORMAT_LANGUAGE
enumrange< T >::Iterator end(enumrange< T >)
virtual OUString ToString() const override
bool HasDataLinks() const
NavigatorReminder(const SwPaM &rPaM)
NonTextFieldmark(const SwPaM &rPaM)
virtual SwPosition & GetOtherMarkPos() const override
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
MarkBase(const SwPaM &rPaM, const OUString &rName)
void SendLOKShowMessage(const SfxViewShell *pViewShell)
tools::Rectangle SVRect() const
Definition: swrect.hxx:292
void SetXBookmark(css::uno::Reference< css::text::XTextContent > const &xBkmk)
void UpdateFramesForRemoveDeleteRedline(SwDoc &rDoc, SwPaM const &rPam)
virtual bool IsInContent() const override
constexpr OUStringLiteral ODF_FORMDATE_DATEFORMAT
constexpr OUStringLiteral ODF_FORMDATE_CURRENTDATE
bool IsVisible() const
virtual bool IsInClipboard() const override
#define SAL_INFO(area, stream)
virtual void RemoveButton() override
sal_Int32 GetIndex() const
Definition: index.hxx:91
bool IsClipBoard() const
Definition: doc.hxx:962
virtual SwPosition & GetMarkPos() const override
static VclPtr< reference_type > Create(Arg &&...arg)
virtual void SetMarkPos(const SwPosition &rNewPos)
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: pam.cxx:184
virtual void InitDoc(SwDoc &io_rDoc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
void * p
QPRO_FUNC_TYPE nType
void SetPortionPaintArea(const SwRect &rPortionPaintArea)
IFieldmark::parameter_map_t m_vParams
virtual const SwPosition & GetMarkEnd() const =0
virtual ~DateFieldmark() override
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:184
virtual void SetCurrentDate(double fDate) override
virtual void CallSwClientNotify(const SfxHint &rHint) const override
Definition: calbck.cxx:325
virtual OUString GetContent() const override
Fieldmark(const SwPaM &rPaM)
virtual sfx2::LinkManager & GetLinkManager()=0
virtual void SetHideCondition(const OUString &rHideCondition) override
struct _xmlTextWriter * xmlTextWriterPtr
tools::SvRef< SwServerObject > m_aRefObj
virtual const SwPosition & GetMarkStart() const =0
bool ReplaceRange(SwPaM &rPam, const OUString &rNewStr, const bool bRegExReplace) override
Replace selected range in a TextNode with string.
InsertMode
Definition: IMark.hxx:31
virtual void SetOtherMarkPos(const SwPosition &rNewPos)
rtl::OString toString() const
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:183
bool IsTextNode() const
Definition: node.hxx:646
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
virtual void Invalidate() override
virtual IFieldmark::parameter_map_t * GetParameters() override
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:864
virtual const SwPosition & GetOtherMarkPos() const =0
OUString anyToString(uno::Any const &value)
bool m_bDetectedRangeSegmentation false
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Base class of the Writer document model elements.
Definition: node.hxx:81
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
virtual OUString GetDateInStandardDateFormat(double fDate) const override