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 <utility>
34#include <xmloff/odffields.hxx>
35#include <libxml/xmlwriter.h>
36#include <comphelper/random.hxx>
39#include <sal/log.hxx>
40#include <svl/numformat.hxx>
41#include <svl/zforlist.hxx>
42#include <edtwin.hxx>
46#include <comphelper/lok.hxx>
47#include <txtfrm.hxx>
48#include <LibreOfficeKit/LibreOfficeKitEnums.h>
49#include <rtl/strbuf.hxx>
50#include <strings.hrc>
51#include <tools/json_writer.hxx>
52
53using namespace ::sw::mark;
54using namespace ::com::sun::star;
55using namespace ::com::sun::star::uno;
56
57namespace sw::mark
58{
59
60 SwPosition FindFieldSep(IFieldmark const& rMark)
61 {
62 SwPosition const& rStartPos(rMark.GetMarkStart());
63 SwPosition const& rEndPos(rMark.GetMarkEnd());
64 SwNodes const& rNodes(rStartPos.GetNodes());
65 SwNodeOffset const nStartNode(rStartPos.GetNodeIndex());
66 SwNodeOffset const nEndNode(rEndPos.GetNodeIndex());
67 int nFields(0);
68 std::optional<SwPosition> ret;
69 for (SwNodeOffset n = nEndNode; nStartNode <= n; --n)
70 {
71 SwNode *const pNode(rNodes[n]);
72 if (pNode->IsTextNode())
73 {
74 SwTextNode & rTextNode(*pNode->GetTextNode());
75 sal_Int32 const nStart(n == nStartNode
76 ? rStartPos.GetContentIndex() + 1
77 : 0);
78 sal_Int32 const nEnd(n == nEndNode
79 // subtract 1 to ignore the end char
80 ? rEndPos.GetContentIndex() - 1
81 : rTextNode.Len());
82 for (sal_Int32 i = nEnd; nStart < i; --i)
83 {
84 const sal_Unicode c(rTextNode.GetText()[i - 1]);
85 switch (c)
86 {
88 --nFields;
89 assert(0 <= nFields);
90 break;
92 ++nFields;
93 // fields in field result could happen by manual
94 // editing, although the field update deletes them
95 break;
97 if (nFields == 0)
98 {
99 assert(!ret); // one per field
100 ret.emplace(rTextNode, i - 1);
101#ifndef DBG_UTIL
102 return *ret;
103#endif
104 }
105 break;
106 }
107 }
108 }
109 else if (pNode->IsEndNode() && !pNode->StartOfSectionNode()->IsSectionNode())
110 {
111 assert(nStartNode <= pNode->StartOfSectionIndex());
112 // fieldmark cannot overlap node section, unless it's a section
113 n = pNode->StartOfSectionIndex();
114 }
115 else
116 {
117 assert(pNode->IsNoTextNode() || pNode->IsSectionNode()
118 || (pNode->IsEndNode() && pNode->StartOfSectionNode()->IsSectionNode()));
119 }
120 }
121 assert(ret); // must have found it
122 return *ret;
123 }
124} // namespace sw::mark
125
126namespace
127{
128 void lcl_FixPosition(SwPosition& rPos)
129 {
130 // make sure the position has 1) the proper node, and 2) a proper index
131 SwTextNode* pTextNode = rPos.GetNode().GetTextNode();
132 if(pTextNode == nullptr && rPos.GetContentIndex() > 0)
133 {
134 SAL_INFO(
135 "sw.core",
136 "illegal position: " << rPos.GetContentIndex()
137 << " without proper TextNode");
138 rPos.nContent.Assign(nullptr, 0);
139 }
140 else if(pTextNode != nullptr && rPos.GetContentIndex() > pTextNode->Len())
141 {
142 SAL_INFO(
143 "sw.core",
144 "illegal position: " << rPos.GetContentIndex()
145 << " is beyond " << pTextNode->Len());
146 rPos.nContent.Assign(pTextNode, pTextNode->Len());
147 }
148 }
149
150 void lcl_AssertFieldMarksSet(const Fieldmark& rField,
151 const sal_Unicode aStartMark,
152 const sal_Unicode aEndMark)
153 {
154 if (aEndMark != CH_TXT_ATR_FORMELEMENT)
155 {
156 SwPosition const& rStart(rField.GetMarkStart());
157 assert(rStart.GetNode().GetTextNode()->GetText()[rStart.GetContentIndex()] == aStartMark); (void) rStart; (void) aStartMark;
158 SwPosition const sepPos(sw::mark::FindFieldSep(rField));
159 assert(sepPos.GetNode().GetTextNode()->GetText()[sepPos.GetContentIndex()] == CH_TXT_ATR_FIELDSEP); (void) sepPos;
160 }
161 else
162 { // must be m_pPos1 < m_pPos2 because of asymmetric SplitNode update
163 assert(rField.GetMarkPos().GetContentIndex() + 1 == rField.GetOtherMarkPos().GetContentIndex());
164 }
165 SwPosition const& rEnd(rField.GetMarkEnd());
166 assert(rEnd.GetNode().GetTextNode()->GetText()[rEnd.GetContentIndex() - 1] == aEndMark); (void) rEnd;
167 }
168
169 void lcl_SetFieldMarks(Fieldmark& rField,
170 SwDoc& io_rDoc,
171 const sal_Unicode aStartMark,
172 const sal_Unicode aEndMark,
173 SwPosition const*const pSepPos)
174 {
175 io_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::UI_REPLACE, nullptr);
176 OUString startChar(aStartMark);
177 if (aEndMark != CH_TXT_ATR_FORMELEMENT
178 && rField.GetMarkStart() == rField.GetMarkEnd())
179 {
180 // do only 1 InsertString call - to expand existing bookmarks at the
181 // position over the whole field instead of just aStartMark
182 startChar += OUStringChar(CH_TXT_ATR_FIELDSEP) + OUStringChar(aEndMark);
183 }
184
185 SwPosition start = rField.GetMarkStart();
186 if (aEndMark != CH_TXT_ATR_FORMELEMENT)
187 {
188 SwPaM aStartPaM(start);
189 io_rDoc.getIDocumentContentOperations().InsertString(aStartPaM, startChar);
190 start.AdjustContent( -startChar.getLength() ); // restore, it was moved by InsertString
191 // do not manipulate via reference directly but call SetMarkStartPos
192 // which works even if start and end pos were the same
193 rField.SetMarkStartPos( start );
194 SwPosition& rEnd = rField.GetMarkEnd(); // note: retrieve after
195 // setting start, because if start==end it can go stale, see SetMarkPos()
196 assert(pSepPos == nullptr || (start < *pSepPos && *pSepPos <= rEnd));
197 if (startChar.getLength() == 1)
198 {
199 *aStartPaM.GetPoint() = pSepPos ? *pSepPos : rEnd;
200 io_rDoc.getIDocumentContentOperations().InsertString(aStartPaM, OUString(CH_TXT_ATR_FIELDSEP));
201 if (!pSepPos || rEnd < *pSepPos)
202 { // rEnd is not moved automatically if it's same as insert pos
203 rEnd.AdjustContent(1);
204 }
205 }
206 assert(pSepPos == nullptr || (start < *pSepPos && *pSepPos <= rEnd));
207 }
208 else
209 {
210 assert(pSepPos == nullptr);
211 }
212
213 SwPosition& rEnd = rField.GetMarkEnd();
214 if (aEndMark && startChar.getLength() == 1)
215 {
216 SwPaM aEndPaM(rEnd);
217 io_rDoc.getIDocumentContentOperations().InsertString(aEndPaM, OUString(aEndMark));
218 if (aEndMark != CH_TXT_ATR_FORMELEMENT)
219 {
220 rEnd.AdjustContent(1); // InsertString didn't move non-empty mark
221 }
222 else
223 { // InsertString moved the mark's end, not its start
224 assert(rField.GetMarkPos().GetContentIndex() + 1 == rField.GetOtherMarkPos().GetContentIndex());
225 }
226 }
227 lcl_AssertFieldMarksSet(rField, aStartMark, aEndMark);
228
229 io_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::UI_REPLACE, nullptr);
230 }
231
232 void lcl_RemoveFieldMarks(const Fieldmark& rField,
233 SwDoc& io_rDoc,
234 const sal_Unicode aStartMark,
235 const sal_Unicode aEndMark)
236 {
237 io_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::UI_REPLACE, nullptr);
238
239 const SwPosition& rStart = rField.GetMarkStart();
240 SwTextNode const*const pStartTextNode = rStart.GetNode().GetTextNode();
241 assert(pStartTextNode);
242 if (aEndMark != CH_TXT_ATR_FORMELEMENT)
243 {
244 (void) pStartTextNode;
245 // check this before start / end because of the +1 / -1 ...
246 SwPosition const sepPos(sw::mark::FindFieldSep(rField));
247 io_rDoc.GetDocumentContentOperationsManager().DeleteDummyChar(rStart, aStartMark);
249 }
250
251 const SwPosition& rEnd = rField.GetMarkEnd();
252 SwTextNode *const pEndTextNode = rEnd.GetNode().GetTextNode();
253 assert(pEndTextNode);
254 const sal_Int32 nEndPos = (rEnd == rStart)
255 ? rEnd.GetContentIndex()
256 : rEnd.GetContentIndex() - 1;
257 assert(pEndTextNode->GetText()[nEndPos] == aEndMark);
258 SwPosition const aEnd(*pEndTextNode, nEndPos);
260
261 io_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::UI_REPLACE, nullptr);
262 }
263
264 auto InvalidatePosition(SwPosition const& rPos) -> void
265 {
266 SwUpdateAttr const aHint(rPos.GetContentIndex(), rPos.GetContentIndex(), 0);
267 rPos.GetNode().GetTextNode()->CallSwClientNotify(sw::LegacyModifyHint(&aHint, &aHint));
268 }
269}
270
271namespace sw::mark
272{
274 OUString aName)
275 : m_oPos1(*aPaM.GetPoint())
276 , m_aName(std::move(aName))
277 {
278 m_oPos1->SetMark(this);
279 lcl_FixPosition(*m_oPos1);
280 if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint()))
281 {
283 lcl_FixPosition(*m_oPos2);
284 }
285 }
286
288 { m_wXBookmark = xBkmk.get(); }
289
290 // For fieldmarks, the CH_TXT_ATR_FIELDSTART and CH_TXT_ATR_FIELDEND
291 // themselves are part of the covered range. This is guaranteed by
292 // TextFieldmark::InitDoc/lcl_AssureFieldMarksSet.
294 {
295 return GetMarkStart() <= rPos && rPos < GetMarkEnd();
296 }
297
298 void MarkBase::SetMarkPos(const SwPosition& rNewPos)
299 {
300 m_oPos1.emplace(rNewPos);
301 m_oPos1->SetMark(this);
302 }
303
305 {
306 m_oPos2.emplace(rNewPos);
307 m_oPos2->SetMark(this);
308 }
309
310 OUString MarkBase::ToString( ) const
311 {
312 return "Mark: ( Name, [ Node1, Index1 ] ): ( " + m_aName + ", [ "
313 + OUString::number( sal_Int32(GetMarkPos().GetNodeIndex()) ) + ", "
314 + OUString::number( GetMarkPos().GetContentIndex( ) ) + " ] )";
315 }
316
318 {
319 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("MarkBase"));
320 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(m_aName.toUtf8().getStr()));
321 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("markPos"));
322 GetMarkPos().dumpAsXml(pWriter);
323 (void)xmlTextWriterEndElement(pWriter);
324 if (IsExpanded())
325 {
326 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("otherMarkPos"));
327 GetOtherMarkPos().dumpAsXml(pWriter);
328 (void)xmlTextWriterEndElement(pWriter);
329 }
330 (void)xmlTextWriterEndElement(pWriter);
331 }
332
334 { }
335
336 OUString MarkBase::GenerateNewName(std::u16string_view rPrefix)
337 {
338 static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
339
340 if (bHack)
341 {
342 static sal_Int64 nIdCounter = SAL_CONST_INT64(6000000000);
343 return rPrefix + OUString::number(nIdCounter++);
344 }
345 else
346 {
347 static OUString sUniquePostfix;
348 static sal_Int32 nCount = SAL_MAX_INT32;
349 if(nCount == SAL_MAX_INT32)
350 {
352 std::numeric_limits<unsigned int>::max()));
353 sUniquePostfix = "_" + OUString::number(n);
354 nCount = 0;
355 }
356 // putting the counter in front of the random parts will speed up string comparisons
357 return rPrefix + OUString::number(nCount++) + sUniquePostfix;
358 }
359 }
360
361 void MarkBase::SwClientNotify(const SwModify&, const SfxHint& rHint)
362 {
363 CallSwClientNotify(rHint);
364 if (rHint.GetId() != SfxHintId::SwLegacyModify)
365 return;
366 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
367 if(RES_REMOVE_UNO_OBJECT == pLegacy->GetWhich())
368 { // invalidate cached uno object
369 SetXBookmark(nullptr);
370 }
371 }
372
374 {
375 }
376
378 : MarkBase(rPaM, MarkBase::GenerateNewName(u"__NavigatorReminder__"))
379 { }
380
382 : MarkBase(aPaM, MarkBase::GenerateNewName(u"__UnoMark__"))
383 { }
384
386 : MarkBase(aPaM, MarkBase::GenerateNewName(u"__DdeLink__"))
387 { }
388
390 {
391 m_aRefObj = pObj;
392 }
393
395 {
396 if(m_aRefObj.is())
398 }
399
401 {
402 if( m_aRefObj.is() )
403 {
404 if(m_aRefObj->HasDataLinks())
405 {
407 p->SendDataChanged();
408 }
409 m_aRefObj->SetNoServer();
410 }
411 }
412
414 const vcl::KeyCode& rCode,
415 const OUString& rName)
416 : DdeBookmark(aPaM)
417 , m_aCode(rCode)
418 , m_bHidden(false)
419 {
420 m_aName = rName;
421 }
422
424 {
425 if (!comphelper::LibreOfficeKit::isActive() || GetMarkPos().GetDoc().IsClipBoard())
426 return;
427
428 SfxViewShell* pViewShell = SfxViewShell::Current();
429 if (!pViewShell)
430 return;
431
432 OUString fieldCommand = GetName();
433 tools::JsonWriter aJson;
434 aJson.put("commandName", ".uno:DeleteBookmark");
435 aJson.put("success", true);
436 {
437 auto result = aJson.startNode("result");
438 aJson.put("DeleteBookmark", fieldCommand);
439 }
440
441 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData());
442 }
443
445 sw::mark::InsertMode const, SwPosition const*const)
446 {
447 if (io_rDoc.GetIDocumentUndoRedo().DoesUndo())
448 {
449 io_rDoc.GetIDocumentUndoRedo().AppendUndo(
450 std::make_unique<SwUndoInsBookmark>(*this));
451 }
452 io_rDoc.getIDocumentState().SetModified();
454 }
455
457 {
459
460 if (io_rDoc.GetIDocumentUndoRedo().DoesUndo())
461 {
462 io_rDoc.GetIDocumentUndoRedo().AppendUndo(
463 std::make_unique<SwUndoDeleteBookmark>(*this));
464 }
465 io_rDoc.getIDocumentState().SetModified();
467 }
468
469 // invalidate text frames in case it's hidden or Formatting Marks enabled
471 {
472 InvalidatePosition(GetMarkPos());
473 if (IsExpanded())
474 {
475 InvalidatePosition(GetOtherMarkPos());
476 }
477 }
478
479 void Bookmark::Hide(bool const isHide)
480 {
481 if (isHide != m_bHidden)
482 {
483 m_bHidden = isHide;
485 }
486 }
487
488 void Bookmark::SetHideCondition(OUString const& rHideCondition)
489 {
490 if (m_sHideCondition != rHideCondition)
491 {
492 m_sHideCondition = rHideCondition;
493 // don't eval condition here yet - probably only needed for
494 // UI editing condition and that doesn't exist yet
495 }
496 }
497
499 {
500 SwDoc& rDoc( GetMarkPos().GetDoc() );
501 return rDoc.GetXmlIdRegistry();
502 }
503
505 {
506 SwDoc& rDoc( GetMarkPos().GetDoc() );
507 return rDoc.IsClipBoard();
508 }
509
511 {
512 return false;
513 }
514
516 {
517 SwDoc& rDoc( GetMarkPos().GetDoc() );
518 return !rDoc.IsInHeaderFooter( GetMarkPos().GetNode() );
519 }
520
521 uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject()
522 {
523 SwDoc& rDoc( GetMarkPos().GetDoc() );
524 const uno::Reference< rdf::XMetadatable> xMeta(
525 SwXBookmark::CreateXBookmark(rDoc, this) );
526 return xMeta;
527 }
528
530 : MarkBase(rPaM, MarkBase::GenerateNewName(u"__Fieldmark__"))
531 {
532 if(!IsExpanded())
534 }
535
536 void Fieldmark::SetMarkStartPos( const SwPosition& rNewStartPos )
537 {
538 if ( GetMarkPos( ) <= GetOtherMarkPos( ) )
539 return SetMarkPos( rNewStartPos );
540 else
541 return SetOtherMarkPos( rNewStartPos );
542 }
543
544 OUString Fieldmark::ToString( ) const
545 {
546 return "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " + m_aName + ", "
547 + m_aFieldname + ", [ " + OUString::number( sal_Int32(GetMarkPos().GetNodeIndex( )) )
548 + ", " + OUString::number( GetMarkPos( ).GetContentIndex( ) ) + " ], ["
549 + OUString::number( sal_Int32(GetOtherMarkPos().GetNodeIndex( )) ) + ", "
550 + OUString::number( GetOtherMarkPos( ).GetContentIndex( ) ) + " ] ) ";
551 }
552
554 {
555 // TODO: Does exist a better solution to trigger a format of the
556 // fieldmark portion? If yes, please use it.
557 SwPaM aPaM( GetMarkPos(), GetOtherMarkPos() );
558 aPaM.InvalidatePaM();
559 }
560
562 {
563 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("Fieldmark"));
564 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fieldname"), BAD_CAST(m_aFieldname.toUtf8().getStr()));
565 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fieldHelptext"), BAD_CAST(m_aFieldHelptext.toUtf8().getStr()));
566 MarkBase::dumpAsXml(pWriter);
567 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("parameters"));
568 for (auto& rParam : m_vParams)
569 {
570 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("parameter"));
571 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(rParam.first.toUtf8().getStr()));
572 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(comphelper::anyToString(rParam.second).toUtf8().getStr()));
573 (void)xmlTextWriterEndElement(pWriter);
574 }
575 (void)xmlTextWriterEndElement(pWriter);
576 (void)xmlTextWriterEndElement(pWriter);
577 }
578
579 TextFieldmark::TextFieldmark(const SwPaM& rPaM, const OUString& rName)
580 : Fieldmark(rPaM)
581 , m_pDocumentContentOperationsManager(nullptr)
582 {
583 if ( !rName.isEmpty() )
584 m_aName = rName;
585 }
586
588 {
589 if (!comphelper::LibreOfficeKit::isActive() || GetMarkPos().GetDoc().IsClipBoard())
590 return;
591
592 SfxViewShell* pViewShell = SfxViewShell::Current();
593 if (!pViewShell)
594 return;
595
596 OUString fieldCommand;
597 (*GetParameters())[OUString(ODF_CODE_PARAM)] >>= fieldCommand;
598 tools::JsonWriter aJson;
599 aJson.put("commandName", ".uno:DeleteTextFormField");
600 aJson.put("success", true);
601 {
602 auto result = aJson.startNode("result");
603 aJson.put("DeleteTextFormField", fieldCommand);
604 }
605
606 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.extractData());
607 }
608
610 sw::mark::InsertMode const eMode, SwPosition const*const pSepPos)
611 {
614 {
615 lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, pSepPos);
616 }
617 else
618 {
619 lcl_AssertFieldMarksSet(*this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
620 }
621 }
622
624 {
625 IDocumentUndoRedo & rIDUR(rDoc.GetIDocumentUndoRedo());
626 if (rIDUR.DoesUndo())
627 {
628 rIDUR.AppendUndo(std::make_unique<SwUndoDelTextFieldmark>(*this));
629 }
630 ::sw::UndoGuard const ug(rIDUR); // prevent SwUndoDeletes
631 lcl_RemoveFieldMarks(*this, rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
632 // notify layouts to unhide - for the entire fieldmark, as in InitDoc()
633 SwPaM const tmp(GetMarkPos(), GetOtherMarkPos());
635 }
636
638 {
639 const SwTextNode& rTextNode = *GetMarkEnd().GetNode().GetTextNode();
640 SwPosition const sepPos(sw::mark::FindFieldSep(*this));
641 const sal_Int32 nStart(sepPos.GetContentIndex());
642 const sal_Int32 nEnd(GetMarkEnd().GetContentIndex());
643
644 OUString sContent;
645 const sal_Int32 nLen = rTextNode.GetText().getLength();
646 if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2)
647 sContent = rTextNode.GetText().copy(nStart + 1, nEnd - nStart - 2);
648
649 return sContent;
650 }
651
652 void TextFieldmark::ReplaceContent(const OUString& sNewContent)
653 {
655 return;
656
657 SwPosition const sepPos(sw::mark::FindFieldSep(*this));
658 const sal_Int32 nStart(sepPos.GetContentIndex());
659 const sal_Int32 nEnd(GetMarkEnd().GetContentIndex());
660
661 const sal_Int32 nLen = GetMarkEnd().GetNode().GetTextNode()->GetText().getLength();
662 if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2)
663 {
664 SwPaM aFieldPam(GetMarkStart().GetNode(), nStart + 1,
665 GetMarkStart().GetNode(), nEnd - 1);
666 m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false);
667 }
668 else
669 {
670 SwPaM aFieldStartPam(GetMarkStart().GetNode(), nStart + 1);
671 m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent);
672 }
673 Invalidate();
674 }
675
677 : Fieldmark(rPaM)
678 { }
679
681 sw::mark::InsertMode const eMode, SwPosition const*const pSepPos)
682 {
683 assert(pSepPos == nullptr);
685 {
686 lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT, pSepPos);
687 }
688 else
689 {
690 lcl_AssertFieldMarksSet(*this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
691 }
692 }
693
695 {
696 IDocumentUndoRedo & rIDUR(rDoc.GetIDocumentUndoRedo());
697 if (rIDUR.DoesUndo())
698 {
699 rIDUR.AppendUndo(std::make_unique<SwUndoDelNoTextFieldmark>(*this));
700 }
701 ::sw::UndoGuard const ug(rIDUR); // prevent SwUndoDeletes
702 lcl_RemoveFieldMarks(*this, rDoc,
704 }
705
706
707 CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM, const OUString& rName)
708 : NonTextFieldmark(rPaM)
709 {
710 if (!rName.isEmpty())
711 m_aName = rName;
712 }
713
715 {
716 if ( IsChecked() != checked )
717 {
718 (*GetParameters())[OUString(ODF_FORMCHECKBOX_RESULT)] <<= checked;
719 // mark document as modified
720 SwDoc& rDoc( GetMarkPos().GetDoc() );
722 }
723 }
724
726 {
727 bool bResult = false;
728 parameter_map_t::const_iterator pResult = GetParameters()->find(OUString(ODF_FORMCHECKBOX_RESULT));
729 if(pResult != GetParameters()->end())
730 pResult->second >>= bResult;
731 return bResult;
732 }
733
735 {
736 return IsChecked() ? "1" : "0";
737 }
738
739 void CheckboxFieldmark::ReplaceContent(const OUString& sNewContent)
740 {
741 SetChecked(sNewContent.toBoolean());
742 Invalidate();
743 }
744
746 : NonTextFieldmark(rPaM)
747 , m_pButton(nullptr)
748 {
749 }
750
752 {
754 }
755
757 {
758 if(m_pButton)
760 }
761
763 {
764 if (!m_pButton)
765 return;
766
767 m_pButton->Invalidate();
768 m_pButton->LaunchPopup();
769 }
770
771 DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM, const OUString& rName)
773 {
774 if (!rName.isEmpty())
775 m_aName = rName;
776 }
777
779 {
780 }
781
783 {
784 if(pEditWin)
785 {
786 if(!m_pButton)
788 m_pButton->CalcPosAndSize(m_aPortionPaintArea);
789 m_pButton->Show();
790 }
791 }
792
794 {
796 }
797
804 OUString DropDownFieldmark::GetContent(sal_Int32* pIndex) const
805 {
806 sal_Int32 nIndex = pIndex ? *pIndex : -1;
807 auto rParameters = *GetParameters();
808 if (nIndex < 0)
809 rParameters[ODF_FORMDROPDOWN_RESULT] >>= nIndex;
810
811 uno::Sequence<OUString> aSeq;
812 rParameters[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq;
813 nIndex = std::min(nIndex, aSeq.getLength() - 1);
814
815 if (nIndex < 0)
816 {
817 if (pIndex)
818 *pIndex = -1;
819 return OUString();
820 }
821
822 if (pIndex)
823 *pIndex = nIndex;
824
825 return aSeq[nIndex];
826 }
827
829 {
830 return GetContent(nullptr);
831 }
832
840 void DropDownFieldmark::AddContent(const OUString& rText, sal_Int32* pIndex)
841 {
842 uno::Sequence<OUString> aSeq;
843 sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
844 (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq;
845
846 // no duplicates: if it already exists, modify the given index to point to it
847 const sal_Int32 nCurrentTextPos = comphelper::findValue(aSeq, rText);
848 if (nCurrentTextPos != -1)
849 {
850 if (pIndex)
851 *pIndex = nCurrentTextPos;
852 return;
853 }
854
855 const sal_Int32 nLen = aSeq.getLength();
856 const sal_Int32 nNewPos = pIndex && *pIndex > -1 ? std::min(*pIndex, nLen) : nLen;
857
858 // need to shift list result index up if adding new entry before it
859 sal_Int32 nResultIndex = -1;
860 (*pParameters)[ODF_FORMDROPDOWN_RESULT] >>= nResultIndex;
861 if (nNewPos <= nResultIndex)
862 (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= nResultIndex + 1;
863
864 auto aList = comphelper::sequenceToContainer<std::vector<OUString>>(aSeq);
865 if (nNewPos < nLen)
866 aList.insert(aList.begin() + nNewPos, rText);
867 else
868 {
869 if (pIndex)
870 *pIndex = nLen;
871 aList.push_back(rText);
872 }
873
875 Invalidate();
876 }
877
893 void DropDownFieldmark::ReplaceContent(const OUString* pText, sal_Int32* pIndex)
894 {
895 if (!pIndex && !pText)
896 return;
897
898 uno::Sequence<OUString> aSeq;
899 sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
900 (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq;
901 const sal_Int32 nLen = aSeq.getLength();
902
903 if (!pText)
904 {
905 if (*pIndex < 0 || *pIndex >= nLen)
906 *pIndex = nLen - 1;
907
908 // select pIndex as the new value for the list box
909 (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= *pIndex;
910 Invalidate();
911 return;
912 }
913
914 if (!pIndex)
915 {
916 const sal_Int32 nNewPos = comphelper::findValue(aSeq, *pText);
917 if (nNewPos != -1)
918 {
919 (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= nNewPos;
920 Invalidate();
921 }
922 return;
923 }
924
925 if (*pIndex > -1 && *pIndex < nLen)
926 {
927 auto aList = comphelper::sequenceToContainer<std::vector<OUString>>(aSeq);
928 aList[*pIndex] = *pText;
930 Invalidate();
931 }
932 }
933
934 void DropDownFieldmark::ReplaceContent(const OUString& rNewContent)
935 {
936 ReplaceContent(&rNewContent, nullptr);
937 }
938
943 void DropDownFieldmark::DelContent(sal_Int32 nDelIndex)
944 {
945 sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
946 uno::Sequence<OUString> aSeq;
947 if (nDelIndex < 0)
948 {
949 pParameters->erase(ODF_FORMDROPDOWN_RESULT);
950 (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= aSeq;
951 Invalidate();
952 return;
953 }
954
955 (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq;
956 if (nDelIndex >= aSeq.getLength())
957 return;
958
959 // If deleting the current choice, select the first entry instead
960 // else need to shift list result index down if deleting an entry before it
961 sal_Int32 nResultIndex = -1;
962 (*pParameters)[ODF_FORMDROPDOWN_RESULT] >>= nResultIndex;
963 if (nDelIndex == nResultIndex)
964 nResultIndex = 0;
965 else if (nDelIndex < nResultIndex)
966 --nResultIndex;
967
969 if (nResultIndex != -1)
970 (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= nResultIndex;
971 (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= aSeq;
972 Invalidate();
973 }
974
975 void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea)
976 {
977 m_aPortionPaintArea = rPortionPaintArea;
978 if(m_pButton)
979 {
980 m_pButton->Show();
981 m_pButton->CalcPosAndSize(m_aPortionPaintArea);
982 }
983 }
984
986 {
988 return;
989
990 if (!pViewShell || pViewShell->isLOKMobilePhone())
991 return;
992
994 return;
995
996 OStringBuffer sPayload;
997 sPayload = OString::Concat("{\"action\": \"show\","
998 " \"type\": \"drop-down\", \"textArea\": \"") +
1000 // Add field params to the message
1001 sPayload.append(" \"params\": { \"items\": [");
1002
1003 // List items
1004 auto pParameters = this->GetParameters();
1005 auto pListEntriesIter = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
1006 css::uno::Sequence<OUString> vListEntries;
1007 if (pListEntriesIter != pParameters->end())
1008 {
1009 pListEntriesIter->second >>= vListEntries;
1010 for (const OUString& sItem : std::as_const(vListEntries))
1011 sPayload.append("\"" + OUStringToOString(sItem, RTL_TEXTENCODING_UTF8) + "\", ");
1012 sPayload.setLength(sPayload.getLength() - 2);
1013 }
1014 sPayload.append("], ");
1015
1016 // Selected item
1017 auto pSelectedItemIter = pParameters->find(ODF_FORMDROPDOWN_RESULT);
1018 sal_Int32 nSelection = -1;
1019 if (pSelectedItemIter != pParameters->end())
1020 {
1021 pSelectedItemIter->second >>= nSelection;
1022 }
1023 sPayload.append("\"selected\": \"" + OString::number(nSelection) + "\", ");
1024
1025 // Placeholder text
1026 sPayload.append("\"placeholderText\": \"" + OUStringToOString(SwResId(STR_DROP_DOWN_EMPTY_LIST), RTL_TEXTENCODING_UTF8) + "\"}}");
1027 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.toString().getStr());
1028 }
1029
1031 {
1032 OString sPayload = "{\"action\": \"hide\", \"type\": \"drop-down\"}";
1033 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.getStr());
1034 }
1035
1038 , m_pNumberFormatter(nullptr)
1039 , m_pDocumentContentOperationsManager(nullptr)
1040 {
1041 }
1042
1044 {
1045 }
1046
1048 sw::mark::InsertMode eMode, SwPosition const*const pSepPos)
1049 {
1053 {
1054 lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, pSepPos);
1055 }
1056 else
1057 {
1058 lcl_AssertFieldMarksSet(*this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
1059 }
1060 }
1061
1063 {
1064 IDocumentUndoRedo & rIDUR(rDoc.GetIDocumentUndoRedo());
1065 if (rIDUR.DoesUndo())
1066 {
1067 // TODO does this need a 3rd Undo class?
1068 rIDUR.AppendUndo(std::make_unique<SwUndoDelTextFieldmark>(*this));
1069 }
1070 ::sw::UndoGuard const ug(rIDUR); // prevent SwUndoDeletes
1071 lcl_RemoveFieldMarks(*this, rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
1072 // notify layouts to unhide - for the entire fieldmark, as in InitDoc()
1073 SwPaM const tmp(GetMarkPos(), GetOtherMarkPos());
1075 }
1076
1078 {
1079 if(pEditWin)
1080 {
1081 if(!m_pButton)
1084 m_pButton->CalcPosAndSize(aPaintArea);
1085 m_pButton->Show();
1086 }
1087 }
1088
1090 {
1091 if (rPortionPaintArea.IsEmpty())
1092 return;
1093
1094 m_aPaintAreaStart = rPortionPaintArea;
1096 }
1097
1098 void DateFieldmark::SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea)
1099 {
1100 if (rPortionPaintArea.IsEmpty())
1101 return;
1102
1103 if(m_aPaintAreaEnd == rPortionPaintArea &&
1104 m_pButton && m_pButton->IsVisible())
1105 return;
1106
1107 m_aPaintAreaEnd = rPortionPaintArea;
1108 if(m_pButton)
1109 {
1110 m_pButton->Show();
1112 m_pButton->CalcPosAndSize(aPaintArea);
1113 m_pButton->Invalidate();
1114 }
1116 }
1117
1119 {
1120 const SwTextNode* const pTextNode = GetMarkEnd().GetNode().GetTextNode();
1121 SwPosition const sepPos(sw::mark::FindFieldSep(*this));
1122 const sal_Int32 nStart(sepPos.GetContentIndex());
1123 const sal_Int32 nEnd (GetMarkEnd().GetContentIndex());
1124
1125 OUString sContent;
1126 if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() &&
1127 nEnd > nStart + 2)
1128 sContent = pTextNode->GetText().copy(nStart + 1, nEnd - nStart - 2);
1129 return sContent;
1130 }
1131
1132 void DateFieldmark::ReplaceContent(const OUString& sNewContent)
1133 {
1135 return;
1136
1137 const SwTextNode* const pTextNode = GetMarkEnd().GetNode().GetTextNode();
1138 SwPosition const sepPos(sw::mark::FindFieldSep(*this));
1139 const sal_Int32 nStart(sepPos.GetContentIndex());
1140 const sal_Int32 nEnd (GetMarkEnd().GetContentIndex());
1141
1142 if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() &&
1143 nEnd > nStart + 2)
1144 {
1145 SwPaM aFieldPam(GetMarkStart().GetNode(), nStart + 1,
1146 GetMarkStart().GetNode(), nEnd - 1);
1147 m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false);
1148 }
1149 else
1150 {
1151 SwPaM aFieldStartPam(GetMarkStart().GetNode(), nStart + 1);
1152 m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent);
1153 }
1154
1155 }
1156
1157 std::pair<bool, double> DateFieldmark::GetCurrentDate() const
1158 {
1159 // Check current date param first
1160 std::pair<bool, double> aResult = ParseCurrentDateParam();
1161 if(aResult.first)
1162 return aResult;
1163
1164 const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
1165 bool bFoundValidDate = false;
1166 double dCurrentDate = 0;
1167 OUString sDateFormat;
1168 auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
1169 if (pResult != pParameters->end())
1170 {
1171 pResult->second >>= sDateFormat;
1172 }
1173
1174 OUString sLang;
1175 pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
1176 if (pResult != pParameters->end())
1177 {
1178 pResult->second >>= sLang;
1179 }
1180
1181 // Get current content of the field
1182 OUString sContent = GetContent();
1183
1184 sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
1185 if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
1186 {
1187 sal_Int32 nCheckPos = 0;
1189 m_pNumberFormatter->PutEntry(sDateFormat,
1190 nCheckPos,
1191 nType,
1192 nFormat,
1193 LanguageTag(sLang).getLanguageType());
1194 }
1195
1196 if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
1197 {
1198 bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sContent, nFormat, dCurrentDate);
1199 }
1200 return std::pair<bool, double>(bFoundValidDate, dCurrentDate);
1201 }
1202
1204 {
1205 // Replace current content with the selected date
1207
1208 // Also save the current date in a standard format
1209 sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
1210 (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= GetDateInStandardDateFormat(fDate);
1211 }
1212
1214 {
1215 OUString sCurrentDate;
1217 if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
1218 {
1219 sal_Int32 nCheckPos = 0;
1221 OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
1223 nCheckPos,
1224 nType,
1225 nFormat,
1227 }
1228
1229 if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
1230 {
1231 const Color* pCol = nullptr;
1232 m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentDate, &pCol, false);
1233 }
1234 return sCurrentDate;
1235 }
1236
1237 std::pair<bool, double> DateFieldmark::ParseCurrentDateParam() const
1238 {
1239 bool bFoundValidDate = false;
1240 double dCurrentDate = 0;
1241
1242 const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
1243 auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
1244 OUString sCurrentDate;
1245 if (pResult != pParameters->end())
1246 {
1247 pResult->second >>= sCurrentDate;
1248 }
1249 if(!sCurrentDate.isEmpty())
1250 {
1252 if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
1253 {
1254 sal_Int32 nCheckPos = 0;
1256 OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
1258 nCheckPos,
1259 nType,
1260 nFormat,
1262 }
1263
1264 if(nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
1265 {
1266 bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate);
1267 }
1268 }
1269 return std::pair<bool, double>(bFoundValidDate, dCurrentDate);
1270 }
1271
1272
1274 {
1275 // Get current date format and language
1276 OUString sDateFormat;
1277 const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
1278 auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
1279 if (pResult != pParameters->end())
1280 {
1281 pResult->second >>= sDateFormat;
1282 }
1283
1284 OUString sLang;
1285 pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
1286 if (pResult != pParameters->end())
1287 {
1288 pResult->second >>= sLang;
1289 }
1290
1291 // Fill the content with the specified format
1292 OUString sCurrentContent;
1293 sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
1294 if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
1295 {
1296 sal_Int32 nCheckPos = 0;
1298 OUString sFormat = sDateFormat;
1300 nCheckPos,
1301 nType,
1302 nFormat,
1303 LanguageTag(sLang).getLanguageType());
1304 }
1305
1306 if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
1307 {
1308 const Color* pCol = nullptr;
1309 m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentContent, &pCol, false);
1310 }
1311 return sCurrentContent;
1312 }
1313
1315 {
1316 std::pair<bool, double> aResult = ParseCurrentDateParam();
1317 if(!aResult.first)
1318 return;
1319
1320 // Current date became invalid
1321 if(GetDateInCurrentDateFormat(aResult.second) != GetContent())
1322 {
1323 sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
1324 (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString();
1325 }
1326 }
1327}
1328
1329/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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 sfx2::LinkManager & GetLinkManager()=0
virtual void SetModified()=0
Must be called manually at changes of format.
SfxHintId GetId() const
bool isLOKMobilePhone() const
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
virtual void libreOfficeKitViewCallback(int nType, const char *pPayload) const override
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge=LANGUAGE_DONTKNOW)
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
SwContentIndex & Assign(const SwContentNode *, sal_Int32)
Definition: index.cxx:206
Definition: doc.hxx:195
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:402
bool IsClipBoard() const
Definition: doc.hxx:972
IDocumentLinksAdministration const & getIDocumentLinksAdministration() const
Definition: doc.cxx:268
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:323
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:152
::sfx2::IXmlIdRegistry & GetXmlIdRegistry()
Definition: docnew.cxx:816
::sw::DocumentContentOperationsManager const & GetDocumentContentOperationsManager() const
Definition: doc.cxx:333
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1421
bool IsInHeaderFooter(const SwNode &) const
Definition: doclay.cxx:1566
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:61
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:897
bool IsNoTextNode() const
Definition: node.hxx:699
bool IsEndNode() const
Definition: node.hxx:683
SwNodeOffset StartOfSectionIndex() const
Definition: node.hxx:724
bool IsSectionNode() const
Definition: node.hxx:695
bool IsTextNode() const
Definition: node.hxx:687
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
const SwPosition * GetMark() const
Definition: pam.hxx:263
const SwPosition * GetPoint() const
Definition: pam.hxx:261
void InvalidatePaM()
Definition: pam.cxx:1335
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:259
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
bool IsEmpty() const
Definition: swrect.hxx:304
Point TopLeft() const
Definition: swrect.hxx:254
Point BottomRight() const
Definition: swrect.hxx:266
tools::Rectangle SVRect() const
Definition: swrect.hxx:292
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:111
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
const OUString & GetText() const
Definition: ndtxt.hxx:242
static rtl::Reference< SwXBookmark > CreateXBookmark(SwDoc &rDoc, ::sw::mark::IMark *pBookmark)
Definition: unobkm.cxx:157
void disposeAndClear()
static VclPtr< reference_type > Create(Arg &&... arg)
void RemoveServer(SvLinkSource *rObj)
bool ReplaceRange(SwPaM &rPam, const OUString &rNewStr, const bool bRegExReplace) override
Replace selected range in a TextNode with string.
bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND) override
Insert string into existing text node at position rRg.Point().
void DeleteDummyChar(SwPosition const &rPos, sal_Unicode cDummy)
void SetHideCondition(const OUString &rHideCondition) override
css::uno::Reference< css::rdf::XMetadatable > MakeUnoObject() override
auto InvalidateFrames() -> void override
bool IsInClipboard() const override
void DeregisterFromDoc(SwDoc &io_rDoc) override
bool IsInUndo() const override
void Hide(bool rHide) override
::sfx2::IXmlIdRegistry & GetRegistry() override
Bookmark(const SwPaM &rPaM, const vcl::KeyCode &rCode, const OUString &rName)
bool IsInContent() const override
void InitDoc(SwDoc &io_Doc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
bool IsChecked() const override
void SetChecked(bool checked) override
void ReplaceContent(const OUString &sNewContent) override
OUString GetContent() const override
CheckboxFieldmark(const SwPaM &rPaM, const OUString &rName)
void SetPortionPaintAreaStart(const SwRect &rPortionPaintArea)
std::pair< bool, double > ParseCurrentDateParam() const
std::pair< bool, double > GetCurrentDate() const override
void InitDoc(SwDoc &io_rDoc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
void SetCurrentDate(double fDate) override
DateFieldmark(const SwPaM &rPaM)
SvNumberFormatter * m_pNumberFormatter
void ReleaseDoc(SwDoc &rDoc) override
OUString GetDateInStandardDateFormat(double fDate) const override
OUString GetContent() const override
void ReplaceContent(const OUString &sNewContent) override
void ShowButton(SwEditWin *pEditWin) override
void SetPortionPaintAreaEnd(const SwRect &rPortionPaintArea)
OUString GetDateInCurrentDateFormat(double fDate) const
sw::DocumentContentOperationsManager * m_pDocumentContentOperationsManager
void SetRefObject(SwServerObject *pObj)
DdeBookmark(const SwPaM &rPaM)
tools::SvRef< SwServerObject > m_aRefObj
virtual void DeregisterFromDoc(SwDoc &rDoc)
void SendLOKShowMessage(const SfxViewShell *pViewShell)
void DelContent(sal_Int32 nDelIndex=-1) override
Remove everything if the given index is negative, else remove the given index (if valid).
void ShowButton(SwEditWin *pEditWin) override
void AddContent(const OUString &rText, sal_Int32 *pIndex=nullptr) override
AddContent : INSERTS a new choice.
DropDownFieldmark(const SwPaM &rPaM, const OUString &rName)
void SetPortionPaintArea(const SwRect &rPortionPaintArea)
OUString GetContent() const override
void ReplaceContent(const OUString *pText, sal_Int32 *pIndex) override
ReplaceContent : changes the list result index or renames the existing choices.
static void SendLOKHideMessage(const SfxViewShell *pViewShell)
Fieldmark with a drop down button (e.g. this button opens the date picker for a date field)
void dumpAsXml(xmlTextWriterPtr pWriter) const override
void Invalidate() override
IFieldmark::parameter_map_t m_vParams
void SetMarkStartPos(const SwPosition &rNewStartPos)
Fieldmark(const SwPaM &rPaM)
OUString ToString() const override
IFieldmark::parameter_map_t * GetParameters() override
void SwClientNotify(const SwModify &, const SfxHint &) override
virtual void SetOtherMarkPos(const SwPosition &rNewPos)
const OUString & GetName() const override
std::optional< SwPosition > m_oPos1
OUString ToString() const override
void SetXBookmark(rtl::Reference< SwXBookmark > const &xBkmk)
void dumpAsXml(xmlTextWriterPtr pWriter) const override
std::optional< SwPosition > m_oPos2
SwPosition & GetMarkEnd() const override
unotools::WeakReference< SwXBookmark > m_wXBookmark
virtual auto InvalidateFrames() -> void
bool IsCoveringPosition(const SwPosition &rPos) const override
bool IsExpanded() const override
virtual void SetMarkPos(const SwPosition &rNewPos)
MarkBase(const SwPaM &rPaM, OUString aName)
SwPosition & GetMarkPos() const override
SwPosition & GetMarkStart() const override
SwPosition & GetOtherMarkPos() const override
static OUString GenerateNewName(std::u16string_view rPrefix)
NavigatorReminder(const SwPaM &rPaM)
NonTextFieldmark(const SwPaM &rPaM)
void ReleaseDoc(SwDoc &rDoc) override
void InitDoc(SwDoc &io_rDoc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
void InitDoc(SwDoc &io_rDoc, sw::mark::InsertMode eMode, SwPosition const *pSepPos) override
void ReplaceContent(const OUString &sNewContent) override
TextFieldmark(const SwPaM &rPaM, const OUString &rName)
sw::DocumentContentOperationsManager * m_pDocumentContentOperationsManager
void ReleaseDoc(SwDoc &rDoc) override
OUString GetContent() const override
UnoMark(const SwPaM &rPaM)
void put(const char *pPropName, const OUString &rPropValue)
char * extractData()
ScopedJsonWriterNode startNode(const char *)
rtl::OString toString() const
T * get() const
bool is() const
int nCount
struct _xmlTextWriter * xmlTextWriterPtr
float u
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:181
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_REMOVE_UNO_OBJECT(181)
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:178
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:182
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:180
sal_Int32 nIndex
OUString aName
Mode eMode
void * p
sal_Int64 n
Sequence< sal_Int8 > aSeq
#define SAL_INFO(area, stream)
double getLength(const B2DPolygon &rCandidate)
unsigned int uniform_uint_distribution(unsigned int a, unsigned int b)
OUString anyToString(uno::Any const &value)
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
void removeElementAt(css::uno::Sequence< T > &_rSeq, sal_Int32 _nPos)
int i
end
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
SwPosition FindFieldSep(IFieldmark const &rMark)
return position of the CH_TXT_ATR_FIELDSEP for rMark
InsertMode
Definition: IMark.hxx:32
void UpdateFramesForRemoveDeleteRedline(SwDoc &rDoc, SwPaM const &rPam)
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
constexpr OUStringLiteral ODF_FORMCHECKBOX_RESULT
constexpr OUStringLiteral ODF_FORMDROPDOWN_RESULT
constexpr OUStringLiteral ODF_FORMDATE_CURRENTDATE
constexpr OUStringLiteral ODF_FORMDATE_DATEFORMAT
constexpr OUStringLiteral ODF_FORMDATE_CURRENTDATE_FORMAT
#define ODF_FORMDATE_CURRENTDATE_LANGUAGE
constexpr OUStringLiteral ODF_FORMDROPDOWN_LISTENTRY
constexpr OUStringLiteral ODF_CODE_PARAM
constexpr OUStringLiteral ODF_FORMDATE_DATEFORMAT_LANGUAGE
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:1020
OUString m_aName
QPRO_FUNC_TYPE nType
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: pam.cxx:222
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:77
const SwNodes & GetNodes() const
Definition: pam.hxx:78
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
void AdjustContent(sal_Int32 nDelta)
Adjust content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:261
SwContentIndex nContent
Definition: pam.hxx:39
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
#define SAL_MAX_INT32
sal_uInt16 sal_Unicode
Any result
SvNumFormatType
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND