File: | home/maarten/src/libreoffice/core/sw/inc/node.hxx |
Warning: | line 724, column 5 Returning null reference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <hintids.hxx> | ||||
21 | #include <hints.hxx> | ||||
22 | |||||
23 | #include <comphelper/lok.hxx> | ||||
24 | #include <comphelper/string.hxx> | ||||
25 | #include <editeng/fontitem.hxx> | ||||
26 | #include <editeng/escapementitem.hxx> | ||||
27 | #include <editeng/lrspitem.hxx> | ||||
28 | #include <editeng/rsiditem.hxx> | ||||
29 | #include <sal/log.hxx> | ||||
30 | #include <anchoredobject.hxx> | ||||
31 | #include <txtfld.hxx> | ||||
32 | #include <txtinet.hxx> | ||||
33 | #include <fmtanchr.hxx> | ||||
34 | #include <fmtinfmt.hxx> | ||||
35 | #include <fmtrfmrk.hxx> | ||||
36 | #include <txttxmrk.hxx> | ||||
37 | #include <fchrfmt.hxx> | ||||
38 | #include <txtftn.hxx> | ||||
39 | #include <fmtflcnt.hxx> | ||||
40 | #include <fmtfld.hxx> | ||||
41 | #include <frmatr.hxx> | ||||
42 | #include <ftnidx.hxx> | ||||
43 | #include <ftninfo.hxx> | ||||
44 | #include <fmtftn.hxx> | ||||
45 | #include <fmtmeta.hxx> | ||||
46 | #include <charfmt.hxx> | ||||
47 | #include <ndtxt.hxx> | ||||
48 | #include <doc.hxx> | ||||
49 | #include <IDocumentUndoRedo.hxx> | ||||
50 | #include <IDocumentSettingAccess.hxx> | ||||
51 | #include <IDocumentListsAccess.hxx> | ||||
52 | #include <IDocumentRedlineAccess.hxx> | ||||
53 | #include <IDocumentLayoutAccess.hxx> | ||||
54 | #include <docary.hxx> | ||||
55 | #include <pam.hxx> | ||||
56 | #include <fldbas.hxx> | ||||
57 | #include <paratr.hxx> | ||||
58 | #include <txtfrm.hxx> | ||||
59 | #include <ftnfrm.hxx> | ||||
60 | #include <rootfrm.hxx> | ||||
61 | #include <expfld.hxx> | ||||
62 | #include <section.hxx> | ||||
63 | #include <mvsave.hxx> | ||||
64 | #include <swcache.hxx> | ||||
65 | #include <SwGrammarMarkUp.hxx> | ||||
66 | #include <redline.hxx> | ||||
67 | #include <IMark.hxx> | ||||
68 | #include <scriptinfo.hxx> | ||||
69 | #include <istyleaccess.hxx> | ||||
70 | #include <SwStyleNameMapper.hxx> | ||||
71 | #include <numrule.hxx> | ||||
72 | #include <docsh.hxx> | ||||
73 | #include <SwNodeNum.hxx> | ||||
74 | #include <svl/grabbagitem.hxx> | ||||
75 | #include <svl/intitem.hxx> | ||||
76 | #include <list.hxx> | ||||
77 | #include <sortedobjs.hxx> | ||||
78 | #include <calbck.hxx> | ||||
79 | #include <attrhint.hxx> | ||||
80 | #include <memory> | ||||
81 | #include <unoparagraph.hxx> | ||||
82 | #include <wrtsh.hxx> | ||||
83 | #include <frameformats.hxx> | ||||
84 | #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> | ||||
85 | #include <svl/itemiter.hxx> | ||||
86 | |||||
87 | using namespace ::com::sun::star; | ||||
88 | |||||
89 | typedef std::vector<SwTextAttr*> SwpHts; | ||||
90 | |||||
91 | |||||
92 | // unfortunately everyone can change Hints without ensuring order or the linking between them | ||||
93 | #ifdef DBG_UTIL | ||||
94 | #define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \ | ||||
95 | !pNd->GetDoc().IsInReading() ) \ | ||||
96 | pNd->GetpSwpHints()->Check(true); } | ||||
97 | #define CHECK_SWPHINTS_IF_FRM(pNd) { if( pNd->GetpSwpHints() && \ | ||||
98 | !pNd->GetDoc().IsInReading() ) \ | ||||
99 | pNd->GetpSwpHints()->Check(getLayoutFrame(nullptr, nullptr, nullptr) != nullptr); } | ||||
100 | #else | ||||
101 | #define CHECK_SWPHINTS(pNd) | ||||
102 | #define CHECK_SWPHINTS_IF_FRM(pNd) | ||||
103 | #endif | ||||
104 | |||||
105 | SwTextNode *SwNodes::MakeTextNode( const SwNodeIndex & rWhere, | ||||
106 | SwTextFormatColl *pColl, bool const bNewFrames) | ||||
107 | { | ||||
108 | OSL_ENSURE( pColl, "Collection pointer is 0." )do { if (true && (!(pColl))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "108" ": "), "%s", "Collection pointer is 0."); } } while (false); | ||||
109 | |||||
110 | SwTextNode *pNode = new SwTextNode( rWhere, pColl, nullptr ); | ||||
111 | |||||
112 | SwNodeIndex aIdx( *pNode ); | ||||
113 | |||||
114 | // call method <UpdateOutlineNode(..)> only for the document nodes array | ||||
115 | if ( IsDocNodes() ) | ||||
116 | UpdateOutlineNode(*pNode); | ||||
117 | |||||
118 | // if there is no layout or it is in a hidden section, MakeFrames is not needed | ||||
119 | const SwSectionNode* pSectNd; | ||||
120 | if (!bNewFrames || | ||||
121 | !GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell() || | ||||
122 | ( nullptr != (pSectNd = pNode->FindSectionNode()) && | ||||
123 | pSectNd->GetSection().IsHiddenFlag() )) | ||||
124 | return pNode; | ||||
125 | |||||
126 | SwNodeIndex aTmp( rWhere ); | ||||
127 | do { | ||||
128 | // max. 2 loops: | ||||
129 | // 1. take the successor | ||||
130 | // 2. take the predecessor | ||||
131 | |||||
132 | SwNode * pNd = & aTmp.GetNode(); | ||||
133 | switch (pNd->GetNodeType()) | ||||
134 | { | ||||
135 | case SwNodeType::Table: | ||||
136 | static_cast<SwTableNode*>(pNd)->MakeFramesForAdjacentContentNode(aIdx); | ||||
137 | return pNode; | ||||
138 | |||||
139 | case SwNodeType::Section: | ||||
140 | if( static_cast<SwSectionNode*>(pNd)->GetSection().IsHidden() || | ||||
141 | static_cast<SwSectionNode*>(pNd)->IsContentHidden() ) | ||||
142 | { | ||||
143 | SwNodeIndex aTmpIdx( *pNode ); | ||||
144 | pNd = FindPrvNxtFrameNode( aTmpIdx, pNode ); | ||||
145 | if( !pNd ) | ||||
146 | return pNode; | ||||
147 | aTmp = *pNd; | ||||
148 | break; | ||||
149 | } | ||||
150 | static_cast<SwSectionNode*>(pNd)->MakeFramesForAdjacentContentNode(aIdx); | ||||
151 | return pNode; | ||||
152 | |||||
153 | case SwNodeType::Text: | ||||
154 | case SwNodeType::Grf: | ||||
155 | case SwNodeType::Ole: | ||||
156 | static_cast<SwContentNode*>(pNd)->MakeFramesForAdjacentContentNode(*pNode); | ||||
157 | return pNode; | ||||
158 | |||||
159 | case SwNodeType::End: | ||||
160 | if( pNd->StartOfSectionNode()->IsSectionNode() && | ||||
161 | aTmp.GetIndex() < rWhere.GetIndex() ) | ||||
162 | { | ||||
163 | if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag()) | ||||
164 | { | ||||
165 | if( !GoPrevSection( &aTmp, true, false ) || | ||||
166 | aTmp.GetNode().FindTableNode() != | ||||
167 | pNode->FindTableNode() ) | ||||
168 | return pNode; | ||||
169 | } | ||||
170 | else | ||||
171 | aTmp = *pNd->StartOfSectionNode(); | ||||
172 | break; | ||||
173 | } | ||||
174 | else if( pNd->StartOfSectionNode()->IsTableNode() && | ||||
175 | aTmp.GetIndex() < rWhere.GetIndex() ) | ||||
176 | { | ||||
177 | // after a table node | ||||
178 | aTmp = *pNd->StartOfSectionNode(); | ||||
179 | break; | ||||
180 | } | ||||
181 | [[fallthrough]]; | ||||
182 | default: | ||||
183 | if( rWhere == aTmp ) | ||||
184 | aTmp -= 2; | ||||
185 | else | ||||
186 | return pNode; | ||||
187 | break; | ||||
188 | } | ||||
189 | } while( true ); | ||||
190 | } | ||||
191 | |||||
192 | SwTextNode::SwTextNode( const SwNodeIndex &rWhere, SwTextFormatColl *pTextColl, const SfxItemSet* pAutoAttr ) | ||||
193 | : SwContentNode( rWhere, SwNodeType::Text, pTextColl ), | ||||
194 | m_Text(), | ||||
195 | m_pParaIdleData_Impl(nullptr), | ||||
196 | m_bContainsHiddenChars(false), | ||||
197 | m_bHiddenCharsHidePara(false), | ||||
198 | m_bRecalcHiddenCharFlags(false), | ||||
199 | m_bLastOutlineState( false ), | ||||
200 | m_bNotifiable( false ), | ||||
201 | mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ), | ||||
202 | mbInSetOrResetAttr( false ), | ||||
203 | m_pNumStringCache(), | ||||
204 | m_wXParagraph(), | ||||
205 | maFillAttributes() | ||||
206 | { | ||||
207 | InitSwParaStatistics( true ); | ||||
208 | |||||
209 | if( pAutoAttr
| ||||
210 | SetAttr( *pAutoAttr ); | ||||
211 | |||||
212 | if (!IsInList() && GetNumRule() && !GetListId().isEmpty()) | ||||
213 | { | ||||
214 | // #i101516# | ||||
215 | // apply paragraph style's assigned outline style list level as | ||||
216 | // list level of the paragraph, if it has none set already. | ||||
217 | if ( !HasAttrListLevel() && | ||||
218 | pTextColl && pTextColl->IsAssignedToListLevelOfOutlineStyle() ) | ||||
219 | { | ||||
220 | SetAttrListLevel( pTextColl->GetAssignedOutlineStyleLevel() ); | ||||
221 | } | ||||
222 | AddToList(); | ||||
223 | } | ||||
224 | GetNodes().UpdateOutlineNode(*this); | ||||
225 | |||||
226 | m_bNotifiable = true; | ||||
227 | |||||
228 | m_bContainsHiddenChars = m_bHiddenCharsHidePara = false; | ||||
229 | m_bRecalcHiddenCharFlags = true; | ||||
230 | } | ||||
231 | |||||
232 | SwTextNode::~SwTextNode() | ||||
233 | { | ||||
234 | // delete only removes the pointer not the array elements! | ||||
235 | if ( m_pSwpHints ) | ||||
236 | { | ||||
237 | // do not delete attributes twice when those delete their content | ||||
238 | std::unique_ptr<SwpHints> pTmpHints(std::move(m_pSwpHints)); | ||||
239 | |||||
240 | for( size_t j = pTmpHints->Count(); j; ) | ||||
241 | { | ||||
242 | // first remove the attribute from the array otherwise | ||||
243 | // if would delete itself | ||||
244 | DestroyAttr( pTmpHints->Get( --j ) ); | ||||
245 | } | ||||
246 | } | ||||
247 | |||||
248 | // must be removed from outline nodes by now | ||||
249 | #if OSL_DEBUG_LEVEL1 > 0 && !defined NDEBUG | ||||
250 | SwOutlineNodes::size_type foo; | ||||
251 | assert(!GetNodes().GetOutLineNds().Seek_Entry(this, &foo))(static_cast <bool> (!GetNodes().GetOutLineNds().Seek_Entry (this, &foo)) ? void (0) : __assert_fail ("!GetNodes().GetOutLineNds().Seek_Entry(this, &foo)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 251, __extension__ __PRETTY_FUNCTION__)); | ||||
252 | #endif | ||||
253 | |||||
254 | RemoveFromList(); | ||||
255 | |||||
256 | InitSwParaStatistics( false ); | ||||
257 | DelFrames(nullptr); // must be called here while it's still a SwTextNode | ||||
258 | DelFrames_TextNodePart(); | ||||
259 | } | ||||
260 | |||||
261 | void SwTextNode::FileLoadedInitHints() | ||||
262 | { | ||||
263 | if (m_pSwpHints) | ||||
264 | { | ||||
265 | m_pSwpHints->MergePortions(*this); | ||||
266 | } | ||||
267 | } | ||||
268 | |||||
269 | SwContentFrame *SwTextNode::MakeFrame( SwFrame* pSib ) | ||||
270 | { | ||||
271 | SwContentFrame *pFrame = sw::MakeTextFrame(*this, pSib, sw::FrameMode::New); | ||||
272 | return pFrame; | ||||
273 | } | ||||
274 | |||||
275 | sal_Int32 SwTextNode::Len() const | ||||
276 | { | ||||
277 | return m_Text.getLength(); | ||||
278 | } | ||||
279 | |||||
280 | // After a split node, it's necessary to actualize the ref-pointer of the ftnfrms. | ||||
281 | static void lcl_ChangeFootnoteRef( SwTextNode &rNode ) | ||||
282 | { | ||||
283 | SwpHints *pSwpHints = rNode.GetpSwpHints(); | ||||
284 | if( !(pSwpHints && rNode.GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell()) ) | ||||
285 | return; | ||||
286 | |||||
287 | SwContentFrame* pFrame = nullptr; | ||||
288 | // OD 07.11.2002 #104840# - local variable to remember first footnote | ||||
289 | // of node <rNode> in order to invalidate position of its first content. | ||||
290 | // Thus, in its <MakeAll()> it will checked its position relative to its reference. | ||||
291 | SwFootnoteFrame* pFirstFootnoteOfNode = nullptr; | ||||
292 | for( size_t j = pSwpHints->Count(); j; ) | ||||
293 | { | ||||
294 | SwTextAttr* pHt = pSwpHints->Get(--j); | ||||
295 | if (RES_TXTATR_FTN == pHt->Which()) | ||||
296 | { | ||||
297 | if( !pFrame ) | ||||
298 | { | ||||
299 | pFrame = SwIterator<SwContentFrame, SwTextNode, sw::IteratorMode::UnwrapMulti>(rNode).First(); | ||||
300 | if (!pFrame) | ||||
301 | return; | ||||
302 | } | ||||
303 | SwTextFootnote *pAttr = static_cast<SwTextFootnote*>(pHt); | ||||
304 | OSL_ENSURE( pAttr->GetStartNode(), "FootnoteAtr without StartNode." )do { if (true && (!(pAttr->GetStartNode()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "304" ": "), "%s", "FootnoteAtr without StartNode."); } } while (false); | ||||
305 | SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 ); | ||||
306 | SwContentNode *pNd = aIdx.GetNode().GetContentNode(); | ||||
307 | if ( !pNd ) | ||||
308 | pNd = pFrame->GetAttrSet()->GetDoc()-> | ||||
309 | GetNodes().GoNextSection( &aIdx, true, false ); | ||||
310 | if ( !pNd ) | ||||
311 | continue; | ||||
312 | |||||
313 | SwIterator<SwContentFrame, SwContentNode, sw::IteratorMode::UnwrapMulti> aIter(*pNd); | ||||
314 | SwContentFrame* pContent = aIter.First(); | ||||
315 | if( pContent ) | ||||
316 | { | ||||
317 | OSL_ENSURE( pContent->getRootFrame() == pFrame->getRootFrame(),do { if (true && (!(pContent->getRootFrame() == pFrame ->getRootFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "318" ": "), "%s", "lcl_ChangeFootnoteRef: Layout double?" ); } } while (false) | ||||
318 | "lcl_ChangeFootnoteRef: Layout double?" )do { if (true && (!(pContent->getRootFrame() == pFrame ->getRootFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "318" ": "), "%s", "lcl_ChangeFootnoteRef: Layout double?" ); } } while (false); | ||||
319 | SwFootnoteFrame *pFootnote = pContent->FindFootnoteFrame(); | ||||
320 | if( pFootnote && pFootnote->GetAttr() == pAttr ) | ||||
321 | { | ||||
322 | while( pFootnote->GetMaster() ) | ||||
323 | pFootnote = pFootnote->GetMaster(); | ||||
324 | // #104840# - remember footnote frame | ||||
325 | pFirstFootnoteOfNode = pFootnote; | ||||
326 | while ( pFootnote ) | ||||
327 | { | ||||
328 | pFootnote->SetRef( pFrame ); | ||||
329 | pFootnote = pFootnote->GetFollow(); | ||||
330 | static_cast<SwTextFrame*>(pFrame)->SetFootnote( true ); | ||||
331 | } | ||||
332 | } | ||||
333 | #if OSL_DEBUG_LEVEL1 > 0 | ||||
334 | while( nullptr != (pContent = aIter.Next()) ) | ||||
335 | { | ||||
336 | SwFootnoteFrame *pDbgFootnote = pContent->FindFootnoteFrame(); | ||||
337 | OSL_ENSURE( !pDbgFootnote || pDbgFootnote->GetRef() == pFrame,do { if (true && (!(!pDbgFootnote || pDbgFootnote-> GetRef() == pFrame))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "338" ": "), "%s", "lcl_ChangeFootnoteRef: Who's that guy?" ); } } while (false) | ||||
338 | "lcl_ChangeFootnoteRef: Who's that guy?" )do { if (true && (!(!pDbgFootnote || pDbgFootnote-> GetRef() == pFrame))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "338" ": "), "%s", "lcl_ChangeFootnoteRef: Who's that guy?" ); } } while (false); | ||||
339 | } | ||||
340 | #endif | ||||
341 | } | ||||
342 | } | ||||
343 | } // end of for-loop on <SwpHints> | ||||
344 | // #104840# - invalidate | ||||
345 | if ( pFirstFootnoteOfNode ) | ||||
346 | { | ||||
347 | SwContentFrame* pContent = pFirstFootnoteOfNode->ContainsContent(); | ||||
348 | if ( pContent ) | ||||
349 | { | ||||
350 | pContent->InvalidatePos_(); | ||||
351 | } | ||||
352 | } | ||||
353 | } | ||||
354 | |||||
355 | namespace sw { | ||||
356 | |||||
357 | // check if there are flys on the existing frames (now on "pNode") | ||||
358 | // that need to be moved to the new frames of "this" | ||||
359 | void MoveMergedFlysAndFootnotes(std::vector<SwTextFrame*> const& rFrames, | ||||
360 | SwTextNode const& rFirstNode, SwTextNode & rSecondNode, | ||||
361 | bool isSplitNode) | ||||
362 | { | ||||
363 | if (!isSplitNode) | ||||
364 | { | ||||
365 | lcl_ChangeFootnoteRef(rSecondNode); | ||||
366 | } | ||||
367 | for (sal_uLong nIndex = rSecondNode.GetIndex() + 1; ; ++nIndex) | ||||
368 | { | ||||
369 | SwNode *const pTmp(rSecondNode.GetNodes()[nIndex]); | ||||
370 | if (pTmp->IsCreateFrameWhenHidingRedlines() || pTmp->IsEndNode()) | ||||
371 | { | ||||
372 | break; | ||||
373 | } | ||||
374 | else if (pTmp->IsStartNode()) | ||||
375 | { | ||||
376 | nIndex = pTmp->EndOfSectionIndex(); | ||||
377 | } | ||||
378 | else if (pTmp->GetRedlineMergeFlag() == SwNode::Merge::NonFirst | ||||
379 | && pTmp->IsTextNode()) | ||||
380 | { | ||||
381 | lcl_ChangeFootnoteRef(*pTmp->GetTextNode()); | ||||
382 | } | ||||
383 | } | ||||
384 | for (SwTextFrame *const pFrame : rFrames) | ||||
385 | { | ||||
386 | if (SwSortedObjs *const pObjs = pFrame->GetDrawObjs()) | ||||
387 | { | ||||
388 | std::vector<SwAnchoredObject*> objs; | ||||
389 | objs.reserve(pObjs->size()); | ||||
390 | for (SwAnchoredObject *const pObj : *pObjs) | ||||
391 | { | ||||
392 | objs.push_back(pObj); | ||||
393 | } | ||||
394 | for (SwAnchoredObject *const pObj : objs) | ||||
395 | { | ||||
396 | SwFrameFormat & rFormat(pObj->GetFrameFormat()); | ||||
397 | SwFormatAnchor const& rAnchor(rFormat.GetAnchor()); | ||||
398 | if (rFirstNode.GetIndex() < rAnchor.GetContentAnchor()->nNode.GetIndex()) | ||||
399 | { | ||||
400 | // move it to the new frame of "this" | ||||
401 | rFormat.NotifyClients(&rAnchor, &rAnchor); | ||||
402 | // note pObjs will be deleted if it becomes empty | ||||
403 | assert(!pFrame->GetDrawObjs() || !pObjs->Contains(*pObj))(static_cast <bool> (!pFrame->GetDrawObjs() || !pObjs ->Contains(*pObj)) ? void (0) : __assert_fail ("!pFrame->GetDrawObjs() || !pObjs->Contains(*pObj)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 403, __extension__ __PRETTY_FUNCTION__)); | ||||
404 | } | ||||
405 | } | ||||
406 | } | ||||
407 | } | ||||
408 | } | ||||
409 | |||||
410 | } // namespace | ||||
411 | |||||
412 | SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos, | ||||
413 | std::function<void (SwTextNode *, sw::mark::RestoreMode)> const*const pContentIndexRestore) | ||||
414 | { | ||||
415 | bool isHide(false); | ||||
416 | SwNode::Merge const eOldMergeFlag(GetRedlineMergeFlag()); | ||||
417 | bool parentIsOutline = IsOutline(); | ||||
418 | |||||
419 | // create a node "in front" of me | ||||
420 | const sal_Int32 nSplitPos = rPos.nContent.GetIndex(); | ||||
421 | const sal_Int32 nTextLen = m_Text.getLength(); | ||||
422 | SwTextNode* const pNode = | ||||
423 | MakeNewTextNode( rPos.nNode, false, nSplitPos==nTextLen ); | ||||
424 | |||||
425 | // the first paragraph gets the XmlId, | ||||
426 | // _except_ if it is empty and the second is not empty | ||||
427 | if (nSplitPos != 0) { | ||||
428 | pNode->RegisterAsCopyOf(*this, true); | ||||
429 | if (nSplitPos == nTextLen) | ||||
430 | { | ||||
431 | RemoveMetadataReference(); | ||||
432 | // NB: SwUndoSplitNode will call pNode->JoinNext, | ||||
433 | // which is sufficient even in this case! | ||||
434 | } | ||||
435 | } | ||||
436 | |||||
437 | ResetAttr( RES_PARATR_LIST_ISRESTART ); | ||||
438 | ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); | ||||
439 | ResetAttr( RES_PARATR_LIST_ISCOUNTED ); | ||||
440 | if ( GetNumRule() == nullptr || (parentIsOutline && !IsOutline()) ) | ||||
441 | { | ||||
442 | ResetAttr( RES_PARATR_LIST_ID ); | ||||
443 | ResetAttr( RES_PARATR_LIST_LEVEL ); | ||||
444 | } | ||||
445 | |||||
446 | if ( HasWriterListeners() && !m_Text.isEmpty() && (nTextLen / 2) < nSplitPos ) | ||||
447 | { | ||||
448 | // optimization for SplitNode: If a split is at the end of a node then | ||||
449 | // move the frames from the current to the new one and create new ones | ||||
450 | // for the current one. As a result, no need for recreating the layout. | ||||
451 | |||||
452 | LockModify(); // disable notifications | ||||
453 | |||||
454 | // If fly frames are moved, they don't need to destroy their layout | ||||
455 | // frames. Set a flag that is checked in SwTextFlyCnt::SetAnchor. | ||||
456 | if ( HasHints() ) | ||||
457 | { | ||||
458 | pNode->GetOrCreateSwpHints().SetInSplitNode(true); | ||||
459 | } | ||||
460 | |||||
461 | // Move the first part of the content to the new node and delete | ||||
462 | // it in the old node. | ||||
463 | SwIndex aIdx( this ); | ||||
464 | CutText( pNode, aIdx, nSplitPos ); | ||||
465 | |||||
466 | if( GetWrong() ) | ||||
467 | { | ||||
468 | pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) ); | ||||
469 | } | ||||
470 | SetWrongDirty(WrongState::TODO); | ||||
471 | |||||
472 | if( GetGrammarCheck() ) | ||||
473 | { | ||||
474 | pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) ); | ||||
475 | } | ||||
476 | SetGrammarCheckDirty( true ); | ||||
477 | |||||
478 | SetWordCountDirty( true ); | ||||
479 | |||||
480 | if( GetSmartTags() ) | ||||
481 | { | ||||
482 | pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) ); | ||||
483 | } | ||||
484 | SetSmartTagDirty( true ); | ||||
485 | |||||
486 | if ( pNode->HasHints() ) | ||||
487 | { | ||||
488 | if ( pNode->m_pSwpHints->CanBeDeleted() ) | ||||
489 | { | ||||
490 | pNode->m_pSwpHints.reset(); | ||||
491 | } | ||||
492 | else | ||||
493 | { | ||||
494 | pNode->m_pSwpHints->SetInSplitNode(false); | ||||
495 | } | ||||
496 | |||||
497 | // All fly frames anchored as char that are moved to the new | ||||
498 | // node must have their layout frames deleted. | ||||
499 | // This comment is sort of silly because we actually delete the | ||||
500 | // layout frames of those which were not moved? | ||||
501 | // JP 01.10.96: delete all empty and not-to-be-expanded attributes | ||||
502 | if ( HasHints() ) | ||||
503 | { | ||||
504 | for ( size_t j = m_pSwpHints->Count(); j; ) | ||||
505 | { | ||||
506 | SwTextAttr* const pHt = m_pSwpHints->Get( --j ); | ||||
507 | if ( RES_TXTATR_FLYCNT == pHt ->Which() ) | ||||
508 | { | ||||
509 | pHt->GetFlyCnt().GetFrameFormat()->DelFrames(); | ||||
510 | } | ||||
511 | else if ( pHt->DontExpand() ) | ||||
512 | { | ||||
513 | const sal_Int32* const pEnd = pHt->GetEnd(); | ||||
514 | if (pEnd && pHt->GetStart() == *pEnd ) | ||||
515 | { | ||||
516 | // delete it! | ||||
517 | m_pSwpHints->DeleteAtPos( j ); | ||||
518 | DestroyAttr( pHt ); | ||||
519 | } | ||||
520 | } | ||||
521 | } | ||||
522 | } | ||||
523 | |||||
524 | } | ||||
525 | |||||
526 | if (pContentIndexRestore) | ||||
527 | { // call before making frames and before RegisterToNode | ||||
528 | (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys); | ||||
529 | } | ||||
530 | if (eOldMergeFlag != SwNode::Merge::None) | ||||
531 | { // clear before making frames and before RegisterToNode | ||||
532 | SetRedlineMergeFlag(SwNode::Merge::None); | ||||
533 | } // now RegisterToNode will set merge flags in both nodes properly! | ||||
534 | |||||
535 | std::vector<SwTextFrame*> frames; | ||||
536 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this); | ||||
537 | for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) | ||||
538 | { | ||||
539 | if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
540 | { | ||||
541 | isHide = true; | ||||
542 | } | ||||
543 | frames.push_back(pFrame); | ||||
544 | } | ||||
545 | for (SwTextFrame * pFrame : frames) | ||||
546 | { | ||||
547 | pFrame->RegisterToNode( *pNode ); | ||||
548 | if (!pFrame->IsFollow() && pFrame->GetOffset()) | ||||
549 | { | ||||
550 | pFrame->SetOffset( TextFrameIndex(0) ); | ||||
551 | } | ||||
552 | } | ||||
553 | |||||
554 | if ( IsInCache() ) | ||||
555 | { | ||||
556 | SwFrame::GetCache().Delete( this ); | ||||
557 | SetInCache( false ); | ||||
558 | } | ||||
559 | |||||
560 | UnlockModify(); // enable notify again | ||||
561 | |||||
562 | // If there is an accessible layout we must call modify even | ||||
563 | // with length zero, because we have to notify about the changed | ||||
564 | // text node. | ||||
565 | const SwRootFrame *pRootFrame; | ||||
566 | if ( (nTextLen != nSplitPos) || | ||||
567 | ( (pRootFrame = pNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()) != nullptr && | ||||
568 | pRootFrame->IsAnyShellAccessible() ) ) | ||||
569 | { | ||||
570 | // tell the frames that something was "deleted" at the end | ||||
571 | if( 1 == nTextLen - nSplitPos ) | ||||
572 | { | ||||
573 | SwDelChr aHint( nSplitPos ); | ||||
574 | pNode->NotifyClients( nullptr, &aHint ); | ||||
575 | } | ||||
576 | else | ||||
577 | { | ||||
578 | SwDelText aHint( nSplitPos, nTextLen - nSplitPos ); | ||||
579 | pNode->NotifyClients( nullptr, &aHint ); | ||||
580 | } | ||||
581 | } | ||||
582 | if ( HasHints() ) | ||||
583 | { | ||||
584 | MoveTextAttr_To_AttrSet(); | ||||
585 | } | ||||
586 | // in case there are frames, the RegisterToNode has set the merge flag | ||||
587 | pNode->MakeFramesForAdjacentContentNode(*this); | ||||
588 | lcl_ChangeFootnoteRef( *this ); | ||||
589 | if (pContentIndexRestore) | ||||
590 | { // call after making frames; listeners will take care of adding to the right frame | ||||
591 | (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys); | ||||
592 | } | ||||
593 | if (eOldMergeFlag != SwNode::Merge::None) | ||||
594 | { | ||||
595 | MoveMergedFlysAndFootnotes(frames, *pNode, *this, true); | ||||
596 | } | ||||
597 | } | ||||
598 | else | ||||
599 | { | ||||
600 | SwWrongList *pList = GetWrong(); | ||||
601 | SetWrong( nullptr, false ); | ||||
602 | SetWrongDirty(WrongState::TODO); | ||||
603 | |||||
604 | SwGrammarMarkUp *pList3 = GetGrammarCheck(); | ||||
605 | SetGrammarCheck( nullptr, false ); | ||||
606 | SetGrammarCheckDirty( true ); | ||||
607 | |||||
608 | SetWordCountDirty( true ); | ||||
609 | |||||
610 | SwWrongList *pList2 = GetSmartTags(); | ||||
611 | SetSmartTags( nullptr, false ); | ||||
612 | SetSmartTagDirty( true ); | ||||
613 | |||||
614 | SwIndex aIdx( this ); | ||||
615 | CutText( pNode, aIdx, nSplitPos ); | ||||
616 | |||||
617 | // JP 01.10.96: delete all empty and not-to-be-expanded attributes | ||||
618 | if ( HasHints() ) | ||||
619 | { | ||||
620 | for ( size_t j = m_pSwpHints->Count(); j; ) | ||||
621 | { | ||||
622 | SwTextAttr* const pHt = m_pSwpHints->Get( --j ); | ||||
623 | const sal_Int32* const pEnd = pHt->GetEnd(); | ||||
624 | if ( pHt->DontExpand() && pEnd && (pHt->GetStart() == *pEnd) ) | ||||
625 | { | ||||
626 | // delete it! | ||||
627 | m_pSwpHints->DeleteAtPos( j ); | ||||
628 | DestroyAttr( pHt ); | ||||
629 | } | ||||
630 | } | ||||
631 | MoveTextAttr_To_AttrSet(); | ||||
632 | } | ||||
633 | |||||
634 | if( pList ) | ||||
635 | { | ||||
636 | pNode->SetWrong( pList->SplitList( nSplitPos ) ); | ||||
637 | SetWrong( pList, false ); | ||||
638 | } | ||||
639 | |||||
640 | if( pList3 ) | ||||
641 | { | ||||
642 | pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) ); | ||||
643 | SetGrammarCheck( pList3, false ); | ||||
644 | } | ||||
645 | |||||
646 | if( pList2 ) | ||||
647 | { | ||||
648 | pNode->SetSmartTags( pList2->SplitList( nSplitPos ) ); | ||||
649 | SetSmartTags( pList2, false ); | ||||
650 | } | ||||
651 | |||||
652 | if (pContentIndexRestore) | ||||
653 | { // call before making frames and before RegisterToNode | ||||
654 | (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys); | ||||
655 | } | ||||
656 | |||||
657 | std::vector<SwTextFrame*> frames; | ||||
658 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this); | ||||
659 | for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) | ||||
660 | { | ||||
661 | frames.push_back(pFrame); | ||||
662 | if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
663 | { | ||||
664 | isHide = true; | ||||
665 | } | ||||
666 | } | ||||
667 | bool bNonMerged(false); | ||||
668 | bool bRecreateThis(false); | ||||
669 | for (SwTextFrame * pFrame : frames) | ||||
670 | { | ||||
671 | // sw_redlinehide: for this to work properly with hidden nodes, | ||||
672 | // the frame needs to listen on them too. | ||||
673 | // also: have to check the frame; this->GetRedlineMergeFlag() | ||||
674 | // is None in case there's a delete redline inside the paragraph, | ||||
675 | // but that could still result in a merged frame after split... | ||||
676 | if (pFrame->GetMergedPara()) | ||||
677 | { | ||||
678 | // Can't special case this == First here - that could (if | ||||
679 | // both nodes are still merged by redline) lead to | ||||
680 | // duplicate frames on "this". | ||||
681 | // Update the extents with new node; also inits merge flag, | ||||
682 | // so the MakeFramesForAdjacentContentNode below respects it | ||||
683 | pFrame->RegisterToNode(*pNode); | ||||
684 | if (pFrame->GetText().isEmpty()) | ||||
685 | { | ||||
686 | // turns out it's empty - in this case, it was not | ||||
687 | // invalidated because Cut didn't sent it any hints, | ||||
688 | // so we have to invalidate it here! | ||||
689 | pFrame->Prepare(PrepareHint::Clear, nullptr, false); | ||||
690 | } | ||||
691 | if (!pFrame->GetMergedPara() || | ||||
692 | !pFrame->GetMergedPara()->listener.IsListeningTo(this)) | ||||
693 | { | ||||
694 | // it's no longer listening - need to recreate frame | ||||
695 | // (note this is idempotent, can be done once per frame) | ||||
696 | SetRedlineMergeFlag(SwNode::Merge::None); | ||||
697 | bRecreateThis = true; | ||||
698 | } | ||||
699 | } | ||||
700 | else | ||||
701 | { | ||||
702 | bNonMerged = true; | ||||
703 | } | ||||
704 | } | ||||
705 | assert(!(bNonMerged && bRecreateThis))(static_cast <bool> (!(bNonMerged && bRecreateThis )) ? void (0) : __assert_fail ("!(bNonMerged && bRecreateThis)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 705, __extension__ __PRETTY_FUNCTION__)); // 2 layouts not handled yet - maybe best to simply use the other branch then? | ||||
706 | if (!frames.empty() && bNonMerged) | ||||
707 | { | ||||
708 | // the existing frame on "this" should have been updated by Cut | ||||
709 | MakeFramesForAdjacentContentNode(*pNode); | ||||
710 | lcl_ChangeFootnoteRef(*pNode); | ||||
711 | } | ||||
712 | else if (bRecreateThis) | ||||
713 | { | ||||
714 | assert(pNode->HasWriterListeners())(static_cast <bool> (pNode->HasWriterListeners()) ? void (0) : __assert_fail ("pNode->HasWriterListeners()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 714, __extension__ __PRETTY_FUNCTION__)); // was just moved there | ||||
715 | pNode->MakeFramesForAdjacentContentNode(*this); | ||||
716 | lcl_ChangeFootnoteRef(*this); | ||||
717 | } | ||||
718 | |||||
719 | if (pContentIndexRestore) | ||||
720 | { // call after making frames; listeners will take care of adding to the right frame | ||||
721 | (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys); | ||||
722 | } | ||||
723 | |||||
724 | if (bRecreateThis) | ||||
725 | { | ||||
726 | MoveMergedFlysAndFootnotes(frames, *pNode, *this, true); | ||||
727 | } | ||||
728 | } | ||||
729 | |||||
730 | #ifndef NDEBUG | ||||
731 | if (isHide) // otherwise flags won't be set anyway | ||||
732 | { | ||||
733 | // First | ||||
734 | // -> First,NonFirst | ||||
735 | // -> First,Hidden | ||||
736 | // -> None,First | ||||
737 | // Hidden | ||||
738 | // -> Hidden,Hidden (if still inside merge rl) | ||||
739 | // -> NonFirst,First (if redline was split) | ||||
740 | // NonFirst | ||||
741 | // -> NonFirst,First (if split after end of "incoming" redline & | ||||
742 | // before start of "outgoing" redline) | ||||
743 | // -> NonFirst,None (if split after end of "incoming" redline) | ||||
744 | // -> NonFirst,Hidden (if split after start of "outgoing" redline) | ||||
745 | // -> Hidden, NonFirst (if split before end of "incoming" redline) | ||||
746 | // None | ||||
747 | // -> None,None | ||||
748 | // -> First,NonFirst (if splitting inside a delete redline) | ||||
749 | SwNode::Merge const eFirst(pNode->GetRedlineMergeFlag()); | ||||
750 | SwNode::Merge const eSecond(GetRedlineMergeFlag()); | ||||
751 | switch (eOldMergeFlag) | ||||
752 | { | ||||
753 | case Merge::First: | ||||
754 | assert((eFirst == Merge::First && eSecond == Merge::NonFirst)(static_cast <bool> ((eFirst == Merge::First && eSecond == Merge::NonFirst) || (eFirst == Merge::First && eSecond == Merge::Hidden) || (eFirst == Merge::None && eSecond == Merge::First)) ? void (0) : __assert_fail ("(eFirst == Merge::First && eSecond == Merge::NonFirst) || (eFirst == Merge::First && eSecond == Merge::Hidden) || (eFirst == Merge::None && eSecond == Merge::First)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 756, __extension__ __PRETTY_FUNCTION__)) | ||||
755 | || (eFirst == Merge::First && eSecond == Merge::Hidden)(static_cast <bool> ((eFirst == Merge::First && eSecond == Merge::NonFirst) || (eFirst == Merge::First && eSecond == Merge::Hidden) || (eFirst == Merge::None && eSecond == Merge::First)) ? void (0) : __assert_fail ("(eFirst == Merge::First && eSecond == Merge::NonFirst) || (eFirst == Merge::First && eSecond == Merge::Hidden) || (eFirst == Merge::None && eSecond == Merge::First)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 756, __extension__ __PRETTY_FUNCTION__)) | ||||
756 | || (eFirst == Merge::None && eSecond == Merge::First))(static_cast <bool> ((eFirst == Merge::First && eSecond == Merge::NonFirst) || (eFirst == Merge::First && eSecond == Merge::Hidden) || (eFirst == Merge::None && eSecond == Merge::First)) ? void (0) : __assert_fail ("(eFirst == Merge::First && eSecond == Merge::NonFirst) || (eFirst == Merge::First && eSecond == Merge::Hidden) || (eFirst == Merge::None && eSecond == Merge::First)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 756, __extension__ __PRETTY_FUNCTION__)); | ||||
757 | break; | ||||
758 | case Merge::Hidden: | ||||
759 | assert((eFirst == Merge::Hidden && eSecond == Merge::Hidden)(static_cast <bool> ((eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)) ? void (0) : __assert_fail ("(eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 763, __extension__ __PRETTY_FUNCTION__)) | ||||
760 | || (eFirst == Merge::NonFirst && eSecond == Merge::First)(static_cast <bool> ((eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)) ? void (0) : __assert_fail ("(eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 763, __extension__ __PRETTY_FUNCTION__)) | ||||
761 | // next ones can happen temp. in UndoDelete :((static_cast <bool> ((eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)) ? void (0) : __assert_fail ("(eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 763, __extension__ __PRETTY_FUNCTION__)) | ||||
762 | || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)(static_cast <bool> ((eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)) ? void (0) : __assert_fail ("(eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 763, __extension__ __PRETTY_FUNCTION__)) | ||||
763 | || (eFirst == Merge::NonFirst && eSecond == Merge::None))(static_cast <bool> ((eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)) ? void (0) : __assert_fail ("(eFirst == Merge::Hidden && eSecond == Merge::Hidden) || (eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) || (eFirst == Merge::NonFirst && eSecond == Merge::None)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 763, __extension__ __PRETTY_FUNCTION__)); | ||||
764 | break; | ||||
765 | case Merge::NonFirst: | ||||
766 | assert((eFirst == Merge::NonFirst && eSecond == Merge::First)(static_cast <bool> ((eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)) ? void (0) : __assert_fail ("(eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 769, __extension__ __PRETTY_FUNCTION__)) | ||||
767 | || (eFirst == Merge::NonFirst && eSecond == Merge::None)(static_cast <bool> ((eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)) ? void (0) : __assert_fail ("(eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 769, __extension__ __PRETTY_FUNCTION__)) | ||||
768 | || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden)(static_cast <bool> ((eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)) ? void (0) : __assert_fail ("(eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 769, __extension__ __PRETTY_FUNCTION__)) | ||||
769 | || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst))(static_cast <bool> ((eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)) ? void (0) : __assert_fail ("(eFirst == Merge::NonFirst && eSecond == Merge::First) || (eFirst == Merge::NonFirst && eSecond == Merge::None) || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden) || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 769, __extension__ __PRETTY_FUNCTION__)); | ||||
770 | break; | ||||
771 | case Merge::None: | ||||
772 | assert((eFirst == Merge::None && eSecond == Merge::None)(static_cast <bool> ((eFirst == Merge::None && eSecond == Merge::None) || (eFirst == Merge::First && eSecond == Merge::NonFirst)) ? void (0) : __assert_fail ("(eFirst == Merge::None && eSecond == Merge::None) || (eFirst == Merge::First && eSecond == Merge::NonFirst)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 773, __extension__ __PRETTY_FUNCTION__)) | ||||
773 | || (eFirst == Merge::First && eSecond == Merge::NonFirst))(static_cast <bool> ((eFirst == Merge::None && eSecond == Merge::None) || (eFirst == Merge::First && eSecond == Merge::NonFirst)) ? void (0) : __assert_fail ("(eFirst == Merge::None && eSecond == Merge::None) || (eFirst == Merge::First && eSecond == Merge::NonFirst)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 773, __extension__ __PRETTY_FUNCTION__)); | ||||
774 | break; | ||||
775 | } | ||||
776 | } | ||||
777 | #else | ||||
778 | (void) isHide; | ||||
779 | #endif | ||||
780 | |||||
781 | { | ||||
782 | // Send Hint for PageDesc. This should be done in the Layout when | ||||
783 | // pasting the frames, but that causes other problems that look | ||||
784 | // expensive to solve. | ||||
785 | const SfxPoolItem *pItem; | ||||
786 | if( HasWriterListeners() && SfxItemState::SET == pNode->GetSwAttrSet(). | ||||
787 | GetItemState( RES_PAGEDESC, true, &pItem ) ) | ||||
788 | { | ||||
789 | pNode->ModifyNotification( pItem, pItem ); | ||||
790 | } | ||||
791 | } | ||||
792 | return pNode; | ||||
793 | } | ||||
794 | |||||
795 | void SwTextNode::MoveTextAttr_To_AttrSet() | ||||
796 | { | ||||
797 | OSL_ENSURE( m_pSwpHints, "MoveTextAttr_To_AttrSet without SwpHints?" )do { if (true && (!(m_pSwpHints))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "797" ": "), "%s", "MoveTextAttr_To_AttrSet without SwpHints?" ); } } while (false); | ||||
798 | for ( size_t i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) | ||||
799 | { | ||||
800 | SwTextAttr *pHt = m_pSwpHints->Get(i); | ||||
801 | |||||
802 | if( pHt->GetStart() ) | ||||
803 | break; | ||||
804 | |||||
805 | const sal_Int32* pHtEndIdx = pHt->GetEnd(); | ||||
806 | |||||
807 | if( !pHtEndIdx ) | ||||
808 | continue; | ||||
809 | |||||
810 | if (*pHtEndIdx < m_Text.getLength() || pHt->IsCharFormatAttr()) | ||||
811 | break; | ||||
812 | |||||
813 | if( !pHt->IsDontMoveAttr() && | ||||
814 | SetAttr( pHt->GetAttr() ) ) | ||||
815 | { | ||||
816 | m_pSwpHints->DeleteAtPos(i); | ||||
817 | DestroyAttr( pHt ); | ||||
818 | --i; | ||||
819 | } | ||||
820 | } | ||||
821 | |||||
822 | } | ||||
823 | |||||
824 | namespace sw { | ||||
825 | |||||
826 | /// if first node is deleted & second survives, then the first node's frame | ||||
827 | /// will be deleted too; prevent this by moving the frame to the second node | ||||
828 | /// if necessary. | ||||
829 | void MoveDeletedPrevFrames(const SwTextNode & rDeletedPrev, SwTextNode & rNode) | ||||
830 | { | ||||
831 | std::vector<SwTextFrame*> frames; | ||||
832 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rDeletedPrev); | ||||
833 | for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) | ||||
834 | { | ||||
835 | if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
836 | { | ||||
837 | frames.push_back(pFrame); | ||||
838 | } | ||||
839 | } | ||||
840 | { | ||||
841 | auto frames2(frames); | ||||
842 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIt(rNode); | ||||
843 | for (SwTextFrame* pFrame = aIt.First(); pFrame; pFrame = aIt.Next()) | ||||
844 | { | ||||
845 | if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
846 | { | ||||
847 | auto const it(std::find(frames2.begin(), frames2.end(), pFrame)); | ||||
848 | assert(it != frames2.end())(static_cast <bool> (it != frames2.end()) ? void (0) : __assert_fail ("it != frames2.end()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 848, __extension__ __PRETTY_FUNCTION__)); | ||||
849 | frames2.erase(it); | ||||
850 | } | ||||
851 | } | ||||
852 | assert(frames2.empty())(static_cast <bool> (frames2.empty()) ? void (0) : __assert_fail ("frames2.empty()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 852, __extension__ __PRETTY_FUNCTION__)); | ||||
853 | } | ||||
854 | for (SwTextFrame *const pFrame : frames) | ||||
855 | { | ||||
856 | pFrame->RegisterToNode(rNode, true); | ||||
857 | } | ||||
858 | } | ||||
859 | |||||
860 | // typical Join: | ||||
861 | // None,Node->None | ||||
862 | // None,First->First | ||||
863 | // First,NonFirst->First | ||||
864 | // NonFirst,First->NonFirst | ||||
865 | // NonFirst,None->NonFirst | ||||
866 | |||||
867 | /// if first node is First, its frames may need to be moved, never deleted. | ||||
868 | /// if first node is NonFirst, second node's own frames (First/None) must be deleted | ||||
869 | void CheckResetRedlineMergeFlag(SwTextNode & rNode, Recreate const eRecreateMerged) | ||||
870 | { | ||||
871 | if (eRecreateMerged != sw::Recreate::No) | ||||
872 | { | ||||
873 | SwTextNode * pMergeNode(&rNode); | ||||
874 | if (eRecreateMerged == sw::Recreate::Predecessor | ||||
875 | // tdf#135018 check that there is a predecessor node, i.e. rNode | ||||
876 | // isn't the first node after the body start node | ||||
877 | && rNode.GetNodes()[rNode.GetIndex() - 1]->StartOfSectionIndex() != 0) | ||||
878 | { | ||||
879 | for (sal_uLong i = rNode.GetIndex() - 1; ; --i) | ||||
880 | { | ||||
881 | SwNode *const pNode(rNode.GetNodes()[i]); | ||||
882 | assert(!pNode->IsStartNode())(static_cast <bool> (!pNode->IsStartNode()) ? void ( 0) : __assert_fail ("!pNode->IsStartNode()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 882, __extension__ __PRETTY_FUNCTION__)); | ||||
883 | if (pNode->IsEndNode()) | ||||
884 | { | ||||
885 | i = pNode->StartOfSectionIndex(); | ||||
886 | } | ||||
887 | else if (pNode->IsTextNode()) | ||||
888 | { | ||||
889 | pMergeNode = pNode->GetTextNode(); // use predecessor to merge | ||||
890 | break; | ||||
891 | } | ||||
892 | } | ||||
893 | } | ||||
894 | std::vector<SwTextFrame*> frames; | ||||
895 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pMergeNode); | ||||
896 | for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) | ||||
897 | { | ||||
898 | if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
899 | { | ||||
900 | frames.push_back(pFrame); | ||||
901 | } | ||||
902 | } | ||||
903 | auto eMode(sw::FrameMode::Existing); | ||||
904 | for (SwTextFrame * pFrame : frames) | ||||
905 | { | ||||
906 | SwTextNode & rFirstNode(pFrame->GetMergedPara() | ||||
907 | ? *pFrame->GetMergedPara()->pFirstNode | ||||
908 | : *pMergeNode); | ||||
909 | assert(rFirstNode.GetIndex() <= rNode.GetIndex())(static_cast <bool> (rFirstNode.GetIndex() <= rNode. GetIndex()) ? void (0) : __assert_fail ("rFirstNode.GetIndex() <= rNode.GetIndex()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 909, __extension__ __PRETTY_FUNCTION__)); | ||||
910 | pFrame->SetMergedPara(sw::CheckParaRedlineMerge( | ||||
911 | *pFrame, rFirstNode, eMode)); | ||||
912 | assert(pFrame->GetMergedPara())(static_cast <bool> (pFrame->GetMergedPara()) ? void (0) : __assert_fail ("pFrame->GetMergedPara()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 912, __extension__ __PRETTY_FUNCTION__)); | ||||
913 | assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode))(static_cast <bool> (pFrame->GetMergedPara()->listener .IsListeningTo(&rNode)) ? void (0) : __assert_fail ("pFrame->GetMergedPara()->listener.IsListeningTo(&rNode)" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 913, __extension__ __PRETTY_FUNCTION__)); | ||||
914 | assert(rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex())(static_cast <bool> (rNode.GetIndex() <= pFrame-> GetMergedPara()->pLastNode->GetIndex()) ? void (0) : __assert_fail ("rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 914, __extension__ __PRETTY_FUNCTION__)); | ||||
915 | eMode = sw::FrameMode::New; // Existing is not idempotent! | ||||
916 | } | ||||
917 | } | ||||
918 | else if (rNode.GetRedlineMergeFlag() != SwNode::Merge::None) | ||||
919 | { | ||||
920 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode); | ||||
921 | for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) | ||||
922 | { | ||||
923 | if (auto const pMergedPara = pFrame->GetMergedPara()) | ||||
924 | { | ||||
925 | if (pMergedPara->pFirstNode == pMergedPara->pLastNode) | ||||
926 | { | ||||
927 | assert(pMergedPara->pFirstNode == &rNode)(static_cast <bool> (pMergedPara->pFirstNode == & rNode) ? void (0) : __assert_fail ("pMergedPara->pFirstNode == &rNode" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 927, __extension__ __PRETTY_FUNCTION__)); | ||||
928 | rNode.SetRedlineMergeFlag(SwNode::Merge::None); | ||||
929 | } | ||||
930 | break; // checking once is enough | ||||
931 | } | ||||
932 | else if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
933 | { | ||||
934 | rNode.SetRedlineMergeFlag(SwNode::Merge::None); | ||||
935 | break; // checking once is enough | ||||
936 | } | ||||
937 | } | ||||
938 | } | ||||
939 | } | ||||
940 | |||||
941 | } // namespace | ||||
942 | |||||
943 | SwContentNode *SwTextNode::JoinNext() | ||||
944 | { | ||||
945 | SwNodes& rNds = GetNodes(); | ||||
946 | SwNodeIndex aIdx( *this ); | ||||
947 | if( SwContentNode::CanJoinNext( &aIdx ) ) | ||||
948 | { | ||||
949 | SwDoc& rDoc = rNds.GetDoc(); | ||||
950 | const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create()); | ||||
951 | pContentStore->Save(rDoc, aIdx.GetIndex(), SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF)); | ||||
952 | SwTextNode *pTextNode = aIdx.GetNode().GetTextNode(); | ||||
953 | sal_Int32 nOldLen = m_Text.getLength(); | ||||
954 | |||||
955 | // METADATA: merge | ||||
956 | JoinMetadatable(*pTextNode, !Len(), !pTextNode->Len()); | ||||
957 | |||||
958 | SwWrongList *pList = GetWrong(); | ||||
959 | if( pList ) | ||||
960 | { | ||||
961 | pList->JoinList( pTextNode->GetWrong(), nOldLen ); | ||||
962 | SetWrongDirty(WrongState::TODO); | ||||
963 | SetWrong( nullptr, false ); | ||||
964 | } | ||||
965 | else | ||||
966 | { | ||||
967 | pList = pTextNode->GetWrong(); | ||||
968 | if( pList ) | ||||
969 | { | ||||
970 | pList->Move( 0, nOldLen ); | ||||
971 | SetWrongDirty(WrongState::TODO); | ||||
972 | pTextNode->SetWrong( nullptr, false ); | ||||
973 | } | ||||
974 | } | ||||
975 | |||||
976 | SwGrammarMarkUp *pList3 = GetGrammarCheck(); | ||||
977 | if( pList3 ) | ||||
978 | { | ||||
979 | pList3->JoinGrammarList( pTextNode->GetGrammarCheck(), nOldLen ); | ||||
980 | SetGrammarCheckDirty( true ); | ||||
981 | SetGrammarCheck( nullptr, false ); | ||||
982 | } | ||||
983 | else | ||||
984 | { | ||||
985 | pList3 = pTextNode->GetGrammarCheck(); | ||||
986 | if( pList3 ) | ||||
987 | { | ||||
988 | pList3->MoveGrammar( 0, nOldLen ); | ||||
989 | SetGrammarCheckDirty( true ); | ||||
990 | pTextNode->SetGrammarCheck( nullptr, false ); | ||||
991 | } | ||||
992 | } | ||||
993 | |||||
994 | SwWrongList *pList2 = GetSmartTags(); | ||||
995 | if( pList2 ) | ||||
996 | { | ||||
997 | pList2->JoinList( pTextNode->GetSmartTags(), nOldLen ); | ||||
998 | SetSmartTagDirty( true ); | ||||
999 | SetSmartTags( nullptr, false ); | ||||
1000 | } | ||||
1001 | else | ||||
1002 | { | ||||
1003 | pList2 = pTextNode->GetSmartTags(); | ||||
1004 | if( pList2 ) | ||||
1005 | { | ||||
1006 | pList2->Move( 0, nOldLen ); | ||||
1007 | SetSmartTagDirty( true ); | ||||
1008 | pTextNode->SetSmartTags( nullptr, false ); | ||||
1009 | } | ||||
1010 | } | ||||
1011 | |||||
1012 | { // scope for SwIndex | ||||
1013 | pTextNode->CutText( this, SwIndex(pTextNode), pTextNode->Len() ); | ||||
1014 | } | ||||
1015 | // move all Bookmarks/TOXMarks | ||||
1016 | if( !pContentStore->Empty()) | ||||
1017 | pContentStore->Restore( rDoc, GetIndex(), nOldLen ); | ||||
1018 | |||||
1019 | if( pTextNode->HasAnyIndex() ) | ||||
1020 | { | ||||
1021 | // move all ShellCursor/StackCursor/UnoCursor out of delete range | ||||
1022 | rDoc.CorrAbs( aIdx, SwPosition( *this ), nOldLen, true ); | ||||
1023 | } | ||||
1024 | SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag()); | ||||
1025 | rNds.Delete(aIdx); | ||||
1026 | SetWrong( pList, false ); | ||||
1027 | SetGrammarCheck( pList3, false ); | ||||
1028 | SetSmartTags( pList2, false ); | ||||
1029 | InvalidateNumRule(); | ||||
1030 | CheckResetRedlineMergeFlag(*this, eOldMergeFlag == SwNode::Merge::First | ||||
1031 | ? sw::Recreate::ThisNode | ||||
1032 | : sw::Recreate::No); | ||||
1033 | } | ||||
1034 | else { | ||||
1035 | OSL_FAIL( "No TextNode." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1035" ": "), "%s", "No TextNode."); } } while (false); | ||||
1036 | } | ||||
1037 | |||||
1038 | return this; | ||||
1039 | } | ||||
1040 | |||||
1041 | void SwTextNode::JoinPrev() | ||||
1042 | { | ||||
1043 | SwNodes& rNds = GetNodes(); | ||||
1044 | SwNodeIndex aIdx( *this ); | ||||
1045 | if( SwContentNode::CanJoinPrev( &aIdx ) ) | ||||
1046 | { | ||||
1047 | SwDoc& rDoc = rNds.GetDoc(); | ||||
1048 | const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create()); | ||||
1049 | pContentStore->Save( rDoc, aIdx.GetIndex(), SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF)); | ||||
1050 | SwTextNode *pTextNode = aIdx.GetNode().GetTextNode(); | ||||
1051 | const sal_Int32 nLen = pTextNode->Len(); | ||||
1052 | |||||
1053 | SwWrongList *pList = pTextNode->GetWrong(); | ||||
1054 | if( pList ) | ||||
1055 | { | ||||
1056 | pList->JoinList( GetWrong(), Len() ); | ||||
1057 | SetWrongDirty(WrongState::TODO); | ||||
1058 | pTextNode->SetWrong( nullptr, false ); | ||||
1059 | SetWrong( nullptr ); | ||||
1060 | } | ||||
1061 | else | ||||
1062 | { | ||||
1063 | pList = GetWrong(); | ||||
1064 | if( pList ) | ||||
1065 | { | ||||
1066 | pList->Move( 0, nLen ); | ||||
1067 | SetWrongDirty(WrongState::TODO); | ||||
1068 | SetWrong( nullptr, false ); | ||||
1069 | } | ||||
1070 | } | ||||
1071 | |||||
1072 | SwGrammarMarkUp *pList3 = pTextNode->GetGrammarCheck(); | ||||
1073 | if( pList3 ) | ||||
1074 | { | ||||
1075 | pList3->JoinGrammarList( GetGrammarCheck(), Len() ); | ||||
1076 | SetGrammarCheckDirty( true ); | ||||
1077 | pTextNode->SetGrammarCheck( nullptr, false ); | ||||
1078 | SetGrammarCheck( nullptr ); | ||||
1079 | } | ||||
1080 | else | ||||
1081 | { | ||||
1082 | pList3 = GetGrammarCheck(); | ||||
1083 | if( pList3 ) | ||||
1084 | { | ||||
1085 | pList3->MoveGrammar( 0, nLen ); | ||||
1086 | SetGrammarCheckDirty( true ); | ||||
1087 | SetGrammarCheck( nullptr, false ); | ||||
1088 | } | ||||
1089 | } | ||||
1090 | |||||
1091 | SwWrongList *pList2 = pTextNode->GetSmartTags(); | ||||
1092 | if( pList2 ) | ||||
1093 | { | ||||
1094 | pList2->JoinList( GetSmartTags(), Len() ); | ||||
1095 | SetSmartTagDirty( true ); | ||||
1096 | pTextNode->SetSmartTags( nullptr, false ); | ||||
1097 | SetSmartTags( nullptr ); | ||||
1098 | } | ||||
1099 | else | ||||
1100 | { | ||||
1101 | pList2 = GetSmartTags(); | ||||
1102 | if( pList2 ) | ||||
1103 | { | ||||
1104 | pList2->Move( 0, nLen ); | ||||
1105 | SetSmartTagDirty( true ); | ||||
1106 | SetSmartTags( nullptr, false ); | ||||
1107 | } | ||||
1108 | } | ||||
1109 | |||||
1110 | { // scope for SwIndex | ||||
1111 | pTextNode->CutText( this, SwIndex(this), SwIndex(pTextNode), nLen ); | ||||
1112 | } | ||||
1113 | // move all Bookmarks/TOXMarks | ||||
1114 | if( !pContentStore->Empty() ) | ||||
1115 | pContentStore->Restore( rDoc, GetIndex() ); | ||||
1116 | |||||
1117 | if( pTextNode->HasAnyIndex() ) | ||||
1118 | { | ||||
1119 | // move all ShellCursor/StackCursor/UnoCursor out of delete range | ||||
1120 | rDoc.CorrAbs( aIdx, SwPosition( *this ), nLen, true ); | ||||
1121 | } | ||||
1122 | SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag()); | ||||
1123 | if (eOldMergeFlag == SwNode::Merge::First | ||||
1124 | && !IsCreateFrameWhenHidingRedlines()) | ||||
1125 | { | ||||
1126 | sw::MoveDeletedPrevFrames(*pTextNode, *this); | ||||
1127 | } | ||||
1128 | rNds.Delete(aIdx); | ||||
1129 | SetWrong( pList, false ); | ||||
1130 | SetGrammarCheck( pList3, false ); | ||||
1131 | SetSmartTags( pList2, false ); | ||||
1132 | InvalidateNumRule(); | ||||
1133 | sw::CheckResetRedlineMergeFlag(*this, | ||||
1134 | eOldMergeFlag == SwNode::Merge::NonFirst | ||||
1135 | ? sw::Recreate::Predecessor | ||||
1136 | : sw::Recreate::No); | ||||
1137 | } | ||||
1138 | else { | ||||
1139 | OSL_FAIL( "No TextNode." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1139" ": "), "%s", "No TextNode."); } } while (false); | ||||
1140 | } | ||||
1141 | } | ||||
1142 | |||||
1143 | // create an AttrSet with ranges for Frame-/Para/Char-attributes | ||||
1144 | void SwTextNode::NewAttrSet( SwAttrPool& rPool ) | ||||
1145 | { | ||||
1146 | OSL_ENSURE( !mpAttrSet, "AttrSet is set after all" )do { if (true && (!(!mpAttrSet))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1146" ": "), "%s", "AttrSet is set after all"); } } while (false); | ||||
1147 | SwAttrSet aNewAttrSet( rPool, aTextNodeSetRange ); | ||||
1148 | |||||
1149 | // put names of parent style and conditional style: | ||||
1150 | const SwFormatColl* pAnyFormatColl = &GetAnyFormatColl(); | ||||
1151 | const SwFormatColl* pFormatColl = GetFormatColl(); | ||||
1152 | OUString sVal; | ||||
1153 | SwStyleNameMapper::FillProgName( pAnyFormatColl->GetName(), sVal, SwGetPoolIdFromName::TxtColl ); | ||||
1154 | SfxStringItem aAnyFormatColl( RES_FRMATR_STYLE_NAME, sVal ); | ||||
1155 | if ( pFormatColl != pAnyFormatColl ) | ||||
1156 | SwStyleNameMapper::FillProgName( pFormatColl->GetName(), sVal, SwGetPoolIdFromName::TxtColl ); | ||||
1157 | SfxStringItem aFormatColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal ); | ||||
1158 | aNewAttrSet.Put( aAnyFormatColl ); | ||||
1159 | aNewAttrSet.Put( aFormatColl ); | ||||
1160 | |||||
1161 | aNewAttrSet.SetParent( &pAnyFormatColl->GetAttrSet() ); | ||||
1162 | mpAttrSet = GetDoc().GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA, &sVal ); | ||||
1163 | } | ||||
1164 | |||||
1165 | // override SwIndexReg::Update => text hints do not need SwIndex for start/end! | ||||
1166 | void SwTextNode::Update( | ||||
1167 | SwIndex const & rPos, | ||||
1168 | const sal_Int32 nChangeLen, | ||||
1169 | const bool bNegative, | ||||
1170 | const bool bDelete ) | ||||
1171 | { | ||||
1172 | SetAutoCompleteWordDirty( true ); | ||||
1173 | |||||
1174 | std::unique_ptr<SwpHts> pCollector; | ||||
1175 | const sal_Int32 nChangePos = rPos.GetIndex(); | ||||
1176 | |||||
1177 | if ( HasHints() ) | ||||
1178 | { | ||||
1179 | if ( bNegative ) | ||||
1180 | { | ||||
1181 | std::vector<SwTextInputField*> aTextInputFields; | ||||
1182 | |||||
1183 | const sal_Int32 nChangeEnd = nChangePos + nChangeLen; | ||||
1184 | for ( size_t n = 0; n < m_pSwpHints->Count(); ++n ) | ||||
1185 | { | ||||
1186 | bool bTextAttrChanged = false; | ||||
1187 | bool bStartOfTextAttrChanged = false; | ||||
1188 | SwTextAttr * const pHint = m_pSwpHints->GetWithoutResorting(n); | ||||
1189 | if ( pHint->GetStart() > nChangePos ) | ||||
1190 | { | ||||
1191 | if ( pHint->GetStart() > nChangeEnd ) | ||||
1192 | { | ||||
1193 | pHint->SetStart( pHint->GetStart() - nChangeLen ); | ||||
1194 | } | ||||
1195 | else | ||||
1196 | { | ||||
1197 | pHint->SetStart( nChangePos ); | ||||
1198 | } | ||||
1199 | bStartOfTextAttrChanged = true; | ||||
1200 | } | ||||
1201 | |||||
1202 | const sal_Int32 * const pEnd = pHint->GetEnd(); | ||||
1203 | if (pEnd && *pEnd > nChangePos ) | ||||
1204 | { | ||||
1205 | if( *pEnd > nChangeEnd ) | ||||
1206 | { | ||||
1207 | pHint->SetEnd(*pEnd - nChangeLen); | ||||
1208 | } | ||||
1209 | else | ||||
1210 | { | ||||
1211 | pHint->SetEnd(nChangePos); | ||||
1212 | } | ||||
1213 | bTextAttrChanged = !bStartOfTextAttrChanged; | ||||
1214 | } | ||||
1215 | |||||
1216 | if ( bTextAttrChanged | ||||
1217 | && pHint->Which() == RES_TXTATR_INPUTFIELD ) | ||||
1218 | { | ||||
1219 | SwTextInputField* pTextInputField = dynamic_cast<SwTextInputField*>(pHint); | ||||
1220 | if ( pTextInputField ) | ||||
1221 | aTextInputFields.push_back(pTextInputField); | ||||
1222 | } | ||||
1223 | } | ||||
1224 | |||||
1225 | //wait until all the attribute positions are correct | ||||
1226 | //before updating the field contents | ||||
1227 | for (SwTextInputField* pTextInputField : aTextInputFields) | ||||
1228 | { | ||||
1229 | pTextInputField->UpdateFieldContent(); | ||||
1230 | } | ||||
1231 | |||||
1232 | m_pSwpHints->MergePortions( *this ); | ||||
1233 | } | ||||
1234 | else | ||||
1235 | { | ||||
1236 | bool bNoExp = false; | ||||
1237 | bool bResort = false; | ||||
1238 | bool bMergePortionsNeeded = false; | ||||
1239 | const int coArrSz = RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN; | ||||
1240 | std::vector<SwTextInputField*> aTextInputFields; | ||||
1241 | |||||
1242 | bool aDontExp[ coArrSz ] = {}; | ||||
1243 | |||||
1244 | for ( size_t n = 0; n < m_pSwpHints->Count(); ++n ) | ||||
1245 | { | ||||
1246 | bool bTextAttrChanged = false; | ||||
1247 | SwTextAttr * const pHint = m_pSwpHints->GetWithoutResorting(n); | ||||
1248 | const sal_Int32 * const pEnd = pHint->GetEnd(); | ||||
1249 | if ( pHint->GetStart() >= nChangePos ) | ||||
1250 | { | ||||
1251 | pHint->SetStart( pHint->GetStart() + nChangeLen ); | ||||
1252 | if ( pEnd ) | ||||
1253 | { | ||||
1254 | pHint->SetEnd(*pEnd + nChangeLen); | ||||
1255 | } | ||||
1256 | } | ||||
1257 | else if ( pEnd && (*pEnd >= nChangePos) ) | ||||
1258 | { | ||||
1259 | if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() ) | ||||
1260 | { | ||||
1261 | pHint->SetEnd(*pEnd + nChangeLen); | ||||
1262 | bTextAttrChanged = true; | ||||
1263 | } | ||||
1264 | else // *pEnd == nChangePos | ||||
1265 | { | ||||
1266 | const sal_uInt16 nWhich = pHint->Which(); | ||||
1267 | |||||
1268 | OSL_ENSURE(!isCHRATR(nWhich), "Update: char attr hint?")do { if (true && (!(!isCHRATR(nWhich)))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1268" ": "), "%s", "Update: char attr hint?"); } } while (false); | ||||
1269 | if (!(isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich))) | ||||
1270 | continue; | ||||
1271 | |||||
1272 | const sal_uInt16 nWhPos = nWhich - RES_CHRATR_BEGIN; | ||||
1273 | |||||
1274 | if( aDontExp[ nWhPos ] ) | ||||
1275 | continue; | ||||
1276 | |||||
1277 | if ( pHint->DontExpand() ) | ||||
1278 | { | ||||
1279 | pHint->SetDontExpand( false ); | ||||
1280 | bResort = true; | ||||
1281 | // could have a continuation with IgnoreStart()... | ||||
1282 | if (pHint->IsFormatIgnoreEnd()) | ||||
1283 | { | ||||
1284 | bMergePortionsNeeded = true; | ||||
1285 | } | ||||
1286 | if ( pHint->IsCharFormatAttr() ) | ||||
1287 | { | ||||
1288 | bNoExp = true; | ||||
1289 | aDontExp[ RES_TXTATR_CHARFMT - RES_CHRATR_BEGIN ] = true; | ||||
1290 | aDontExp[ RES_TXTATR_INETFMT - RES_CHRATR_BEGIN ] = true; | ||||
1291 | } | ||||
1292 | else | ||||
1293 | aDontExp[ nWhPos ] = true; | ||||
1294 | } | ||||
1295 | else if( bNoExp ) | ||||
1296 | { | ||||
1297 | if (!pCollector) | ||||
1298 | { | ||||
1299 | pCollector.reset( new SwpHts ); | ||||
1300 | } | ||||
1301 | auto it = std::find_if(pCollector->begin(), pCollector->end(), | ||||
1302 | [nWhich](const SwTextAttr *pTmp) { return nWhich == pTmp->Which(); }); | ||||
1303 | if (it != pCollector->end()) | ||||
1304 | { | ||||
1305 | SwTextAttr *pTmp = *it; | ||||
1306 | pCollector->erase( it ); | ||||
1307 | SwTextAttr::Destroy( pTmp, GetDoc().GetAttrPool() ); | ||||
1308 | } | ||||
1309 | SwTextAttr * const pTmp = | ||||
1310 | MakeTextAttr( GetDoc(), | ||||
1311 | pHint->GetAttr(), nChangePos, nChangePos + nChangeLen); | ||||
1312 | pCollector->push_back( pTmp ); | ||||
1313 | } | ||||
1314 | else | ||||
1315 | { | ||||
1316 | pHint->SetEnd(*pEnd + nChangeLen); | ||||
1317 | bTextAttrChanged = true; | ||||
1318 | } | ||||
1319 | } | ||||
1320 | } | ||||
1321 | |||||
1322 | if ( bTextAttrChanged | ||||
1323 | && pHint->Which() == RES_TXTATR_INPUTFIELD ) | ||||
1324 | { | ||||
1325 | SwTextInputField* pTextInputField = dynamic_cast<SwTextInputField*>(pHint); | ||||
1326 | if ( pTextInputField ) | ||||
1327 | aTextInputFields.push_back(pTextInputField); | ||||
1328 | } | ||||
1329 | } | ||||
1330 | |||||
1331 | //wait until all the attribute positions are correct | ||||
1332 | //before updating the field contents | ||||
1333 | for (SwTextInputField* pTextInputField : aTextInputFields) | ||||
1334 | { | ||||
1335 | pTextInputField->UpdateFieldContent(); | ||||
1336 | } | ||||
1337 | |||||
1338 | if (bMergePortionsNeeded) | ||||
1339 | { | ||||
1340 | m_pSwpHints->MergePortions(*this); // does Resort too | ||||
1341 | } | ||||
1342 | else if (bResort) | ||||
1343 | { | ||||
1344 | m_pSwpHints->Resort(); | ||||
1345 | } | ||||
1346 | } | ||||
1347 | } | ||||
1348 | |||||
1349 | bool bSortMarks = false; | ||||
1350 | SwIndexReg aTmpIdxReg; | ||||
1351 | if ( !bNegative && !bDelete ) | ||||
1352 | { | ||||
1353 | const SwRedlineTable& rTable = GetDoc().getIDocumentRedlineAccess().GetRedlineTable(); | ||||
1354 | for (SwRangeRedline* pRedl : rTable) | ||||
1355 | { | ||||
1356 | if ( pRedl->HasMark() ) | ||||
1357 | { | ||||
1358 | SwPosition* const pEnd = pRedl->End(); | ||||
1359 | if ( this == &pEnd->nNode.GetNode() && | ||||
1360 | *pRedl->GetPoint() != *pRedl->GetMark() ) | ||||
1361 | { | ||||
1362 | SwIndex & rIdx = pEnd->nContent; | ||||
1363 | if (nChangePos == rIdx.GetIndex()) | ||||
1364 | { | ||||
1365 | rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() ); | ||||
1366 | } | ||||
1367 | } | ||||
1368 | } | ||||
1369 | else if ( this == &pRedl->GetPoint()->nNode.GetNode() ) | ||||
1370 | { | ||||
1371 | SwIndex & rIdx = pRedl->GetPoint()->nContent; | ||||
1372 | if (nChangePos == rIdx.GetIndex()) | ||||
1373 | { | ||||
1374 | rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() ); | ||||
1375 | } | ||||
1376 | // the unused position must not be on a SwTextNode | ||||
1377 | bool const isOneUsed(&pRedl->GetBound() == pRedl->GetPoint()); | ||||
1378 | assert(!pRedl->GetBound(!isOneUsed).nNode.GetNode().IsTextNode())(static_cast <bool> (!pRedl->GetBound(!isOneUsed).nNode .GetNode().IsTextNode()) ? void (0) : __assert_fail ("!pRedl->GetBound(!isOneUsed).nNode.GetNode().IsTextNode()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1378, __extension__ __PRETTY_FUNCTION__)); | ||||
1379 | assert(!pRedl->GetBound(!isOneUsed).nContent.GetIdxReg())(static_cast <bool> (!pRedl->GetBound(!isOneUsed).nContent .GetIdxReg()) ? void (0) : __assert_fail ("!pRedl->GetBound(!isOneUsed).nContent.GetIdxReg()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1379, __extension__ __PRETTY_FUNCTION__)); (void)isOneUsed; | ||||
1380 | } | ||||
1381 | } | ||||
1382 | |||||
1383 | // Bookmarks must never grow to either side, when editing (directly) | ||||
1384 | // to the left or right (i#29942)! Exception: if the bookmark has | ||||
1385 | // 2 positions and start == end, then expand it (tdf#96479) | ||||
1386 | { | ||||
1387 | bool bAtLeastOneBookmarkMoved = false; | ||||
1388 | bool bAtLeastOneExpandedBookmarkAtInsertionPosition = false; | ||||
1389 | // A text node already knows its marks via its SwIndexes. | ||||
1390 | o3tl::sorted_vector<const sw::mark::IMark*> aSeenMarks; | ||||
1391 | const SwIndex* next; | ||||
1392 | for (const SwIndex* pIndex = GetFirstIndex(); pIndex; pIndex = next ) | ||||
1393 | { | ||||
1394 | next = pIndex->GetNext(); | ||||
1395 | const sw::mark::IMark* pMark = pIndex->GetMark(); | ||||
1396 | if (!pMark) | ||||
1397 | continue; | ||||
1398 | // Only handle bookmarks once, if they start and end at this node as well. | ||||
1399 | if (!aSeenMarks.insert(pMark).second) | ||||
1400 | continue; | ||||
1401 | const SwPosition* pEnd = &pMark->GetMarkEnd(); | ||||
1402 | SwIndex & rEndIdx = const_cast<SwIndex&>(pEnd->nContent); | ||||
1403 | if( this == &pEnd->nNode.GetNode() && | ||||
1404 | rPos.GetIndex() == rEndIdx.GetIndex() ) | ||||
1405 | { | ||||
1406 | if (&rEndIdx == next) // nasty corner case: | ||||
1407 | { // don't switch to iterating aTmpIdxReg! | ||||
1408 | next = rEndIdx.GetNext(); | ||||
1409 | } | ||||
1410 | // tdf#96479: if start == end, ignore the other position | ||||
1411 | // so it is moved! | ||||
1412 | rEndIdx.Assign( &aTmpIdxReg, rEndIdx.GetIndex() ); | ||||
1413 | bAtLeastOneBookmarkMoved = true; | ||||
1414 | } | ||||
1415 | else if ( !bAtLeastOneExpandedBookmarkAtInsertionPosition ) | ||||
1416 | { | ||||
1417 | if ( pMark->IsExpanded() ) | ||||
1418 | { | ||||
1419 | const SwPosition* pStart = &pMark->GetMarkStart(); | ||||
1420 | if ( this == &pStart->nNode.GetNode() | ||||
1421 | && rPos.GetIndex() == pStart->nContent.GetIndex() ) | ||||
1422 | { | ||||
1423 | bAtLeastOneExpandedBookmarkAtInsertionPosition = true; | ||||
1424 | } | ||||
1425 | } | ||||
1426 | } | ||||
1427 | } | ||||
1428 | |||||
1429 | bSortMarks = bAtLeastOneBookmarkMoved && bAtLeastOneExpandedBookmarkAtInsertionPosition; | ||||
1430 | } | ||||
1431 | |||||
1432 | // at-char anchored flys shouldn't be moved, either. | ||||
1433 | #if OSL_DEBUG_LEVEL1 > 0 | ||||
1434 | std::vector<SwFrameFormat*> checkFormats; | ||||
1435 | const SwFrameFormats& rFormats = *GetDoc().GetSpzFrameFormats(); | ||||
1436 | for (auto& rpFormat : rFormats) | ||||
1437 | { | ||||
1438 | const SwFormatAnchor& rAnchor = rpFormat->GetAnchor(); | ||||
1439 | const SwPosition* pContentAnchor = rAnchor.GetContentAnchor(); | ||||
1440 | if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR && pContentAnchor) | ||||
1441 | { | ||||
1442 | // The fly is at-char anchored and has an anchor position. | ||||
1443 | SwIndex& rEndIdx = const_cast<SwIndex&>(pContentAnchor->nContent); | ||||
1444 | if (&pContentAnchor->nNode.GetNode() == this && rEndIdx.GetIndex() == rPos.GetIndex()) | ||||
1445 | { | ||||
1446 | // The anchor position is exactly our insert position. | ||||
1447 | #if 0 | ||||
1448 | rEndIdx.Assign(&aTmpIdxReg, rEndIdx.GetIndex()); | ||||
1449 | #endif | ||||
1450 | checkFormats.push_back( rpFormat ); | ||||
1451 | } | ||||
1452 | } | ||||
1453 | } | ||||
1454 | #endif | ||||
1455 | std::vector<SwFrameFormat*> const*const pFlys(GetAnchoredFlys()); | ||||
1456 | for (size_t i = 0; pFlys && i != pFlys->size(); ++i) | ||||
1457 | { | ||||
1458 | SwFrameFormat const*const pFormat = (*pFlys)[i]; | ||||
1459 | const SwFormatAnchor& rAnchor = pFormat->GetAnchor(); | ||||
1460 | const SwPosition* pContentAnchor = rAnchor.GetContentAnchor(); | ||||
1461 | if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR && pContentAnchor) | ||||
1462 | { | ||||
1463 | // The fly is at-char anchored and has an anchor position. | ||||
1464 | SwIndex& rEndIdx = const_cast<SwIndex&>(pContentAnchor->nContent); | ||||
1465 | if (&pContentAnchor->nNode.GetNode() == this && rEndIdx.GetIndex() == rPos.GetIndex()) | ||||
1466 | { | ||||
1467 | // The anchor position is exactly our insert position. | ||||
1468 | rEndIdx.Assign(&aTmpIdxReg, rEndIdx.GetIndex()); | ||||
1469 | #if OSL_DEBUG_LEVEL1 > 0 | ||||
1470 | auto checkPos = std::find( checkFormats.begin(), checkFormats.end(), pFormat ); | ||||
1471 | assert( checkPos != checkFormats.end())(static_cast <bool> (checkPos != checkFormats.end()) ? void (0) : __assert_fail ("checkPos != checkFormats.end()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1471, __extension__ __PRETTY_FUNCTION__)); | ||||
1472 | checkFormats.erase( checkPos ); | ||||
1473 | #endif | ||||
1474 | } | ||||
1475 | } | ||||
1476 | } | ||||
1477 | #if OSL_DEBUG_LEVEL1 > 0 | ||||
1478 | assert( checkFormats.empty())(static_cast <bool> (checkFormats.empty()) ? void (0) : __assert_fail ("checkFormats.empty()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1478, __extension__ __PRETTY_FUNCTION__)); | ||||
1479 | #endif | ||||
1480 | |||||
1481 | // The cursors of other shells shouldn't be moved, either. | ||||
1482 | if (SwDocShell* pDocShell = GetDoc().GetDocShell()) | ||||
1483 | { | ||||
1484 | if (pDocShell->GetWrtShell()) | ||||
1485 | { | ||||
1486 | for (SwViewShell& rShell : pDocShell->GetWrtShell()->GetRingContainer()) | ||||
1487 | { | ||||
1488 | auto pWrtShell = dynamic_cast<SwWrtShell*>(&rShell); | ||||
1489 | if (!pWrtShell || pWrtShell == pDocShell->GetWrtShell()) | ||||
1490 | continue; | ||||
1491 | |||||
1492 | SwShellCursor* pCursor = pWrtShell->GetCursor_(); | ||||
1493 | if (!pCursor) | ||||
1494 | continue; | ||||
1495 | |||||
1496 | SwIndex& rIndex = pCursor->Start()->nContent; | ||||
1497 | if (&pCursor->Start()->nNode.GetNode() == this && rIndex.GetIndex() == rPos.GetIndex()) | ||||
1498 | { | ||||
1499 | // The cursor position of this other shell is exactly our insert position. | ||||
1500 | rIndex.Assign(&aTmpIdxReg, rIndex.GetIndex()); | ||||
1501 | } | ||||
1502 | } | ||||
1503 | } | ||||
1504 | } | ||||
1505 | } | ||||
1506 | |||||
1507 | // base class | ||||
1508 | SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete ); | ||||
1509 | |||||
1510 | if (pCollector) | ||||
1511 | { | ||||
1512 | const size_t nCount = pCollector->size(); | ||||
1513 | for ( size_t i = 0; i < nCount; ++i ) | ||||
1514 | { | ||||
1515 | m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this ); | ||||
1516 | } | ||||
1517 | } | ||||
1518 | |||||
1519 | aTmpIdxReg.MoveTo( *this ); | ||||
1520 | if ( bSortMarks ) | ||||
1521 | { | ||||
1522 | getIDocumentMarkAccess()->assureSortedMarkContainers(); | ||||
1523 | } | ||||
1524 | |||||
1525 | //Any drawing objects anchored into this text node may be sorted by their | ||||
1526 | //anchor position which may have changed here, so resort them | ||||
1527 | SwContentFrame* pContentFrame = getLayoutFrame(GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()); | ||||
1528 | SwSortedObjs* pSortedObjs = pContentFrame ? pContentFrame->GetDrawObjs() : nullptr; | ||||
1529 | if (pSortedObjs) | ||||
1530 | pSortedObjs->UpdateAll(); | ||||
1531 | |||||
1532 | // Update the paragraph signatures. | ||||
1533 | if (SwEditShell* pEditShell = GetDoc().GetEditShell()) | ||||
1534 | { | ||||
1535 | pEditShell->ValidateParagraphSignatures(this, true); | ||||
1536 | } | ||||
1537 | |||||
1538 | // Inform LOK clients about change in position of redlines (if any) | ||||
1539 | // Don't emit notifications during save: redline flags are temporarily changed during save, but | ||||
1540 | // it's not useful to let clients know about such changes. | ||||
1541 | if (!comphelper::LibreOfficeKit::isActive() || GetDoc().IsInWriting()) | ||||
1542 | return; | ||||
1543 | |||||
1544 | const SwRedlineTable& rTable = GetDoc().getIDocumentRedlineAccess().GetRedlineTable(); | ||||
1545 | for (SwRedlineTable::size_type nRedlnPos = 0; nRedlnPos < rTable.size(); ++nRedlnPos) | ||||
1546 | { | ||||
1547 | SwRangeRedline* pRedln = rTable[nRedlnPos]; | ||||
1548 | if (pRedln->HasMark()) | ||||
1549 | { | ||||
1550 | if (this == &pRedln->End()->nNode.GetNode() && *pRedln->GetPoint() != *pRedln->GetMark()) | ||||
1551 | { | ||||
1552 | // Redline is changed only when some change occurs before it | ||||
1553 | if (nChangePos <= pRedln->Start()->nContent.GetIndex()) | ||||
1554 | { | ||||
1555 | SwRedlineTable::LOKRedlineNotification(RedlineNotification::Modify, pRedln); | ||||
1556 | } | ||||
1557 | } | ||||
1558 | } | ||||
1559 | else if (this == &pRedln->GetPoint()->nNode.GetNode()) | ||||
1560 | SwRedlineTable::LOKRedlineNotification(RedlineNotification::Modify, pRedln); | ||||
1561 | } | ||||
1562 | } | ||||
1563 | |||||
1564 | void SwTextNode::ChgTextCollUpdateNum( const SwTextFormatColl *pOldColl, | ||||
1565 | const SwTextFormatColl *pNewColl) | ||||
1566 | { | ||||
1567 | SwDoc& rDoc = GetDoc(); | ||||
1568 | // query the OutlineLevel and if it changed, notify the Nodes-Array! | ||||
1569 | const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ? | ||||
1570 | pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL; | ||||
1571 | const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ? | ||||
1572 | pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL; | ||||
1573 | |||||
1574 | if ( MAXLEVEL != nNewLevel && -1 != nNewLevel ) | ||||
1575 | { | ||||
1576 | SetAttrListLevel(nNewLevel); | ||||
1577 | } | ||||
1578 | rDoc.GetNodes().UpdateOutlineNode(*this); | ||||
1579 | |||||
1580 | SwNodes& rNds = GetNodes(); | ||||
1581 | // If Level 0 (Chapter), update the footnotes! | ||||
1582 | if( ( !nNewLevel || !nOldLevel) && !rDoc.GetFootnoteIdxs().empty() && | ||||
1583 | FTNNUM_CHAPTER == rDoc.GetFootnoteInfo().m_eNum && | ||||
1584 | rNds.IsDocNodes() ) | ||||
1585 | { | ||||
1586 | SwNodeIndex aTmpIndex( rNds, GetIndex()); | ||||
1587 | |||||
1588 | rDoc.GetFootnoteIdxs().UpdateFootnote( aTmpIndex); | ||||
1589 | } | ||||
1590 | |||||
1591 | if( pNewColl && RES_CONDTXTFMTCOLL == pNewColl->Which() ) | ||||
1592 | { | ||||
1593 | // check the condition of the text node again | ||||
1594 | ChkCondColl(); | ||||
1595 | } | ||||
1596 | } | ||||
1597 | |||||
1598 | // If positioned exactly at the end of a CharStyle or Hyperlink, | ||||
1599 | // set its DontExpand flag. | ||||
1600 | bool SwTextNode::DontExpandFormat( const SwIndex& rIdx, bool bFlag, | ||||
1601 | bool bFormatToTextAttributes ) | ||||
1602 | { | ||||
1603 | const sal_Int32 nIdx = rIdx.GetIndex(); | ||||
1604 | if (bFormatToTextAttributes && nIdx == m_Text.getLength()) | ||||
1605 | { | ||||
1606 | FormatToTextAttr( this ); | ||||
1607 | } | ||||
1608 | |||||
1609 | bool bRet = false; | ||||
1610 | if ( HasHints() ) | ||||
1611 | { | ||||
1612 | m_pSwpHints->SortIfNeedBe(); | ||||
1613 | int nPos = m_pSwpHints->GetLastPosSortedByEnd(nIdx); | ||||
1614 | for ( ; nPos >= 0; --nPos) | ||||
1615 | { | ||||
1616 | SwTextAttr *pTmp = m_pSwpHints->GetSortedByEnd( nPos ); | ||||
1617 | const sal_Int32 *pEnd = pTmp->GetEnd(); | ||||
1618 | if( !pEnd ) | ||||
1619 | continue; | ||||
1620 | assert( *pEnd <= nIdx )(static_cast <bool> (*pEnd <= nIdx) ? void (0) : __assert_fail ("*pEnd <= nIdx", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1620, __extension__ __PRETTY_FUNCTION__)); | ||||
1621 | if( nIdx != *pEnd ) | ||||
1622 | break; | ||||
1623 | if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag() | ||||
1624 | && *pEnd > pTmp->GetStart()) | ||||
1625 | { | ||||
1626 | bRet = true; | ||||
1627 | m_pSwpHints->NoteInHistory( pTmp ); | ||||
1628 | pTmp->SetDontExpand( bFlag ); | ||||
1629 | } | ||||
1630 | } | ||||
1631 | } | ||||
1632 | return bRet; | ||||
1633 | } | ||||
1634 | |||||
1635 | static bool lcl_GetTextAttrDefault(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd) | ||||
1636 | { | ||||
1637 | return ((nHintStart <= nIndex) && (nIndex < nHintEnd)); | ||||
1638 | } | ||||
1639 | static bool lcl_GetTextAttrExpand(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd) | ||||
1640 | { | ||||
1641 | return ((nHintStart < nIndex) && (nIndex <= nHintEnd)); | ||||
1642 | } | ||||
1643 | static bool lcl_GetTextAttrParent(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd) | ||||
1644 | { | ||||
1645 | return ((nHintStart < nIndex) && (nIndex < nHintEnd)); | ||||
1646 | } | ||||
1647 | |||||
1648 | static void | ||||
1649 | lcl_GetTextAttrs( | ||||
1650 | std::vector<SwTextAttr *> *const pVector, | ||||
1651 | SwTextAttr **const ppTextAttr, | ||||
1652 | SwpHints const *const pSwpHints, | ||||
1653 | sal_Int32 const nIndex, sal_uInt16 const nWhich, | ||||
1654 | enum SwTextNode::GetTextAttrMode const eMode) | ||||
1655 | { | ||||
1656 | assert(nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END)(static_cast <bool> (nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END) ? void (0) : __assert_fail ("nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1656, __extension__ __PRETTY_FUNCTION__)); | ||||
1657 | if (!pSwpHints) | ||||
1658 | return; | ||||
1659 | size_t const nSize = pSwpHints->Count(); | ||||
1660 | sal_Int32 nPreviousIndex(0); // index of last hint with nWhich | ||||
1661 | bool (*pMatchFunc)(sal_Int32, sal_Int32, sal_Int32)=nullptr; | ||||
1662 | switch (eMode) | ||||
1663 | { | ||||
1664 | case SwTextNode::DEFAULT: pMatchFunc = &lcl_GetTextAttrDefault; break; | ||||
1665 | case SwTextNode::EXPAND: pMatchFunc = &lcl_GetTextAttrExpand; break; | ||||
1666 | case SwTextNode::PARENT: pMatchFunc = &lcl_GetTextAttrParent; break; | ||||
1667 | default: assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1667, __extension__ __PRETTY_FUNCTION__)); | ||||
1668 | } | ||||
1669 | |||||
1670 | for( size_t i = pSwpHints->GetFirstPosSortedByWhichAndStart(nWhich); i < nSize; ++i ) | ||||
1671 | { | ||||
1672 | SwTextAttr *const pHint = pSwpHints->GetSortedByWhichAndStart(i); | ||||
1673 | if (pHint->Which() != nWhich) | ||||
1674 | break; // hints are sorted by which&start, so we are done... | ||||
1675 | |||||
1676 | sal_Int32 const nHintStart = pHint->GetStart(); | ||||
1677 | if (nIndex < nHintStart) | ||||
1678 | break; // hints are sorted by which&start, so we are done... | ||||
1679 | |||||
1680 | sal_Int32 const*const pEndIdx = pHint->GetEnd(); | ||||
1681 | // cannot have hint with no end and no dummy char | ||||
1682 | assert(pEndIdx || pHint->HasDummyChar())(static_cast <bool> (pEndIdx || pHint->HasDummyChar( )) ? void (0) : __assert_fail ("pEndIdx || pHint->HasDummyChar()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1682, __extension__ __PRETTY_FUNCTION__)); | ||||
1683 | // If EXPAND is set, simulate the text input behavior, i.e. | ||||
1684 | // move the start, and expand the end. | ||||
1685 | bool const bContained( pEndIdx | ||||
1686 | ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx) | ||||
1687 | : (nHintStart == nIndex) ); | ||||
1688 | if (bContained) | ||||
1689 | { | ||||
1690 | if (pVector) | ||||
1691 | { | ||||
1692 | if (nPreviousIndex < nHintStart) | ||||
1693 | { | ||||
1694 | pVector->clear(); // clear hints that are outside pHint | ||||
1695 | nPreviousIndex = nHintStart; | ||||
1696 | } | ||||
1697 | pVector->push_back(pHint); | ||||
1698 | } | ||||
1699 | else | ||||
1700 | { | ||||
1701 | *ppTextAttr = pHint; // and possibly overwrite outer hint | ||||
1702 | } | ||||
1703 | if (!pEndIdx) | ||||
1704 | { | ||||
1705 | break; | ||||
1706 | } | ||||
1707 | } | ||||
1708 | } | ||||
1709 | } | ||||
1710 | |||||
1711 | std::vector<SwTextAttr *> | ||||
1712 | SwTextNode::GetTextAttrsAt(sal_Int32 const nIndex, sal_uInt16 const nWhich) const | ||||
1713 | { | ||||
1714 | assert(nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END)(static_cast <bool> (nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END) ? void (0) : __assert_fail ("nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1714, __extension__ __PRETTY_FUNCTION__)); | ||||
1715 | std::vector<SwTextAttr *> ret; | ||||
1716 | lcl_GetTextAttrs(&ret, nullptr, m_pSwpHints.get(), nIndex, nWhich, DEFAULT); | ||||
1717 | return ret; | ||||
1718 | } | ||||
1719 | |||||
1720 | SwTextAttr * | ||||
1721 | SwTextNode::GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, | ||||
1722 | enum GetTextAttrMode const eMode) const | ||||
1723 | { | ||||
1724 | assert( (nWhich == RES_TXTATR_META)(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)) | ||||
1725 | || (nWhich == RES_TXTATR_METAFIELD)(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)) | ||||
1726 | || (nWhich == RES_TXTATR_AUTOFMT)(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)) | ||||
1727 | || (nWhich == RES_TXTATR_INETFMT)(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)) | ||||
1728 | || (nWhich == RES_TXTATR_CJK_RUBY)(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)) | ||||
1729 | || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER)(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)) | ||||
1730 | || (nWhich == RES_TXTATR_INPUTFIELD ) )(static_cast <bool> ((nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY ) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )) ? void (0) : __assert_fail ("(nWhich == RES_TXTATR_META) || (nWhich == RES_TXTATR_METAFIELD) || (nWhich == RES_TXTATR_AUTOFMT) || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) || (nWhich == RES_TXTATR_INPUTFIELD )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1730, __extension__ __PRETTY_FUNCTION__)); | ||||
1731 | // "GetTextAttrAt() will give wrong result for this hint!") | ||||
1732 | |||||
1733 | SwTextAttr * pRet(nullptr); | ||||
1734 | lcl_GetTextAttrs(nullptr, & pRet, m_pSwpHints.get(), nIndex, nWhich, eMode); | ||||
1735 | return pRet; | ||||
1736 | } | ||||
1737 | |||||
1738 | const SwTextInputField* SwTextNode::GetOverlappingInputField( const SwTextAttr& rTextAttr ) const | ||||
1739 | { | ||||
1740 | const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextAttrAt( rTextAttr.GetStart(), RES_TXTATR_INPUTFIELD, PARENT )); | ||||
1741 | |||||
1742 | if ( pTextInputField == nullptr && rTextAttr.End() != nullptr ) | ||||
1743 | { | ||||
1744 | pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextAttrAt( *(rTextAttr.End()), RES_TXTATR_INPUTFIELD, PARENT )); | ||||
1745 | } | ||||
1746 | |||||
1747 | return pTextInputField; | ||||
1748 | } | ||||
1749 | |||||
1750 | void SwTextNode::DelFrames_TextNodePart() | ||||
1751 | { | ||||
1752 | SetWrong( nullptr ); | ||||
1753 | SetWrongDirty(WrongState::TODO); | ||||
1754 | |||||
1755 | SetGrammarCheck( nullptr ); | ||||
1756 | SetGrammarCheckDirty( true ); | ||||
1757 | |||||
1758 | SetSmartTags( nullptr ); | ||||
1759 | SetSmartTagDirty( true ); | ||||
1760 | |||||
1761 | SetWordCountDirty( true ); | ||||
1762 | SetAutoCompleteWordDirty( true ); | ||||
1763 | } | ||||
1764 | |||||
1765 | SwTextField* SwTextNode::GetFieldTextAttrAt( | ||||
1766 | const sal_Int32 nIndex, | ||||
1767 | const bool bIncludeInputFieldAtStart ) const | ||||
1768 | { | ||||
1769 | SwTextField* pTextField = dynamic_cast<SwTextField*>(GetTextAttrForCharAt( nIndex, RES_TXTATR_FIELD )); | ||||
1770 | if ( pTextField == nullptr ) | ||||
1771 | { | ||||
1772 | pTextField = dynamic_cast<SwTextField*>(GetTextAttrForCharAt( nIndex, RES_TXTATR_ANNOTATION )); | ||||
1773 | } | ||||
1774 | if ( pTextField == nullptr ) | ||||
1775 | { | ||||
1776 | pTextField = | ||||
1777 | dynamic_cast<SwTextField*>( GetTextAttrAt( | ||||
1778 | nIndex, | ||||
1779 | RES_TXTATR_INPUTFIELD, | ||||
1780 | bIncludeInputFieldAtStart ? DEFAULT : EXPAND )); | ||||
1781 | } | ||||
1782 | |||||
1783 | return pTextField; | ||||
1784 | } | ||||
1785 | |||||
1786 | static SwCharFormat* lcl_FindCharFormat( const SwCharFormats* pCharFormats, const OUString& rName ) | ||||
1787 | { | ||||
1788 | if( !rName.isEmpty() ) | ||||
1789 | { | ||||
1790 | const size_t nArrLen = pCharFormats->size(); | ||||
1791 | for( size_t i = 1; i < nArrLen; i++ ) | ||||
1792 | { | ||||
1793 | SwCharFormat* pFormat = (*pCharFormats)[ i ]; | ||||
1794 | if( pFormat->GetName()==rName ) | ||||
1795 | return pFormat; | ||||
1796 | } | ||||
1797 | } | ||||
1798 | return nullptr; | ||||
1799 | } | ||||
1800 | |||||
1801 | static void lcl_CopyHint( | ||||
1802 | const sal_uInt16 nWhich, | ||||
1803 | const SwTextAttr * const pHt, | ||||
1804 | SwTextAttr *const pNewHt, | ||||
1805 | SwDoc *const pOtherDoc, | ||||
1806 | SwTextNode *const pDest ) | ||||
1807 | { | ||||
1808 | assert(nWhich == pHt->Which())(static_cast <bool> (nWhich == pHt->Which()) ? void ( 0) : __assert_fail ("nWhich == pHt->Which()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1808, __extension__ __PRETTY_FUNCTION__)); // wrong hint-id | ||||
1809 | switch( nWhich ) | ||||
1810 | { | ||||
1811 | // copy nodesarray section with footnote content | ||||
1812 | case RES_TXTATR_FTN : | ||||
1813 | assert(pDest)(static_cast <bool> (pDest) ? void (0) : __assert_fail ( "pDest", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 1813, __extension__ __PRETTY_FUNCTION__)); // "lcl_CopyHint: no destination text node?" | ||||
1814 | static_cast<const SwTextFootnote*>(pHt)->CopyFootnote( *static_cast<SwTextFootnote*>(pNewHt), *pDest); | ||||
1815 | break; | ||||
1816 | |||||
1817 | // Fields that are copied into different SwDocs must be registered | ||||
1818 | // at their new FieldTypes. | ||||
1819 | |||||
1820 | case RES_TXTATR_FIELD : | ||||
1821 | { | ||||
1822 | if( pOtherDoc != nullptr ) | ||||
1823 | { | ||||
1824 | static_txtattr_cast<const SwTextField*>(pHt)->CopyTextField( | ||||
1825 | static_txtattr_cast<SwTextField*>(pNewHt)); | ||||
1826 | } | ||||
1827 | |||||
1828 | // Table Formula must be copied relative. | ||||
1829 | const SwFormatField& rField = pHt->GetFormatField(); | ||||
1830 | if( SwFieldIds::Table == rField.GetField()->GetTyp()->Which() | ||||
1831 | && static_cast<const SwTableField*>(rField.GetField())->IsIntrnlName()) | ||||
1832 | { | ||||
1833 | // convert internal formula to external | ||||
1834 | const SwTableNode* const pDstTableNd = | ||||
1835 | static_txtattr_cast<const SwTextField*>(pHt)->GetTextNode().FindTableNode(); | ||||
1836 | if( pDstTableNd ) | ||||
1837 | { | ||||
1838 | SwTableField* const pTableField = | ||||
1839 | const_cast<SwTableField*>(static_cast<const SwTableField*>( | ||||
1840 | pNewHt->GetFormatField().GetField())); | ||||
1841 | pTableField->PtrToBoxNm( &pDstTableNd->GetTable() ); | ||||
1842 | } | ||||
1843 | } | ||||
1844 | } | ||||
1845 | break; | ||||
1846 | |||||
1847 | case RES_TXTATR_INPUTFIELD : | ||||
1848 | case RES_TXTATR_ANNOTATION : | ||||
1849 | if( pOtherDoc != nullptr ) | ||||
1850 | { | ||||
1851 | static_txtattr_cast<const SwTextField*>(pHt)->CopyTextField( | ||||
1852 | static_txtattr_cast<SwTextField*>(pNewHt)); | ||||
1853 | } | ||||
1854 | break; | ||||
1855 | |||||
1856 | case RES_TXTATR_TOXMARK : | ||||
1857 | if( pOtherDoc && pDest && pDest->GetpSwpHints() | ||||
1858 | && pDest->GetpSwpHints()->Contains( pNewHt ) ) | ||||
1859 | { | ||||
1860 | // ToXMarks that are copied to different SwDocs must register | ||||
1861 | // at their new ToX (SwModify). | ||||
1862 | static_txtattr_cast<SwTextTOXMark*>(pNewHt)->CopyTOXMark(*pOtherDoc); | ||||
1863 | } | ||||
1864 | break; | ||||
1865 | |||||
1866 | case RES_TXTATR_CHARFMT : | ||||
1867 | // For CharacterStyles, the format must be copied too. | ||||
1868 | if( pDest && pDest->GetpSwpHints() | ||||
1869 | && pDest->GetpSwpHints()->Contains( pNewHt ) ) | ||||
1870 | { | ||||
1871 | SwCharFormat* pFormat = pHt->GetCharFormat().GetCharFormat(); | ||||
1872 | |||||
1873 | if (pOtherDoc) | ||||
1874 | { | ||||
1875 | pFormat = pOtherDoc->CopyCharFormat( *pFormat ); | ||||
1876 | } | ||||
1877 | const_cast<SwFormatCharFormat&>( | ||||
1878 | pNewHt->GetCharFormat() ).SetCharFormat( pFormat ); | ||||
1879 | } | ||||
1880 | break; | ||||
1881 | case RES_TXTATR_INETFMT : | ||||
1882 | { | ||||
1883 | // For Hyperlinks, the format must be copied too. | ||||
1884 | if( pOtherDoc && pDest && pDest->GetpSwpHints() | ||||
1885 | && pDest->GetpSwpHints()->Contains( pNewHt ) ) | ||||
1886 | { | ||||
1887 | const SwDoc& rDoc = static_txtattr_cast< | ||||
1888 | const SwTextINetFormat*>(pHt)->GetTextNode().GetDoc(); | ||||
1889 | const SwCharFormats* pCharFormats = rDoc.GetCharFormats(); | ||||
1890 | const SwFormatINetFormat& rFormat = pHt->GetINetFormat(); | ||||
1891 | SwCharFormat* pFormat; | ||||
1892 | pFormat = lcl_FindCharFormat( pCharFormats, rFormat.GetINetFormat() ); | ||||
1893 | if( pFormat ) | ||||
1894 | pOtherDoc->CopyCharFormat( *pFormat ); | ||||
1895 | pFormat = lcl_FindCharFormat( pCharFormats, rFormat.GetVisitedFormat() ); | ||||
1896 | if( pFormat ) | ||||
1897 | pOtherDoc->CopyCharFormat( *pFormat ); | ||||
1898 | } | ||||
1899 | //JP 24.04.98: The attribute must point to a text node, so that | ||||
1900 | // the styles can be created. | ||||
1901 | SwTextINetFormat *const pINetHt = static_txtattr_cast<SwTextINetFormat*>(pNewHt); | ||||
1902 | if ( !pINetHt->GetpTextNode() ) | ||||
1903 | { | ||||
1904 | pINetHt->ChgTextNode( pDest ); | ||||
1905 | } | ||||
1906 | |||||
1907 | //JP 22.10.97: set up link to char style | ||||
1908 | pINetHt->GetCharFormat(); | ||||
1909 | break; | ||||
1910 | } | ||||
1911 | case RES_TXTATR_META: | ||||
1912 | case RES_TXTATR_METAFIELD: | ||||
1913 | OSL_ENSURE( pNewHt, "copying Meta should not fail!" )do { if (true && (!(pNewHt))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1913" ": "), "%s", "copying Meta should not fail!"); } } while (false); | ||||
1914 | OSL_ENSURE( pDestdo { if (true && (!(pDest && (u'\xFFF9' == pDest ->GetText()[pNewHt->GetStart()])))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1916" ": "), "%s", "missing CH_TXTATR?"); } } while (false ) | ||||
1915 | && (CH_TXTATR_INWORD == pDest->GetText()[pNewHt->GetStart()]),do { if (true && (!(pDest && (u'\xFFF9' == pDest ->GetText()[pNewHt->GetStart()])))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1916" ": "), "%s", "missing CH_TXTATR?"); } } while (false ) | ||||
1916 | "missing CH_TXTATR?")do { if (true && (!(pDest && (u'\xFFF9' == pDest ->GetText()[pNewHt->GetStart()])))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "1916" ": "), "%s", "missing CH_TXTATR?"); } } while (false ); | ||||
1917 | break; | ||||
1918 | } | ||||
1919 | } | ||||
1920 | |||||
1921 | /// copy attributes at position nTextStartIdx to node pDest | ||||
1922 | // BP 7.6.93: Intentionally copy only attributes _with_ EndIdx! | ||||
1923 | // CopyAttr is usually called when attributes are set on a | ||||
1924 | // node with no text. | ||||
1925 | void SwTextNode::CopyAttr( SwTextNode *pDest, const sal_Int32 nTextStartIdx, | ||||
1926 | const sal_Int32 nOldPos ) | ||||
1927 | { | ||||
1928 | if ( HasHints() ) | ||||
1929 | { | ||||
1930 | SwDoc* const pOtherDoc = (&pDest->GetDoc() != &GetDoc()) ? | ||||
1931 | &pDest->GetDoc() : nullptr; | ||||
1932 | |||||
1933 | for ( size_t i = 0; i < m_pSwpHints->Count(); ++i ) | ||||
1934 | { | ||||
1935 | SwTextAttr *const pHt = m_pSwpHints->Get(i); | ||||
1936 | sal_Int32 const nAttrStartIdx = pHt->GetStart(); | ||||
1937 | if ( nTextStartIdx < nAttrStartIdx ) | ||||
1938 | break; // beyond end of text, because nLen == 0 | ||||
1939 | |||||
1940 | const sal_Int32 *const pEndIdx = pHt->GetEnd(); | ||||
1941 | if ( pEndIdx && !pHt->HasDummyChar() ) | ||||
1942 | { | ||||
1943 | sal_uInt16 const nWhich = pHt->Which(); | ||||
1944 | if (RES_TXTATR_INPUTFIELD != nWhich // fdo#74981 skip fields | ||||
1945 | && ( *pEndIdx > nTextStartIdx | ||||
1946 | || (*pEndIdx == nTextStartIdx | ||||
1947 | && nAttrStartIdx == nTextStartIdx))) | ||||
1948 | { | ||||
1949 | if ( RES_TXTATR_REFMARK != nWhich ) | ||||
1950 | { | ||||
1951 | // attribute in the area => copy | ||||
1952 | SwTextAttr *const pNewHt = | ||||
1953 | pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos, SetAttrMode::IS_COPY); | ||||
1954 | if ( pNewHt ) | ||||
1955 | { | ||||
1956 | lcl_CopyHint( nWhich, pHt, pNewHt, | ||||
1957 | pOtherDoc, pDest ); | ||||
1958 | } | ||||
1959 | } | ||||
1960 | else if( !pOtherDoc | ||||
1961 | ? GetDoc().IsCopyIsMove() | ||||
1962 | : nullptr == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) ) | ||||
1963 | { | ||||
1964 | pDest->InsertItem( | ||||
1965 | pHt->GetAttr(), nOldPos, nOldPos, SetAttrMode::IS_COPY); | ||||
1966 | } | ||||
1967 | } | ||||
1968 | } | ||||
1969 | } | ||||
1970 | } | ||||
1971 | |||||
1972 | if( this != pDest ) | ||||
1973 | { | ||||
1974 | // notify layout frames, to prevent disappearance of footnote numbers | ||||
1975 | SwUpdateAttr aHint( | ||||
1976 | nOldPos, | ||||
1977 | nOldPos, | ||||
1978 | 0); | ||||
1979 | |||||
1980 | pDest->ModifyNotification( nullptr, &aHint ); | ||||
1981 | } | ||||
1982 | } | ||||
1983 | |||||
1984 | /// copy text and attributes to node pDest | ||||
1985 | void SwTextNode::CopyText( SwTextNode *const pDest, | ||||
1986 | const SwIndex &rStart, | ||||
1987 | const sal_Int32 nLen, | ||||
1988 | const bool bForceCopyOfAllAttrs ) | ||||
1989 | { | ||||
1990 | SwIndex const aIdx( pDest, pDest->m_Text.getLength() ); | ||||
1991 | CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs ); | ||||
1992 | } | ||||
1993 | |||||
1994 | void SwTextNode::CopyText( SwTextNode *const pDest, | ||||
1995 | const SwIndex &rDestStart, | ||||
1996 | const SwIndex &rStart, | ||||
1997 | sal_Int32 nLen, | ||||
1998 | const bool bForceCopyOfAllAttrs ) | ||||
1999 | { | ||||
2000 | CHECK_SWPHINTS_IF_FRM(this); | ||||
2001 | CHECK_SWPHINTS(pDest); | ||||
2002 | sal_Int32 nTextStartIdx = rStart.GetIndex(); | ||||
2003 | sal_Int32 nDestStart = rDestStart.GetIndex(); // remember old Pos | ||||
2004 | |||||
2005 | if (pDest->GetDoc().IsClipBoard() && GetNum()) | ||||
2006 | { | ||||
2007 | // #i111677# cache expansion of source (for clipboard) | ||||
2008 | pDest->m_pNumStringCache.reset( (nTextStartIdx != 0) | ||||
2009 | ? new OUString // fdo#49076: numbering only if copy from para start | ||||
2010 | : new OUString(GetNumString())); | ||||
2011 | } | ||||
2012 | |||||
2013 | if( !nLen ) | ||||
2014 | { | ||||
2015 | // if no length is given, copy attributes at position rStart | ||||
2016 | CopyAttr( pDest, nTextStartIdx, nDestStart ); | ||||
2017 | |||||
2018 | // copy hard attributes on whole paragraph | ||||
2019 | if( HasSwAttrSet() ) | ||||
2020 | { | ||||
2021 | // i#96213 all or just the Char attributes? | ||||
2022 | if ( !bForceCopyOfAllAttrs && | ||||
2023 | ( nDestStart || | ||||
2024 | pDest->HasSwAttrSet() || | ||||
2025 | nLen != pDest->GetText().getLength())) | ||||
2026 | { | ||||
2027 | SfxItemSet aCharSet( | ||||
2028 | pDest->GetDoc().GetAttrPool(), | ||||
2029 | svl::Items< | ||||
2030 | RES_CHRATR_BEGIN, RES_CHRATR_END - 1, | ||||
2031 | RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT, | ||||
2032 | RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1>{} ); | ||||
2033 | aCharSet.Put( *GetpSwAttrSet() ); | ||||
2034 | if( aCharSet.Count() ) | ||||
2035 | { | ||||
2036 | pDest->SetAttr( aCharSet, nDestStart, nDestStart ); | ||||
2037 | } | ||||
2038 | } | ||||
2039 | else | ||||
2040 | { | ||||
2041 | GetpSwAttrSet()->CopyToModify( *pDest ); | ||||
2042 | } | ||||
2043 | } | ||||
2044 | return; | ||||
2045 | } | ||||
2046 | |||||
2047 | // 1. copy text | ||||
2048 | const sal_Int32 oldLen = pDest->m_Text.getLength(); | ||||
2049 | // JP 15.02.96: missing attribute handling at the end! | ||||
2050 | // hence call InsertText and don't modify m_Text directly | ||||
2051 | pDest->InsertText( m_Text.copy(nTextStartIdx, nLen), rDestStart, | ||||
2052 | SwInsertFlags::EMPTYEXPAND ); | ||||
2053 | |||||
2054 | // update with actual new size | ||||
2055 | nLen = pDest->m_Text.getLength() - oldLen; | ||||
2056 | if ( !nLen ) // string not longer? | ||||
2057 | return; | ||||
2058 | |||||
2059 | SwDoc* const pOtherDoc = (&pDest->GetDoc() != &GetDoc()) ? &pDest->GetDoc() : nullptr; | ||||
2060 | |||||
2061 | // copy hard attributes on whole paragraph | ||||
2062 | if( HasSwAttrSet() ) | ||||
2063 | { | ||||
2064 | // i#96213 all or just the Char attributes? | ||||
2065 | if ( !bForceCopyOfAllAttrs && | ||||
2066 | ( nDestStart || | ||||
2067 | pDest->HasSwAttrSet() || | ||||
2068 | nLen != pDest->GetText().getLength())) | ||||
2069 | { | ||||
2070 | SfxItemSet aCharSet( | ||||
2071 | pDest->GetDoc().GetAttrPool(), | ||||
2072 | svl::Items< | ||||
2073 | RES_CHRATR_BEGIN, RES_CHRATR_END - 1, | ||||
2074 | RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT, | ||||
2075 | RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1>{}); | ||||
2076 | aCharSet.Put( *GetpSwAttrSet() ); | ||||
2077 | if( aCharSet.Count() ) | ||||
2078 | { | ||||
2079 | pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen ); | ||||
2080 | } | ||||
2081 | } | ||||
2082 | else | ||||
2083 | { | ||||
2084 | GetpSwAttrSet()->CopyToModify( *pDest ); | ||||
2085 | } | ||||
2086 | } | ||||
2087 | |||||
2088 | bool const bUndoNodes = !pOtherDoc | ||||
2089 | && GetDoc().GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); | ||||
2090 | |||||
2091 | // Fetch end only now, because copying into self updates the start index | ||||
2092 | // and all attributes | ||||
2093 | nTextStartIdx = rStart.GetIndex(); | ||||
2094 | const sal_Int32 nEnd = nTextStartIdx + nLen; | ||||
2095 | |||||
2096 | // 2. copy attributes | ||||
2097 | // Iterate over attribute array until the start of the attribute | ||||
2098 | // is behind the copied range | ||||
2099 | const size_t nSize = m_pSwpHints ? m_pSwpHints->Count() : 0; | ||||
2100 | |||||
2101 | // If copying into self, inserting can delete attributes! | ||||
2102 | // Hence first copy into temp-array, and then move that into hints array. | ||||
2103 | SwpHts aArr; | ||||
2104 | |||||
2105 | // Del-Array for all RefMarks without extent | ||||
2106 | SwpHts aRefMrkArr; | ||||
2107 | |||||
2108 | std::vector<std::pair<sal_Int32, sal_Int32>> metaFieldRanges; | ||||
2109 | sal_Int32 nDeletedDummyChars(0); | ||||
2110 | for (size_t n = 0; n < nSize; ++n) | ||||
2111 | { | ||||
2112 | SwTextAttr * const pHt = m_pSwpHints->Get(n); | ||||
2113 | |||||
2114 | const sal_Int32 nAttrStartIdx = pHt->GetStart(); | ||||
2115 | if ( nAttrStartIdx >= nEnd ) | ||||
2116 | break; | ||||
2117 | |||||
2118 | const sal_Int32 * const pEndIdx = pHt->GetEnd(); | ||||
2119 | const sal_uInt16 nWhich = pHt->Which(); | ||||
2120 | |||||
2121 | // JP 26.04.94: RefMarks are never copied. If the refmark doesn't have | ||||
2122 | // an extent, there is a dummy char in the text, which | ||||
2123 | // must be removed. So we first copy the attribute, | ||||
2124 | // but remember it, and when we're done delete it, | ||||
2125 | // which also deletes the dummy character! | ||||
2126 | // JP 14.08.95: May RefMarks be moved? | ||||
2127 | const bool bCopyRefMark = RES_TXTATR_REFMARK == nWhich | ||||
2128 | && ( bUndoNodes | ||||
2129 | || ( !pOtherDoc | ||||
2130 | ? GetDoc().IsCopyIsMove() | ||||
2131 | : nullptr == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) ) ); | ||||
2132 | |||||
2133 | if ( pEndIdx | ||||
2134 | && RES_TXTATR_REFMARK == nWhich | ||||
2135 | && !bCopyRefMark ) | ||||
2136 | { | ||||
2137 | continue; | ||||
2138 | } | ||||
2139 | |||||
2140 | // Input Fields are only copied, if completely covered by copied text | ||||
2141 | if ( nWhich == RES_TXTATR_INPUTFIELD ) | ||||
2142 | { | ||||
2143 | assert(pEndIdx != nullptr &&(static_cast <bool> (pEndIdx != nullptr && "<SwTextNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!" ) ? void (0) : __assert_fail ("pEndIdx != nullptr && \"<SwTextNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!\"" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2144, __extension__ __PRETTY_FUNCTION__)) | ||||
2144 | "<SwTextNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!" )(static_cast <bool> (pEndIdx != nullptr && "<SwTextNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!" ) ? void (0) : __assert_fail ("pEndIdx != nullptr && \"<SwTextNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!\"" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2144, __extension__ __PRETTY_FUNCTION__)); | ||||
2145 | if ( nAttrStartIdx < nTextStartIdx | ||||
2146 | || ( pEndIdx != nullptr | ||||
2147 | && *pEndIdx > nEnd ) ) | ||||
2148 | { | ||||
2149 | continue; | ||||
2150 | } | ||||
2151 | } | ||||
2152 | |||||
2153 | if (nWhich == RES_TXTATR_METAFIELD) | ||||
2154 | { | ||||
2155 | // Skip metadata fields. Also remember the range to strip the text later. | ||||
2156 | metaFieldRanges.emplace_back(nAttrStartIdx, pEndIdx ? *pEndIdx : nEnd); | ||||
2157 | continue; | ||||
2158 | } | ||||
2159 | |||||
2160 | sal_Int32 nAttrStt = 0; | ||||
2161 | sal_Int32 nAttrEnd = 0; | ||||
2162 | |||||
2163 | if( nAttrStartIdx < nTextStartIdx ) | ||||
2164 | { | ||||
2165 | // start is before selection | ||||
2166 | // copy hints with end and CH_TXTATR only if dummy char is copied | ||||
2167 | if ( pEndIdx && (*pEndIdx > nTextStartIdx) && !pHt->HasDummyChar() ) | ||||
2168 | { | ||||
2169 | // attribute with extent and the end is in the selection | ||||
2170 | nAttrStt = nDestStart; | ||||
2171 | nAttrEnd = (*pEndIdx > nEnd) | ||||
2172 | ? rDestStart.GetIndex() | ||||
2173 | : nDestStart + (*pEndIdx) - nTextStartIdx; | ||||
2174 | } | ||||
2175 | else | ||||
2176 | { | ||||
2177 | continue; | ||||
2178 | } | ||||
2179 | } | ||||
2180 | else | ||||
2181 | { | ||||
2182 | // start is in the selection | ||||
2183 | nAttrStt = nDestStart + ( nAttrStartIdx - nTextStartIdx ); | ||||
2184 | if( pEndIdx ) | ||||
2185 | { | ||||
2186 | nAttrEnd = *pEndIdx > nEnd | ||||
2187 | ? rDestStart.GetIndex() | ||||
2188 | : nDestStart + ( *pEndIdx - nTextStartIdx ); | ||||
2189 | } | ||||
2190 | else | ||||
2191 | { | ||||
2192 | nAttrEnd = nAttrStt; | ||||
2193 | } | ||||
2194 | } | ||||
2195 | |||||
2196 | SwTextAttr * pNewHt = nullptr; | ||||
2197 | |||||
2198 | if( pDest == this ) | ||||
2199 | { | ||||
2200 | // copy the hint here, but insert it later | ||||
2201 | pNewHt = MakeTextAttr( GetDoc(), pHt->GetAttr(), | ||||
2202 | nAttrStt, nAttrEnd, CopyOrNewType::Copy, pDest ); | ||||
2203 | |||||
2204 | lcl_CopyHint(nWhich, pHt, pNewHt, nullptr, pDest); | ||||
2205 | aArr.push_back( pNewHt ); | ||||
2206 | } | ||||
2207 | else | ||||
2208 | { | ||||
2209 | pNewHt = pDest->InsertItem( | ||||
2210 | pHt->GetAttr(), | ||||
2211 | nAttrStt - nDeletedDummyChars, | ||||
2212 | nAttrEnd - nDeletedDummyChars, | ||||
2213 | SetAttrMode::NOTXTATRCHR | SetAttrMode::IS_COPY); | ||||
2214 | if (pNewHt) | ||||
2215 | { | ||||
2216 | lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest ); | ||||
2217 | } | ||||
2218 | else if (pHt->HasDummyChar()) | ||||
2219 | { | ||||
2220 | // The attribute that has failed to be copied would insert | ||||
2221 | // dummy char, so positions of the following attributes have | ||||
2222 | // to be shifted by one to compensate for that missing char. | ||||
2223 | ++nDeletedDummyChars; | ||||
2224 | } | ||||
2225 | } | ||||
2226 | |||||
2227 | if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark ) | ||||
2228 | { | ||||
2229 | aRefMrkArr.push_back( pNewHt ); | ||||
2230 | } | ||||
2231 | } | ||||
2232 | |||||
2233 | // Strip the metadata fields, since we don't copy the RDF entries | ||||
2234 | // yet and so they are inconsistent upon copy/pasting. | ||||
2235 | if (!metaFieldRanges.empty()) | ||||
2236 | { | ||||
2237 | // Reverse to remove without messing the offsets. | ||||
2238 | std::reverse(metaFieldRanges.begin(), metaFieldRanges.end()); | ||||
2239 | for (const auto& pair : metaFieldRanges) | ||||
2240 | { | ||||
2241 | const SwIndex aIdx(pDest, pair.first); | ||||
2242 | pDest->EraseText(aIdx, pair.second - pair.first); | ||||
2243 | } | ||||
2244 | } | ||||
2245 | |||||
2246 | // this can only happen when copying into self | ||||
2247 | for (SwTextAttr* i : aArr) | ||||
2248 | { | ||||
2249 | InsertHint( i, SetAttrMode::NOTXTATRCHR ); | ||||
2250 | } | ||||
2251 | |||||
2252 | if( pDest->GetpSwpHints() ) | ||||
2253 | { | ||||
2254 | for (SwTextAttr* pNewHt : aRefMrkArr) | ||||
2255 | { | ||||
2256 | if( pNewHt->GetEnd() ) | ||||
2257 | { | ||||
2258 | pDest->GetpSwpHints()->Delete( pNewHt ); | ||||
2259 | pDest->DestroyAttr( pNewHt ); | ||||
2260 | } | ||||
2261 | else | ||||
2262 | { | ||||
2263 | const SwIndex aIdx( pDest, pNewHt->GetStart() ); | ||||
2264 | pDest->EraseText( aIdx, 1 ); | ||||
2265 | } | ||||
2266 | } | ||||
2267 | } | ||||
2268 | |||||
2269 | CHECK_SWPHINTS_IF_FRM(this); | ||||
2270 | CHECK_SWPHINTS(pDest); | ||||
2271 | } | ||||
2272 | |||||
2273 | OUString SwTextNode::InsertText( const OUString & rStr, const SwIndex & rIdx, | ||||
2274 | const SwInsertFlags nMode ) | ||||
2275 | { | ||||
2276 | assert(rIdx <= m_Text.getLength())(static_cast <bool> (rIdx <= m_Text.getLength()) ? void (0) : __assert_fail ("rIdx <= m_Text.getLength()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2276, __extension__ __PRETTY_FUNCTION__)); // invalid index | ||||
2277 | |||||
2278 | const sal_Int32 aPos = rIdx.GetIndex(); | ||||
2279 | sal_Int32 nLen = m_Text.getLength() - aPos; | ||||
2280 | sal_Int32 const nOverflow(rStr.getLength() - GetSpaceLeft()); | ||||
2281 | SAL_WARN_IF(nOverflow > 0, "sw.core",do { if (true && (nOverflow > 0)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "SwTextNode::InsertText: node text with insertion > capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: node text with insertion > capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: node text with insertion > capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SwTextNode::InsertText: node text with insertion > capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: node text with insertion > capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: node text with insertion > capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
2282 | "SwTextNode::InsertText: node text with insertion > capacity.")do { if (true && (nOverflow > 0)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "SwTextNode::InsertText: node text with insertion > capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: node text with insertion > capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: node text with insertion > capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SwTextNode::InsertText: node text with insertion > capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: node text with insertion > capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: node text with insertion > capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2282" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
2283 | OUString const sInserted( | ||||
2284 | (nOverflow > 0) ? rStr.copy(0, rStr.getLength() - nOverflow) : rStr); | ||||
2285 | if (sInserted.isEmpty()) | ||||
2286 | { | ||||
2287 | return sInserted; | ||||
2288 | } | ||||
2289 | m_Text = m_Text.replaceAt(aPos, 0, sInserted); | ||||
2290 | assert(GetSpaceLeft()>=0)(static_cast <bool> (GetSpaceLeft()>=0) ? void (0) : __assert_fail ("GetSpaceLeft()>=0", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2290, __extension__ __PRETTY_FUNCTION__)); | ||||
2291 | nLen = m_Text.getLength() - aPos - nLen; | ||||
2292 | assert(nLen != 0)(static_cast <bool> (nLen != 0) ? void (0) : __assert_fail ("nLen != 0", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2292, __extension__ __PRETTY_FUNCTION__)); | ||||
2293 | |||||
2294 | bool bOldExpFlg = IsIgnoreDontExpand(); | ||||
2295 | if (nMode & SwInsertFlags::FORCEHINTEXPAND) | ||||
2296 | { | ||||
2297 | SetIgnoreDontExpand( true ); | ||||
2298 | } | ||||
2299 | |||||
2300 | Update( rIdx, nLen ); // text content changed! | ||||
2301 | |||||
2302 | if (nMode & SwInsertFlags::FORCEHINTEXPAND) | ||||
2303 | { | ||||
2304 | SetIgnoreDontExpand( bOldExpFlg ); | ||||
2305 | } | ||||
2306 | |||||
2307 | if ( HasWriterListeners() ) | ||||
2308 | { // send this before messing with hints, which will send RES_UPDATE_ATTR | ||||
2309 | SwInsText aHint( aPos, nLen ); | ||||
2310 | NotifyClients( nullptr, &aHint ); | ||||
2311 | } | ||||
2312 | |||||
2313 | if ( HasHints() ) | ||||
2314 | { | ||||
2315 | m_pSwpHints->SortIfNeedBe(); | ||||
2316 | bool const bHadHints(!m_pSwpHints->CanBeDeleted()); | ||||
2317 | bool bMergePortionsNeeded(false); | ||||
2318 | for ( size_t i = 0; i < m_pSwpHints->Count() && | ||||
2319 | rIdx >= m_pSwpHints->GetWithoutResorting(i)->GetStart(); ++i ) | ||||
2320 | { | ||||
2321 | SwTextAttr * const pHt = m_pSwpHints->GetWithoutResorting( i ); | ||||
2322 | const sal_Int32 * const pEndIdx = pHt->GetEnd(); | ||||
2323 | if( !pEndIdx ) | ||||
2324 | continue; | ||||
2325 | |||||
2326 | if( rIdx == *pEndIdx ) | ||||
2327 | { | ||||
2328 | if ( (nMode & SwInsertFlags::NOHINTEXPAND) || | ||||
2329 | (!(nMode & SwInsertFlags::FORCEHINTEXPAND) | ||||
2330 | && pHt->DontExpand()) ) | ||||
2331 | { | ||||
2332 | m_pSwpHints->DeleteAtPos(i); | ||||
2333 | // on empty attributes also adjust Start | ||||
2334 | if( rIdx == pHt->GetStart() ) | ||||
2335 | pHt->SetStart( pHt->GetStart() - nLen ); | ||||
2336 | pHt->SetEnd(*pEndIdx - nLen); | ||||
2337 | // could be that pHt has IsFormatIgnoreEnd set, and it's | ||||
2338 | // not a RSID-only hint - now we have the inserted text | ||||
2339 | // between pHt and its continuation... which we don't know. | ||||
2340 | // punt the job to MergePortions below. | ||||
2341 | if (pHt->IsFormatIgnoreEnd()) | ||||
2342 | { | ||||
2343 | bMergePortionsNeeded = true; | ||||
2344 | } | ||||
2345 | InsertHint( pHt, SetAttrMode::NOHINTADJUST ); | ||||
2346 | } | ||||
2347 | // empty hints at insert position? | ||||
2348 | else if ( (nMode & SwInsertFlags::EMPTYEXPAND) | ||||
2349 | && (*pEndIdx == pHt->GetStart()) ) | ||||
2350 | { | ||||
2351 | m_pSwpHints->DeleteAtPos(i); | ||||
2352 | pHt->SetStart( pHt->GetStart() - nLen ); | ||||
2353 | const size_t nCurrentLen = m_pSwpHints->Count(); | ||||
2354 | InsertHint( pHt/* AUTOSTYLES:, SetAttrMode::NOHINTADJUST*/ ); | ||||
2355 | if ( nCurrentLen > m_pSwpHints->Count() && i ) | ||||
2356 | { | ||||
2357 | --i; | ||||
2358 | } | ||||
2359 | continue; | ||||
2360 | } | ||||
2361 | else | ||||
2362 | { | ||||
2363 | continue; | ||||
2364 | } | ||||
2365 | } | ||||
2366 | if ( !(nMode & SwInsertFlags::NOHINTEXPAND) && | ||||
2367 | rIdx == nLen && pHt->GetStart() == rIdx.GetIndex() && | ||||
2368 | !pHt->IsDontExpandStartAttr() ) | ||||
2369 | { | ||||
2370 | // no field, at paragraph start, HintExpand | ||||
2371 | m_pSwpHints->DeleteAtPos(i); | ||||
2372 | pHt->SetStart( pHt->GetStart() - nLen ); | ||||
2373 | // no effect on format ignore flags here (para start) | ||||
2374 | InsertHint( pHt, SetAttrMode::NOHINTADJUST ); | ||||
2375 | } | ||||
2376 | } | ||||
2377 | if (bMergePortionsNeeded) | ||||
2378 | { | ||||
2379 | m_pSwpHints->MergePortions(*this); | ||||
2380 | } | ||||
2381 | SAL_WARN_IF(bHadHints && m_pSwpHints->CanBeDeleted(), "sw.core",do { if (true && (bHadHints && m_pSwpHints-> CanBeDeleted())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "SwTextNode::InsertText: unexpected loss of hints" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: unexpected loss of hints" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: unexpected loss of hints"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SwTextNode::InsertText: unexpected loss of hints" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: unexpected loss of hints" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: unexpected loss of hints"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
2382 | "SwTextNode::InsertText: unexpected loss of hints")do { if (true && (bHadHints && m_pSwpHints-> CanBeDeleted())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "SwTextNode::InsertText: unexpected loss of hints" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: unexpected loss of hints" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: unexpected loss of hints"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SwTextNode::InsertText: unexpected loss of hints" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::InsertText: unexpected loss of hints" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::InsertText: unexpected loss of hints"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2382" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
2383 | } | ||||
2384 | |||||
2385 | // By inserting a character, the hidden flags | ||||
2386 | // at the TextNode can become invalid: | ||||
2387 | SetCalcHiddenCharFlags(); | ||||
2388 | |||||
2389 | CHECK_SWPHINTS(this); | ||||
2390 | return sInserted; | ||||
2391 | } | ||||
2392 | |||||
2393 | void SwTextNode::CutText( SwTextNode * const pDest, | ||||
2394 | const SwIndex & rStart, const sal_Int32 nLen ) | ||||
2395 | { | ||||
2396 | assert(pDest)(static_cast <bool> (pDest) ? void (0) : __assert_fail ( "pDest", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2396, __extension__ __PRETTY_FUNCTION__)); // Cut requires a destination | ||||
2397 | SwIndex aDestStt(pDest, pDest->GetText().getLength()); | ||||
2398 | CutImpl( pDest, aDestStt, rStart, nLen, false ); | ||||
2399 | } | ||||
2400 | |||||
2401 | void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart, | ||||
2402 | const SwIndex & rStart, sal_Int32 nLen, const bool bUpdate ) | ||||
2403 | { | ||||
2404 | assert(pDest)(static_cast <bool> (pDest) ? void (0) : __assert_fail ( "pDest", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2404, __extension__ __PRETTY_FUNCTION__)); // Cut requires a destination | ||||
2405 | |||||
2406 | assert(&GetDoc() == &pDest->GetDoc())(static_cast <bool> (&GetDoc() == &pDest->GetDoc ()) ? void (0) : __assert_fail ("&GetDoc() == &pDest->GetDoc()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2406, __extension__ __PRETTY_FUNCTION__)); // must be same document | ||||
2407 | |||||
2408 | assert(pDest != this)(static_cast <bool> (pDest != this) ? void (0) : __assert_fail ("pDest != this", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2408, __extension__ __PRETTY_FUNCTION__)); // destination must be different node | ||||
2409 | |||||
2410 | if( !nLen ) | ||||
2411 | { | ||||
2412 | // if no length is given, copy attributes at position rStart | ||||
2413 | CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() ); | ||||
2414 | return; | ||||
2415 | } | ||||
2416 | |||||
2417 | sal_Int32 nTextStartIdx = rStart.GetIndex(); | ||||
2418 | sal_Int32 nDestStart = rDestStart.GetIndex(); // remember old Pos | ||||
2419 | const sal_Int32 nInitSize = pDest->m_Text.getLength(); | ||||
2420 | |||||
2421 | if (pDest->GetSpaceLeft() < nLen) | ||||
2422 | { // FIXME: could only happen when called from SwRangeRedline::Show. | ||||
2423 | // unfortunately can't really do anything here to handle that... | ||||
2424 | abort(); | ||||
2425 | } | ||||
2426 | pDest->m_Text = pDest->m_Text.replaceAt(nDestStart, 0, | ||||
2427 | m_Text.copy(nTextStartIdx, nLen)); | ||||
2428 | OUString const newText = m_Text.replaceAt(nTextStartIdx, nLen, ""); | ||||
2429 | nLen = pDest->m_Text.getLength() - nInitSize; // update w/ current size! | ||||
2430 | if (!nLen) // String didn't grow? | ||||
2431 | return; | ||||
2432 | |||||
2433 | if (bUpdate) | ||||
2434 | { | ||||
2435 | // Update all SwIndex | ||||
2436 | pDest->Update( rDestStart, nLen, false, false/*??? why was it true*/); | ||||
2437 | } | ||||
2438 | |||||
2439 | CHECK_SWPHINTS(pDest); | ||||
2440 | |||||
2441 | const sal_Int32 nEnd = rStart.GetIndex() + nLen; | ||||
2442 | bool const bUndoNodes = | ||||
2443 | GetDoc().GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); | ||||
2444 | |||||
2445 | // copy hard attributes on whole paragraph | ||||
2446 | if (HasSwAttrSet()) | ||||
2447 | { | ||||
2448 | bool hasSwAttrSet = pDest->HasSwAttrSet(); | ||||
2449 | if (hasSwAttrSet) | ||||
2450 | { | ||||
2451 | // if we have our own property set it doesn't mean | ||||
2452 | // that this set defines any style different to Standard one. | ||||
2453 | hasSwAttrSet = false; | ||||
2454 | |||||
2455 | // so, let's check deeper if property set has defined any property | ||||
2456 | if (pDest->GetpSwAttrSet()) | ||||
2457 | { | ||||
2458 | // check all items in the property set | ||||
2459 | SfxItemIter aIter( *pDest->GetpSwAttrSet() ); | ||||
2460 | const SfxPoolItem* pItem = aIter.GetCurItem(); | ||||
2461 | do | ||||
2462 | { | ||||
2463 | // check current item | ||||
2464 | sal_uInt16 nWhich = IsInvalidItem( pItem ) | ||||
2465 | ? pDest->GetpSwAttrSet()->GetWhichByPos( aIter.GetCurPos() ) | ||||
2466 | : pItem->Which(); | ||||
2467 | if( RES_FRMATR_STYLE_NAME != nWhich && | ||||
2468 | RES_FRMATR_CONDITIONAL_STYLE_NAME != nWhich && | ||||
2469 | SfxItemState::SET == pDest->GetpSwAttrSet()->GetItemState( nWhich, false ) ) | ||||
2470 | { | ||||
2471 | // check if parent value (original value in style) has the same value as in [pItem] | ||||
2472 | const SfxPoolItem& rParentItem = pDest->GetpSwAttrSet()->GetParent()->Get( nWhich, true ); | ||||
2473 | |||||
2474 | hasSwAttrSet = (rParentItem != *pItem); | ||||
2475 | |||||
2476 | // property set is not empty => no need to make anymore checks | ||||
2477 | if (hasSwAttrSet) | ||||
2478 | break; | ||||
2479 | } | ||||
2480 | |||||
2481 | // let's check next item | ||||
2482 | pItem = aIter.NextItem(); | ||||
2483 | } while (pItem); | ||||
2484 | } | ||||
2485 | } | ||||
2486 | |||||
2487 | // all or just the Char attributes? | ||||
2488 | if( nInitSize || hasSwAttrSet || | ||||
2489 | nLen != pDest->GetText().getLength()) | ||||
2490 | { | ||||
2491 | SfxItemSet aCharSet( | ||||
2492 | pDest->GetDoc().GetAttrPool(), | ||||
2493 | svl::Items< | ||||
2494 | RES_CHRATR_BEGIN, RES_CHRATR_END - 1, | ||||
2495 | RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT, | ||||
2496 | RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1>{}); | ||||
2497 | aCharSet.Put( *GetpSwAttrSet() ); | ||||
2498 | if( aCharSet.Count() ) | ||||
2499 | pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen ); | ||||
2500 | } | ||||
2501 | else | ||||
2502 | { | ||||
2503 | GetpSwAttrSet()->CopyToModify( *pDest ); | ||||
2504 | } | ||||
2505 | } | ||||
2506 | |||||
2507 | // notify frames - before moving hints, because footnotes | ||||
2508 | // want to find their anchor text frame in the follow chain | ||||
2509 | SwInsText aInsHint( nDestStart, nLen ); | ||||
2510 | pDest->ModifyNotification( nullptr, &aInsHint ); | ||||
2511 | sw::MoveText const moveHint(pDest, nDestStart, nTextStartIdx, nLen); | ||||
2512 | CallSwClientNotify(moveHint); | ||||
2513 | SwDelText aDelHint( nTextStartIdx, nLen ); | ||||
2514 | ModifyNotification( nullptr, &aDelHint ); | ||||
2515 | |||||
2516 | // 2. move attributes | ||||
2517 | // Iterate over attribute array until the start of the attribute | ||||
2518 | // is behind the moved range | ||||
2519 | bool bMergePortionsNeeded(false); | ||||
2520 | size_t nAttrCnt = 0; | ||||
2521 | while (m_pSwpHints && (nAttrCnt < m_pSwpHints->Count())) | ||||
2522 | { | ||||
2523 | SwTextAttr * const pHt = m_pSwpHints->Get(nAttrCnt); | ||||
2524 | const sal_Int32 nAttrStartIdx = pHt->GetStart(); | ||||
2525 | if ( nAttrStartIdx >= nEnd ) | ||||
2526 | break; | ||||
2527 | const sal_Int32 * const pEndIdx = pHt->GetEnd(); | ||||
2528 | const sal_uInt16 nWhich = pHt->Which(); | ||||
2529 | SwTextAttr *pNewHt = nullptr; | ||||
2530 | |||||
2531 | // if the hint has a dummy character, then it must not be split! | ||||
2532 | if(nAttrStartIdx < nTextStartIdx) | ||||
2533 | { | ||||
2534 | // start is before the range | ||||
2535 | if (!pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich | ||||
2536 | || bUndoNodes ) && pEndIdx && *pEndIdx > nTextStartIdx) | ||||
2537 | { | ||||
2538 | // attribute with extent and end of attribute is in the range | ||||
2539 | pNewHt = MakeTextAttr( pDest->GetDoc(), pHt->GetAttr(), | ||||
2540 | nDestStart, | ||||
2541 | nDestStart + ( | ||||
2542 | *pEndIdx > nEnd | ||||
2543 | ? nLen | ||||
2544 | : *pEndIdx - nTextStartIdx ) ); | ||||
2545 | } | ||||
2546 | } | ||||
2547 | else | ||||
2548 | { | ||||
2549 | // start is inside the range | ||||
2550 | if (!pEndIdx || *pEndIdx < nEnd || | ||||
2551 | (!bUndoNodes && RES_TXTATR_REFMARK == nWhich) | ||||
2552 | || pHt->HasDummyChar() ) | ||||
2553 | { | ||||
2554 | // do not delete note and later add it -> sidebar flickering | ||||
2555 | if (GetDoc().GetDocShell()) | ||||
2556 | { | ||||
2557 | GetDoc().GetDocShell()->Broadcast( SfxHint(SfxHintId::SwSplitNodeOperation)); | ||||
2558 | } | ||||
2559 | // move attribute | ||||
2560 | m_pSwpHints->Delete( pHt ); | ||||
2561 | // reset start/end indexes | ||||
2562 | if (pHt->IsFormatIgnoreStart() || pHt->IsFormatIgnoreEnd()) | ||||
2563 | { | ||||
2564 | bMergePortionsNeeded = true; | ||||
2565 | } | ||||
2566 | pHt->SetStart(nDestStart + (nAttrStartIdx - nTextStartIdx)); | ||||
2567 | if (pEndIdx) | ||||
2568 | { | ||||
2569 | pHt->SetEnd( nDestStart + ( | ||||
2570 | *pEndIdx > nEnd | ||||
2571 | ? nLen | ||||
2572 | : *pEndIdx - nTextStartIdx ) ); | ||||
2573 | } | ||||
2574 | pDest->InsertHint( pHt, | ||||
2575 | SetAttrMode::NOTXTATRCHR | ||||
2576 | | SetAttrMode::DONTREPLACE ); | ||||
2577 | if (GetDoc().GetDocShell()) | ||||
2578 | { | ||||
2579 | GetDoc().GetDocShell()->Broadcast( SfxHint(SfxHintId::SwSplitNodeOperation)); | ||||
2580 | } | ||||
2581 | continue; // iterate while loop, no ++ ! | ||||
2582 | } | ||||
2583 | // the end is behind the range | ||||
2584 | else if (RES_TXTATR_REFMARK != nWhich || bUndoNodes) | ||||
2585 | { | ||||
2586 | pNewHt = MakeTextAttr( GetDoc(), pHt->GetAttr(), | ||||
2587 | nDestStart + (nAttrStartIdx - nTextStartIdx), | ||||
2588 | nDestStart + (*pEndIdx > nEnd | ||||
2589 | ? nLen | ||||
2590 | : *pEndIdx - nTextStartIdx)); | ||||
2591 | } | ||||
2592 | } | ||||
2593 | if (pNewHt) | ||||
2594 | { | ||||
2595 | const bool bSuccess( pDest->InsertHint( pNewHt, | ||||
2596 | SetAttrMode::NOTXTATRCHR | ||||
2597 | | SetAttrMode::DONTREPLACE | ||||
2598 | | SetAttrMode::IS_COPY) ); | ||||
2599 | if (bSuccess) | ||||
2600 | { | ||||
2601 | lcl_CopyHint( nWhich, pHt, pNewHt, nullptr, pDest ); | ||||
2602 | } | ||||
2603 | } | ||||
2604 | ++nAttrCnt; | ||||
2605 | } | ||||
2606 | // If there are still empty attributes around, they have a higher priority | ||||
2607 | // than any attributes that become empty due to the move. | ||||
2608 | // So temporarily remove them and Update the array, then re-insert the | ||||
2609 | // removed ones so they overwrite the others. | ||||
2610 | if (m_pSwpHints && nAttrCnt < m_pSwpHints->Count()) | ||||
2611 | { | ||||
2612 | SwpHts aArr; | ||||
2613 | while (nAttrCnt < m_pSwpHints->Count()) | ||||
2614 | { | ||||
2615 | SwTextAttr * const pHt = m_pSwpHints->Get(nAttrCnt); | ||||
2616 | if (nEnd != pHt->GetStart()) | ||||
2617 | break; | ||||
2618 | const sal_Int32 * const pEndIdx = pHt->GetEnd(); | ||||
2619 | if (pEndIdx && *pEndIdx == nEnd) | ||||
2620 | { | ||||
2621 | aArr.push_back( pHt ); | ||||
2622 | m_pSwpHints->Delete( pHt ); | ||||
2623 | } | ||||
2624 | else | ||||
2625 | { | ||||
2626 | ++nAttrCnt; | ||||
2627 | } | ||||
2628 | } | ||||
2629 | Update( rStart, nLen, true, true ); | ||||
2630 | |||||
2631 | for (SwTextAttr* pHt : aArr) | ||||
2632 | { | ||||
2633 | pHt->SetStart( rStart.GetIndex() ); | ||||
2634 | pHt->SetEnd( rStart.GetIndex() ); | ||||
2635 | InsertHint( pHt ); | ||||
2636 | } | ||||
2637 | } | ||||
2638 | else | ||||
2639 | { | ||||
2640 | Update( rStart, nLen, true, true ); | ||||
2641 | } | ||||
2642 | |||||
2643 | // set after moving hints | ||||
2644 | m_Text = newText; | ||||
2645 | |||||
2646 | if (bMergePortionsNeeded) | ||||
2647 | { | ||||
2648 | m_pSwpHints->MergePortions(*this); | ||||
2649 | } | ||||
2650 | |||||
2651 | CHECK_SWPHINTS(this); | ||||
2652 | |||||
2653 | TryDeleteSwpHints(); | ||||
2654 | } | ||||
2655 | |||||
2656 | void SwTextNode::EraseText(const SwIndex &rIdx, const sal_Int32 nCount, | ||||
2657 | const SwInsertFlags nMode ) | ||||
2658 | { | ||||
2659 | assert(rIdx <= m_Text.getLength())(static_cast <bool> (rIdx <= m_Text.getLength()) ? void (0) : __assert_fail ("rIdx <= m_Text.getLength()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2659, __extension__ __PRETTY_FUNCTION__)); // invalid index | ||||
2660 | |||||
2661 | const sal_Int32 nStartIdx = rIdx.GetIndex(); | ||||
2662 | const sal_Int32 nCnt = (nCount==SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF)) | ||||
2663 | ? m_Text.getLength() - nStartIdx : nCount; | ||||
2664 | const sal_Int32 nEndIdx = nStartIdx + nCnt; | ||||
2665 | if (nEndIdx <= m_Text.getLength()) | ||||
2666 | m_Text = m_Text.replaceAt(nStartIdx, nCnt, ""); | ||||
2667 | |||||
2668 | // GCAttr(); don't remove all empty ones, just the ones that are in the | ||||
2669 | // range but not at the end of the range. | ||||
2670 | |||||
2671 | for ( size_t i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) | ||||
2672 | { | ||||
2673 | SwTextAttr *pHt = m_pSwpHints->Get(i); | ||||
2674 | |||||
2675 | const sal_Int32 nHintStart = pHt->GetStart(); | ||||
2676 | |||||
2677 | if ( nHintStart < nStartIdx ) | ||||
2678 | continue; | ||||
2679 | |||||
2680 | if ( nHintStart > nEndIdx ) | ||||
2681 | break; // hints are sorted by end, so break here | ||||
2682 | |||||
2683 | const sal_Int32* pHtEndIdx = pHt->GetEnd(); | ||||
2684 | const sal_uInt16 nWhich = pHt->Which(); | ||||
2685 | |||||
2686 | if( !pHtEndIdx ) | ||||
2687 | { | ||||
2688 | // attribute with neither end nor CH_TXTATR? | ||||
2689 | assert(pHt->HasDummyChar())(static_cast <bool> (pHt->HasDummyChar()) ? void (0) : __assert_fail ("pHt->HasDummyChar()", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2689, __extension__ __PRETTY_FUNCTION__)); | ||||
2690 | if (isTXTATR(nWhich) && (nHintStart < nEndIdx)) | ||||
2691 | { | ||||
2692 | m_pSwpHints->DeleteAtPos(i); | ||||
2693 | DestroyAttr( pHt ); | ||||
2694 | --i; | ||||
2695 | } | ||||
2696 | continue; | ||||
2697 | } | ||||
2698 | |||||
2699 | assert(!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)(static_cast <bool> (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx ))) ? void (0) : __assert_fail ("!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2702, __extension__ __PRETTY_FUNCTION__)) | ||||
2700 | && pHt->HasDummyChar() )(static_cast <bool> (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx ))) ? void (0) : __assert_fail ("!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2702, __extension__ __PRETTY_FUNCTION__)) | ||||
2701 | // next line: deleting exactly dummy char: DeleteAttributes(static_cast <bool> (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx ))) ? void (0) : __assert_fail ("!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2702, __extension__ __PRETTY_FUNCTION__)) | ||||
2702 | || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)))(static_cast <bool> (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx ))) ? void (0) : __assert_fail ("!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) && pHt->HasDummyChar() ) || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 2702, __extension__ __PRETTY_FUNCTION__)); | ||||
2703 | // "ERROR: deleting left-overlapped attribute with CH_TXTATR"); | ||||
2704 | |||||
2705 | // Delete the hint if: | ||||
2706 | // 1. The hint ends before the deletion end position or | ||||
2707 | // 2. The hint ends at the deletion end position and | ||||
2708 | // we are not in empty expand mode and | ||||
2709 | // the hint is a [toxmark|refmark|ruby|inputfield] text attribute | ||||
2710 | // 3. deleting exactly the dummy char of an hint with end and dummy | ||||
2711 | // char deletes the hint | ||||
2712 | if ( (*pHtEndIdx < nEndIdx) | ||||
2713 | || ( (*pHtEndIdx == nEndIdx) && | ||||
2714 | !(SwInsertFlags::EMPTYEXPAND & nMode) && | ||||
2715 | ( (RES_TXTATR_TOXMARK == nWhich) || | ||||
2716 | (RES_TXTATR_REFMARK == nWhich) || | ||||
2717 | (RES_TXTATR_CJK_RUBY == nWhich) || | ||||
2718 | (RES_TXTATR_INPUTFIELD == nWhich) ) ) | ||||
2719 | || ( (nHintStart < nEndIdx) && | ||||
2720 | pHt->HasDummyChar() ) | ||||
2721 | ) | ||||
2722 | { | ||||
2723 | m_pSwpHints->DeleteAtPos(i); | ||||
2724 | DestroyAttr( pHt ); | ||||
2725 | --i; | ||||
2726 | } | ||||
2727 | } | ||||
2728 | |||||
2729 | OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?")do { if (true && (!(rIdx.GetIndex() == nStartIdx))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2729" ": "), "%s", "huh? start index has changed?"); } } while (false); | ||||
2730 | |||||
2731 | TryDeleteSwpHints(); | ||||
2732 | |||||
2733 | Update( rIdx, nCnt, true ); | ||||
2734 | |||||
2735 | if( 1 == nCnt ) | ||||
2736 | { | ||||
2737 | SwDelChr aHint( nStartIdx ); | ||||
2738 | NotifyClients( nullptr, &aHint ); | ||||
2739 | } | ||||
2740 | else | ||||
2741 | { | ||||
2742 | SwDelText aHint( nStartIdx, nCnt ); | ||||
2743 | NotifyClients( nullptr, &aHint ); | ||||
2744 | } | ||||
2745 | |||||
2746 | OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?")do { if (true && (!(rIdx.GetIndex() == nStartIdx))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "2746" ": "), "%s", "huh? start index has changed?"); } } while (false); | ||||
2747 | |||||
2748 | // By deleting a character, the hidden flags | ||||
2749 | // at the TextNode can become invalid: | ||||
2750 | SetCalcHiddenCharFlags(); | ||||
2751 | |||||
2752 | CHECK_SWPHINTS(this); | ||||
2753 | } | ||||
2754 | |||||
2755 | void SwTextNode::GCAttr() | ||||
2756 | { | ||||
2757 | if ( !HasHints() ) | ||||
2758 | return; | ||||
2759 | |||||
2760 | bool bChanged = false; | ||||
2761 | sal_Int32 nMin = m_Text.getLength(); | ||||
2762 | sal_Int32 nMax = 0; | ||||
2763 | const bool bAll = nMin != 0; // on empty paragraphs only remove INetFormats | ||||
2764 | |||||
2765 | for ( size_t i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) | ||||
2766 | { | ||||
2767 | SwTextAttr * const pHt = m_pSwpHints->Get(i); | ||||
2768 | |||||
2769 | // if end and start are equal, delete it | ||||
2770 | const sal_Int32 * const pEndIdx = pHt->GetEnd(); | ||||
2771 | if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == pHt->GetStart()) | ||||
2772 | && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) ) | ||||
2773 | { | ||||
2774 | bChanged = true; | ||||
2775 | nMin = std::min( nMin, pHt->GetStart() ); | ||||
2776 | nMax = std::max( nMax, *pHt->GetEnd() ); | ||||
2777 | DestroyAttr( m_pSwpHints->Cut(i) ); | ||||
2778 | --i; | ||||
2779 | } | ||||
2780 | else | ||||
2781 | { | ||||
2782 | pHt->SetDontExpand( false ); | ||||
2783 | } | ||||
2784 | } | ||||
2785 | TryDeleteSwpHints(); | ||||
2786 | |||||
2787 | if(bChanged) | ||||
2788 | { | ||||
2789 | // textframes react to aHint, others to aNew | ||||
2790 | SwUpdateAttr aHint( | ||||
2791 | nMin, | ||||
2792 | nMax, | ||||
2793 | 0); | ||||
2794 | |||||
2795 | NotifyClients( nullptr, &aHint ); | ||||
2796 | SwFormatChg aNew( GetTextColl() ); | ||||
2797 | NotifyClients( nullptr, &aNew ); | ||||
2798 | } | ||||
2799 | } | ||||
2800 | |||||
2801 | SwNumRule* SwTextNode::GetNumRule(bool bInParent) const | ||||
2802 | { | ||||
2803 | SwNumRule* pRet = nullptr; | ||||
2804 | |||||
2805 | const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent ); | ||||
2806 | bool bNoNumRule = false; | ||||
2807 | if ( pItem ) | ||||
2808 | { | ||||
2809 | OUString sNumRuleName = | ||||
2810 | static_cast<const SwNumRuleItem *>(pItem)->GetValue(); | ||||
2811 | if (!sNumRuleName.isEmpty()) | ||||
2812 | { | ||||
2813 | pRet = GetDoc().FindNumRulePtr( sNumRuleName ); | ||||
2814 | } | ||||
2815 | else // numbering is turned off | ||||
2816 | bNoNumRule = true; | ||||
2817 | } | ||||
2818 | |||||
2819 | if ( !bNoNumRule ) | ||||
2820 | { | ||||
2821 | if ( pRet && pRet == GetDoc().GetOutlineNumRule() && | ||||
2822 | ( !HasSwAttrSet() || | ||||
2823 | SfxItemState::SET != | ||||
2824 | GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, false ) ) ) | ||||
2825 | { | ||||
2826 | SwTextFormatColl* pColl = GetTextColl(); | ||||
2827 | if ( pColl ) | ||||
2828 | { | ||||
2829 | const SwNumRuleItem& rDirectItem = pColl->GetNumRule( false ); | ||||
2830 | if ( rDirectItem.GetValue().isEmpty() ) | ||||
2831 | { | ||||
2832 | pRet = nullptr; | ||||
2833 | } | ||||
2834 | } | ||||
2835 | } | ||||
2836 | } | ||||
2837 | |||||
2838 | return pRet; | ||||
2839 | } | ||||
2840 | |||||
2841 | void SwTextNode::NumRuleChgd() | ||||
2842 | { | ||||
2843 | if ( IsInList() ) | ||||
2844 | { | ||||
2845 | SwNumRule* pNumRule = GetNumRule(); | ||||
2846 | if ( pNumRule && pNumRule != GetNum()->GetNumRule() ) | ||||
2847 | { | ||||
2848 | mpNodeNum->ChangeNumRule( *pNumRule ); | ||||
2849 | if (mpNodeNumRLHidden) | ||||
2850 | { | ||||
2851 | mpNodeNumRLHidden->ChangeNumRule(*pNumRule); | ||||
2852 | } | ||||
2853 | } | ||||
2854 | } | ||||
2855 | |||||
2856 | if( IsInCache() ) | ||||
2857 | { | ||||
2858 | SwFrame::GetCache().Delete( this ); | ||||
2859 | SetInCache( false ); | ||||
2860 | } | ||||
2861 | SetInSwFntCache( false ); | ||||
2862 | |||||
2863 | // Sending "noop" modify in order to cause invalidations of registered | ||||
2864 | // <SwTextFrame> instances to get the list style change respectively the change | ||||
2865 | // in the list tree reflected in the layout. | ||||
2866 | // Important note: | ||||
2867 | { | ||||
2868 | SvxLRSpaceItem& rLR = const_cast<SvxLRSpaceItem&>(GetSwAttrSet().GetLRSpace()); | ||||
2869 | NotifyClients( &rLR, &rLR ); | ||||
2870 | } | ||||
2871 | |||||
2872 | SetWordCountDirty( true ); | ||||
2873 | } | ||||
2874 | |||||
2875 | // -> #i27615# | ||||
2876 | bool SwTextNode::IsNumbered(SwRootFrame const*const pLayout) const | ||||
2877 | { | ||||
2878 | SwNumRule* pRule = GetNum(pLayout) ? GetNum(pLayout)->GetNumRule() : nullptr; | ||||
2879 | return pRule && IsCountedInList(); | ||||
2880 | } | ||||
2881 | |||||
2882 | bool SwTextNode::HasMarkedLabel() const | ||||
2883 | { | ||||
2884 | bool bResult = false; | ||||
2885 | |||||
2886 | if ( IsInList() ) | ||||
2887 | { | ||||
2888 | bResult = | ||||
2889 | GetDoc().getIDocumentListsAccess().getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() ); | ||||
2890 | } | ||||
2891 | |||||
2892 | return bResult; | ||||
2893 | } | ||||
2894 | // <- #i27615# | ||||
2895 | |||||
2896 | SwTextNode* SwTextNode::MakeNewTextNode( const SwNodeIndex& rPos, bool bNext, | ||||
2897 | bool bChgFollow ) | ||||
2898 | { | ||||
2899 | // ignore hard PageBreak/PageDesc/ColumnBreak from Auto-Set | ||||
2900 | std::unique_ptr<SwAttrSet> pNewAttrSet; | ||||
2901 | // #i75353# | ||||
2902 | bool bClearHardSetNumRuleWhenFormatCollChanges( false ); | ||||
2903 | if( HasSwAttrSet() ) | ||||
2904 | { | ||||
2905 | pNewAttrSet.reset(new SwAttrSet( *GetpSwAttrSet() )); | ||||
2906 | const SfxItemSet* pTmpSet = GetpSwAttrSet(); | ||||
2907 | |||||
2908 | if (bNext
| ||||
2909 | pTmpSet = pNewAttrSet.get(); | ||||
2910 | |||||
2911 | // !bNext: remove PageBreaks/PageDesc/ColBreak from this | ||||
2912 | bool bRemoveFromCache = false; | ||||
2913 | std::vector<sal_uInt16> aClearWhichIds; | ||||
2914 | if ( bNext
| ||||
2915 | bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) ); | ||||
2916 | else | ||||
2917 | aClearWhichIds.push_back( RES_PAGEDESC ); | ||||
2918 | |||||
2919 | if( SfxItemState::SET == pTmpSet->GetItemState( RES_BREAK, false ) ) | ||||
2920 | { | ||||
2921 | if ( bNext ) | ||||
2922 | pNewAttrSet->ClearItem( RES_BREAK ); | ||||
2923 | else | ||||
2924 | aClearWhichIds.push_back( RES_BREAK ); | ||||
2925 | bRemoveFromCache = true; | ||||
2926 | } | ||||
2927 | if( SfxItemState::SET == pTmpSet->GetItemState( RES_KEEP, false ) ) | ||||
2928 | { | ||||
2929 | if ( bNext ) | ||||
2930 | pNewAttrSet->ClearItem( RES_KEEP ); | ||||
2931 | else | ||||
2932 | aClearWhichIds.push_back( RES_KEEP ); | ||||
2933 | bRemoveFromCache = true; | ||||
2934 | } | ||||
2935 | if( SfxItemState::SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, false ) ) | ||||
2936 | { | ||||
2937 | if ( bNext ) | ||||
2938 | pNewAttrSet->ClearItem( RES_PARATR_SPLIT ); | ||||
2939 | else | ||||
2940 | aClearWhichIds.push_back( RES_PARATR_SPLIT ); | ||||
2941 | bRemoveFromCache = true; | ||||
2942 | } | ||||
2943 | if(SfxItemState::SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, false)) | ||||
2944 | { | ||||
2945 | SwNumRule * pRule = GetNumRule(); | ||||
2946 | |||||
2947 | if (pRule && IsOutline()) | ||||
2948 | { | ||||
2949 | if ( bNext ) | ||||
2950 | pNewAttrSet->ClearItem(RES_PARATR_NUMRULE); | ||||
2951 | else | ||||
2952 | { | ||||
2953 | // #i75353# | ||||
2954 | // No clear of hard set numbering rule at an outline paragraph at this point. | ||||
2955 | // Only if the paragraph style changes - see below. | ||||
2956 | bClearHardSetNumRuleWhenFormatCollChanges = true; | ||||
2957 | } | ||||
2958 | bRemoveFromCache = true; | ||||
2959 | } | ||||
2960 | } | ||||
2961 | |||||
2962 | if ( !aClearWhichIds.empty() ) | ||||
2963 | bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds ); | ||||
2964 | |||||
2965 | if( !bNext
| ||||
2966 | { | ||||
2967 | SwFrame::GetCache().Delete( this ); | ||||
2968 | SetInCache( false ); | ||||
2969 | } | ||||
2970 | } | ||||
2971 | SwNodes& rNds = GetNodes(); | ||||
2972 | |||||
2973 | SwTextFormatColl* pColl = GetTextColl(); | ||||
2974 | |||||
2975 | SwTextNode *pNode = new SwTextNode( rPos, pColl, pNewAttrSet.get() ); | ||||
2976 | |||||
2977 | pNewAttrSet.reset(); | ||||
2978 | |||||
2979 | const SwNumRule* pRule = GetNumRule(); | ||||
2980 | if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) | ||||
2981 | { | ||||
2982 | // #i55459# | ||||
2983 | // - correction: parameter <bNext> has to be checked, as it was in the | ||||
2984 | // previous implementation. | ||||
2985 | if ( !bNext && !IsCountedInList() ) | ||||
2986 | SetCountedInList(true); | ||||
2987 | } | ||||
2988 | |||||
2989 | // In case the numbering caused a style from the pool to be assigned to | ||||
2990 | // the new node, don't overwrite that here! | ||||
2991 | if( pColl != pNode->GetTextColl() || | ||||
2992 | ( bChgFollow && pColl != GetTextColl() )) | ||||
2993 | return pNode; // that ought to be enough? | ||||
2994 | |||||
2995 | pNode->ChgTextCollUpdateNum( nullptr, pColl ); // for numbering/outline | ||||
2996 | if( bNext || !bChgFollow ) | ||||
2997 | return pNode; | ||||
2998 | |||||
2999 | SwTextFormatColl *pNextColl = &pColl->GetNextTextFormatColl(); | ||||
3000 | // i#101870 perform action on different paragraph styles before applying | ||||
3001 | // the new paragraph style | ||||
3002 | if (pNextColl != pColl) | ||||
3003 | { | ||||
3004 | // #i75353# | ||||
3005 | if ( bClearHardSetNumRuleWhenFormatCollChanges ) | ||||
3006 | { | ||||
3007 | std::vector<sal_uInt16> aClearWhichIds; | ||||
3008 | aClearWhichIds.push_back( RES_PARATR_NUMRULE ); | ||||
3009 | if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() ) | ||||
3010 | { | ||||
3011 | SwFrame::GetCache().Delete( this ); | ||||
3012 | SetInCache( false ); | ||||
3013 | } | ||||
3014 | } | ||||
3015 | } | ||||
3016 | ChgFormatColl( pNextColl ); | ||||
3017 | |||||
3018 | return pNode; | ||||
3019 | } | ||||
3020 | |||||
3021 | SwContentNode* SwTextNode::AppendNode( const SwPosition & rPos ) | ||||
3022 | { | ||||
3023 | // position behind which it will be inserted | ||||
3024 | SwNodeIndex aIdx( rPos.nNode, 1 ); | ||||
3025 | SwTextNode* pNew = MakeNewTextNode( aIdx ); | ||||
| |||||
3026 | |||||
3027 | // reset list attributes at appended text node | ||||
3028 | pNew->ResetAttr( RES_PARATR_LIST_ISRESTART ); | ||||
3029 | pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); | ||||
3030 | pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED ); | ||||
3031 | if ( pNew->GetNumRule() == nullptr ) | ||||
3032 | { | ||||
3033 | pNew->ResetAttr( RES_PARATR_LIST_ID ); | ||||
3034 | pNew->ResetAttr( RES_PARATR_LIST_LEVEL ); | ||||
3035 | } | ||||
3036 | |||||
3037 | if (!IsInList() && GetNumRule() && !GetListId().isEmpty()) | ||||
3038 | { | ||||
3039 | AddToList(); | ||||
3040 | } | ||||
3041 | |||||
3042 | if( HasWriterListeners() ) | ||||
3043 | MakeFramesForAdjacentContentNode(*pNew); | ||||
3044 | return pNew; | ||||
3045 | } | ||||
3046 | |||||
3047 | SwTextAttr * SwTextNode::GetTextAttrForCharAt( | ||||
3048 | const sal_Int32 nIndex, | ||||
3049 | const sal_uInt16 nWhich ) const | ||||
3050 | { | ||||
3051 | assert(nWhich >= RES_TXTATR_BEGIN && nWhich <= RES_TXTATR_END)(static_cast <bool> (nWhich >= RES_TXTATR_BEGIN && nWhich <= RES_TXTATR_END) ? void (0) : __assert_fail ("nWhich >= RES_TXTATR_BEGIN && nWhich <= RES_TXTATR_END" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3051, __extension__ __PRETTY_FUNCTION__)); | ||||
3052 | if ( HasHints() ) | ||||
3053 | { | ||||
3054 | for ( size_t i = 0; i < m_pSwpHints->Count(); ++i ) | ||||
3055 | { | ||||
3056 | SwTextAttr * const pHint = m_pSwpHints->Get(i); | ||||
3057 | const sal_Int32 nStartPos = pHint->GetStart(); | ||||
3058 | if ( nIndex < nStartPos ) | ||||
3059 | { | ||||
3060 | return nullptr; | ||||
3061 | } | ||||
3062 | if ( (nIndex == nStartPos) && pHint->HasDummyChar() ) | ||||
3063 | { | ||||
3064 | return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() ) | ||||
3065 | ? pHint : nullptr; | ||||
3066 | } | ||||
3067 | } | ||||
3068 | } | ||||
3069 | return nullptr; | ||||
3070 | } | ||||
3071 | |||||
3072 | namespace | ||||
3073 | { | ||||
3074 | |||||
3075 | sal_uInt16 lcl_BoundListLevel(const int nActualLevel) | ||||
3076 | { | ||||
3077 | return static_cast<sal_uInt16>( std::min( std::max(nActualLevel, 0), MAXLEVEL-1 ) ); | ||||
3078 | } | ||||
3079 | |||||
3080 | } | ||||
3081 | |||||
3082 | // -> #i29560# | ||||
3083 | bool SwTextNode::HasNumber() const | ||||
3084 | { | ||||
3085 | bool bResult = false; | ||||
3086 | |||||
3087 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
3088 | if ( pRule ) | ||||
3089 | { | ||||
3090 | const SwNumFormat& aFormat(pRule->Get(lcl_BoundListLevel(GetActualListLevel()))); | ||||
3091 | |||||
3092 | // #i40041# | ||||
3093 | bResult = aFormat.IsEnumeration() && | ||||
3094 | SVX_NUM_NUMBER_NONE != aFormat.GetNumberingType(); | ||||
3095 | } | ||||
3096 | |||||
3097 | return bResult; | ||||
3098 | } | ||||
3099 | |||||
3100 | bool SwTextNode::HasBullet() const | ||||
3101 | { | ||||
3102 | bool bResult = false; | ||||
3103 | |||||
3104 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
3105 | if ( pRule ) | ||||
3106 | { | ||||
3107 | const SwNumFormat& aFormat(pRule->Get(lcl_BoundListLevel(GetActualListLevel()))); | ||||
3108 | |||||
3109 | bResult = aFormat.IsItemize(); | ||||
3110 | } | ||||
3111 | |||||
3112 | return bResult; | ||||
3113 | } | ||||
3114 | // <- #i29560# | ||||
3115 | |||||
3116 | // #128041# - introduce parameter <_bInclPrefixAndSuffixStrings> | ||||
3117 | //i53420 added max outline parameter | ||||
3118 | OUString SwTextNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, | ||||
3119 | const unsigned int _nRestrictToThisLevel, | ||||
3120 | SwRootFrame const*const pLayout) const | ||||
3121 | { | ||||
3122 | if (GetDoc().IsClipBoard() && m_pNumStringCache) | ||||
3123 | { | ||||
3124 | // #i111677# do not expand number strings in clipboard documents | ||||
3125 | return *m_pNumStringCache; | ||||
3126 | } | ||||
3127 | const SwNumRule* pRule = GetNum(pLayout) ? GetNum(pLayout)->GetNumRule() : nullptr; | ||||
3128 | if ( pRule && | ||||
3129 | IsCountedInList() ) | ||||
3130 | { | ||||
3131 | SvxNumberType const& rNumberType( | ||||
3132 | pRule->Get( lcl_BoundListLevel(GetActualListLevel()) ) ); | ||||
3133 | if (rNumberType.IsTextFormat() || | ||||
3134 | |||||
3135 | (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType())) | ||||
3136 | { | ||||
3137 | return pRule->MakeNumString( GetNum(pLayout)->GetNumberVector(), | ||||
3138 | _bInclPrefixAndSuffixStrings, | ||||
3139 | false, | ||||
3140 | _nRestrictToThisLevel, | ||||
3141 | nullptr, | ||||
3142 | GetLang(0)); | ||||
3143 | } | ||||
3144 | } | ||||
3145 | |||||
3146 | return OUString(); | ||||
3147 | } | ||||
3148 | |||||
3149 | long SwTextNode::GetLeftMarginWithNum( bool bTextLeft ) const | ||||
3150 | { | ||||
3151 | long nRet = 0; | ||||
3152 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
3153 | if( pRule ) | ||||
3154 | { | ||||
3155 | const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel())); | ||||
3156 | |||||
3157 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) | ||||
3158 | { | ||||
3159 | nRet = rFormat.GetAbsLSpace(); | ||||
3160 | |||||
3161 | if( !bTextLeft ) | ||||
3162 | { | ||||
3163 | if( 0 > rFormat.GetFirstLineOffset() && | ||||
3164 | nRet > -rFormat.GetFirstLineOffset() ) | ||||
3165 | nRet = nRet + rFormat.GetFirstLineOffset(); | ||||
3166 | else | ||||
3167 | nRet = 0; | ||||
3168 | } | ||||
3169 | |||||
3170 | if( pRule->IsAbsSpaces() ) | ||||
3171 | nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft(); | ||||
3172 | } | ||||
3173 | else if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) | ||||
3174 | { | ||||
3175 | if ( AreListLevelIndentsApplicable() ) | ||||
3176 | { | ||||
3177 | nRet = rFormat.GetIndentAt(); | ||||
3178 | // #i90401# | ||||
3179 | // Only negative first line indents have consider for the left margin | ||||
3180 | if ( !bTextLeft && | ||||
3181 | rFormat.GetFirstLineIndent() < 0 ) | ||||
3182 | { | ||||
3183 | nRet = nRet + rFormat.GetFirstLineIndent(); | ||||
3184 | } | ||||
3185 | } | ||||
3186 | } | ||||
3187 | } | ||||
3188 | |||||
3189 | return nRet; | ||||
3190 | } | ||||
3191 | |||||
3192 | bool SwTextNode::GetFirstLineOfsWithNum( short& rFLOffset ) const | ||||
3193 | { | ||||
3194 | // #i95907# | ||||
3195 | rFLOffset = 0; | ||||
3196 | |||||
3197 | // #i51089# | ||||
3198 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
3199 | if ( pRule ) | ||||
3200 | { | ||||
3201 | if ( IsCountedInList() ) | ||||
3202 | { | ||||
3203 | const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel())); | ||||
3204 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) | ||||
3205 | { | ||||
3206 | rFLOffset = rFormat.GetFirstLineOffset(); //TODO: overflow | ||||
3207 | |||||
3208 | if (!getIDocumentSettingAccess()->get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) | ||||
3209 | { | ||||
3210 | SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); | ||||
3211 | rFLOffset = rFLOffset + aItem.GetTextFirstLineOffset(); | ||||
3212 | } | ||||
3213 | } | ||||
3214 | else if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) | ||||
3215 | { | ||||
3216 | if ( AreListLevelIndentsApplicable() ) | ||||
3217 | { | ||||
3218 | rFLOffset = rFormat.GetFirstLineIndent(); | ||||
3219 | } | ||||
3220 | else if (!getIDocumentSettingAccess()->get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) | ||||
3221 | { | ||||
3222 | SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); | ||||
3223 | rFLOffset = aItem.GetTextFirstLineOffset(); | ||||
3224 | } | ||||
3225 | } | ||||
3226 | } | ||||
3227 | |||||
3228 | return true; | ||||
3229 | } | ||||
3230 | |||||
3231 | rFLOffset = GetSwAttrSet().GetLRSpace().GetTextFirstLineOffset(); | ||||
3232 | return false; | ||||
3233 | } | ||||
3234 | |||||
3235 | SwTwips SwTextNode::GetAdditionalIndentForStartingNewList() const | ||||
3236 | { | ||||
3237 | SwTwips nAdditionalIndent = 0; | ||||
3238 | |||||
3239 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
3240 | if ( pRule ) | ||||
3241 | { | ||||
3242 | const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel())); | ||||
3243 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) | ||||
3244 | { | ||||
3245 | nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); | ||||
3246 | |||||
3247 | if (getIDocumentSettingAccess()->get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) | ||||
3248 | { | ||||
3249 | nAdditionalIndent = nAdditionalIndent - | ||||
3250 | GetSwAttrSet().GetLRSpace().GetTextFirstLineOffset(); | ||||
3251 | } | ||||
3252 | } | ||||
3253 | else if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) | ||||
3254 | { | ||||
3255 | if ( AreListLevelIndentsApplicable() ) | ||||
3256 | { | ||||
3257 | nAdditionalIndent = rFormat.GetIndentAt() + rFormat.GetFirstLineIndent(); | ||||
3258 | } | ||||
3259 | else | ||||
3260 | { | ||||
3261 | nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); | ||||
3262 | if (getIDocumentSettingAccess()->get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) | ||||
3263 | { | ||||
3264 | nAdditionalIndent = nAdditionalIndent - | ||||
3265 | GetSwAttrSet().GetLRSpace().GetTextFirstLineOffset(); | ||||
3266 | } | ||||
3267 | } | ||||
3268 | } | ||||
3269 | } | ||||
3270 | else | ||||
3271 | { | ||||
3272 | nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); | ||||
3273 | } | ||||
3274 | |||||
3275 | return nAdditionalIndent; | ||||
3276 | } | ||||
3277 | |||||
3278 | // #i96772# | ||||
3279 | void SwTextNode::ClearLRSpaceItemDueToListLevelIndents( std::shared_ptr<SvxLRSpaceItem>& o_rLRSpaceItem ) const | ||||
3280 | { | ||||
3281 | if ( AreListLevelIndentsApplicable() ) | ||||
3282 | { | ||||
3283 | const SwNumRule* pRule = GetNumRule(); | ||||
3284 | if ( pRule && GetActualListLevel() >= 0 ) | ||||
3285 | { | ||||
3286 | const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel())); | ||||
3287 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) | ||||
3288 | { | ||||
3289 | o_rLRSpaceItem = std::make_shared<SvxLRSpaceItem>(RES_LR_SPACE); | ||||
3290 | } | ||||
3291 | } | ||||
3292 | } | ||||
3293 | } | ||||
3294 | |||||
3295 | // #i91133# | ||||
3296 | long SwTextNode::GetLeftMarginForTabCalculation() const | ||||
3297 | { | ||||
3298 | long nLeftMarginForTabCalc = 0; | ||||
3299 | |||||
3300 | bool bLeftMarginForTabCalcSetToListLevelIndent( false ); | ||||
3301 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
3302 | if( pRule ) | ||||
3303 | { | ||||
3304 | const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel())); | ||||
3305 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) | ||||
3306 | { | ||||
3307 | if ( AreListLevelIndentsApplicable() ) | ||||
3308 | { | ||||
3309 | nLeftMarginForTabCalc = rFormat.GetIndentAt(); | ||||
3310 | bLeftMarginForTabCalcSetToListLevelIndent = true; | ||||
3311 | } | ||||
3312 | } | ||||
3313 | } | ||||
3314 | if ( !bLeftMarginForTabCalcSetToListLevelIndent ) | ||||
3315 | { | ||||
3316 | nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTextLeft(); | ||||
3317 | } | ||||
3318 | |||||
3319 | return nLeftMarginForTabCalc; | ||||
3320 | } | ||||
3321 | |||||
3322 | static void Replace0xFF( | ||||
3323 | SwTextNode const& rNode, | ||||
3324 | OUStringBuffer & rText, | ||||
3325 | sal_Int32 & rTextStt, | ||||
3326 | sal_Int32 nEndPos ) | ||||
3327 | { | ||||
3328 | if (!rNode.GetpSwpHints()) | ||||
3329 | return; | ||||
3330 | |||||
3331 | sal_Unicode cSrchChr = CH_TXTATR_BREAKWORDu'\x0001'; | ||||
3332 | for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter, cSrchChr = CH_TXTATR_INWORDu'\xFFF9' ) | ||||
3333 | { | ||||
3334 | sal_Int32 nPos = rText.indexOf(cSrchChr); | ||||
3335 | while (-1 != nPos && nPos < nEndPos) | ||||
3336 | { | ||||
3337 | const SwTextAttr* const pAttr = | ||||
3338 | rNode.GetTextAttrForCharAt(rTextStt + nPos); | ||||
3339 | if( pAttr ) | ||||
3340 | { | ||||
3341 | switch( pAttr->Which() ) | ||||
3342 | { | ||||
3343 | case RES_TXTATR_FIELD: | ||||
3344 | case RES_TXTATR_ANNOTATION: | ||||
3345 | rText.remove(nPos, 1); | ||||
3346 | ++rTextStt; | ||||
3347 | break; | ||||
3348 | |||||
3349 | case RES_TXTATR_FTN: | ||||
3350 | rText.remove(nPos, 1); | ||||
3351 | ++rTextStt; | ||||
3352 | break; | ||||
3353 | |||||
3354 | default: | ||||
3355 | rText.remove(nPos, 1); | ||||
3356 | ++rTextStt; | ||||
3357 | } | ||||
3358 | } | ||||
3359 | else | ||||
3360 | { | ||||
3361 | ++nPos; | ||||
3362 | ++nEndPos; | ||||
3363 | } | ||||
3364 | nPos = rText.indexOf(cSrchChr, nPos); | ||||
3365 | } | ||||
3366 | } | ||||
3367 | } | ||||
3368 | |||||
3369 | // Expand fields | ||||
3370 | // #i83479# - handling of new parameters | ||||
3371 | OUString SwTextNode::GetExpandText(SwRootFrame const*const pLayout, | ||||
3372 | const sal_Int32 nIdx, | ||||
3373 | const sal_Int32 nLen, | ||||
3374 | const bool bWithNum, | ||||
3375 | const bool bAddSpaceAfterListLabelStr, | ||||
3376 | const bool bWithSpacesForLevel, | ||||
3377 | const ExpandMode eAdditionalMode) const | ||||
3378 | |||||
3379 | { | ||||
3380 | ExpandMode eMode = ExpandMode::ExpandFields | eAdditionalMode; | ||||
3381 | if (pLayout && pLayout->IsHideRedlines()) | ||||
3382 | { | ||||
3383 | eMode |= ExpandMode::HideDeletions; | ||||
3384 | } | ||||
3385 | |||||
3386 | ModelToViewHelper aConversionMap(*this, pLayout, eMode); | ||||
3387 | const OUString aExpandText = aConversionMap.getViewText(); | ||||
3388 | const sal_Int32 nExpandBegin = aConversionMap.ConvertToViewPosition( nIdx ); | ||||
3389 | sal_Int32 nEnd = nLen == -1 ? GetText().getLength() : nIdx + nLen; | ||||
3390 | const sal_Int32 nExpandEnd = aConversionMap.ConvertToViewPosition( nEnd ); | ||||
3391 | OUStringBuffer aText(aExpandText.copy(nExpandBegin, nExpandEnd-nExpandBegin)); | ||||
3392 | |||||
3393 | // remove dummy characters of Input Fields | ||||
3394 | comphelper::string::remove(aText, CH_TXT_ATR_INPUTFIELDSTARTu'\x0004'); | ||||
3395 | comphelper::string::remove(aText, CH_TXT_ATR_INPUTFIELDENDu'\x0005'); | ||||
3396 | |||||
3397 | if( bWithNum ) | ||||
3398 | { | ||||
3399 | if (!GetNumString(true, MAXLEVEL, pLayout).isEmpty()) | ||||
3400 | { | ||||
3401 | if ( bAddSpaceAfterListLabelStr ) | ||||
3402 | { | ||||
3403 | const sal_Unicode aSpace = ' '; | ||||
3404 | aText.insert(0, aSpace); | ||||
3405 | } | ||||
3406 | aText.insert(0, GetNumString(true, MAXLEVEL, pLayout)); | ||||
3407 | } | ||||
3408 | } | ||||
3409 | |||||
3410 | if (bWithSpacesForLevel) | ||||
3411 | { | ||||
3412 | const sal_Unicode aSpace = ' '; | ||||
3413 | for (int nLevel = GetActualListLevel(); nLevel > 0; --nLevel) | ||||
3414 | { | ||||
3415 | aText.insert(0, aSpace); | ||||
3416 | aText.insert(0, aSpace); | ||||
3417 | } | ||||
3418 | } | ||||
3419 | |||||
3420 | return aText.makeStringAndClear(); | ||||
3421 | } | ||||
3422 | |||||
3423 | bool SwTextNode::CopyExpandText(SwTextNode& rDestNd, const SwIndex* pDestIdx, | ||||
3424 | sal_Int32 nIdx, sal_Int32 nLen, | ||||
3425 | SwRootFrame const*const pLayout, bool bWithNum, | ||||
3426 | bool bWithFootnote, bool bReplaceTabsWithSpaces ) const | ||||
3427 | { | ||||
3428 | if( &rDestNd == this ) | ||||
3429 | return false; | ||||
3430 | |||||
3431 | SwIndex aDestIdx(&rDestNd, rDestNd.GetText().getLength()); | ||||
3432 | if( pDestIdx ) | ||||
3433 | aDestIdx = *pDestIdx; | ||||
3434 | const sal_Int32 nDestStt = aDestIdx.GetIndex(); | ||||
3435 | |||||
3436 | // first, start with the text | ||||
3437 | OUStringBuffer buf(GetText()); | ||||
3438 | if( bReplaceTabsWithSpaces ) | ||||
3439 | buf.replace('\t', ' '); | ||||
3440 | |||||
3441 | // mask hidden characters | ||||
3442 | const sal_Unicode cChar = CH_TXTATR_BREAKWORDu'\x0001'; | ||||
3443 | SwScriptInfo::MaskHiddenRanges(*this, buf, 0, buf.getLength(), cChar); | ||||
3444 | |||||
3445 | buf.remove(0, nIdx); | ||||
3446 | if (nLen != -1) | ||||
3447 | { | ||||
3448 | buf.truncate(nLen); | ||||
3449 | } | ||||
3450 | // remove dummy characters of Input Fields | ||||
3451 | { | ||||
3452 | comphelper::string::remove(buf, CH_TXT_ATR_INPUTFIELDSTARTu'\x0004'); | ||||
3453 | comphelper::string::remove(buf, CH_TXT_ATR_INPUTFIELDENDu'\x0005'); | ||||
3454 | } | ||||
3455 | rDestNd.InsertText(buf.makeStringAndClear(), aDestIdx); | ||||
3456 | nLen = aDestIdx.GetIndex() - nDestStt; | ||||
3457 | |||||
3458 | // set all char attributes with Symbol font | ||||
3459 | if ( HasHints() ) | ||||
3460 | { | ||||
3461 | sal_Int32 nInsPos = nDestStt - nIdx; | ||||
3462 | for ( size_t i = 0; i < m_pSwpHints->Count(); ++i ) | ||||
3463 | { | ||||
3464 | const SwTextAttr* pHt = m_pSwpHints->Get(i); | ||||
3465 | const sal_Int32 nAttrStartIdx = pHt->GetStart(); | ||||
3466 | const sal_uInt16 nWhich = pHt->Which(); | ||||
3467 | if (nIdx + nLen <= nAttrStartIdx) | ||||
3468 | break; // behind end of text | ||||
3469 | |||||
3470 | const sal_Int32 *pEndIdx = pHt->End(); | ||||
3471 | if( pEndIdx && *pEndIdx > nIdx && | ||||
3472 | ( RES_CHRATR_FONT == nWhich || | ||||
3473 | RES_TXTATR_CHARFMT == nWhich || | ||||
3474 | RES_TXTATR_AUTOFMT == nWhich )) | ||||
3475 | { | ||||
3476 | const SvxFontItem* const pFont = | ||||
3477 | CharFormat::GetItem( *pHt, RES_CHRATR_FONT ); | ||||
3478 | if ( pFont && RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) == pFont->GetCharSet() ) | ||||
3479 | { | ||||
3480 | // attribute in area => copy | ||||
3481 | rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont), | ||||
3482 | nInsPos + nAttrStartIdx, nInsPos + *pEndIdx ); | ||||
3483 | } | ||||
3484 | } | ||||
3485 | else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) ) | ||||
3486 | { | ||||
3487 | aDestIdx = nInsPos + nAttrStartIdx; | ||||
3488 | switch( nWhich ) | ||||
3489 | { | ||||
3490 | case RES_TXTATR_FIELD: | ||||
3491 | case RES_TXTATR_ANNOTATION: | ||||
3492 | { | ||||
3493 | OUString const aExpand( | ||||
3494 | static_txtattr_cast<SwTextField const*>(pHt)->GetFormatField().GetField()->ExpandField(true, pLayout)); | ||||
3495 | if (!aExpand.isEmpty()) | ||||
3496 | { | ||||
3497 | ++aDestIdx; // insert behind | ||||
3498 | OUString const ins( | ||||
3499 | rDestNd.InsertText( aExpand, aDestIdx)); | ||||
3500 | SAL_INFO_IF(ins.getLength() != aExpand.getLength(),do { if (true && (ins.getLength() != aExpand.getLength ())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "GetExpandText lossage" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "GetExpandText lossage") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
3501 | "sw.core", "GetExpandText lossage")do { if (true && (ins.getLength() != aExpand.getLength ())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "GetExpandText lossage" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "GetExpandText lossage") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3501" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
3502 | aDestIdx = nInsPos + nAttrStartIdx; | ||||
3503 | nInsPos += ins.getLength(); | ||||
3504 | } | ||||
3505 | rDestNd.EraseText( aDestIdx, 1 ); | ||||
3506 | --nInsPos; | ||||
3507 | } | ||||
3508 | break; | ||||
3509 | |||||
3510 | case RES_TXTATR_FTN: | ||||
3511 | { | ||||
3512 | if ( bWithFootnote ) | ||||
3513 | { | ||||
3514 | const SwFormatFootnote& rFootnote = pHt->GetFootnote(); | ||||
3515 | OUString sExpand; | ||||
3516 | auto const number(pLayout && pLayout->IsHideRedlines() | ||||
3517 | ? rFootnote.GetNumberRLHidden() | ||||
3518 | : rFootnote.GetNumber()); | ||||
3519 | if( !rFootnote.GetNumStr().isEmpty() ) | ||||
3520 | sExpand = rFootnote.GetNumStr(); | ||||
3521 | else if( rFootnote.IsEndNote() ) | ||||
3522 | sExpand = GetDoc().GetEndNoteInfo().m_aFormat. | ||||
3523 | GetNumStr(number); | ||||
3524 | else | ||||
3525 | sExpand = GetDoc().GetFootnoteInfo().m_aFormat. | ||||
3526 | GetNumStr(number); | ||||
3527 | if( !sExpand.isEmpty() ) | ||||
3528 | { | ||||
3529 | ++aDestIdx; // insert behind | ||||
3530 | SvxEscapementItem aItem( SvxEscapement::Superscript, RES_CHRATR_ESCAPEMENT ); | ||||
3531 | rDestNd.InsertItem( | ||||
3532 | aItem, | ||||
3533 | aDestIdx.GetIndex(), | ||||
3534 | aDestIdx.GetIndex() ); | ||||
3535 | OUString const ins( rDestNd.InsertText(sExpand, aDestIdx, SwInsertFlags::EMPTYEXPAND)); | ||||
3536 | SAL_INFO_IF(ins.getLength() != sExpand.getLength(),do { if (true && (ins.getLength() != sExpand.getLength ())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "GetExpandText lossage" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "GetExpandText lossage") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
3537 | "sw.core", "GetExpandText lossage")do { if (true && (ins.getLength() != sExpand.getLength ())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "GetExpandText lossage" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "GetExpandText lossage") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "GetExpandText lossage"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "GetExpandText lossage"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3537" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
3538 | aDestIdx = nInsPos + nAttrStartIdx; | ||||
3539 | nInsPos += ins.getLength(); | ||||
3540 | } | ||||
3541 | } | ||||
3542 | rDestNd.EraseText( aDestIdx, 1 ); | ||||
3543 | --nInsPos; | ||||
3544 | } | ||||
3545 | break; | ||||
3546 | |||||
3547 | default: | ||||
3548 | rDestNd.EraseText( aDestIdx, 1 ); | ||||
3549 | --nInsPos; | ||||
3550 | } | ||||
3551 | } | ||||
3552 | } | ||||
3553 | } | ||||
3554 | |||||
3555 | if( bWithNum ) | ||||
3556 | { | ||||
3557 | aDestIdx = nDestStt; | ||||
3558 | rDestNd.InsertText( GetNumString(true, MAXLEVEL, pLayout), aDestIdx ); | ||||
3559 | } | ||||
3560 | |||||
3561 | aDestIdx = 0; | ||||
3562 | sal_Int32 nStartDelete(-1); | ||||
3563 | while (aDestIdx < rDestNd.GetText().getLength()) | ||||
3564 | { | ||||
3565 | sal_Unicode const cur(rDestNd.GetText()[aDestIdx.GetIndex()]); | ||||
3566 | if ( (cChar == cur) // filter substituted hidden text | ||||
3567 | || (CH_TXT_ATR_FIELDSTARTu'\x0007' == cur) // filter all fieldmarks | ||||
3568 | || (CH_TXT_ATR_FIELDSEPu'\x0003' == cur) | ||||
3569 | || (CH_TXT_ATR_FIELDENDu'\x0008' == cur) | ||||
3570 | || (CH_TXT_ATR_FORMELEMENTu'\x0006' == cur)) | ||||
3571 | { | ||||
3572 | if (-1 == nStartDelete) | ||||
3573 | { | ||||
3574 | nStartDelete = aDestIdx.GetIndex(); // start deletion range | ||||
3575 | } | ||||
3576 | ++aDestIdx; | ||||
3577 | if (aDestIdx < rDestNd.GetText().getLength()) | ||||
3578 | { | ||||
3579 | continue; | ||||
3580 | } // else: end of paragraph => delete, see below | ||||
3581 | } | ||||
3582 | else | ||||
3583 | { | ||||
3584 | if (-1 == nStartDelete) | ||||
3585 | { | ||||
3586 | ++aDestIdx; | ||||
3587 | continue; | ||||
3588 | } // else: delete, see below | ||||
3589 | } | ||||
3590 | assert(-1 != nStartDelete)(static_cast <bool> (-1 != nStartDelete) ? void (0) : __assert_fail ("-1 != nStartDelete", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3590, __extension__ __PRETTY_FUNCTION__)); // without delete range, would have continued | ||||
3591 | rDestNd.EraseText( | ||||
3592 | SwIndex(&rDestNd, nStartDelete), | ||||
3593 | aDestIdx.GetIndex() - nStartDelete); | ||||
3594 | assert(aDestIdx.GetIndex() == nStartDelete)(static_cast <bool> (aDestIdx.GetIndex() == nStartDelete ) ? void (0) : __assert_fail ("aDestIdx.GetIndex() == nStartDelete" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3594, __extension__ __PRETTY_FUNCTION__)); | ||||
3595 | nStartDelete = -1; // reset | ||||
3596 | } | ||||
3597 | |||||
3598 | return true; | ||||
3599 | } | ||||
3600 | |||||
3601 | OUString SwTextNode::GetRedlineText() const | ||||
3602 | { | ||||
3603 | std::vector<sal_Int32> aRedlArr; | ||||
3604 | const SwDoc& rDoc = GetDoc(); | ||||
3605 | SwRedlineTable::size_type nRedlPos = rDoc.getIDocumentRedlineAccess().GetRedlinePos( *this, RedlineType::Delete ); | ||||
3606 | if( SwRedlineTable::npos != nRedlPos ) | ||||
3607 | { | ||||
3608 | // some redline-delete object exists for the node | ||||
3609 | const sal_uLong nNdIdx = GetIndex(); | ||||
3610 | for( ; nRedlPos < rDoc.getIDocumentRedlineAccess().GetRedlineTable().size() ; ++nRedlPos ) | ||||
3611 | { | ||||
3612 | const SwRangeRedline* pTmp = rDoc.getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ]; | ||||
3613 | if( RedlineType::Delete == pTmp->GetType() ) | ||||
3614 | { | ||||
3615 | const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End(); | ||||
3616 | if( pRStt->nNode < nNdIdx ) | ||||
3617 | { | ||||
3618 | if( pREnd->nNode > nNdIdx ) | ||||
3619 | // paragraph is fully deleted | ||||
3620 | return OUString(); | ||||
3621 | else if( pREnd->nNode == nNdIdx ) | ||||
3622 | { | ||||
3623 | // deleted from 0 to nContent | ||||
3624 | aRedlArr.push_back( 0 ); | ||||
3625 | aRedlArr.push_back( pREnd->nContent.GetIndex() ); | ||||
3626 | } | ||||
3627 | } | ||||
3628 | else if( pRStt->nNode == nNdIdx ) | ||||
3629 | { | ||||
3630 | //aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() ); | ||||
3631 | aRedlArr.push_back( pRStt->nContent.GetIndex() ); | ||||
3632 | if( pREnd->nNode == nNdIdx ) | ||||
3633 | aRedlArr.push_back( pREnd->nContent.GetIndex() ); | ||||
3634 | else | ||||
3635 | { | ||||
3636 | aRedlArr.push_back(GetText().getLength()); | ||||
3637 | break; // that was all | ||||
3638 | } | ||||
3639 | } | ||||
3640 | else | ||||
3641 | break; // that was all | ||||
3642 | } | ||||
3643 | } | ||||
3644 | } | ||||
3645 | |||||
3646 | OUStringBuffer aText(GetText()); | ||||
3647 | |||||
3648 | sal_Int32 nTextStt = 0; | ||||
3649 | sal_Int32 nIdxEnd = aText.getLength(); | ||||
3650 | for( size_t n = 0; n < aRedlArr.size(); n += 2 ) | ||||
3651 | { | ||||
3652 | sal_Int32 nStt = aRedlArr[ n ]; | ||||
3653 | sal_Int32 nEnd = aRedlArr[ n+1 ]; | ||||
3654 | if( ( 0 <= nStt && nStt <= nIdxEnd ) || | ||||
3655 | ( 0 <= nEnd && nEnd <= nIdxEnd )) | ||||
3656 | { | ||||
3657 | if( nStt < 0 ) nStt = 0; | ||||
3658 | if( nIdxEnd < nEnd ) nEnd = nIdxEnd; | ||||
3659 | const sal_Int32 nDelCnt = nEnd - nStt; | ||||
3660 | aText.remove(nStt - nTextStt, nDelCnt); | ||||
3661 | Replace0xFF(*this, aText, nTextStt, nStt - nTextStt); | ||||
3662 | nTextStt += nDelCnt; | ||||
3663 | } | ||||
3664 | else if( nStt >= nIdxEnd ) | ||||
3665 | break; | ||||
3666 | } | ||||
3667 | Replace0xFF(*this, aText, nTextStt, aText.getLength()); | ||||
3668 | |||||
3669 | return aText.makeStringAndClear(); | ||||
3670 | } | ||||
3671 | |||||
3672 | void SwTextNode::ReplaceText( const SwIndex& rStart, const sal_Int32 nDelLen, | ||||
3673 | const OUString & rStr) | ||||
3674 | { | ||||
3675 | assert( rStart.GetIndex() < m_Text.getLength() // index out of bounds(static_cast <bool> (rStart.GetIndex() < m_Text.getLength () && rStart.GetIndex() + nDelLen <= m_Text.getLength ()) ? void (0) : __assert_fail ("rStart.GetIndex() < m_Text.getLength() && rStart.GetIndex() + nDelLen <= m_Text.getLength()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3676, __extension__ __PRETTY_FUNCTION__)) | ||||
3676 | && rStart.GetIndex() + nDelLen <= m_Text.getLength())(static_cast <bool> (rStart.GetIndex() < m_Text.getLength () && rStart.GetIndex() + nDelLen <= m_Text.getLength ()) ? void (0) : __assert_fail ("rStart.GetIndex() < m_Text.getLength() && rStart.GetIndex() + nDelLen <= m_Text.getLength()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3676, __extension__ __PRETTY_FUNCTION__)); | ||||
3677 | |||||
3678 | sal_Int32 const nOverflow(rStr.getLength() - nDelLen - GetSpaceLeft()); | ||||
3679 | SAL_WARN_IF(nOverflow > 0, "sw.core",do { if (true && (nOverflow > 0)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "SwTextNode::ReplaceText: node text with insertion > node capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::ReplaceText: node text with insertion > node capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::ReplaceText: node text with insertion > node capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SwTextNode::ReplaceText: node text with insertion > node capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::ReplaceText: node text with insertion > node capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::ReplaceText: node text with insertion > node capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
3680 | "SwTextNode::ReplaceText: node text with insertion > node capacity.")do { if (true && (nOverflow > 0)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "SwTextNode::ReplaceText: node text with insertion > node capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::ReplaceText: node text with insertion > node capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::ReplaceText: node text with insertion > node capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SwTextNode::ReplaceText: node text with insertion > node capacity." ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "SwTextNode::ReplaceText: node text with insertion > node capacity." ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SwTextNode::ReplaceText: node text with insertion > node capacity." ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3680" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
3681 | OUString const sInserted( | ||||
3682 | (nOverflow > 0) ? rStr.copy(0, rStr.getLength() - nOverflow) : rStr); | ||||
3683 | if (sInserted.isEmpty() && 0 == nDelLen) | ||||
3684 | { | ||||
3685 | return; // nothing to do | ||||
3686 | } | ||||
3687 | |||||
3688 | const sal_Int32 nStartPos = rStart.GetIndex(); | ||||
3689 | sal_Int32 nEndPos = nStartPos + nDelLen; | ||||
3690 | sal_Int32 nLen = nDelLen; | ||||
3691 | for( sal_Int32 nPos = nStartPos; nPos < nEndPos; ++nPos ) | ||||
3692 | { | ||||
3693 | if ((CH_TXTATR_BREAKWORDu'\x0001' == m_Text[nPos]) || | ||||
3694 | (CH_TXTATR_INWORDu'\xFFF9' == m_Text[nPos])) | ||||
3695 | { | ||||
3696 | SwTextAttr *const pHint = GetTextAttrForCharAt( nPos ); | ||||
3697 | if (pHint) | ||||
3698 | { | ||||
3699 | assert(!( pHint->GetEnd() && pHint->HasDummyChar()(static_cast <bool> (!( pHint->GetEnd() && pHint ->HasDummyChar() && (pHint->GetStart() < nEndPos ) && (*pHint->GetEnd() > nEndPos) )) ? void (0) : __assert_fail ("!( pHint->GetEnd() && pHint->HasDummyChar() && (pHint->GetStart() < nEndPos) && (*pHint->GetEnd() > nEndPos) )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3701, __extension__ __PRETTY_FUNCTION__)) | ||||
3700 | && (pHint->GetStart() < nEndPos)(static_cast <bool> (!( pHint->GetEnd() && pHint ->HasDummyChar() && (pHint->GetStart() < nEndPos ) && (*pHint->GetEnd() > nEndPos) )) ? void (0) : __assert_fail ("!( pHint->GetEnd() && pHint->HasDummyChar() && (pHint->GetStart() < nEndPos) && (*pHint->GetEnd() > nEndPos) )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3701, __extension__ __PRETTY_FUNCTION__)) | ||||
3701 | && (*pHint->GetEnd() > nEndPos) ))(static_cast <bool> (!( pHint->GetEnd() && pHint ->HasDummyChar() && (pHint->GetStart() < nEndPos ) && (*pHint->GetEnd() > nEndPos) )) ? void (0) : __assert_fail ("!( pHint->GetEnd() && pHint->HasDummyChar() && (pHint->GetStart() < nEndPos) && (*pHint->GetEnd() > nEndPos) )" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3701, __extension__ __PRETTY_FUNCTION__)); | ||||
3702 | // "deleting left-overlapped attribute with CH_TXTATR" | ||||
3703 | DeleteAttribute( pHint ); | ||||
3704 | --nEndPos; | ||||
3705 | --nLen; | ||||
3706 | } | ||||
3707 | } | ||||
3708 | } | ||||
3709 | |||||
3710 | bool bOldExpFlg = IsIgnoreDontExpand(); | ||||
3711 | SetIgnoreDontExpand( true ); | ||||
3712 | |||||
3713 | if (nLen && sInserted.getLength()) | ||||
3714 | { | ||||
3715 | // Replace the 1st char, then delete the rest and insert. | ||||
3716 | // This way the attributes of the 1st char are expanded! | ||||
3717 | m_Text = m_Text.replaceAt(nStartPos, 1, sInserted.copy(0, 1)); | ||||
3718 | |||||
3719 | ++const_cast<SwIndex&>(rStart); | ||||
3720 | m_Text = m_Text.replaceAt(rStart.GetIndex(), nLen - 1, ""); | ||||
3721 | Update( rStart, nLen - 1, true ); | ||||
3722 | |||||
3723 | OUString aTmpText( sInserted.copy(1) ); | ||||
3724 | m_Text = m_Text.replaceAt(rStart.GetIndex(), 0, aTmpText); | ||||
3725 | Update( rStart, aTmpText.getLength() ); | ||||
3726 | } | ||||
3727 | else | ||||
3728 | { | ||||
3729 | m_Text = m_Text.replaceAt(nStartPos, nLen, ""); | ||||
3730 | Update( rStart, nLen, true ); | ||||
3731 | |||||
3732 | m_Text = m_Text.replaceAt(nStartPos, 0, sInserted); | ||||
3733 | Update( rStart, sInserted.getLength() ); | ||||
3734 | } | ||||
3735 | |||||
3736 | SetIgnoreDontExpand( bOldExpFlg ); | ||||
3737 | SwDelText aDelHint( nStartPos, nDelLen ); | ||||
3738 | NotifyClients( nullptr, &aDelHint ); | ||||
3739 | |||||
3740 | SwInsText aHint( nStartPos, sInserted.getLength() ); | ||||
3741 | NotifyClients( nullptr, &aHint ); | ||||
3742 | } | ||||
3743 | |||||
3744 | namespace { | ||||
3745 | void lcl_ResetParAttrs( SwTextNode &rTextNode ) | ||||
3746 | { | ||||
3747 | std::set<sal_uInt16> aAttrs; | ||||
3748 | aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_ID ); | ||||
3749 | aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_LEVEL ); | ||||
3750 | aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_ISRESTART ); | ||||
3751 | aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_RESTARTVALUE ); | ||||
3752 | aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_ISCOUNTED ); | ||||
3753 | SwPaM aPam( rTextNode ); | ||||
3754 | // #i96644# | ||||
3755 | // suppress side effect "send data changed events" | ||||
3756 | rTextNode.GetDoc().ResetAttrs( aPam, false, aAttrs, false ); | ||||
3757 | } | ||||
3758 | |||||
3759 | // Helper method for special handling of modified attributes at text node. | ||||
3760 | // The following is handled: | ||||
3761 | // (1) on changing the paragraph style - RES_FMT_CHG: | ||||
3762 | // Check, if list style of the text node is changed. If yes, add respectively | ||||
3763 | // remove the text node to the corresponding list. | ||||
3764 | // (2) on changing the attributes - RES_ATTRSET_CHG: | ||||
3765 | // Same as (1). | ||||
3766 | // (3) on changing the list style - RES_PARATR_NUMRULE: | ||||
3767 | // Same as (1). | ||||
3768 | void HandleModifyAtTextNode( SwTextNode& rTextNode, | ||||
3769 | const SfxPoolItem* pOldValue, | ||||
3770 | const SfxPoolItem* pNewValue ) | ||||
3771 | { | ||||
3772 | const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() : | ||||
3773 | pNewValue ? pNewValue->Which() : 0 ; | ||||
3774 | bool bNumRuleSet = false; | ||||
3775 | bool bParagraphStyleChanged = false; | ||||
3776 | OUString sNumRule; | ||||
3777 | OUString sOldNumRule; | ||||
3778 | switch ( nWhich ) | ||||
3779 | { | ||||
3780 | case RES_FMT_CHG: | ||||
3781 | { | ||||
3782 | bParagraphStyleChanged = true; | ||||
3783 | if( rTextNode.GetNodes().IsDocNodes() ) | ||||
3784 | { | ||||
3785 | const SwNumRule* pFormerNumRuleAtTextNode = | ||||
3786 | rTextNode.GetNum() ? rTextNode.GetNum()->GetNumRule() : nullptr; | ||||
3787 | if ( pFormerNumRuleAtTextNode ) | ||||
3788 | { | ||||
3789 | sOldNumRule = pFormerNumRuleAtTextNode->GetName(); | ||||
3790 | } | ||||
3791 | if ( rTextNode.IsEmptyListStyleDueToSetOutlineLevelAttr() ) | ||||
3792 | { | ||||
3793 | const SwNumRuleItem& rNumRuleItem = rTextNode.GetTextColl()->GetNumRule(); | ||||
3794 | if ( !rNumRuleItem.GetValue().isEmpty() ) | ||||
3795 | { | ||||
3796 | rTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
3797 | } | ||||
3798 | } | ||||
3799 | const SwNumRule* pNumRuleAtTextNode = rTextNode.GetNumRule(); | ||||
3800 | if ( pNumRuleAtTextNode ) | ||||
3801 | { | ||||
3802 | bNumRuleSet = true; | ||||
3803 | sNumRule = pNumRuleAtTextNode->GetName(); | ||||
3804 | } | ||||
3805 | } | ||||
3806 | break; | ||||
3807 | } | ||||
3808 | case RES_ATTRSET_CHG: | ||||
3809 | { | ||||
3810 | const SfxPoolItem* pItem = nullptr; | ||||
3811 | const SwNumRule* pFormerNumRuleAtTextNode = | ||||
3812 | rTextNode.GetNum() ? rTextNode.GetNum()->GetNumRule() : nullptr; | ||||
3813 | if ( pFormerNumRuleAtTextNode ) | ||||
3814 | { | ||||
3815 | sOldNumRule = pFormerNumRuleAtTextNode->GetName(); | ||||
3816 | } | ||||
3817 | |||||
3818 | const SwAttrSetChg* pSet = dynamic_cast<const SwAttrSetChg*>(pNewValue); | ||||
3819 | if ( pSet && pSet->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, false, &pItem ) == | ||||
3820 | SfxItemState::SET ) | ||||
3821 | { | ||||
3822 | // #i70748# | ||||
3823 | rTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
3824 | bNumRuleSet = true; | ||||
3825 | } | ||||
3826 | // #i70748# | ||||
3827 | // The new list style set at the paragraph. | ||||
3828 | const SwNumRule* pNumRuleAtTextNode = rTextNode.GetNumRule(); | ||||
3829 | if ( pNumRuleAtTextNode ) | ||||
3830 | { | ||||
3831 | sNumRule = pNumRuleAtTextNode->GetName(); | ||||
3832 | } | ||||
3833 | break; | ||||
3834 | } | ||||
3835 | case RES_PARATR_NUMRULE: | ||||
3836 | { | ||||
3837 | if ( rTextNode.GetNodes().IsDocNodes() ) | ||||
3838 | { | ||||
3839 | const SwNumRule* pFormerNumRuleAtTextNode = | ||||
3840 | rTextNode.GetNum() ? rTextNode.GetNum()->GetNumRule() : nullptr; | ||||
3841 | if ( pFormerNumRuleAtTextNode ) | ||||
3842 | { | ||||
3843 | sOldNumRule = pFormerNumRuleAtTextNode->GetName(); | ||||
3844 | } | ||||
3845 | |||||
3846 | if ( pNewValue ) | ||||
3847 | { | ||||
3848 | // #i70748# | ||||
3849 | rTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
3850 | bNumRuleSet = true; | ||||
3851 | } | ||||
3852 | // #i70748# | ||||
3853 | // The new list style set at the paragraph. | ||||
3854 | const SwNumRule* pNumRuleAtTextNode = rTextNode.GetNumRule(); | ||||
3855 | if ( pNumRuleAtTextNode ) | ||||
3856 | { | ||||
3857 | sNumRule = pNumRuleAtTextNode->GetName(); | ||||
3858 | } | ||||
3859 | } | ||||
3860 | break; | ||||
3861 | } | ||||
3862 | } | ||||
3863 | if ( sNumRule != sOldNumRule ) | ||||
3864 | { | ||||
3865 | if ( bNumRuleSet ) | ||||
3866 | { | ||||
3867 | if (sNumRule.isEmpty()) | ||||
3868 | { | ||||
3869 | rTextNode.RemoveFromList(); | ||||
3870 | if ( bParagraphStyleChanged ) | ||||
3871 | { | ||||
3872 | lcl_ResetParAttrs(rTextNode); | ||||
3873 | } | ||||
3874 | } | ||||
3875 | else | ||||
3876 | { | ||||
3877 | rTextNode.RemoveFromList(); | ||||
3878 | // If new list style is the outline style, apply outline | ||||
3879 | // level as the list level. | ||||
3880 | if (sNumRule==SwNumRule::GetOutlineRuleName()) | ||||
3881 | { | ||||
3882 | // #i70748# | ||||
3883 | OSL_ENSURE( rTextNode.GetTextColl()->IsAssignedToListLevelOfOutlineStyle(),do { if (true && (!(rTextNode.GetTextColl()->IsAssignedToListLevelOfOutlineStyle ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3884" ": "), "%s", "<HandleModifyAtTextNode()> - text node with outline style, but its paragraph style is not assigned to outline style." ); } } while (false) | ||||
3884 | "<HandleModifyAtTextNode()> - text node with outline style, but its paragraph style is not assigned to outline style." )do { if (true && (!(rTextNode.GetTextColl()->IsAssignedToListLevelOfOutlineStyle ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3884" ": "), "%s", "<HandleModifyAtTextNode()> - text node with outline style, but its paragraph style is not assigned to outline style." ); } } while (false); | ||||
3885 | const int nNewListLevel = | ||||
3886 | rTextNode.GetTextColl()->GetAssignedOutlineStyleLevel(); | ||||
3887 | if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL ) | ||||
3888 | { | ||||
3889 | rTextNode.SetAttrListLevel( nNewListLevel ); | ||||
3890 | } | ||||
3891 | } | ||||
3892 | rTextNode.AddToList(); | ||||
3893 | } | ||||
3894 | } | ||||
3895 | else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0> | ||||
3896 | { | ||||
3897 | rTextNode.RemoveFromList(); | ||||
3898 | if ( bParagraphStyleChanged ) | ||||
3899 | { | ||||
3900 | lcl_ResetParAttrs(rTextNode); | ||||
3901 | // #i70748# | ||||
3902 | if ( dynamic_cast<const SfxUInt16Item &>(rTextNode.GetAttr( RES_PARATR_OUTLINELEVEL, false )).GetValue() > 0 ) | ||||
3903 | { | ||||
3904 | rTextNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); | ||||
3905 | } | ||||
3906 | } | ||||
3907 | } | ||||
3908 | } | ||||
3909 | else if (!sNumRule.isEmpty() && !rTextNode.IsInList()) | ||||
3910 | { | ||||
3911 | rTextNode.AddToList(); | ||||
3912 | } | ||||
3913 | } | ||||
3914 | // End of method <HandleModifyAtTextNode> | ||||
3915 | } | ||||
3916 | |||||
3917 | SwFormatColl* SwTextNode::ChgFormatColl( SwFormatColl *pNewColl ) | ||||
3918 | { | ||||
3919 | OSL_ENSURE( pNewColl,"ChgFormatColl: Collectionpointer has value 0." )do { if (true && (!(pNewColl))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3919" ": "), "%s", "ChgFormatColl: Collectionpointer has value 0." ); } } while (false); | ||||
3920 | OSL_ENSURE( dynamic_cast<const SwTextFormatColl *>(pNewColl) != nullptr,do { if (true && (!(dynamic_cast<const SwTextFormatColl *>(pNewColl) != nullptr))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3921" ": "), "%s", "ChgFormatColl: is not a Text Collection pointer." ); } } while (false) | ||||
3921 | "ChgFormatColl: is not a Text Collection pointer." )do { if (true && (!(dynamic_cast<const SwTextFormatColl *>(pNewColl) != nullptr))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3921" ": "), "%s", "ChgFormatColl: is not a Text Collection pointer." ); } } while (false); | ||||
3922 | |||||
3923 | SwTextFormatColl *pOldColl = GetTextColl(); | ||||
3924 | if( pNewColl != pOldColl ) | ||||
3925 | { | ||||
3926 | SetCalcHiddenCharFlags(); | ||||
3927 | SwContentNode::ChgFormatColl( pNewColl ); | ||||
3928 | OSL_ENSURE( !mbInSetOrResetAttr,do { if (true && (!(!mbInSetOrResetAttr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3929" ": "), "%s", "DEBUG OSL_ENSURE(ON - <SwTextNode::ChgFormatColl(..)> called during <Set/ResetAttr(..)>" ); } } while (false) | ||||
3929 | "DEBUG OSL_ENSURE(ON - <SwTextNode::ChgFormatColl(..)> called during <Set/ResetAttr(..)>" )do { if (true && (!(!mbInSetOrResetAttr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "3929" ": "), "%s", "DEBUG OSL_ENSURE(ON - <SwTextNode::ChgFormatColl(..)> called during <Set/ResetAttr(..)>" ); } } while (false); | ||||
3930 | if ( !mbInSetOrResetAttr ) | ||||
3931 | { | ||||
3932 | SwFormatChg aTmp1( pOldColl ); | ||||
3933 | SwFormatChg aTmp2( pNewColl ); | ||||
3934 | HandleModifyAtTextNode( *this, &aTmp1, &aTmp2 ); | ||||
3935 | } | ||||
3936 | |||||
3937 | // reset fill information on parent style change | ||||
3938 | if(maFillAttributes) | ||||
3939 | { | ||||
3940 | maFillAttributes.reset(); | ||||
3941 | } | ||||
3942 | } | ||||
3943 | |||||
3944 | // only for real nodes-array | ||||
3945 | if( GetNodes().IsDocNodes() ) | ||||
3946 | { | ||||
3947 | ChgTextCollUpdateNum( pOldColl, static_cast<SwTextFormatColl *>(pNewColl) ); | ||||
3948 | } | ||||
3949 | |||||
3950 | GetNodes().UpdateOutlineNode(*this); | ||||
3951 | |||||
3952 | return pOldColl; | ||||
3953 | } | ||||
3954 | |||||
3955 | const SwNodeNum* SwTextNode::GetNum(SwRootFrame const*const pLayout) const | ||||
3956 | { | ||||
3957 | // invariant: it's only in list in Hide mode if it's in list in normal mode | ||||
3958 | assert(mpNodeNum || !mpNodeNumRLHidden)(static_cast <bool> (mpNodeNum || !mpNodeNumRLHidden) ? void (0) : __assert_fail ("mpNodeNum || !mpNodeNumRLHidden", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3958, __extension__ __PRETTY_FUNCTION__)); | ||||
3959 | return pLayout && pLayout->IsHideRedlines() ? mpNodeNumRLHidden.get() : mpNodeNum.get(); | ||||
3960 | } | ||||
3961 | |||||
3962 | void SwTextNode::DoNum(std::function<void (SwNodeNum &)> const& rFunc) | ||||
3963 | { | ||||
3964 | // temp. clear because GetActualListLevel() may be called and the assert | ||||
3965 | // there triggered during update, which is unhelpful | ||||
3966 | std::unique_ptr<SwNodeNum> pBackup = std::move(mpNodeNumRLHidden); | ||||
3967 | assert(mpNodeNum)(static_cast <bool> (mpNodeNum) ? void (0) : __assert_fail ("mpNodeNum", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 3967, __extension__ __PRETTY_FUNCTION__)); | ||||
3968 | rFunc(*mpNodeNum); | ||||
3969 | if (pBackup) | ||||
3970 | { | ||||
3971 | mpNodeNumRLHidden = std::move(pBackup); | ||||
3972 | rFunc(*mpNodeNumRLHidden); | ||||
3973 | } | ||||
3974 | } | ||||
3975 | |||||
3976 | SwNumberTree::tNumberVector | ||||
3977 | SwTextNode::GetNumberVector(SwRootFrame const*const pLayout) const | ||||
3978 | { | ||||
3979 | if (SwNodeNum const*const pNum = GetNum(pLayout)) | ||||
3980 | { | ||||
3981 | return pNum->GetNumberVector(); | ||||
3982 | } | ||||
3983 | else | ||||
3984 | { | ||||
3985 | SwNumberTree::tNumberVector aResult; | ||||
3986 | return aResult; | ||||
3987 | } | ||||
3988 | } | ||||
3989 | |||||
3990 | bool SwTextNode::IsOutline() const | ||||
3991 | { | ||||
3992 | bool bResult = false; | ||||
3993 | |||||
3994 | if ( GetAttrOutlineLevel() > 0 ) | ||||
3995 | { | ||||
3996 | bResult = !IsInRedlines(); | ||||
3997 | } | ||||
3998 | else | ||||
3999 | { | ||||
4000 | const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : nullptr ); | ||||
4001 | if ( pRule && pRule->IsOutlineRule() ) | ||||
4002 | { | ||||
4003 | bResult = !IsInRedlines(); | ||||
4004 | } | ||||
4005 | } | ||||
4006 | |||||
4007 | return bResult; | ||||
4008 | } | ||||
4009 | |||||
4010 | bool SwTextNode::IsOutlineStateChanged() const | ||||
4011 | { | ||||
4012 | return IsOutline() != m_bLastOutlineState; | ||||
4013 | } | ||||
4014 | |||||
4015 | void SwTextNode::UpdateOutlineState() | ||||
4016 | { | ||||
4017 | m_bLastOutlineState = IsOutline(); | ||||
4018 | } | ||||
4019 | |||||
4020 | int SwTextNode::GetAttrOutlineLevel() const | ||||
4021 | { | ||||
4022 | return static_cast<const SfxUInt16Item &>(GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue(); | ||||
4023 | } | ||||
4024 | |||||
4025 | void SwTextNode::SetAttrOutlineLevel(int nLevel) | ||||
4026 | { | ||||
4027 | assert(0 <= nLevel && nLevel <= MAXLEVEL)(static_cast <bool> (0 <= nLevel && nLevel <= MAXLEVEL) ? void (0) : __assert_fail ("0 <= nLevel && nLevel <= MAXLEVEL" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4027, __extension__ __PRETTY_FUNCTION__)); // Level Out Of Range | ||||
4028 | if ( 0 <= nLevel && nLevel <= MAXLEVEL ) | ||||
4029 | { | ||||
4030 | SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL, | ||||
4031 | static_cast<sal_uInt16>(nLevel) ) ); | ||||
4032 | } | ||||
4033 | } | ||||
4034 | |||||
4035 | bool SwTextNode::GetAttrOutlineContentVisible(bool& bOutlineContentVisibleAttr) | ||||
4036 | { | ||||
4037 | SfxGrabBagItem aGrabBagItem(dynamic_cast<const SfxGrabBagItem&>(GetAttr(RES_PARATR_GRABBAG))); | ||||
4038 | auto it = aGrabBagItem.GetGrabBag().find("OutlineContentVisibleAttr"); | ||||
4039 | if (it != aGrabBagItem.GetGrabBag().end()) | ||||
4040 | { | ||||
4041 | it->second >>= bOutlineContentVisibleAttr; | ||||
4042 | return true; | ||||
4043 | } | ||||
4044 | return false; | ||||
4045 | } | ||||
4046 | |||||
4047 | void SwTextNode::SetAttrOutlineContentVisible(bool bVisible) | ||||
4048 | { | ||||
4049 | SfxGrabBagItem aGrabBagItem(RES_PARATR_GRABBAG); | ||||
4050 | aGrabBagItem.GetGrabBag()["OutlineContentVisibleAttr"] <<= bVisible; | ||||
4051 | GetTextNode()->SetAttr(aGrabBagItem); | ||||
4052 | } | ||||
4053 | |||||
4054 | // #i70748# | ||||
4055 | |||||
4056 | void SwTextNode::SetEmptyListStyleDueToSetOutlineLevelAttr() | ||||
4057 | { | ||||
4058 | if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr ) | ||||
4059 | { | ||||
4060 | SetAttr( SwNumRuleItem() ); | ||||
4061 | mbEmptyListStyleSetDueToSetOutlineLevelAttr = true; | ||||
4062 | } | ||||
4063 | } | ||||
4064 | |||||
4065 | void SwTextNode::ResetEmptyListStyleDueToResetOutlineLevelAttr() | ||||
4066 | { | ||||
4067 | if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr ) | ||||
4068 | { | ||||
4069 | ResetAttr( RES_PARATR_NUMRULE ); | ||||
4070 | mbEmptyListStyleSetDueToSetOutlineLevelAttr = false; | ||||
4071 | } | ||||
4072 | } | ||||
4073 | |||||
4074 | void SwTextNode::SetAttrListLevel( int nLevel ) | ||||
4075 | { | ||||
4076 | if ( nLevel < 0 || nLevel >= MAXLEVEL ) | ||||
4077 | { | ||||
4078 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4078, __extension__ __PRETTY_FUNCTION__)); // invalid level | ||||
4079 | return; | ||||
4080 | } | ||||
4081 | |||||
4082 | SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL, | ||||
4083 | static_cast<sal_Int16>(nLevel) ); | ||||
4084 | SetAttr( aNewListLevelItem ); | ||||
4085 | } | ||||
4086 | |||||
4087 | bool SwTextNode::HasAttrListLevel() const | ||||
4088 | { | ||||
4089 | return GetpSwAttrSet() && | ||||
4090 | GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, false ) == SfxItemState::SET; | ||||
4091 | } | ||||
4092 | |||||
4093 | int SwTextNode::GetAttrListLevel() const | ||||
4094 | { | ||||
4095 | int nAttrListLevel = 0; | ||||
4096 | |||||
4097 | const SfxInt16Item& aListLevelItem = | ||||
4098 | dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL )); | ||||
4099 | nAttrListLevel = static_cast<int>(aListLevelItem.GetValue()); | ||||
4100 | |||||
4101 | return nAttrListLevel; | ||||
4102 | } | ||||
4103 | |||||
4104 | int SwTextNode::GetActualListLevel() const | ||||
4105 | { | ||||
4106 | assert(!GetNum() || !mpNodeNumRLHidden || // must be in sync(static_cast <bool> (!GetNum() || !mpNodeNumRLHidden || GetNum()->GetLevelInListTree() == mpNodeNumRLHidden->GetLevelInListTree ()) ? void (0) : __assert_fail ("!GetNum() || !mpNodeNumRLHidden || GetNum()->GetLevelInListTree() == mpNodeNumRLHidden->GetLevelInListTree()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4107, __extension__ __PRETTY_FUNCTION__)) | ||||
4107 | GetNum()->GetLevelInListTree() == mpNodeNumRLHidden->GetLevelInListTree())(static_cast <bool> (!GetNum() || !mpNodeNumRLHidden || GetNum()->GetLevelInListTree() == mpNodeNumRLHidden->GetLevelInListTree ()) ? void (0) : __assert_fail ("!GetNum() || !mpNodeNumRLHidden || GetNum()->GetLevelInListTree() == mpNodeNumRLHidden->GetLevelInListTree()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4107, __extension__ __PRETTY_FUNCTION__)); | ||||
4108 | return GetNum() ? GetNum()->GetLevelInListTree() : -1; | ||||
4109 | } | ||||
4110 | |||||
4111 | void SwTextNode::SetListRestart( bool bRestart ) | ||||
4112 | { | ||||
4113 | if ( !bRestart ) | ||||
4114 | { | ||||
4115 | // attribute not contained in paragraph style's attribute set. Thus, | ||||
4116 | // it can be reset to the attribute pool default by resetting the attribute. | ||||
4117 | ResetAttr( RES_PARATR_LIST_ISRESTART ); | ||||
4118 | } | ||||
4119 | else | ||||
4120 | { | ||||
4121 | SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART, | ||||
4122 | true ); | ||||
4123 | SetAttr( aNewIsRestartItem ); | ||||
4124 | } | ||||
4125 | } | ||||
4126 | |||||
4127 | bool SwTextNode::IsListRestart() const | ||||
4128 | { | ||||
4129 | const SfxBoolItem& aIsRestartItem = | ||||
4130 | dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART )); | ||||
4131 | |||||
4132 | return aIsRestartItem.GetValue(); | ||||
4133 | } | ||||
4134 | |||||
4135 | /** Returns if the paragraph has a visible numbering or bullet. | ||||
4136 | This includes all kinds of numbering/bullet/outlines. | ||||
4137 | The concrete list label string has to be checked, too. | ||||
4138 | */ | ||||
4139 | bool SwTextNode::HasVisibleNumberingOrBullet() const | ||||
4140 | { | ||||
4141 | const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
4142 | if ( pRule && IsCountedInList()) | ||||
4143 | { | ||||
4144 | // #i87154# | ||||
4145 | // Correction of #newlistlevelattrs#: | ||||
4146 | // The numbering type has to be checked for bullet lists. | ||||
4147 | const SwNumFormat& rFormat = pRule->Get( lcl_BoundListLevel(GetActualListLevel()) ); | ||||
4148 | return SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() || | ||||
4149 | !pRule->MakeNumString( *(GetNum()) ).isEmpty(); | ||||
4150 | } | ||||
4151 | |||||
4152 | return false; | ||||
4153 | } | ||||
4154 | |||||
4155 | void SwTextNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber ) | ||||
4156 | { | ||||
4157 | const bool bChanged( HasAttrListRestartValue() | ||||
4158 | ? GetAttrListRestartValue() != nNumber | ||||
4159 | : nNumber != USHRT_MAX(32767 *2 +1) ); | ||||
4160 | |||||
4161 | if ( !bChanged && HasAttrListRestartValue() ) | ||||
4162 | return; | ||||
4163 | |||||
4164 | if ( nNumber == USHRT_MAX(32767 *2 +1) ) | ||||
4165 | { | ||||
4166 | ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); | ||||
4167 | } | ||||
4168 | else | ||||
4169 | { | ||||
4170 | SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE, | ||||
4171 | static_cast<sal_Int16>(nNumber) ); | ||||
4172 | SetAttr( aNewListRestartValueItem ); | ||||
4173 | } | ||||
4174 | } | ||||
4175 | |||||
4176 | bool SwTextNode::HasAttrListRestartValue() const | ||||
4177 | { | ||||
4178 | return GetpSwAttrSet() && | ||||
4179 | GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, false ) == SfxItemState::SET; | ||||
4180 | } | ||||
4181 | SwNumberTree::tSwNumTreeNumber SwTextNode::GetAttrListRestartValue() const | ||||
4182 | { | ||||
4183 | OSL_ENSURE( HasAttrListRestartValue(),do { if (true && (!(HasAttrListRestartValue()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4184" ": "), "%s", "<SwTextNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." ); } } while (false) | ||||
4184 | "<SwTextNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." )do { if (true && (!(HasAttrListRestartValue()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4184" ": "), "%s", "<SwTextNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." ); } } while (false); | ||||
4185 | |||||
4186 | const SfxInt16Item& aListRestartValueItem = | ||||
4187 | dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE )); | ||||
4188 | return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue()); | ||||
4189 | } | ||||
4190 | |||||
4191 | SwNumberTree::tSwNumTreeNumber SwTextNode::GetActualListStartValue() const | ||||
4192 | { | ||||
4193 | SwNumberTree::tSwNumTreeNumber nListRestartValue = 1; | ||||
4194 | |||||
4195 | if ( IsListRestart() && HasAttrListRestartValue() ) | ||||
4196 | { | ||||
4197 | nListRestartValue = GetAttrListRestartValue(); | ||||
4198 | } | ||||
4199 | else | ||||
4200 | { | ||||
4201 | SwNumRule* pRule = GetNumRule(); | ||||
4202 | if ( pRule ) | ||||
4203 | { | ||||
4204 | const SwNumFormat* pFormat = | ||||
4205 | pRule->GetNumFormat( static_cast<sal_uInt16>(GetAttrListLevel()) ); | ||||
4206 | if ( pFormat ) | ||||
4207 | { | ||||
4208 | nListRestartValue = pFormat->GetStart(); | ||||
4209 | } | ||||
4210 | } | ||||
4211 | } | ||||
4212 | |||||
4213 | return nListRestartValue; | ||||
4214 | } | ||||
4215 | |||||
4216 | bool SwTextNode::IsNotifiable() const | ||||
4217 | { | ||||
4218 | return m_bNotifiable && IsNotificationEnabled(); | ||||
4219 | } | ||||
4220 | |||||
4221 | bool SwTextNode::IsNotificationEnabled() const | ||||
4222 | { | ||||
4223 | const SwDoc& rDoc = GetDoc(); | ||||
4224 | return !(rDoc.IsInReading() || rDoc.IsInDtor()); | ||||
4225 | } | ||||
4226 | |||||
4227 | void SwTextNode::SetCountedInList( bool bCounted ) | ||||
4228 | { | ||||
4229 | if ( bCounted ) | ||||
4230 | { | ||||
4231 | // attribute not contained in paragraph style's attribute set. Thus, | ||||
4232 | // it can be reset to the attribute pool default by resetting the attribute. | ||||
4233 | ResetAttr( RES_PARATR_LIST_ISCOUNTED ); | ||||
4234 | } | ||||
4235 | else | ||||
4236 | { | ||||
4237 | SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, false ); | ||||
4238 | SetAttr( aIsCountedInListItem ); | ||||
4239 | } | ||||
4240 | } | ||||
4241 | |||||
4242 | bool SwTextNode::IsCountedInList() const | ||||
4243 | { | ||||
4244 | const SfxBoolItem& aIsCountedInListItem = | ||||
4245 | dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED )); | ||||
4246 | |||||
4247 | return aIsCountedInListItem.GetValue(); | ||||
4248 | } | ||||
4249 | |||||
4250 | static SwList * FindList(SwTextNode *const pNode) | ||||
4251 | { | ||||
4252 | const OUString sListId = pNode->GetListId(); | ||||
4253 | if (!sListId.isEmpty()) | ||||
4254 | { | ||||
4255 | auto & rIDLA(pNode->GetDoc().getIDocumentListsAccess()); | ||||
4256 | SwList* pList = rIDLA.getListByName( sListId ); | ||||
4257 | if ( pList == nullptr ) | ||||
4258 | { | ||||
4259 | // Create corresponding list. | ||||
4260 | SwNumRule* pNumRule = pNode->GetNumRule(); | ||||
4261 | if ( pNumRule ) | ||||
4262 | { | ||||
4263 | pList = rIDLA.createList(sListId, pNode->GetNumRule()->GetName()); | ||||
4264 | } | ||||
4265 | } | ||||
4266 | OSL_ENSURE( pList != nullptr,do { if (true && (!(pList != nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4267" ": "), "%s", "<SwTextNode::AddToList()> - no list for given list id. Serious defect" ); } } while (false) | ||||
4267 | "<SwTextNode::AddToList()> - no list for given list id. Serious defect" )do { if (true && (!(pList != nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4267" ": "), "%s", "<SwTextNode::AddToList()> - no list for given list id. Serious defect" ); } } while (false); | ||||
4268 | return pList; | ||||
4269 | } | ||||
4270 | return nullptr; | ||||
4271 | } | ||||
4272 | |||||
4273 | void SwTextNode::AddToList() | ||||
4274 | { | ||||
4275 | if ( IsInList() ) | ||||
4276 | { | ||||
4277 | OSL_FAIL( "<SwTextNode::AddToList()> - the text node is already added to a list. Serious defect" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4277" ": "), "%s", "<SwTextNode::AddToList()> - the text node is already added to a list. Serious defect" ); } } while (false); | ||||
4278 | return; | ||||
4279 | } | ||||
4280 | |||||
4281 | SwList *const pList(FindList(this)); | ||||
4282 | if (!(pList && GetNodes().IsDocNodes())) // not for undo nodes | ||||
4283 | return; | ||||
4284 | |||||
4285 | assert(!mpNodeNum)(static_cast <bool> (!mpNodeNum) ? void (0) : __assert_fail ("!mpNodeNum", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4285, __extension__ __PRETTY_FUNCTION__)); | ||||
4286 | mpNodeNum.reset(new SwNodeNum(this, false)); | ||||
4287 | pList->InsertListItem(*mpNodeNum, false, GetAttrListLevel()); | ||||
4288 | // iterate all frames & if there's one with hidden layout... | ||||
4289 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> iter(*this); | ||||
4290 | for (SwTextFrame* pFrame = iter.First(); pFrame; pFrame = iter.Next()) | ||||
4291 | { | ||||
4292 | if (pFrame->getRootFrame()->IsHideRedlines()) | ||||
4293 | { | ||||
4294 | if (pFrame->GetTextNodeForParaProps() == this) | ||||
4295 | { | ||||
4296 | AddToListRLHidden(); | ||||
4297 | } | ||||
4298 | break; // assume it's consistent, need to check only once | ||||
4299 | } | ||||
4300 | } | ||||
4301 | } | ||||
4302 | |||||
4303 | void SwTextNode::AddToListRLHidden() | ||||
4304 | { | ||||
4305 | if (mpNodeNumRLHidden) | ||||
4306 | { | ||||
4307 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4307, __extension__ __PRETTY_FUNCTION__)); | ||||
4308 | OSL_FAIL( "<SwTextNode::AddToListRLHidden()> - the text node is already added to a list. Serious defect" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4308" ": "), "%s", "<SwTextNode::AddToListRLHidden()> - the text node is already added to a list. Serious defect" ); } } while (false); | ||||
4309 | return; | ||||
4310 | } | ||||
4311 | |||||
4312 | SwList *const pList(FindList(this)); | ||||
4313 | if (pList) | ||||
4314 | { | ||||
4315 | assert(!mpNodeNumRLHidden)(static_cast <bool> (!mpNodeNumRLHidden) ? void (0) : __assert_fail ("!mpNodeNumRLHidden", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4315, __extension__ __PRETTY_FUNCTION__)); | ||||
4316 | mpNodeNumRLHidden.reset(new SwNodeNum(this, true)); | ||||
4317 | pList->InsertListItem(*mpNodeNumRLHidden, true, GetAttrListLevel()); | ||||
4318 | } | ||||
4319 | } | ||||
4320 | |||||
4321 | void SwTextNode::RemoveFromList() | ||||
4322 | { | ||||
4323 | // sw_redlinehide: ensure it's removed from the other half too! | ||||
4324 | RemoveFromListRLHidden(); | ||||
4325 | if ( IsInList() ) | ||||
4326 | { | ||||
4327 | SwList::RemoveListItem( *mpNodeNum ); | ||||
4328 | mpNodeNum.reset(); | ||||
4329 | |||||
4330 | SetWordCountDirty( true ); | ||||
4331 | } | ||||
4332 | } | ||||
4333 | |||||
4334 | void SwTextNode::RemoveFromListRLHidden() | ||||
4335 | { | ||||
4336 | if (mpNodeNumRLHidden) // direct access because RemoveFromList doesn't have layout | ||||
4337 | { | ||||
4338 | assert(mpNodeNumRLHidden->GetParent() || !GetNodes().IsDocNodes())(static_cast <bool> (mpNodeNumRLHidden->GetParent() || !GetNodes().IsDocNodes()) ? void (0) : __assert_fail ("mpNodeNumRLHidden->GetParent() || !GetNodes().IsDocNodes()" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4338, __extension__ __PRETTY_FUNCTION__)); | ||||
4339 | SwList::RemoveListItem(*mpNodeNumRLHidden); | ||||
4340 | mpNodeNumRLHidden.reset(); | ||||
4341 | |||||
4342 | SetWordCountDirty( true ); | ||||
4343 | } | ||||
4344 | } | ||||
4345 | |||||
4346 | bool SwTextNode::IsInList() const | ||||
4347 | { | ||||
4348 | return GetNum() != nullptr && GetNum()->GetParent() != nullptr; | ||||
4349 | } | ||||
4350 | |||||
4351 | bool SwTextNode::IsFirstOfNumRule(SwRootFrame const& rLayout) const | ||||
4352 | { | ||||
4353 | bool bResult = false; | ||||
4354 | |||||
4355 | SwNodeNum const*const pNum(GetNum(&rLayout)); | ||||
4356 | if (pNum && pNum->GetNumRule()) | ||||
4357 | bResult = pNum->IsFirst(); | ||||
4358 | |||||
4359 | return bResult; | ||||
4360 | } | ||||
4361 | |||||
4362 | void SwTextNode::SetListId(OUString const& rListId) | ||||
4363 | { | ||||
4364 | const SfxStringItem& rListIdItem = | ||||
4365 | dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID )); | ||||
4366 | if (rListIdItem.GetValue() != rListId) | ||||
4367 | { | ||||
4368 | if (rListId.isEmpty()) | ||||
4369 | { | ||||
4370 | ResetAttr( RES_PARATR_LIST_ID ); | ||||
4371 | } | ||||
4372 | else | ||||
4373 | { | ||||
4374 | SfxStringItem aNewListIdItem(RES_PARATR_LIST_ID, rListId); | ||||
4375 | SetAttr( aNewListIdItem ); | ||||
4376 | } | ||||
4377 | } | ||||
4378 | } | ||||
4379 | |||||
4380 | OUString SwTextNode::GetListId() const | ||||
4381 | { | ||||
4382 | const SfxStringItem& rListIdItem = | ||||
4383 | dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID )); | ||||
4384 | const OUString& sListId {rListIdItem.GetValue()}; | ||||
4385 | |||||
4386 | // As long as no explicit list id attribute is set, use the list id of | ||||
4387 | // the list, which has been created for the applied list style. | ||||
4388 | if (sListId.isEmpty()) | ||||
4389 | { | ||||
4390 | SwNumRule* pRule = GetNumRule(); | ||||
4391 | if ( pRule ) | ||||
4392 | { | ||||
4393 | return pRule->GetDefaultListId(); | ||||
4394 | } | ||||
4395 | } | ||||
4396 | |||||
4397 | return sListId; | ||||
4398 | } | ||||
4399 | |||||
4400 | /** Determines, if the list level indent attributes can be applied to the | ||||
4401 | paragraph. | ||||
4402 | |||||
4403 | The list level indents can be applied to the paragraph under the one | ||||
4404 | of following conditions: | ||||
4405 | - the list style is directly applied to the paragraph and the paragraph | ||||
4406 | has no own indent attributes. | ||||
4407 | - the list style is applied to the paragraph through one of its paragraph | ||||
4408 | styles, the paragraph has no own indent attributes and on the paragraph | ||||
4409 | style hierarchy from the paragraph to the paragraph style with the | ||||
4410 | list style no indent attributes are found. | ||||
4411 | |||||
4412 | @return boolean | ||||
4413 | */ | ||||
4414 | bool SwTextNode::AreListLevelIndentsApplicable() const | ||||
4415 | { | ||||
4416 | bool bAreListLevelIndentsApplicable( true ); | ||||
4417 | |||||
4418 | if ( !GetNum() || !GetNum()->GetNumRule() ) | ||||
4419 | { | ||||
4420 | // no list style applied to paragraph | ||||
4421 | bAreListLevelIndentsApplicable = false; | ||||
4422 | } | ||||
4423 | else if ( HasSwAttrSet() && | ||||
4424 | GetpSwAttrSet()->GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET ) | ||||
4425 | { | ||||
4426 | // paragraph has hard-set indent attributes | ||||
4427 | bAreListLevelIndentsApplicable = false; | ||||
4428 | } | ||||
4429 | else if ( HasSwAttrSet() && | ||||
4430 | GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET ) | ||||
4431 | { | ||||
4432 | // list style is directly applied to paragraph and paragraph has no | ||||
4433 | // hard-set indent attributes | ||||
4434 | bAreListLevelIndentsApplicable = true; | ||||
4435 | } | ||||
4436 | else | ||||
4437 | { | ||||
4438 | // list style is applied through one of the paragraph styles and | ||||
4439 | // paragraph has no hard-set indent attributes | ||||
4440 | |||||
4441 | // check, paragraph's | ||||
4442 | const SwTextFormatColl* pColl = GetTextColl(); | ||||
4443 | while ( pColl ) | ||||
4444 | { | ||||
4445 | if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET ) | ||||
4446 | { | ||||
4447 | // indent attributes found in the paragraph style hierarchy. | ||||
4448 | bAreListLevelIndentsApplicable = false; | ||||
4449 | break; | ||||
4450 | } | ||||
4451 | |||||
4452 | if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET ) | ||||
4453 | { | ||||
4454 | // paragraph style with the list style found and until now no | ||||
4455 | // indent attributes are found in the paragraph style hierarchy. | ||||
4456 | bAreListLevelIndentsApplicable = true; | ||||
4457 | break; | ||||
4458 | } | ||||
4459 | |||||
4460 | pColl = dynamic_cast<const SwTextFormatColl*>(pColl->DerivedFrom()); | ||||
4461 | OSL_ENSURE( pColl,do { if (true && (!(pColl))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4462" ": "), "%s", "<SwTextNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." ); } } while (false) | ||||
4462 | "<SwTextNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." )do { if (true && (!(pColl))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4462" ": "), "%s", "<SwTextNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." ); } } while (false); | ||||
4463 | } | ||||
4464 | } | ||||
4465 | |||||
4466 | return bAreListLevelIndentsApplicable; | ||||
4467 | } | ||||
4468 | |||||
4469 | /** Retrieves the list tab stop position, if the paragraph's list level defines | ||||
4470 | one and this list tab stop has to merged into the tap stops of the paragraph | ||||
4471 | |||||
4472 | @param nListTabStopPosition | ||||
4473 | output parameter - containing the list tab stop position | ||||
4474 | |||||
4475 | @return boolean - indicating, if a list tab stop position is provided | ||||
4476 | */ | ||||
4477 | bool SwTextNode::GetListTabStopPosition( long& nListTabStopPosition ) const | ||||
4478 | { | ||||
4479 | bool bListTabStopPositionProvided(false); | ||||
4480 | |||||
4481 | const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
4482 | if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 ) | ||||
4483 | { | ||||
4484 | const SwNumFormat& rFormat = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ); | ||||
4485 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT && | ||||
4486 | rFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB ) | ||||
4487 | { | ||||
4488 | bListTabStopPositionProvided = true; | ||||
4489 | nListTabStopPosition = rFormat.GetListtabPos(); | ||||
4490 | |||||
4491 | if ( getIDocumentSettingAccess()->get(DocumentSettingId::TABS_RELATIVE_TO_INDENT) ) | ||||
4492 | { | ||||
4493 | // tab stop position are treated to be relative to the "before text" | ||||
4494 | // indent value of the paragraph. Thus, adjust <nListTabStopPos>. | ||||
4495 | if ( AreListLevelIndentsApplicable() ) | ||||
4496 | { | ||||
4497 | nListTabStopPosition -= rFormat.GetIndentAt(); | ||||
4498 | } | ||||
4499 | else if (!getIDocumentSettingAccess()->get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) | ||||
4500 | { | ||||
4501 | SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); | ||||
4502 | nListTabStopPosition -= aItem.GetTextLeft(); | ||||
4503 | } | ||||
4504 | } | ||||
4505 | } | ||||
4506 | } | ||||
4507 | |||||
4508 | return bListTabStopPositionProvided; | ||||
4509 | } | ||||
4510 | |||||
4511 | OUString SwTextNode::GetLabelFollowedBy() const | ||||
4512 | { | ||||
4513 | const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : nullptr; | ||||
4514 | if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 ) | ||||
4515 | { | ||||
4516 | const SwNumFormat& rFormat = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ); | ||||
4517 | if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) | ||||
4518 | { | ||||
4519 | switch ( rFormat.GetLabelFollowedBy() ) | ||||
4520 | { | ||||
4521 | case SvxNumberFormat::LISTTAB: | ||||
4522 | { | ||||
4523 | return "\t"; | ||||
4524 | } | ||||
4525 | break; | ||||
4526 | case SvxNumberFormat::SPACE: | ||||
4527 | { | ||||
4528 | return " "; | ||||
4529 | } | ||||
4530 | break; | ||||
4531 | case SvxNumberFormat::NEWLINE: | ||||
4532 | { | ||||
4533 | return "\n"; | ||||
4534 | } | ||||
4535 | break; | ||||
4536 | case SvxNumberFormat::NOTHING: | ||||
4537 | { | ||||
4538 | // intentionally left blank. | ||||
4539 | } | ||||
4540 | break; | ||||
4541 | default: | ||||
4542 | { | ||||
4543 | OSL_FAIL( "<SwTextNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4543" ": "), "%s", "<SwTextNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" ); } } while (false); | ||||
4544 | } | ||||
4545 | } | ||||
4546 | } | ||||
4547 | } | ||||
4548 | |||||
4549 | return OUString(); | ||||
4550 | } | ||||
4551 | |||||
4552 | void SwTextNode::CalcHiddenCharFlags() const | ||||
4553 | { | ||||
4554 | sal_Int32 nStartPos; | ||||
4555 | sal_Int32 nEndPos; | ||||
4556 | // Update of the flags is done inside GetBoundsOfHiddenRange() | ||||
4557 | SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos ); | ||||
4558 | } | ||||
4559 | |||||
4560 | // #i12836# enhanced pdf export | ||||
4561 | bool SwTextNode::IsHidden() const | ||||
4562 | { | ||||
4563 | if ( IsHiddenByParaField() || HasHiddenCharAttribute( true ) ) | ||||
4564 | return true; | ||||
4565 | |||||
4566 | const SwSectionNode* pSectNd = FindSectionNode(); | ||||
4567 | return pSectNd && pSectNd->GetSection().IsHiddenFlag(); | ||||
4568 | } | ||||
4569 | |||||
4570 | namespace { | ||||
4571 | // Helper class for special handling of setting attributes at text node: | ||||
4572 | // In constructor an instance of the helper class recognize whose attributes | ||||
4573 | // are set and perform corresponding actions before the intrinsic set of | ||||
4574 | // attributes has been taken place. | ||||
4575 | // In the destructor - after the attributes have been set at the text | ||||
4576 | // node - corresponding actions are performed. | ||||
4577 | // The following is handled: | ||||
4578 | // (1) When the list style attribute - RES_PARATR_NUMRULE - is set, | ||||
4579 | // (A) list style attribute is empty -> the text node is removed from | ||||
4580 | // its list. | ||||
4581 | // (B) list style attribute is not empty | ||||
4582 | // (a) text node has no list style -> add text node to its list after | ||||
4583 | // the attributes have been set. | ||||
4584 | // (b) text node has list style -> change of list style is notified | ||||
4585 | // after the attributes have been set. | ||||
4586 | // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed, | ||||
4587 | // the text node is removed from its current list before the attributes | ||||
4588 | // are set and added to its new list after the attributes have been set. | ||||
4589 | // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set | ||||
4590 | // and changed after the attributes have been set | ||||
4591 | // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set | ||||
4592 | // and changed after the attributes have been set | ||||
4593 | // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - | ||||
4594 | // is set and changed after the attributes have been set | ||||
4595 | // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set | ||||
4596 | // and changed after the attributes have been set | ||||
4597 | // (7) Set or Reset empty list style due to changed outline level - RES_PARATR_OUTLINELEVEL. | ||||
4598 | class HandleSetAttrAtTextNode | ||||
4599 | { | ||||
4600 | public: | ||||
4601 | HandleSetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4602 | const SfxPoolItem& pItem ); | ||||
4603 | HandleSetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4604 | const SfxItemSet& rItemSet ); | ||||
4605 | ~HandleSetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE; | ||||
4606 | |||||
4607 | private: | ||||
4608 | SwTextNode& mrTextNode; | ||||
4609 | bool mbAddTextNodeToList; | ||||
4610 | bool mbUpdateListLevel; | ||||
4611 | bool mbUpdateListRestart; | ||||
4612 | bool mbUpdateListCount; | ||||
4613 | // #i70748# | ||||
4614 | bool mbOutlineLevelSet; | ||||
4615 | }; | ||||
4616 | |||||
4617 | HandleSetAttrAtTextNode::HandleSetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4618 | const SfxPoolItem& pItem ) | ||||
4619 | : mrTextNode( rTextNode ), | ||||
4620 | mbAddTextNodeToList( false ), | ||||
4621 | mbUpdateListLevel( false ), | ||||
4622 | mbUpdateListRestart( false ), | ||||
4623 | mbUpdateListCount( false ), | ||||
4624 | // #i70748# | ||||
4625 | mbOutlineLevelSet( false ) | ||||
4626 | { | ||||
4627 | switch ( pItem.Which() ) | ||||
4628 | { | ||||
4629 | // handle RES_PARATR_NUMRULE | ||||
4630 | case RES_PARATR_NUMRULE: | ||||
4631 | { | ||||
4632 | mrTextNode.RemoveFromList(); | ||||
4633 | |||||
4634 | const SwNumRuleItem& rNumRuleItem = | ||||
4635 | dynamic_cast<const SwNumRuleItem&>(pItem); | ||||
4636 | if ( !rNumRuleItem.GetValue().isEmpty() ) | ||||
4637 | { | ||||
4638 | mbAddTextNodeToList = true; | ||||
4639 | // #i105562# | ||||
4640 | |||||
4641 | mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
4642 | } | ||||
4643 | } | ||||
4644 | break; | ||||
4645 | |||||
4646 | // handle RES_PARATR_LIST_ID | ||||
4647 | case RES_PARATR_LIST_ID: | ||||
4648 | { | ||||
4649 | const SfxStringItem& rListIdItem = | ||||
4650 | dynamic_cast<const SfxStringItem&>(pItem); | ||||
4651 | OSL_ENSURE( rListIdItem.GetValue().getLength() > 0,do { if (true && (!(rListIdItem.GetValue().getLength( ) > 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4652" ": "), "%s", "<HandleSetAttrAtTextNode(..)> - empty list id attribute not expected. Serious defect." ); } } while (false) | ||||
4652 | "<HandleSetAttrAtTextNode(..)> - empty list id attribute not expected. Serious defect." )do { if (true && (!(rListIdItem.GetValue().getLength( ) > 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" ":" "4652" ": "), "%s", "<HandleSetAttrAtTextNode(..)> - empty list id attribute not expected. Serious defect." ); } } while (false); | ||||
4653 | const OUString sListIdOfTextNode = rTextNode.GetListId(); | ||||
4654 | if ( rListIdItem.GetValue() != sListIdOfTextNode ) | ||||
4655 | { | ||||
4656 | mbAddTextNodeToList = true; | ||||
4657 | if ( mrTextNode.IsInList() ) | ||||
4658 | { | ||||
4659 | mrTextNode.RemoveFromList(); | ||||
4660 | } | ||||
4661 | } | ||||
4662 | } | ||||
4663 | break; | ||||
4664 | |||||
4665 | // handle RES_PARATR_LIST_LEVEL | ||||
4666 | case RES_PARATR_LIST_LEVEL: | ||||
4667 | { | ||||
4668 | const SfxInt16Item& aListLevelItem = | ||||
4669 | dynamic_cast<const SfxInt16Item&>(pItem); | ||||
4670 | if ( aListLevelItem.GetValue() != mrTextNode.GetAttrListLevel() ) | ||||
4671 | { | ||||
4672 | mbUpdateListLevel = true; | ||||
4673 | } | ||||
4674 | } | ||||
4675 | break; | ||||
4676 | |||||
4677 | // handle RES_PARATR_LIST_ISRESTART | ||||
4678 | case RES_PARATR_LIST_ISRESTART: | ||||
4679 | { | ||||
4680 | const SfxBoolItem& aListIsRestartItem = | ||||
4681 | dynamic_cast<const SfxBoolItem&>(pItem); | ||||
4682 | if ( aListIsRestartItem.GetValue() != | ||||
4683 | mrTextNode.IsListRestart() ) | ||||
4684 | { | ||||
4685 | mbUpdateListRestart = true; | ||||
4686 | } | ||||
4687 | } | ||||
4688 | break; | ||||
4689 | |||||
4690 | // handle RES_PARATR_LIST_RESTARTVALUE | ||||
4691 | case RES_PARATR_LIST_RESTARTVALUE: | ||||
4692 | { | ||||
4693 | const SfxInt16Item& aListRestartValueItem = | ||||
4694 | dynamic_cast<const SfxInt16Item&>(pItem); | ||||
4695 | if ( !mrTextNode.HasAttrListRestartValue() || | ||||
4696 | aListRestartValueItem.GetValue() != mrTextNode.GetAttrListRestartValue() ) | ||||
4697 | { | ||||
4698 | mbUpdateListRestart = true; | ||||
4699 | } | ||||
4700 | } | ||||
4701 | break; | ||||
4702 | |||||
4703 | // handle RES_PARATR_LIST_ISCOUNTED | ||||
4704 | case RES_PARATR_LIST_ISCOUNTED: | ||||
4705 | { | ||||
4706 | const SfxBoolItem& aIsCountedInListItem = | ||||
4707 | dynamic_cast<const SfxBoolItem&>(pItem); | ||||
4708 | if ( aIsCountedInListItem.GetValue() != | ||||
4709 | mrTextNode.IsCountedInList() ) | ||||
4710 | { | ||||
4711 | mbUpdateListCount = true; | ||||
4712 | } | ||||
4713 | } | ||||
4714 | break; | ||||
4715 | |||||
4716 | // #i70748# | ||||
4717 | // handle RES_PARATR_OUTLINELEVEL | ||||
4718 | case RES_PARATR_OUTLINELEVEL: | ||||
4719 | { | ||||
4720 | const SfxUInt16Item& aOutlineLevelItem = | ||||
4721 | dynamic_cast<const SfxUInt16Item&>(pItem); | ||||
4722 | if ( aOutlineLevelItem.GetValue() != mrTextNode.GetAttrOutlineLevel() ) | ||||
4723 | { | ||||
4724 | mbOutlineLevelSet = true; | ||||
4725 | } | ||||
4726 | } | ||||
4727 | break; | ||||
4728 | } | ||||
4729 | |||||
4730 | } | ||||
4731 | |||||
4732 | HandleSetAttrAtTextNode::HandleSetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4733 | const SfxItemSet& rItemSet ) | ||||
4734 | : mrTextNode( rTextNode ), | ||||
4735 | mbAddTextNodeToList( false ), | ||||
4736 | mbUpdateListLevel( false ), | ||||
4737 | mbUpdateListRestart( false ), | ||||
4738 | mbUpdateListCount( false ), | ||||
4739 | // #i70748# | ||||
4740 | mbOutlineLevelSet( false ) | ||||
4741 | { | ||||
4742 | const SfxPoolItem* pItem = nullptr; | ||||
4743 | // handle RES_PARATR_NUMRULE | ||||
4744 | if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, false, &pItem ) == SfxItemState::SET ) | ||||
4745 | { | ||||
4746 | mrTextNode.RemoveFromList(); | ||||
4747 | |||||
4748 | const SwNumRuleItem* pNumRuleItem = | ||||
4749 | dynamic_cast<const SwNumRuleItem*>(pItem); | ||||
4750 | assert(pNumRuleItem)(static_cast <bool> (pNumRuleItem) ? void (0) : __assert_fail ("pNumRuleItem", "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 4750, __extension__ __PRETTY_FUNCTION__)); | ||||
4751 | if ( !pNumRuleItem->GetValue().isEmpty() ) | ||||
4752 | { | ||||
4753 | mbAddTextNodeToList = true; | ||||
4754 | // #i70748# | ||||
4755 | mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
4756 | } | ||||
4757 | } | ||||
4758 | |||||
4759 | // handle RES_PARATR_LIST_ID | ||||
4760 | if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, false, &pItem ) == SfxItemState::SET ) | ||||
4761 | { | ||||
4762 | const SfxStringItem* pListIdItem = | ||||
4763 | dynamic_cast<const SfxStringItem*>(pItem); | ||||
4764 | const OUString sListIdOfTextNode = mrTextNode.GetListId(); | ||||
4765 | if ( pListIdItem && | ||||
4766 | pListIdItem->GetValue() != sListIdOfTextNode ) | ||||
4767 | { | ||||
4768 | mbAddTextNodeToList = true; | ||||
4769 | if ( mrTextNode.IsInList() ) | ||||
4770 | { | ||||
4771 | mrTextNode.RemoveFromList(); | ||||
4772 | } | ||||
4773 | } | ||||
4774 | } | ||||
4775 | |||||
4776 | // handle RES_PARATR_LIST_LEVEL | ||||
4777 | if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, false, &pItem ) == SfxItemState::SET ) | ||||
4778 | { | ||||
4779 | const SfxInt16Item* pListLevelItem = | ||||
4780 | dynamic_cast<const SfxInt16Item*>(pItem); | ||||
4781 | if (pListLevelItem && pListLevelItem->GetValue() != mrTextNode.GetAttrListLevel()) | ||||
4782 | { | ||||
4783 | mbUpdateListLevel = true; | ||||
4784 | } | ||||
4785 | } | ||||
4786 | |||||
4787 | // handle RES_PARATR_LIST_ISRESTART | ||||
4788 | if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, false, &pItem ) == SfxItemState::SET ) | ||||
4789 | { | ||||
4790 | const SfxBoolItem* pListIsRestartItem = | ||||
4791 | dynamic_cast<const SfxBoolItem*>(pItem); | ||||
4792 | if (pListIsRestartItem && pListIsRestartItem->GetValue() != mrTextNode.IsListRestart()) | ||||
4793 | { | ||||
4794 | mbUpdateListRestart = true; | ||||
4795 | } | ||||
4796 | } | ||||
4797 | |||||
4798 | // handle RES_PARATR_LIST_RESTARTVALUE | ||||
4799 | if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, false, &pItem ) == SfxItemState::SET ) | ||||
4800 | { | ||||
4801 | const SfxInt16Item* pListRestartValueItem = | ||||
4802 | dynamic_cast<const SfxInt16Item*>(pItem); | ||||
4803 | if ( !mrTextNode.HasAttrListRestartValue() || (pListRestartValueItem && | ||||
4804 | pListRestartValueItem->GetValue() != mrTextNode.GetAttrListRestartValue()) ) | ||||
4805 | { | ||||
4806 | mbUpdateListRestart = true; | ||||
4807 | } | ||||
4808 | } | ||||
4809 | |||||
4810 | // handle RES_PARATR_LIST_ISCOUNTED | ||||
4811 | if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, false, &pItem ) == SfxItemState::SET ) | ||||
4812 | { | ||||
4813 | const SfxBoolItem* pIsCountedInListItem = | ||||
4814 | dynamic_cast<const SfxBoolItem*>(pItem); | ||||
4815 | if (pIsCountedInListItem && pIsCountedInListItem->GetValue() != | ||||
4816 | mrTextNode.IsCountedInList()) | ||||
4817 | { | ||||
4818 | mbUpdateListCount = true; | ||||
4819 | } | ||||
4820 | } | ||||
4821 | |||||
4822 | // #i70748# | ||||
4823 | // handle RES_PARATR_OUTLINELEVEL | ||||
4824 | if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, false, &pItem ) == SfxItemState::SET ) | ||||
4825 | { | ||||
4826 | const SfxUInt16Item* pOutlineLevelItem = | ||||
4827 | dynamic_cast<const SfxUInt16Item*>(pItem); | ||||
4828 | if (pOutlineLevelItem && pOutlineLevelItem->GetValue() != | ||||
4829 | mrTextNode.GetAttrOutlineLevel()) | ||||
4830 | { | ||||
4831 | mbOutlineLevelSet = true; | ||||
4832 | } | ||||
4833 | } | ||||
4834 | } | ||||
4835 | |||||
4836 | HandleSetAttrAtTextNode::~HandleSetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE | ||||
4837 | { | ||||
4838 | if ( mbAddTextNodeToList ) | ||||
4839 | { | ||||
4840 | SwNumRule* pNumRuleAtTextNode = mrTextNode.GetNumRule(); | ||||
4841 | if ( pNumRuleAtTextNode ) | ||||
4842 | { | ||||
4843 | mrTextNode.AddToList(); | ||||
4844 | } | ||||
4845 | } | ||||
4846 | else | ||||
4847 | { | ||||
4848 | if ( mbUpdateListLevel && mrTextNode.IsInList() ) | ||||
4849 | { | ||||
4850 | auto const nLevel(mrTextNode.GetAttrListLevel()); | ||||
4851 | mrTextNode.DoNum( | ||||
4852 | [nLevel](SwNodeNum & rNum) { rNum.SetLevelInListTree(nLevel); }); | ||||
4853 | } | ||||
4854 | |||||
4855 | if ( mbUpdateListRestart && mrTextNode.IsInList() ) | ||||
4856 | { | ||||
4857 | mrTextNode.DoNum( | ||||
4858 | [](SwNodeNum & rNum) { | ||||
4859 | rNum.InvalidateMe(); | ||||
4860 | rNum.NotifyInvalidSiblings(); | ||||
4861 | }); | ||||
4862 | } | ||||
4863 | |||||
4864 | if ( mbUpdateListCount && mrTextNode.IsInList() ) | ||||
4865 | { | ||||
4866 | mrTextNode.DoNum( | ||||
4867 | [](SwNodeNum & rNum) { rNum.InvalidateAndNotifyTree(); }); | ||||
4868 | } | ||||
4869 | } | ||||
4870 | |||||
4871 | // #i70748# | ||||
4872 | if (!mbOutlineLevelSet) | ||||
4873 | return; | ||||
4874 | |||||
4875 | mrTextNode.GetNodes().UpdateOutlineNode(mrTextNode); | ||||
4876 | if (mrTextNode.GetAttrOutlineLevel() == 0) | ||||
4877 | { | ||||
4878 | mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
4879 | } | ||||
4880 | else | ||||
4881 | { | ||||
4882 | const SfxPoolItem* pItem = nullptr; | ||||
4883 | if ( mrTextNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE, | ||||
4884 | true, &pItem ) | ||||
4885 | != SfxItemState::SET ) | ||||
4886 | { | ||||
4887 | mrTextNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); | ||||
4888 | } | ||||
4889 | } | ||||
4890 | } | ||||
4891 | // End of class <HandleSetAttrAtTextNode> | ||||
4892 | } | ||||
4893 | |||||
4894 | bool SwTextNode::SetAttr( const SfxPoolItem& pItem ) | ||||
4895 | { | ||||
4896 | const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); | ||||
4897 | mbInSetOrResetAttr = true; | ||||
4898 | |||||
4899 | HandleSetAttrAtTextNode aHandleSetAttr( *this, pItem ); | ||||
4900 | |||||
4901 | bool bRet = SwContentNode::SetAttr( pItem ); | ||||
4902 | |||||
4903 | mbInSetOrResetAttr = bOldIsSetOrResetAttr; | ||||
4904 | |||||
4905 | return bRet; | ||||
4906 | } | ||||
4907 | |||||
4908 | bool SwTextNode::SetAttr( const SfxItemSet& rSet ) | ||||
4909 | { | ||||
4910 | const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); | ||||
4911 | mbInSetOrResetAttr = true; | ||||
4912 | |||||
4913 | HandleSetAttrAtTextNode aHandleSetAttr( *this, rSet ); | ||||
4914 | |||||
4915 | bool bRet = SwContentNode::SetAttr( rSet ); | ||||
4916 | |||||
4917 | mbInSetOrResetAttr = bOldIsSetOrResetAttr; | ||||
4918 | |||||
4919 | return bRet; | ||||
4920 | } | ||||
4921 | |||||
4922 | namespace { | ||||
4923 | // Helper class for special handling of resetting attributes at text node: | ||||
4924 | // In constructor an instance of the helper class recognize whose attributes | ||||
4925 | // are reset and perform corresponding actions before the intrinsic reset of | ||||
4926 | // attributes has been taken place. | ||||
4927 | // In the destructor - after the attributes have been reset at the text | ||||
4928 | // node - corresponding actions are performed. | ||||
4929 | // The following is handled: | ||||
4930 | // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset, | ||||
4931 | // the text is removed from its list before the attributes have been reset. | ||||
4932 | // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset, | ||||
4933 | // the text is removed from its list before the attributes have been reset. | ||||
4934 | // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset. | ||||
4935 | // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset. | ||||
4936 | // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset. | ||||
4937 | // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset. | ||||
4938 | // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset. | ||||
4939 | class HandleResetAttrAtTextNode | ||||
4940 | { | ||||
4941 | public: | ||||
4942 | HandleResetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4943 | const sal_uInt16 nWhich1, | ||||
4944 | sal_uInt16 nWhich2 ); | ||||
4945 | HandleResetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4946 | const std::vector<sal_uInt16>& rWhichArr ); | ||||
4947 | explicit HandleResetAttrAtTextNode( SwTextNode& rTextNode ); | ||||
4948 | |||||
4949 | ~HandleResetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE; | ||||
4950 | |||||
4951 | private: | ||||
4952 | SwTextNode& mrTextNode; | ||||
4953 | bool mbListStyleOrIdReset; | ||||
4954 | bool mbUpdateListLevel; | ||||
4955 | bool mbUpdateListRestart; | ||||
4956 | bool mbUpdateListCount; | ||||
4957 | |||||
4958 | void init( const std::vector<sal_uInt16>& rWhichArr ); | ||||
4959 | }; | ||||
4960 | |||||
4961 | HandleResetAttrAtTextNode::HandleResetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4962 | const sal_uInt16 nWhich1, | ||||
4963 | sal_uInt16 nWhich2 ) | ||||
4964 | : mrTextNode( rTextNode ), | ||||
4965 | mbListStyleOrIdReset( false ), | ||||
4966 | mbUpdateListLevel( false ), | ||||
4967 | mbUpdateListRestart( false ), | ||||
4968 | mbUpdateListCount( false ) | ||||
4969 | { | ||||
4970 | if ( nWhich2 < nWhich1 ) | ||||
4971 | nWhich2 = nWhich1; | ||||
4972 | std::vector<sal_uInt16> rWhichArr; | ||||
4973 | for ( sal_uInt16 nWhich = nWhich1; nWhich <= nWhich2; ++nWhich ) | ||||
4974 | rWhichArr.push_back( nWhich ); | ||||
4975 | |||||
4976 | init( rWhichArr ); | ||||
4977 | } | ||||
4978 | |||||
4979 | HandleResetAttrAtTextNode::HandleResetAttrAtTextNode( SwTextNode& rTextNode, | ||||
4980 | const std::vector<sal_uInt16>& rWhichArr ) | ||||
4981 | : mrTextNode( rTextNode ), | ||||
4982 | mbListStyleOrIdReset( false ), | ||||
4983 | mbUpdateListLevel( false ), | ||||
4984 | mbUpdateListRestart( false ), | ||||
4985 | mbUpdateListCount( false ) | ||||
4986 | { | ||||
4987 | init( rWhichArr ); | ||||
4988 | } | ||||
4989 | |||||
4990 | HandleResetAttrAtTextNode::HandleResetAttrAtTextNode( SwTextNode& rTextNode ) | ||||
4991 | : mrTextNode( rTextNode ), | ||||
4992 | mbListStyleOrIdReset( true ), | ||||
4993 | mbUpdateListLevel( false ), | ||||
4994 | mbUpdateListRestart( false ), | ||||
4995 | mbUpdateListCount( false ) | ||||
4996 | { | ||||
4997 | if ( rTextNode.IsInList() ) | ||||
4998 | { | ||||
4999 | rTextNode.RemoveFromList(); | ||||
5000 | } | ||||
5001 | // #i70748# | ||||
5002 | mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
5003 | } | ||||
5004 | |||||
5005 | void HandleResetAttrAtTextNode::init( const std::vector<sal_uInt16>& rWhichArr ) | ||||
5006 | { | ||||
5007 | bool bRemoveFromList( false ); | ||||
5008 | { | ||||
5009 | for (const auto& rWhich : rWhichArr) | ||||
5010 | { | ||||
5011 | if ( rWhich == RES_PARATR_NUMRULE ) | ||||
5012 | { | ||||
5013 | bRemoveFromList = bRemoveFromList || | ||||
5014 | mrTextNode.GetNumRule() != nullptr; | ||||
5015 | mbListStyleOrIdReset = true; | ||||
5016 | } | ||||
5017 | else if ( rWhich == RES_PARATR_LIST_ID ) | ||||
5018 | { | ||||
5019 | bRemoveFromList = bRemoveFromList || | ||||
5020 | ( mrTextNode.GetpSwAttrSet() && | ||||
5021 | mrTextNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, false ) == SfxItemState::SET ); | ||||
5022 | mbListStyleOrIdReset = true; | ||||
5023 | } | ||||
5024 | else if ( rWhich == RES_PARATR_OUTLINELEVEL ) | ||||
5025 | mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); | ||||
5026 | else if ( rWhich == RES_BACKGROUND ) | ||||
5027 | mrTextNode.ResetAttr( XATTR_FILL_FIRST, XATTR_FILL_LAST ); | ||||
5028 | |||||
5029 | if ( !bRemoveFromList ) | ||||
5030 | { | ||||
5031 | // RES_PARATR_LIST_LEVEL | ||||
5032 | mbUpdateListLevel = mbUpdateListLevel || | ||||
5033 | ( rWhich == RES_PARATR_LIST_LEVEL && | ||||
5034 | mrTextNode.HasAttrListLevel() ); | ||||
5035 | |||||
5036 | // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE | ||||
5037 | mbUpdateListRestart = mbUpdateListRestart || | ||||
5038 | ( rWhich == RES_PARATR_LIST_ISRESTART && | ||||
5039 | mrTextNode.IsListRestart() ) || | ||||
5040 | ( rWhich == RES_PARATR_LIST_RESTARTVALUE && | ||||
5041 | mrTextNode.HasAttrListRestartValue() ); | ||||
5042 | |||||
5043 | // RES_PARATR_LIST_ISCOUNTED | ||||
5044 | mbUpdateListCount = mbUpdateListCount || | ||||
5045 | ( rWhich == RES_PARATR_LIST_ISCOUNTED && | ||||
5046 | !mrTextNode.IsCountedInList() ); | ||||
5047 | } | ||||
5048 | } | ||||
5049 | } | ||||
5050 | |||||
5051 | if ( bRemoveFromList && mrTextNode.IsInList() ) | ||||
5052 | { | ||||
5053 | mrTextNode.RemoveFromList(); | ||||
5054 | } | ||||
5055 | } | ||||
5056 | |||||
5057 | HandleResetAttrAtTextNode::~HandleResetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE | ||||
5058 | { | ||||
5059 | if ( mbListStyleOrIdReset && !mrTextNode.IsInList() ) | ||||
5060 | { | ||||
5061 | // check, if in spite of the reset of the list style or the list id | ||||
5062 | // the paragraph still has to be added to a list. | ||||
5063 | if (mrTextNode.GetNumRule() && !mrTextNode.GetListId().isEmpty()) | ||||
5064 | { | ||||
5065 | // #i96062# | ||||
5066 | // If paragraph has no list level attribute set and list style | ||||
5067 | // is the outline style, apply outline level as the list level. | ||||
5068 | if ( !mrTextNode.HasAttrListLevel() && | ||||
5069 | mrTextNode.GetNumRule()->GetName()==SwNumRule::GetOutlineRuleName() && | ||||
5070 | mrTextNode.GetTextColl()->IsAssignedToListLevelOfOutlineStyle() ) | ||||
5071 | { | ||||
5072 | int nNewListLevel = mrTextNode.GetTextColl()->GetAssignedOutlineStyleLevel(); | ||||
5073 | if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL ) | ||||
5074 | { | ||||
5075 | mrTextNode.SetAttrListLevel( nNewListLevel ); | ||||
5076 | } | ||||
5077 | } | ||||
5078 | mrTextNode.AddToList(); | ||||
5079 | } | ||||
5080 | // #i70748# | ||||
5081 | // #i105562# | ||||
5082 | else | ||||
5083 | { | ||||
5084 | assert(!mrTextNode.GetpSwAttrSet()(static_cast <bool> (!mrTextNode.GetpSwAttrSet() || dynamic_cast <const SfxUInt16Item*>( &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL , false))) ? void (0) : __assert_fail ("!mrTextNode.GetpSwAttrSet() || dynamic_cast<const SfxUInt16Item*>( &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL, false))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 5086, __extension__ __PRETTY_FUNCTION__)) | ||||
5085 | || dynamic_cast<const SfxUInt16Item*>((static_cast <bool> (!mrTextNode.GetpSwAttrSet() || dynamic_cast <const SfxUInt16Item*>( &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL , false))) ? void (0) : __assert_fail ("!mrTextNode.GetpSwAttrSet() || dynamic_cast<const SfxUInt16Item*>( &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL, false))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 5086, __extension__ __PRETTY_FUNCTION__)) | ||||
5086 | &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL, false)))(static_cast <bool> (!mrTextNode.GetpSwAttrSet() || dynamic_cast <const SfxUInt16Item*>( &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL , false))) ? void (0) : __assert_fail ("!mrTextNode.GetpSwAttrSet() || dynamic_cast<const SfxUInt16Item*>( &mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL, false))" , "/home/maarten/src/libreoffice/core/sw/source/core/txtnode/ndtxt.cxx" , 5086, __extension__ __PRETTY_FUNCTION__)); | ||||
5087 | if (mrTextNode.GetpSwAttrSet() | ||||
5088 | && static_cast<const SfxUInt16Item&>( | ||||
5089 | mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL, false)).GetValue() > 0) | ||||
5090 | { | ||||
5091 | mrTextNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); | ||||
5092 | } | ||||
5093 | } | ||||
5094 | } | ||||
5095 | |||||
5096 | if ( !mrTextNode.IsInList() ) | ||||
5097 | return; | ||||
5098 | |||||
5099 | if ( mbUpdateListLevel ) | ||||
5100 | { | ||||
5101 | auto const nLevel(mrTextNode.GetAttrListLevel()); | ||||
5102 | mrTextNode.DoNum( | ||||
5103 | [nLevel](SwNodeNum & rNum) { rNum.SetLevelInListTree(nLevel); }); | ||||
5104 | } | ||||
5105 | |||||
5106 | if ( mbUpdateListRestart ) | ||||
5107 | { | ||||
5108 | mrTextNode.DoNum( | ||||
5109 | [](SwNodeNum & rNum) { | ||||
5110 | rNum.InvalidateMe(); | ||||
5111 | rNum.NotifyInvalidSiblings(); | ||||
5112 | }); | ||||
5113 | } | ||||
5114 | |||||
5115 | if ( mbUpdateListCount ) | ||||
5116 | { | ||||
5117 | mrTextNode.DoNum( | ||||
5118 | [](SwNodeNum & rNum) { rNum.InvalidateAndNotifyTree(); }); | ||||
5119 | } | ||||
5120 | } | ||||
5121 | // End of class <HandleResetAttrAtTextNode> | ||||
5122 | } | ||||
5123 | |||||
5124 | bool SwTextNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 ) | ||||
5125 | { | ||||
5126 | const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); | ||||
5127 | mbInSetOrResetAttr = true; | ||||
5128 | |||||
5129 | HandleResetAttrAtTextNode aHandleResetAttr( *this, nWhich1, nWhich2 ); | ||||
5130 | |||||
5131 | bool bRet = SwContentNode::ResetAttr( nWhich1, nWhich2 ); | ||||
5132 | |||||
5133 | mbInSetOrResetAttr = bOldIsSetOrResetAttr; | ||||
5134 | |||||
5135 | return bRet; | ||||
5136 | } | ||||
5137 | |||||
5138 | bool SwTextNode::ResetAttr( const std::vector<sal_uInt16>& rWhichArr ) | ||||
5139 | { | ||||
5140 | const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); | ||||
5141 | mbInSetOrResetAttr = true; | ||||
5142 | |||||
5143 | HandleResetAttrAtTextNode aHandleResetAttr( *this, rWhichArr ); | ||||
5144 | |||||
5145 | bool bRet = SwContentNode::ResetAttr( rWhichArr ); | ||||
5146 | |||||
5147 | mbInSetOrResetAttr = bOldIsSetOrResetAttr; | ||||
5148 | |||||
5149 | return bRet; | ||||
5150 | } | ||||
5151 | |||||
5152 | sal_uInt16 SwTextNode::ResetAllAttr() | ||||
5153 | { | ||||
5154 | const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); | ||||
5155 | mbInSetOrResetAttr = true; | ||||
5156 | |||||
5157 | HandleResetAttrAtTextNode aHandleResetAttr( *this ); | ||||
5158 | |||||
5159 | const sal_uInt16 nRet = SwContentNode::ResetAllAttr(); | ||||
5160 | |||||
5161 | mbInSetOrResetAttr = bOldIsSetOrResetAttr; | ||||
5162 | |||||
5163 | return nRet; | ||||
5164 | } | ||||
5165 | |||||
5166 | void SwTextNode::dumpAsXml(xmlTextWriterPtr pWriter) const | ||||
5167 | { | ||||
5168 | xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("SwTextNode")); | ||||
5169 | xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST(xmlChar *)("ptr"), "%p", this); | ||||
5170 | xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("index"), BAD_CAST(xmlChar *)(OString::number(GetIndex()).getStr())); | ||||
5171 | |||||
5172 | OUString sText = GetText(); | ||||
5173 | for (int i = 0; i < 32; ++i) | ||||
5174 | sText = sText.replace(i, '*'); | ||||
5175 | xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("m_Text")); | ||||
5176 | xmlTextWriterWriteString(pWriter, BAD_CAST(xmlChar *)(sText.toUtf8().getStr())); | ||||
5177 | xmlTextWriterEndElement(pWriter); | ||||
5178 | |||||
5179 | if (GetFormatColl()) | ||||
5180 | { | ||||
5181 | xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("SwTextFormatColl")); | ||||
5182 | xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("name"), BAD_CAST(xmlChar *)(GetFormatColl()->GetName().toUtf8().getStr())); | ||||
5183 | xmlTextWriterEndElement(pWriter); | ||||
5184 | } | ||||
5185 | |||||
5186 | if (HasSwAttrSet()) | ||||
5187 | { | ||||
5188 | xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("SwAttrSet")); | ||||
5189 | GetSwAttrSet().dumpAsXml(pWriter); | ||||
5190 | xmlTextWriterEndElement(pWriter); | ||||
5191 | } | ||||
5192 | |||||
5193 | if (HasHints()) | ||||
5194 | { | ||||
5195 | xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("SwpHints")); | ||||
5196 | const SwpHints& rHints = GetSwpHints(); | ||||
5197 | for (size_t i = 0; i < rHints.Count(); ++i) | ||||
5198 | rHints.Get(i)->dumpAsXml(pWriter); | ||||
5199 | xmlTextWriterEndElement(pWriter); | ||||
5200 | } | ||||
5201 | |||||
5202 | if (GetNumRule()) | ||||
5203 | GetNumRule()->dumpAsXml(pWriter); | ||||
5204 | |||||
5205 | xmlTextWriterEndElement(pWriter); | ||||
5206 | } | ||||
5207 | |||||
5208 | sal_uInt32 SwTextNode::GetRsid( sal_Int32 nStt, sal_Int32 nEnd ) const | ||||
5209 | { | ||||
5210 | SfxItemSet aSet( const_cast<SfxItemPool&>(static_cast<SfxItemPool const &>(GetDoc().GetAttrPool())), svl::Items<RES_CHRATR_RSID, RES_CHRATR_RSID>{} ); | ||||
5211 | if (GetParaAttr(aSet, nStt, nEnd)) | ||||
5212 | { | ||||
5213 | const SvxRsidItem* pRsid = aSet.GetItem<SvxRsidItem>(RES_CHRATR_RSID); | ||||
5214 | if( pRsid ) | ||||
5215 | return pRsid->GetValue(); | ||||
5216 | } | ||||
5217 | |||||
5218 | return 0; | ||||
5219 | } | ||||
5220 | |||||
5221 | sal_uInt32 SwTextNode::GetParRsid() const | ||||
5222 | { | ||||
5223 | return reinterpret_cast<const SvxRsidItem&>(GetAttr( RES_PARATR_RSID )).GetValue(); | ||||
5224 | } | ||||
5225 | |||||
5226 | bool SwTextNode::CompareParRsid( const SwTextNode &rTextNode ) const | ||||
5227 | { | ||||
5228 | sal_uInt32 nThisRsid = GetParRsid(); | ||||
5229 | sal_uInt32 nRsid = rTextNode.GetParRsid(); | ||||
5230 | |||||
5231 | return nThisRsid == nRsid; | ||||
5232 | } | ||||
5233 | |||||
5234 | bool SwTextNode::CompareRsid( const SwTextNode &rTextNode, sal_Int32 nStt1, sal_Int32 nStt2 ) const | ||||
5235 | { | ||||
5236 | sal_uInt32 nThisRsid = GetRsid( nStt1, nStt1 ); | ||||
5237 | sal_uInt32 nRsid = rTextNode.GetRsid( nStt2, nStt2 ); | ||||
5238 | |||||
5239 | return nThisRsid == nRsid; | ||||
5240 | } | ||||
5241 | |||||
5242 | // sw::Metadatable | ||||
5243 | ::sfx2::IXmlIdRegistry& SwTextNode::GetRegistry() | ||||
5244 | { | ||||
5245 | return GetDoc().GetXmlIdRegistry(); | ||||
5246 | } | ||||
5247 | |||||
5248 | bool SwTextNode::IsInClipboard() const | ||||
5249 | { | ||||
5250 | return GetDoc().IsClipBoard(); | ||||
5251 | } | ||||
5252 | |||||
5253 | bool SwTextNode::IsInUndo() const | ||||
5254 | { | ||||
5255 | return GetDoc().GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); | ||||
5256 | } | ||||
5257 | |||||
5258 | bool SwTextNode::IsInContent() const | ||||
5259 | { | ||||
5260 | return !GetDoc().IsInHeaderFooter( SwNodeIndex(*this) ); | ||||
5261 | } | ||||
5262 | |||||
5263 | void SwTextNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint ) | ||||
5264 | { | ||||
5265 | if (auto pLegacyHint = dynamic_cast<const sw::LegacyModifyHint*>(&rHint)) | ||||
5266 | { | ||||
5267 | bool bWasNotifiable = m_bNotifiable; | ||||
5268 | m_bNotifiable = false; | ||||
5269 | |||||
5270 | const auto pOldValue = pLegacyHint->m_pOld; | ||||
5271 | const auto pNewValue = pLegacyHint->m_pNew; | ||||
5272 | // Override Modify so that deleting styles works properly (outline | ||||
5273 | // numbering!). | ||||
5274 | // Never call ChgTextCollUpdateNum for Nodes in Undo. | ||||
5275 | if( pOldValue | ||||
5276 | && pNewValue | ||||
5277 | && RES_FMT_CHG == pOldValue->Which() | ||||
5278 | && GetRegisteredIn() == static_cast<const SwFormatChg*>(pNewValue)->pChangedFormat | ||||
5279 | && GetNodes().IsDocNodes() ) | ||||
5280 | { | ||||
5281 | ChgTextCollUpdateNum( | ||||
5282 | static_cast<const SwTextFormatColl*>(static_cast<const SwFormatChg*>(pOldValue)->pChangedFormat), | ||||
5283 | static_cast<const SwTextFormatColl*>(static_cast<const SwFormatChg*>(pNewValue)->pChangedFormat) ); | ||||
5284 | } | ||||
5285 | |||||
5286 | // reset fill information | ||||
5287 | if (maFillAttributes && pNewValue) | ||||
5288 | { | ||||
5289 | const sal_uInt16 nWhich = pNewValue->Which(); | ||||
5290 | bool bReset(RES_FMT_CHG == nWhich); // ..on format change (e.g. style changed) | ||||
5291 | |||||
5292 | if(!bReset && RES_ATTRSET_CHG == nWhich) // ..on ItemChange from DrawingLayer FillAttributes | ||||
5293 | { | ||||
5294 | SfxItemIter aIter(*static_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()); | ||||
5295 | |||||
5296 | for(const SfxPoolItem* pItem = aIter.GetCurItem(); pItem && !bReset; pItem = aIter.NextItem()) | ||||
5297 | { | ||||
5298 | bReset = !IsInvalidItem(pItem) && pItem->Which() >= XATTR_FILL_FIRST && pItem->Which() <= XATTR_FILL_LAST; | ||||
5299 | } | ||||
5300 | } | ||||
5301 | |||||
5302 | if(bReset) | ||||
5303 | { | ||||
5304 | maFillAttributes.reset(); | ||||
5305 | } | ||||
5306 | } | ||||
5307 | |||||
5308 | if ( !mbInSetOrResetAttr ) | ||||
5309 | { | ||||
5310 | HandleModifyAtTextNode( *this, pOldValue, pNewValue ); | ||||
5311 | } | ||||
5312 | |||||
5313 | SwContentNode::SwClientNotify(rModify, rHint); | ||||
5314 | |||||
5315 | SwDoc& rDoc = GetDoc(); | ||||
5316 | // #125329# - assure that text node is in document nodes array | ||||
5317 | if ( !rDoc.IsInDtor() && &rDoc.GetNodes() == &GetNodes() ) | ||||
5318 | { | ||||
5319 | rDoc.GetNodes().UpdateOutlineNode(*this); | ||||
5320 | } | ||||
5321 | |||||
5322 | m_bNotifiable = bWasNotifiable; | ||||
5323 | |||||
5324 | if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which())) | ||||
5325 | { // invalidate cached uno object | ||||
5326 | SetXParagraph(css::uno::Reference<css::text::XTextContent>(nullptr)); | ||||
5327 | } | ||||
5328 | } | ||||
5329 | else if (dynamic_cast<const SwAttrHint*>(&rHint)) | ||||
5330 | { | ||||
5331 | if (&rModify == GetRegisteredIn()) | ||||
5332 | ChkCondColl(); | ||||
5333 | } | ||||
5334 | } | ||||
5335 | |||||
5336 | uno::Reference< rdf::XMetadatable > | ||||
5337 | SwTextNode::MakeUnoObject() | ||||
5338 | { | ||||
5339 | const uno::Reference<rdf::XMetadatable> xMeta( | ||||
5340 | SwXParagraph::CreateXParagraph(GetDoc(), this), uno::UNO_QUERY); | ||||
5341 | return xMeta; | ||||
5342 | } | ||||
5343 | |||||
5344 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwTextNode::getSdrAllFillAttributesHelper() const | ||||
5345 | { | ||||
5346 | // create SdrAllFillAttributesHelper on demand | ||||
5347 | if(!maFillAttributes) | ||||
5348 | { | ||||
5349 | const_cast< SwTextNode* >(this)->maFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(GetSwAttrSet()); | ||||
5350 | } | ||||
5351 | |||||
5352 | return maFillAttributes; | ||||
5353 | } | ||||
5354 | |||||
5355 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_SW_INC_NODE_HXX | |||
21 | #define INCLUDED_SW_INC_NODE_HXX | |||
22 | ||||
23 | #include <sal/types.h> | |||
24 | ||||
25 | #include "swdllapi.h" | |||
26 | #include "ndarr.hxx" | |||
27 | #include "ndtyp.hxx" | |||
28 | #include "index.hxx" | |||
29 | #include "fmtcol.hxx" | |||
30 | ||||
31 | #include <memory> | |||
32 | #include <vector> | |||
33 | ||||
34 | class SwContentFrame; | |||
35 | class SwContentNode; | |||
36 | class SwDoc; | |||
37 | class SwEndNode; | |||
38 | class SwFrame; | |||
39 | class SwFrameFormat; | |||
40 | class SwGrfNode; | |||
41 | class SwNoTextNode; | |||
42 | class SwNodeIndex; | |||
43 | class SwOLENode; | |||
44 | class SwRect; | |||
45 | class SwSection; | |||
46 | class SwSectionFormat; | |||
47 | class SwTOXBase; | |||
48 | class SwSectionNode; | |||
49 | class SwStartNode; | |||
50 | class SwTabFrame; | |||
51 | class SwRootFrame; | |||
52 | class SwTable; | |||
53 | class SwTableNode; | |||
54 | class SwTableBox; | |||
55 | class SwTextNode; | |||
56 | class SwPageDesc; | |||
57 | class SwViewShell; | |||
58 | struct SwPosition; | |||
59 | class IStyleAccess; | |||
60 | class IDocumentSettingAccess; | |||
61 | class IDocumentDeviceAccess; | |||
62 | class IDocumentMarkAccess; | |||
63 | class IDocumentRedlineAccess; | |||
64 | class IDocumentStylePoolAccess; | |||
65 | class IDocumentLinksAdministration; | |||
66 | class IDocumentFieldsAccess; | |||
67 | class IDocumentContentOperations; | |||
68 | class IDocumentListItems; | |||
69 | class Point; | |||
70 | enum class SvxFrameDirection; | |||
71 | typedef std::vector<SwOLENode*> SwOLENodes; // docary.hxx | |||
72 | ||||
73 | namespace drawinglayer::attribute { | |||
74 | class SdrAllFillAttributesHelper; | |||
75 | typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr; | |||
76 | } | |||
77 | ||||
78 | /// Base class of the Writer document model elements. | |||
79 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwNode | |||
80 | : private BigPtrEntry | |||
81 | { | |||
82 | friend class SwNodes; | |||
83 | ||||
84 | SwNodeType m_nNodeType; | |||
85 | ||||
86 | /// For text nodes: level of auto format. Was put here because we had still free bits. | |||
87 | sal_uInt8 m_nAFormatNumLvl : 3; | |||
88 | bool m_bIgnoreDontExpand : 1; ///< for Text Attributes - ignore the flag | |||
89 | ||||
90 | public: | |||
91 | /// sw_redlinehide: redline node merge state | |||
92 | enum class Merge { None, First, NonFirst, Hidden }; | |||
93 | bool IsCreateFrameWhenHidingRedlines() const { | |||
94 | return m_eMerge == Merge::None || m_eMerge == Merge::First; | |||
95 | } | |||
96 | void SetRedlineMergeFlag(Merge const eMerge) { m_eMerge = eMerge; } | |||
97 | Merge GetRedlineMergeFlag() const { return m_eMerge; } | |||
98 | private: | |||
99 | Merge m_eMerge; | |||
100 | ||||
101 | #ifdef DBG_UTIL | |||
102 | static long s_nSerial; | |||
103 | long m_nSerial; | |||
104 | #endif | |||
105 | ||||
106 | /// all SwFrameFormat that are anchored at the node | |||
107 | /// invariant: SwFrameFormat is in the list iff | |||
108 | /// SwFrameFormat::GetAnchor().GetContentAnchor() points to this node | |||
109 | std::unique_ptr<std::vector<SwFrameFormat*>> m_pAnchoredFlys; | |||
110 | ||||
111 | protected: | |||
112 | SwStartNode* m_pStartOfSection; | |||
113 | ||||
114 | SwNode( const SwNodeIndex &rWhere, const SwNodeType nNodeId ); | |||
115 | ||||
116 | /// for the initial StartNode | |||
117 | SwNode( SwNodes& rNodes, sal_uLong nPos, const SwNodeType nNodeId ); | |||
118 | ||||
119 | public: | |||
120 | /** the = 0 forces the class to be an abstract base class, but the dtor can be still called | |||
121 | from subclasses */ | |||
122 | virtual ~SwNode() override = 0; | |||
123 | ||||
124 | #ifdef DBG_UTIL | |||
125 | long GetSerial() const { return m_nSerial; } | |||
126 | #endif | |||
127 | ||||
128 | sal_uInt16 GetSectionLevel() const; | |||
129 | ||||
130 | inline sal_uLong StartOfSectionIndex() const; | |||
131 | const SwStartNode* StartOfSectionNode() const { return m_pStartOfSection; } | |||
132 | SwStartNode* StartOfSectionNode() { return m_pStartOfSection; } | |||
133 | ||||
134 | inline sal_uLong EndOfSectionIndex() const; | |||
135 | inline const SwEndNode* EndOfSectionNode() const; | |||
136 | inline SwEndNode* EndOfSectionNode(); | |||
137 | ||||
138 | sal_uInt8 GetAutoFormatLvl() const { return m_nAFormatNumLvl; } | |||
139 | void SetAutoFormatLvl( sal_uInt8 nVal ) { m_nAFormatNumLvl = nVal; } | |||
140 | ||||
141 | bool IsIgnoreDontExpand() const { return m_bIgnoreDontExpand; } | |||
142 | void SetIgnoreDontExpand( bool bNew ) { m_bIgnoreDontExpand = bNew; } | |||
143 | ||||
144 | SwNodeType GetNodeType() const { return m_nNodeType; } | |||
145 | ||||
146 | inline SwStartNode *GetStartNode(); | |||
147 | inline const SwStartNode *GetStartNode() const; | |||
148 | inline SwContentNode *GetContentNode(); | |||
149 | inline const SwContentNode *GetContentNode() const; | |||
150 | inline SwEndNode *GetEndNode(); | |||
151 | inline const SwEndNode *GetEndNode() const; | |||
152 | inline SwTextNode *GetTextNode(); | |||
153 | inline const SwTextNode *GetTextNode() const; | |||
154 | inline SwOLENode *GetOLENode(); | |||
155 | inline const SwOLENode *GetOLENode() const; | |||
156 | inline SwNoTextNode *GetNoTextNode(); | |||
157 | inline const SwNoTextNode *GetNoTextNode() const; | |||
158 | inline SwGrfNode *GetGrfNode(); | |||
159 | inline const SwGrfNode *GetGrfNode() const; | |||
160 | inline SwTableNode *GetTableNode(); | |||
161 | inline const SwTableNode *GetTableNode() const; | |||
162 | inline SwSectionNode *GetSectionNode(); | |||
163 | inline const SwSectionNode *GetSectionNode() const; | |||
164 | ||||
165 | inline bool IsStartNode() const; | |||
166 | inline bool IsContentNode() const; | |||
167 | inline bool IsEndNode() const; | |||
168 | inline bool IsTextNode() const; | |||
169 | inline bool IsTableNode() const; | |||
170 | inline bool IsSectionNode() const; | |||
171 | inline bool IsOLENode() const; | |||
172 | inline bool IsNoTextNode() const; | |||
173 | inline bool IsGrfNode() const; | |||
174 | ||||
175 | /** | |||
176 | Checks if this node is in redlines. | |||
177 | ||||
178 | @retval true this node is in redlines | |||
179 | @retval false else | |||
180 | */ | |||
181 | bool IsInRedlines() const; | |||
182 | ||||
183 | /** Search table node, in which it is. If it is in no table | |||
184 | @return 0. */ | |||
185 | SwTableNode *FindTableNode(); | |||
186 | inline const SwTableNode *FindTableNode() const; | |||
187 | ||||
188 | /** Search section node, in which it is. If it is in no section | |||
189 | @return 0. */ | |||
190 | SwSectionNode *FindSectionNode(); | |||
191 | inline const SwSectionNode *FindSectionNode() const; | |||
192 | ||||
193 | SwStartNode* FindSttNodeByType( SwStartNodeType eTyp ); | |||
194 | inline const SwStartNode* FindSttNodeByType( SwStartNodeType eTyp ) const; | |||
195 | ||||
196 | const SwStartNode* FindTableBoxStartNode() const | |||
197 | { return FindSttNodeByType( SwTableBoxStartNode ); } | |||
198 | const SwStartNode* FindFlyStartNode() const | |||
199 | { return FindSttNodeByType( SwFlyStartNode ); } | |||
200 | const SwStartNode* FindFootnoteStartNode() const | |||
201 | { return FindSttNodeByType( SwFootnoteStartNode ); } | |||
202 | const SwStartNode* FindHeaderStartNode() const | |||
203 | { return FindSttNodeByType( SwHeaderStartNode ); } | |||
204 | const SwStartNode* FindFooterStartNode() const | |||
205 | { return FindSttNodeByType( SwFooterStartNode ); } | |||
206 | ||||
207 | /// Node is in which nodes-array/doc? | |||
208 | inline SwNodes& GetNodes(); | |||
209 | inline const SwNodes& GetNodes() const; | |||
210 | ||||
211 | SwDoc& GetDoc() | |||
212 | { | |||
213 | return GetNodes().GetDoc(); | |||
214 | } | |||
215 | ||||
216 | const SwDoc& GetDoc() const | |||
217 | { | |||
218 | return GetNodes().GetDoc(); | |||
219 | } | |||
220 | ||||
221 | /** Provides access to the document setting interface | |||
222 | */ | |||
223 | const IDocumentSettingAccess* getIDocumentSettingAccess() const; | |||
224 | ||||
225 | /** Provides access to the document device interface | |||
226 | */ | |||
227 | const IDocumentDeviceAccess& getIDocumentDeviceAccess() const; | |||
228 | ||||
229 | /** Provides access to the document bookmark interface | |||
230 | */ | |||
231 | const IDocumentMarkAccess* getIDocumentMarkAccess() const; | |||
232 | ||||
233 | /** Provides access to the document redline interface | |||
234 | */ | |||
235 | const IDocumentRedlineAccess& getIDocumentRedlineAccess() const; | |||
236 | ||||
237 | /** Provides access to the document style pool interface | |||
238 | */ | |||
239 | const IDocumentStylePoolAccess& getIDocumentStylePoolAccess() const; | |||
240 | ||||
241 | /** Provides access to the document draw model interface | |||
242 | */ | |||
243 | const IDocumentDrawModelAccess& getIDocumentDrawModelAccess() const; | |||
244 | ||||
245 | /** Provides access to the document layout interface | |||
246 | */ | |||
247 | const IDocumentLayoutAccess& getIDocumentLayoutAccess() const; | |||
248 | IDocumentLayoutAccess& getIDocumentLayoutAccess(); | |||
249 | ||||
250 | /** Provides access to the document links administration interface | |||
251 | */ | |||
252 | const IDocumentLinksAdministration& getIDocumentLinksAdministration() const; | |||
253 | IDocumentLinksAdministration& getIDocumentLinksAdministration(); | |||
254 | ||||
255 | /** Provides access to the document fields administration interface | |||
256 | */ | |||
257 | const IDocumentFieldsAccess& getIDocumentFieldsAccess() const; | |||
258 | IDocumentFieldsAccess& getIDocumentFieldsAccess(); | |||
259 | ||||
260 | /** Provides access to the document content operations interface | |||
261 | */ | |||
262 | IDocumentContentOperations& getIDocumentContentOperations(); | |||
263 | ||||
264 | /** Provides access to the document automatic styles interface | |||
265 | */ | |||
266 | IStyleAccess& getIDocumentStyleAccess(); | |||
267 | ||||
268 | /** Provides access to the document's numbered items interface */ | |||
269 | IDocumentListItems& getIDocumentListItems(); | |||
270 | ||||
271 | /// Is node in the visible area of the Shell? | |||
272 | bool IsInVisibleArea( SwViewShell const * pSh ) const; | |||
273 | /// Is node in a protected area? | |||
274 | bool IsInProtectSect() const; | |||
275 | /** Is node in something that is protected (range, frame, | |||
276 | table cells ... including anchor in case of frames or footnotes)? */ | |||
277 | bool IsProtect() const; | |||
278 | ||||
279 | /** Search PageDesc with which this node is formatted. If layout is existent | |||
280 | search over layout, else only the hard way is left: search over the nodes | |||
281 | to the front!! */ | |||
282 | const SwPageDesc* FindPageDesc( size_t* pPgDescNdIdx = nullptr ) const; | |||
283 | ||||
284 | /// If node is in a fly return the respective format. | |||
285 | SwFrameFormat* GetFlyFormat() const; | |||
286 | ||||
287 | /// If node is in a table return the respective table box. | |||
288 | SwTableBox* GetTableBox() const; | |||
289 | ||||
290 | sal_uLong GetIndex() const { return GetPos(); } | |||
291 | ||||
292 | const SwTextNode* FindOutlineNodeOfLevel(sal_uInt8 nLvl, SwRootFrame const* pLayout = nullptr) const; | |||
293 | ||||
294 | sal_uInt8 HasPrevNextLayNode() const; | |||
295 | ||||
296 | std::vector<SwFrameFormat *> const* GetAnchoredFlys() const { return m_pAnchoredFlys.get(); } | |||
297 | void AddAnchoredFly(SwFrameFormat *); | |||
298 | void RemoveAnchoredFly(SwFrameFormat *); | |||
299 | ||||
300 | /** | |||
301 | * Dumps the node structure to the given destination (file nodes.xml in the current directory by default) | |||
302 | */ | |||
303 | virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; | |||
304 | ||||
305 | private: | |||
306 | SwNode( const SwNode & rNodes ) = delete; | |||
307 | SwNode & operator= ( const SwNode & rNodes ) = delete; | |||
308 | }; | |||
309 | ||||
310 | /// Starts a section of nodes in the document model. | |||
311 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwStartNode: public SwNode | |||
312 | { | |||
313 | friend class SwNode; | |||
314 | friend class SwNodes; | |||
315 | friend class SwEndNode; ///< to set the theEndOfSection !! | |||
316 | ||||
317 | SwEndNode* m_pEndOfSection; | |||
318 | SwStartNodeType m_eStartNodeType; | |||
319 | ||||
320 | /// for the initial StartNode | |||
321 | SwStartNode( SwNodes& rNodes, sal_uLong nPos ); | |||
322 | ||||
323 | protected: | |||
324 | SwStartNode( const SwNodeIndex &rWhere, | |||
325 | const SwNodeType nNodeType = SwNodeType::Start, | |||
326 | SwStartNodeType = SwNormalStartNode ); | |||
327 | public: | |||
328 | SwStartNodeType GetStartNodeType() const { return m_eStartNodeType; } | |||
329 | ||||
330 | /// Call ChkCondcoll to all ContentNodes of section. | |||
331 | void CheckSectionCondColl() const; | |||
332 | ||||
333 | virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; | |||
334 | ||||
335 | private: | |||
336 | SwStartNode( const SwStartNode & rNode ) = delete; | |||
337 | SwStartNode & operator= ( const SwStartNode & rNode ) = delete; | |||
338 | }; | |||
339 | ||||
340 | /// Ends a section of nodes in the document model. | |||
341 | class SwEndNode : public SwNode | |||
342 | { | |||
343 | friend class SwNodes; | |||
344 | friend class SwTableNode; ///< To enable creation of its EndNote. | |||
345 | friend class SwSectionNode; ///< To enable creation of its EndNote. | |||
346 | ||||
347 | /// for the initial StartNode | |||
348 | SwEndNode( SwNodes& rNodes, sal_uLong nPos, SwStartNode& rSttNd ); | |||
349 | ||||
350 | protected: | |||
351 | SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd ); | |||
352 | ||||
353 | private: | |||
354 | SwEndNode( const SwEndNode & rNode ) = delete; | |||
355 | SwEndNode & operator= ( const SwEndNode & rNode ) = delete; | |||
356 | }; | |||
357 | ||||
358 | // SwContentNode | |||
359 | ||||
360 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwContentNode: public sw::BroadcastingModify, public SwNode, public SwIndexReg | |||
361 | { | |||
362 | ||||
363 | sw::WriterMultiListener m_aCondCollListener; | |||
364 | SwFormatColl* m_pCondColl; | |||
365 | mutable bool mbSetModifyAtAttr; | |||
366 | ||||
367 | protected: | |||
368 | SwContentNode( const SwNodeIndex &rWhere, const SwNodeType nNodeType, | |||
369 | SwFormatColl *pFormatColl ); | |||
370 | /** the = 0 forces the class to be an abstract base class, but the dtor can be still called | |||
371 | from subclasses */ | |||
372 | virtual ~SwContentNode() override = 0; | |||
373 | ||||
374 | /** Attribute-set for all auto attributes of a ContentNode. | |||
375 | (e.g. TextNode or NoTextNode). */ | |||
376 | std::shared_ptr<const SfxItemSet> mpAttrSet; | |||
377 | ||||
378 | /// Make respective nodes create the specific AttrSets. | |||
379 | virtual void NewAttrSet( SwAttrPool& ) = 0; | |||
380 | ||||
381 | /** There some functions that like to remove items from the internal | |||
382 | SwAttrSet (handle): */ | |||
383 | sal_uInt16 ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds ); | |||
384 | ||||
385 | virtual void SwClientNotify( const SwModify&, const SfxHint& rHint) override; | |||
386 | ||||
387 | public: | |||
388 | ||||
389 | /** MakeFrame will be called for a certain layout | |||
390 | pSib is another SwFrame of the same layout (e.g. the SwRootFrame itself, a sibling, the parent) */ | |||
391 | virtual SwContentFrame *MakeFrame( SwFrame* pSib ) = 0; | |||
392 | ||||
393 | virtual SwContentNode *JoinNext(); | |||
394 | /** Is it possible to join two nodes? | |||
395 | In pIdx the second position can be returned. */ | |||
396 | bool CanJoinNext( SwNodeIndex* pIdx =nullptr ) const; | |||
397 | bool CanJoinPrev( SwNodeIndex* pIdx =nullptr ) const; | |||
398 | ||||
399 | void MakeStartIndex( SwIndex * pIdx ) { pIdx->Assign( this, 0 ); } | |||
400 | void MakeEndIndex( SwIndex * pIdx ) { pIdx->Assign( this, Len() ); } | |||
401 | ||||
402 | bool GoNext(SwIndex *, sal_uInt16 nMode ) const; | |||
403 | bool GoPrevious(SwIndex *, sal_uInt16 nMode ) const; | |||
404 | ||||
405 | /// @see GetFrameOfModify | |||
406 | SwContentFrame *getLayoutFrame( const SwRootFrame*, | |||
407 | const SwPosition *pPos = nullptr, | |||
408 | std::pair<Point, bool> const* pViewPosAndCalcFrame = nullptr) const; | |||
409 | /** @return the real size of the frame or an empty rectangle if | |||
410 | no layout exists. Needed for export filters. */ | |||
411 | SwRect FindLayoutRect( const bool bPrtArea = false, | |||
412 | const Point* pPoint = nullptr ) const; | |||
413 | SwRect FindPageFrameRect() const; | |||
414 | ||||
415 | /** Method creates all views of document for given node. The content | |||
416 | frames that are created are put in the respective layout. */ | |||
417 | void MakeFramesForAdjacentContentNode(SwContentNode& rNode); | |||
418 | ||||
419 | /** Method deletes all views of document for the node. The content- | |||
420 | frames are removed from the respective layout. | |||
421 | */ | |||
422 | void DelFrames(SwRootFrame const* pLayout); | |||
423 | ||||
424 | /** @return count of elements of node content. Default is 1. | |||
425 | There are differences between text node and formula node. */ | |||
426 | virtual sal_Int32 Len() const; | |||
427 | ||||
428 | virtual SwContentNode* MakeCopy(SwDoc&, const SwNodeIndex&, bool bNewFrames) const = 0; | |||
429 | ||||
430 | /// Get information from Client. | |||
431 | virtual bool GetInfo( SfxPoolItem& ) const override; | |||
432 | ||||
433 | /// SS for PoolItems: hard attributation. | |||
434 | ||||
435 | /// If bInParent is FALSE search for attribute only in this node. | |||
436 | const SfxPoolItem& GetAttr( sal_uInt16 nWhich, bool bInParent=true ) const; | |||
437 | bool GetAttr( SfxItemSet& rSet ) const; | |||
438 | /// made virtual | |||
439 | virtual bool SetAttr( const SfxPoolItem& ); | |||
440 | virtual bool SetAttr( const SfxItemSet& rSet ); | |||
441 | virtual bool ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 = 0 ); | |||
442 | virtual bool ResetAttr( const std::vector<sal_uInt16>& rWhichArr ); | |||
443 | virtual sal_uInt16 ResetAllAttr(); | |||
444 | ||||
445 | /// Obtains attribute that is not delivered via conditional style! | |||
446 | const SfxPoolItem* GetNoCondAttr( sal_uInt16 nWhich, bool bInParents ) const; | |||
447 | ||||
448 | /** Does node has already its own auto-attributes? | |||
449 | Access to SwAttrSet. */ | |||
450 | inline const SwAttrSet &GetSwAttrSet() const; | |||
451 | const SwAttrSet *GetpSwAttrSet() const { return static_cast<const SwAttrSet*>(mpAttrSet.get()); } | |||
452 | bool HasSwAttrSet() const { return mpAttrSet != nullptr; } | |||
453 | ||||
454 | virtual SwFormatColl* ChgFormatColl( SwFormatColl* ); | |||
455 | SwFormatColl* GetFormatColl() const { return const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn())); } | |||
456 | ||||
457 | //FEATURE::CONDCOLL | |||
458 | inline SwFormatColl& GetAnyFormatColl() const; | |||
459 | void SetCondFormatColl( SwFormatColl* ); | |||
460 | inline SwFormatColl* GetCondFormatColl() const; | |||
461 | ||||
462 | bool IsAnyCondition( SwCollCondition& rTmp ) const; | |||
463 | void ChkCondColl(); | |||
464 | //FEATURE::CONDCOLL | |||
465 | ||||
466 | /** Invalidates NumRule at the node. NumRule is updated | |||
467 | on EndAction of a Shell at the latest. */ | |||
468 | bool InvalidateNumRule(); | |||
469 | ||||
470 | /** determines the text direction for a certain | |||
471 | position. @return -1, if text direction could *not* be determined. */ | |||
472 | SvxFrameDirection GetTextDirection( const SwPosition& rPos, | |||
473 | const Point* pPt ) const; | |||
474 | ||||
475 | void SetModifyAtAttr( bool bSetModifyAtAttr ) const { mbSetModifyAtAttr = bSetModifyAtAttr; } | |||
476 | bool GetModifyAtAttr() const { return mbSetModifyAtAttr; } | |||
477 | ||||
478 | static std::unique_ptr<SwOLENodes> CreateOLENodesArray( const SwFormatColl& rColl, bool bOnlyWithInvalidSize ); | |||
479 | ||||
480 | // Access to DrawingLayer FillAttributes in a preprocessed form for primitive usage | |||
481 | virtual drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const; | |||
482 | ||||
483 | virtual void ModifyNotification(const SfxPoolItem* pOld, const SfxPoolItem* pNew) override | |||
484 | { | |||
485 | SwClientNotify(*this, sw::LegacyModifyHint(pOld, pNew)); | |||
486 | } | |||
487 | ||||
488 | private: | |||
489 | SwContentNode( const SwContentNode & rNode ) = delete; | |||
490 | SwContentNode & operator= ( const SwContentNode & rNode ) = delete; | |||
491 | }; | |||
492 | ||||
493 | // SwTableNode | |||
494 | ||||
495 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwTableNode : public SwStartNode, public sw::BroadcastingModify | |||
496 | { | |||
497 | friend class SwNodes; | |||
498 | std::unique_ptr<SwTable> m_pTable; | |||
499 | protected: | |||
500 | virtual ~SwTableNode() override; | |||
501 | ||||
502 | public: | |||
503 | SwTableNode( const SwNodeIndex & ); | |||
504 | ||||
505 | const SwTable& GetTable() const { return *m_pTable; } | |||
506 | SwTable& GetTable() { return *m_pTable; } | |||
507 | SwTabFrame *MakeFrame( SwFrame* ); | |||
508 | ||||
509 | /// Creates the frms for the table node (i.e. the TabFrames). | |||
510 | void MakeOwnFrames(SwNodeIndex* pIdxBehind); | |||
511 | ||||
512 | /** Method deletes all views of document for the node. | |||
513 | The content frames are removed from the respective layout. */ | |||
514 | void DelFrames(SwRootFrame const* pLayout = nullptr); | |||
515 | ||||
516 | /** Method creates all views of the document for the previous node. | |||
517 | The content frames that are created are put into the respective layout. */ | |||
518 | void MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx); | |||
519 | ||||
520 | SwTableNode* MakeCopy( SwDoc&, const SwNodeIndex& ) const; | |||
521 | void SetNewTable( std::unique_ptr<SwTable> , bool bNewFrames=true ); | |||
522 | ||||
523 | // Removes redline objects that relate to this table from the 'Extra Redlines' table | |||
524 | void RemoveRedlines(); | |||
525 | ||||
526 | private: | |||
527 | SwTableNode( const SwTableNode & rNode ) = delete; | |||
528 | SwTableNode & operator= ( const SwTableNode & rNode ) = delete; | |||
529 | }; | |||
530 | ||||
531 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwSectionNode | |||
532 | : public SwStartNode | |||
533 | { | |||
534 | friend class SwNodes; | |||
535 | ||||
536 | private: | |||
537 | SwSectionNode(const SwSectionNode&) = delete; | |||
538 | SwSectionNode& operator=(const SwSectionNode&) = delete; | |||
539 | ||||
540 | std::unique_ptr<SwSection> const m_pSection; | |||
541 | ||||
542 | protected: | |||
543 | virtual ~SwSectionNode() override; | |||
544 | ||||
545 | public: | |||
546 | SwSectionNode(SwNodeIndex const&, | |||
547 | SwSectionFormat & rFormat, SwTOXBase const*const pTOXBase); | |||
548 | ||||
549 | const SwSection& GetSection() const { return *m_pSection; } | |||
550 | SwSection& GetSection() { return *m_pSection; } | |||
551 | ||||
552 | SwFrame *MakeFrame( SwFrame* ); | |||
553 | ||||
554 | /** Creates the frms for the SectionNode (i.e. the SectionFrames). | |||
555 | On default the frames are created until the end of the range. | |||
556 | When another NodeIndex pEnd is passed a MakeFrames is called up to it. | |||
557 | Used by TableToText. */ | |||
558 | void MakeOwnFrames(SwNodeIndex* pIdxBehind, SwNodeIndex* pEnd = nullptr); | |||
559 | ||||
560 | /** Method deletes all views of document for the node. The | |||
561 | content frames are removed from the respective layout. */ | |||
562 | void DelFrames(SwRootFrame const* pLayout = nullptr, bool bForce = false); | |||
563 | ||||
564 | /** Method creates all views of document for the previous node. | |||
565 | The content frames created are put into the respective layout. */ | |||
566 | void MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx); | |||
567 | ||||
568 | SwSectionNode* MakeCopy( SwDoc&, const SwNodeIndex& ) const; | |||
569 | ||||
570 | /// Set pointer in format of section on itself. | |||
571 | void NodesArrChgd(); | |||
572 | ||||
573 | /** Check for not hidden areas whether there is content that is not in | |||
574 | a hidden sub-area. */ | |||
575 | bool IsContentHidden() const; | |||
576 | ||||
577 | }; | |||
578 | ||||
579 | /** This class is internal, used only during DocumentContentOperationsManager::CopyWithFlyInFly(), and for undo. | |||
580 | ||||
581 | Some of the nodes are then replaced with SwPlaceholderNode, and at the end of the operation, removed again. | |||
582 | FIXME find out if this is really necessary, and if we can avoid creation of the SwPlaceholderNodes in the first place. | |||
583 | */ | |||
584 | class SwPlaceholderNode final : private SwNode | |||
585 | { | |||
586 | private: | |||
587 | friend class SwNodes; | |||
588 | SwPlaceholderNode(const SwNodeIndex &rWhere); | |||
589 | }; | |||
590 | ||||
591 | inline SwEndNode *SwNode::GetEndNode() | |||
592 | { | |||
593 | return SwNodeType::End == m_nNodeType ? static_cast<SwEndNode*>(this) : nullptr; | |||
594 | } | |||
595 | inline const SwEndNode *SwNode::GetEndNode() const | |||
596 | { | |||
597 | return SwNodeType::End == m_nNodeType ? static_cast<const SwEndNode*>(this) : nullptr; | |||
598 | } | |||
599 | inline SwStartNode *SwNode::GetStartNode() | |||
600 | { | |||
601 | return SwNodeType::Start & m_nNodeType ? static_cast<SwStartNode*>(this) : nullptr; | |||
602 | } | |||
603 | inline const SwStartNode *SwNode::GetStartNode() const | |||
604 | { | |||
605 | return SwNodeType::Start & m_nNodeType ? static_cast<const SwStartNode*>(this) : nullptr; | |||
606 | } | |||
607 | inline SwTableNode *SwNode::GetTableNode() | |||
608 | { | |||
609 | return SwNodeType::Table == m_nNodeType ? static_cast<SwTableNode*>(this) : nullptr; | |||
610 | } | |||
611 | inline const SwTableNode *SwNode::GetTableNode() const | |||
612 | { | |||
613 | return SwNodeType::Table == m_nNodeType ? static_cast<const SwTableNode*>(this) : nullptr; | |||
614 | } | |||
615 | inline SwSectionNode *SwNode::GetSectionNode() | |||
616 | { | |||
617 | return SwNodeType::Section == m_nNodeType ? static_cast<SwSectionNode*>(this) : nullptr; | |||
618 | } | |||
619 | inline const SwSectionNode *SwNode::GetSectionNode() const | |||
620 | { | |||
621 | return SwNodeType::Section == m_nNodeType ? static_cast<const SwSectionNode*>(this) : nullptr; | |||
622 | } | |||
623 | inline SwContentNode *SwNode::GetContentNode() | |||
624 | { | |||
625 | return SwNodeType::ContentMask & m_nNodeType ? static_cast<SwContentNode*>(this) : nullptr; | |||
626 | } | |||
627 | inline const SwContentNode *SwNode::GetContentNode() const | |||
628 | { | |||
629 | return SwNodeType::ContentMask & m_nNodeType ? static_cast<const SwContentNode*>(this) : nullptr; | |||
630 | } | |||
631 | ||||
632 | inline bool SwNode::IsStartNode() const | |||
633 | { | |||
634 | return bool(SwNodeType::Start & m_nNodeType); | |||
635 | } | |||
636 | inline bool SwNode::IsContentNode() const | |||
637 | { | |||
638 | return bool(SwNodeType::ContentMask & m_nNodeType); | |||
639 | } | |||
640 | inline bool SwNode::IsEndNode() const | |||
641 | { | |||
642 | return SwNodeType::End == m_nNodeType; | |||
643 | } | |||
644 | inline bool SwNode::IsTextNode() const | |||
645 | { | |||
646 | return SwNodeType::Text == m_nNodeType; | |||
647 | } | |||
648 | inline bool SwNode::IsTableNode() const | |||
649 | { | |||
650 | return SwNodeType::Table == m_nNodeType; | |||
651 | } | |||
652 | inline bool SwNode::IsSectionNode() const | |||
653 | { | |||
654 | return SwNodeType::Section == m_nNodeType; | |||
655 | } | |||
656 | inline bool SwNode::IsNoTextNode() const | |||
657 | { | |||
658 | return bool(SwNodeType::NoTextMask & m_nNodeType); | |||
659 | } | |||
660 | inline bool SwNode::IsOLENode() const | |||
661 | { | |||
662 | return SwNodeType::Ole == m_nNodeType; | |||
663 | } | |||
664 | inline bool SwNode::IsGrfNode() const | |||
665 | { | |||
666 | return SwNodeType::Grf == m_nNodeType; | |||
667 | } | |||
668 | ||||
669 | inline const SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp ) const | |||
670 | { | |||
671 | return const_cast<SwNode*>(this)->FindSttNodeByType( eTyp ); | |||
672 | } | |||
673 | inline const SwTableNode* SwNode::FindTableNode() const | |||
674 | { | |||
675 | return const_cast<SwNode*>(this)->FindTableNode(); | |||
676 | } | |||
677 | inline const SwSectionNode* SwNode::FindSectionNode() const | |||
678 | { | |||
679 | return const_cast<SwNode*>(this)->FindSectionNode(); | |||
680 | } | |||
681 | inline sal_uLong SwNode::StartOfSectionIndex() const | |||
682 | { | |||
683 | return m_pStartOfSection->GetIndex(); | |||
684 | } | |||
685 | inline sal_uLong SwNode::EndOfSectionIndex() const | |||
686 | { | |||
687 | const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection; | |||
688 | return pStNd->m_pEndOfSection->GetIndex(); | |||
689 | } | |||
690 | inline const SwEndNode* SwNode::EndOfSectionNode() const | |||
691 | { | |||
692 | const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection; | |||
693 | return pStNd->m_pEndOfSection; | |||
694 | } | |||
695 | inline SwEndNode* SwNode::EndOfSectionNode() | |||
696 | { | |||
697 | const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection; | |||
698 | return pStNd->m_pEndOfSection; | |||
699 | } | |||
700 | ||||
701 | inline SwNodes& SwNode::GetNodes() | |||
702 | { | |||
703 | return static_cast<SwNodes&>(GetArray()); | |||
704 | } | |||
705 | inline const SwNodes& SwNode::GetNodes() const | |||
706 | { | |||
707 | return static_cast<SwNodes&>(GetArray()); | |||
708 | } | |||
709 | ||||
710 | inline SwFormatColl* SwContentNode::GetCondFormatColl() const | |||
711 | { | |||
712 | return m_pCondColl; | |||
713 | } | |||
714 | ||||
715 | inline SwFormatColl& SwContentNode::GetAnyFormatColl() const | |||
716 | { | |||
717 | return m_pCondColl | |||
718 | ? *m_pCondColl | |||
719 | : *const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn())); | |||
720 | } | |||
721 | ||||
722 | inline const SwAttrSet& SwContentNode::GetSwAttrSet() const | |||
723 | { | |||
724 | return mpAttrSet ? *GetpSwAttrSet() : GetAnyFormatColl().GetAttrSet(); | |||
| ||||
725 | } | |||
726 | ||||
727 | //FEATURE::CONDCOLL | |||
728 | ||||
729 | inline const SfxPoolItem& SwContentNode::GetAttr( sal_uInt16 nWhich, | |||
730 | bool bInParents ) const | |||
731 | { | |||
732 | return GetSwAttrSet().Get( nWhich, bInParents ); | |||
733 | } | |||
734 | ||||
735 | inline SwPlaceholderNode::SwPlaceholderNode(const SwNodeIndex &rWhere) | |||
736 | : SwNode(rWhere, SwNodeType::PlaceHolder) | |||
737 | { | |||
738 | } | |||
739 | ||||
740 | inline SwNodePtr SwNodes::operator[]( sal_uLong n ) const | |||
741 | { | |||
742 | return static_cast<SwNodePtr>(BigPtrArray::operator[] ( n )); | |||
743 | } | |||
744 | ||||
745 | #endif | |||
746 | ||||
747 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |