File: | home/maarten/src/libreoffice/core/sw/source/core/doc/DocumentLinksAdministrationManager.cxx |
Warning: | line 81, column 25 Use of memory after it is freed |
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 <DocumentLinksAdministrationManager.hxx> | |||
21 | ||||
22 | #include <doc.hxx> | |||
23 | #include <DocumentSettingManager.hxx> | |||
24 | #include <IDocumentUndoRedo.hxx> | |||
25 | #include <IDocumentState.hxx> | |||
26 | #include <IDocumentMarkAccess.hxx> | |||
27 | #include <sfx2/objsh.hxx> | |||
28 | #include <sfx2/linkmgr.hxx> | |||
29 | #include <sfx2/docfile.hxx> | |||
30 | #include <dialoghelp.hxx> | |||
31 | #include <linkenum.hxx> | |||
32 | #include <com/sun/star/document/UpdateDocMode.hpp> | |||
33 | #include <swtypes.hxx> | |||
34 | #include <docsh.hxx> | |||
35 | #include <bookmrk.hxx> | |||
36 | #include <swserv.hxx> | |||
37 | #include <swbaslnk.hxx> | |||
38 | #include <section.hxx> | |||
39 | #include <docary.hxx> | |||
40 | #include <frmfmt.hxx> | |||
41 | #include <fmtcntnt.hxx> | |||
42 | #include <swtable.hxx> | |||
43 | #include <ndtxt.hxx> | |||
44 | #include <frameformats.hxx> | |||
45 | #include <tools/urlobj.hxx> | |||
46 | #include <unotools/charclass.hxx> | |||
47 | #include <unotools/securityoptions.hxx> | |||
48 | ||||
49 | using namespace ::com::sun::star; | |||
50 | ||||
51 | //Helper functions for this file | |||
52 | namespace | |||
53 | { | |||
54 | struct FindItem | |||
55 | { | |||
56 | const OUString m_Item; | |||
57 | SwTableNode* pTableNd; | |||
58 | SwSectionNode* pSectNd; | |||
59 | ||||
60 | explicit FindItem(const OUString& rS) | |||
61 | : m_Item(rS), pTableNd(nullptr), pSectNd(nullptr) | |||
62 | {} | |||
63 | }; | |||
64 | ||||
65 | ::sfx2::SvBaseLink* lcl_FindNextRemovableLink( const ::sfx2::SvBaseLinks& rLinks ) | |||
66 | { | |||
67 | for (const auto& rLinkIter : rLinks) | |||
68 | { | |||
69 | ::sfx2::SvBaseLink& rLnk = *rLinkIter; | |||
70 | if ((sfx2::SvBaseLinkObjectType::ClientGraphic == rLnk.GetObjType() || sfx2::SvBaseLinkObjectType::ClientFile == rLnk.GetObjType()) | |||
71 | && dynamic_cast<const SwBaseLink*>(&rLnk) != nullptr) | |||
72 | { | |||
73 | tools::SvRef<sfx2::SvBaseLink> xLink(&rLnk); | |||
74 | ||||
75 | OUString sFName; | |||
76 | sfx2::LinkManager::GetDisplayNames( xLink.get(), nullptr, &sFName ); | |||
77 | ||||
78 | INetURLObject aURL( sFName ); | |||
79 | if( INetProtocol::File == aURL.GetProtocol() || | |||
80 | INetProtocol::Cid == aURL.GetProtocol() ) | |||
81 | return &rLnk; | |||
| ||||
82 | } | |||
83 | } | |||
84 | return nullptr; | |||
85 | } | |||
86 | ||||
87 | ||||
88 | ::sw::mark::DdeBookmark* lcl_FindDdeBookmark( const IDocumentMarkAccess& rMarkAccess, const OUString& rName, const bool bCaseSensitive ) | |||
89 | { | |||
90 | //Iterating over all bookmarks, checking DdeBookmarks | |||
91 | const OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lowercase(rName); | |||
92 | for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getAllMarksBegin(); | |||
93 | ppMark != rMarkAccess.getAllMarksEnd(); | |||
94 | ++ppMark) | |||
95 | { | |||
96 | if (::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(*ppMark)) | |||
97 | { | |||
98 | if ( | |||
99 | (bCaseSensitive && (pBkmk->GetName() == sNameLc)) || | |||
100 | (!bCaseSensitive && GetAppCharClass().lowercase(pBkmk->GetName()) == sNameLc) | |||
101 | ) | |||
102 | { | |||
103 | return pBkmk; | |||
104 | } | |||
105 | } | |||
106 | } | |||
107 | return nullptr; | |||
108 | } | |||
109 | ||||
110 | ||||
111 | bool lcl_FindSection( const SwSectionFormat* pSectFormat, FindItem * const pItem, bool bCaseSensitive ) | |||
112 | { | |||
113 | SwSection* pSect = pSectFormat->GetSection(); | |||
114 | if( pSect ) | |||
115 | { | |||
116 | OUString sNm( bCaseSensitive | |||
117 | ? pSect->GetSectionName() | |||
118 | : GetAppCharClass().lowercase( pSect->GetSectionName() )); | |||
119 | OUString sCompare( bCaseSensitive | |||
120 | ? pItem->m_Item | |||
121 | : GetAppCharClass().lowercase( pItem->m_Item ) ); | |||
122 | if( sNm == sCompare ) | |||
123 | { | |||
124 | // found, so get the data | |||
125 | const SwNodeIndex* pIdx = pSectFormat->GetContent().GetContentIdx(); | |||
126 | if( pIdx && &pSectFormat->GetDoc()->GetNodes() == &pIdx->GetNodes() ) | |||
127 | { | |||
128 | // a table in the normal NodesArr | |||
129 | pItem->pSectNd = pIdx->GetNode().GetSectionNode(); | |||
130 | return false; | |||
131 | } | |||
132 | // If the name is already correct, but not the rest then we don't have them. | |||
133 | // The names are always unique. | |||
134 | } | |||
135 | } | |||
136 | return true; | |||
137 | } | |||
138 | ||||
139 | bool lcl_FindTable( const SwFrameFormat* pTableFormat, FindItem * const pItem ) | |||
140 | { | |||
141 | OUString sNm( GetAppCharClass().lowercase( pTableFormat->GetName() )); | |||
142 | if ( sNm == pItem->m_Item ) | |||
143 | { | |||
144 | SwTable* pTmpTable = SwTable::FindTable( pTableFormat ); | |||
145 | if( pTmpTable ) | |||
146 | { | |||
147 | SwTableBox* pFBox = pTmpTable->GetTabSortBoxes()[0]; | |||
148 | if( pFBox && pFBox->GetSttNd() && | |||
149 | &pTableFormat->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() ) | |||
150 | { | |||
151 | // a table in the normal NodesArr | |||
152 | pItem->pTableNd = const_cast<SwTableNode*>( | |||
153 | pFBox->GetSttNd()->FindTableNode()); | |||
154 | return false; | |||
155 | } | |||
156 | } | |||
157 | // If the name is already correct, but not the rest then we don't have them. | |||
158 | // The names are always unique. | |||
159 | } | |||
160 | return true; | |||
161 | } | |||
162 | ||||
163 | } | |||
164 | ||||
165 | ||||
166 | namespace sw | |||
167 | { | |||
168 | ||||
169 | DocumentLinksAdministrationManager::DocumentLinksAdministrationManager( SwDoc& i_rSwdoc ) | |||
170 | : mbVisibleLinks(true) | |||
171 | , mbLinksUpdated( false ) //#i38810# | |||
172 | , m_pLinkMgr( new sfx2::LinkManager(nullptr) ) | |||
173 | , m_rDoc( i_rSwdoc ) | |||
174 | { | |||
175 | } | |||
176 | ||||
177 | bool DocumentLinksAdministrationManager::IsVisibleLinks() const | |||
178 | { | |||
179 | return mbVisibleLinks; | |||
180 | } | |||
181 | ||||
182 | void DocumentLinksAdministrationManager::SetVisibleLinks(bool bFlag) | |||
183 | { | |||
184 | mbVisibleLinks = bFlag; | |||
185 | } | |||
186 | ||||
187 | sfx2::LinkManager& DocumentLinksAdministrationManager::GetLinkManager() | |||
188 | { | |||
189 | return *m_pLinkMgr; | |||
190 | } | |||
191 | ||||
192 | const sfx2::LinkManager& DocumentLinksAdministrationManager::GetLinkManager() const | |||
193 | { | |||
194 | return *m_pLinkMgr; | |||
195 | } | |||
196 | ||||
197 | // #i42634# Moved common code of SwReader::Read() and SwDocShell::UpdateLinks() | |||
198 | // to new SwDoc::UpdateLinks(): | |||
199 | void DocumentLinksAdministrationManager::UpdateLinks() | |||
200 | { | |||
201 | if (!m_rDoc.GetDocShell()) | |||
202 | return; | |||
203 | SfxObjectCreateMode eMode = m_rDoc.GetDocShell()->GetCreateMode(); | |||
204 | if (eMode == SfxObjectCreateMode::INTERNAL) | |||
205 | return; | |||
206 | if (eMode == SfxObjectCreateMode::ORGANIZER) | |||
207 | return; | |||
208 | if (m_rDoc.GetDocShell()->IsPreview()) | |||
209 | return; | |||
210 | if (GetLinkManager().GetLinks().empty()) | |||
211 | return; | |||
212 | sal_uInt16 nLinkMode = m_rDoc.GetDocumentSettingManager().getLinkUpdateMode(true); | |||
213 | sal_uInt16 nUpdateDocMode = m_rDoc.GetDocShell()->GetUpdateDocMode(); | |||
214 | if (nLinkMode == NEVER && nUpdateDocMode != document::UpdateDocMode::FULL_UPDATE) | |||
215 | return; | |||
216 | ||||
217 | bool bAskUpdate = nLinkMode == MANUAL; | |||
218 | bool bUpdate = true; | |||
219 | switch(nUpdateDocMode) | |||
220 | { | |||
221 | case document::UpdateDocMode::NO_UPDATE: bUpdate = false;break; | |||
222 | case document::UpdateDocMode::QUIET_UPDATE:bAskUpdate = false; break; | |||
223 | case document::UpdateDocMode::FULL_UPDATE: bAskUpdate = true; break; | |||
224 | } | |||
225 | if (nLinkMode == AUTOMATIC && !bAskUpdate) | |||
226 | { | |||
227 | SfxMedium * medium = m_rDoc.GetDocShell()->GetMedium(); | |||
228 | if (!SvtSecurityOptions().isTrustedLocationUriForUpdatingLinks( | |||
229 | medium == nullptr ? OUString() : medium->GetName())) | |||
230 | { | |||
231 | bAskUpdate = true; | |||
232 | } | |||
233 | } | |||
234 | comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = m_rDoc.GetDocShell()->getEmbeddedObjectContainer(); | |||
235 | if (bUpdate) | |||
236 | { | |||
237 | rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true); | |||
238 | ||||
239 | weld::Window* pDlgParent = GetFrameWeld(m_rDoc.GetDocShell()); | |||
240 | GetLinkManager().UpdateAllLinks(bAskUpdate, false, pDlgParent); | |||
241 | } | |||
242 | else | |||
243 | { | |||
244 | rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false); | |||
245 | } | |||
246 | } | |||
247 | ||||
248 | bool DocumentLinksAdministrationManager::GetData( const OUString& rItem, const OUString& rMimeType, | |||
249 | uno::Any & rValue ) const | |||
250 | { | |||
251 | // search for bookmarks and sections case sensitive at first. If nothing is found then try again case insensitive | |||
252 | bool bCaseSensitive = true; | |||
253 | while( true ) | |||
254 | { | |||
255 | ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*m_rDoc.getIDocumentMarkAccess(), rItem, bCaseSensitive); | |||
256 | if(pBkmk) | |||
257 | return SwServerObject(*pBkmk).GetData(rValue, rMimeType); | |||
258 | ||||
259 | // Do we already have the Item? | |||
260 | OUString sItem( bCaseSensitive ? rItem : GetAppCharClass().lowercase(rItem)); | |||
261 | FindItem aPara( sItem ); | |||
262 | for( const SwSectionFormat* pFormat : m_rDoc.GetSections() ) | |||
263 | { | |||
264 | if (!(lcl_FindSection(pFormat, &aPara, bCaseSensitive))) | |||
265 | break; | |||
266 | } | |||
267 | if( aPara.pSectNd ) | |||
268 | { | |||
269 | // found, so get the data | |||
270 | return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType ); | |||
271 | } | |||
272 | if( !bCaseSensitive ) | |||
273 | break; | |||
274 | bCaseSensitive = false; | |||
275 | } | |||
276 | ||||
277 | FindItem aPara( GetAppCharClass().lowercase( rItem )); | |||
278 | for( const SwFrameFormat* pFormat : *m_rDoc.GetTableFrameFormats() ) | |||
279 | { | |||
280 | if (!(lcl_FindTable(pFormat, &aPara))) | |||
281 | break; | |||
282 | } | |||
283 | if( aPara.pTableNd ) | |||
284 | { | |||
285 | return SwServerObject( *aPara.pTableNd ).GetData( rValue, rMimeType ); | |||
286 | } | |||
287 | ||||
288 | return false; | |||
289 | } | |||
290 | ||||
291 | void DocumentLinksAdministrationManager::SetData( const OUString& rItem ) | |||
292 | { | |||
293 | // search for bookmarks and sections case sensitive at first. If nothing is found then try again case insensitive | |||
294 | bool bCaseSensitive = true; | |||
295 | while( true ) | |||
296 | { | |||
297 | ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*m_rDoc.getIDocumentMarkAccess(), rItem, bCaseSensitive); | |||
298 | if(pBkmk) | |||
299 | { | |||
300 | return; | |||
301 | } | |||
302 | ||||
303 | // Do we already have the Item? | |||
304 | OUString sItem( bCaseSensitive ? rItem : GetAppCharClass().lowercase(rItem)); | |||
305 | FindItem aPara( sItem ); | |||
306 | for( const SwSectionFormat* pFormat : m_rDoc.GetSections() ) | |||
307 | { | |||
308 | if (!(lcl_FindSection(pFormat, &aPara, bCaseSensitive))) | |||
309 | break; | |||
310 | } | |||
311 | if( aPara.pSectNd ) | |||
312 | { | |||
313 | // found, so get the data | |||
314 | return; | |||
315 | } | |||
316 | if( !bCaseSensitive ) | |||
317 | break; | |||
318 | bCaseSensitive = false; | |||
319 | } | |||
320 | ||||
321 | OUString sItem(GetAppCharClass().lowercase(rItem)); | |||
322 | FindItem aPara( sItem ); | |||
323 | for( const SwFrameFormat* pFormat : *m_rDoc.GetTableFrameFormats() ) | |||
324 | { | |||
325 | if (!(lcl_FindTable(pFormat, &aPara))) | |||
326 | break; | |||
327 | } | |||
328 | } | |||
329 | ||||
330 | ::sfx2::SvLinkSource* DocumentLinksAdministrationManager::CreateLinkSource(const OUString& rItem) | |||
331 | { | |||
332 | SwServerObject* pObj = nullptr; | |||
333 | ||||
334 | // search for bookmarks and sections case sensitive at first. If nothing is found then try again case insensitive | |||
335 | bool bCaseSensitive = true; | |||
336 | while( true ) | |||
337 | { | |||
338 | // bookmarks | |||
339 | ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*m_rDoc.getIDocumentMarkAccess(), rItem, bCaseSensitive); | |||
340 | if(pBkmk && pBkmk->IsExpanded()) | |||
341 | { | |||
342 | pObj = pBkmk->GetRefObject(); | |||
343 | if( !pObj ) | |||
344 | { | |||
345 | // mark found, but no link yet -> create hotlink | |||
346 | pObj = new SwServerObject(*pBkmk); | |||
347 | pBkmk->SetRefObject(pObj); | |||
348 | GetLinkManager().InsertServer(pObj); | |||
349 | } | |||
350 | } | |||
351 | if(pObj) | |||
352 | return pObj; | |||
353 | ||||
354 | FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lowercase(rItem)); | |||
355 | // sections | |||
356 | for( const SwSectionFormat* pFormat : m_rDoc.GetSections() ) | |||
357 | { | |||
358 | if (!(lcl_FindSection(pFormat, &aPara, bCaseSensitive))) | |||
359 | break; | |||
360 | } | |||
361 | ||||
362 | if(aPara.pSectNd) | |||
363 | { | |||
364 | pObj = aPara.pSectNd->GetSection().GetObject(); | |||
365 | if( !pObj ) | |||
366 | { | |||
367 | // section found, but no link yet -> create hotlink | |||
368 | pObj = new SwServerObject( *aPara.pSectNd ); | |||
369 | aPara.pSectNd->GetSection().SetRefObject( pObj ); | |||
370 | GetLinkManager().InsertServer(pObj); | |||
371 | } | |||
372 | } | |||
373 | if(pObj) | |||
374 | return pObj; | |||
375 | if( !bCaseSensitive ) | |||
376 | break; | |||
377 | bCaseSensitive = false; | |||
378 | } | |||
379 | ||||
380 | FindItem aPara( GetAppCharClass().lowercase(rItem) ); | |||
381 | // tables | |||
382 | for( const SwFrameFormat* pFormat : *m_rDoc.GetTableFrameFormats() ) | |||
383 | { | |||
384 | if (!(lcl_FindTable(pFormat, &aPara))) | |||
385 | break; | |||
386 | } | |||
387 | if(aPara.pTableNd) | |||
388 | { | |||
389 | pObj = aPara.pTableNd->GetTable().GetObject(); | |||
390 | if( !pObj ) | |||
391 | { | |||
392 | // table found, but no link yet -> create hotlink | |||
393 | pObj = new SwServerObject(*aPara.pTableNd); | |||
394 | aPara.pTableNd->GetTable().SetRefObject(pObj); | |||
395 | GetLinkManager().InsertServer(pObj); | |||
396 | } | |||
397 | } | |||
398 | return pObj; | |||
399 | } | |||
400 | ||||
401 | /// embedded all local links (Areas/Graphics) | |||
402 | bool DocumentLinksAdministrationManager::EmbedAllLinks() | |||
403 | { | |||
404 | bool bRet = false; | |||
405 | sfx2::LinkManager& rLnkMgr = GetLinkManager(); | |||
406 | const ::sfx2::SvBaseLinks& rLinks = rLnkMgr.GetLinks(); | |||
407 | if( !rLinks.empty() ) | |||
| ||||
408 | { | |||
409 | ::sw::UndoGuard const undoGuard(m_rDoc.GetIDocumentUndoRedo()); | |||
410 | ||||
411 | ::sfx2::SvBaseLink* pLnk = nullptr; | |||
412 | while( nullptr != (pLnk = lcl_FindNextRemovableLink( rLinks ) ) ) | |||
413 | { | |||
414 | tools::SvRef<sfx2::SvBaseLink> xLink = pLnk; | |||
415 | // Tell the link that it's being destroyed! | |||
416 | xLink->Closed(); | |||
417 | ||||
418 | // if one forgot to remove itself | |||
419 | if( xLink.is() ) | |||
420 | rLnkMgr.Remove( xLink.get() ); | |||
421 | ||||
422 | bRet = true; | |||
423 | } | |||
424 | ||||
425 | m_rDoc.GetIDocumentUndoRedo().DelAllUndoObj(); | |||
426 | m_rDoc.getIDocumentState().SetModified(); | |||
427 | } | |||
428 | return bRet; | |||
429 | } | |||
430 | ||||
431 | void DocumentLinksAdministrationManager::SetLinksUpdated(const bool bNewLinksUpdated) | |||
432 | { | |||
433 | mbLinksUpdated = bNewLinksUpdated; | |||
434 | } | |||
435 | ||||
436 | bool DocumentLinksAdministrationManager::LinksUpdated() const | |||
437 | { | |||
438 | return mbLinksUpdated; | |||
439 | } | |||
440 | ||||
441 | DocumentLinksAdministrationManager::~DocumentLinksAdministrationManager() | |||
442 | { | |||
443 | } | |||
444 | ||||
445 | bool DocumentLinksAdministrationManager::SelectServerObj( const OUString& rStr, SwPaM*& rpPam, std::unique_ptr<SwNodeRange>& rpRange ) const | |||
446 | { | |||
447 | // Do we actually have the Item? | |||
448 | rpPam = nullptr; | |||
449 | rpRange = nullptr; | |||
450 | ||||
451 | OUString sItem( INetURLObject::decode( rStr, | |||
452 | INetURLObject::DecodeMechanism::WithCharset )); | |||
453 | ||||
454 | sal_Int32 nPos = sItem.indexOf( cMarkSeparator ); | |||
455 | ||||
456 | const CharClass& rCC = GetAppCharClass(); | |||
457 | ||||
458 | // Extension for sections: not only link bookmarks/sections | |||
459 | // but also frames (text!), tables, outlines: | |||
460 | if( -1 != nPos ) | |||
461 | { | |||
462 | bool bContinue = false; | |||
463 | OUString sName( sItem.copy( 0, nPos ) ); | |||
464 | OUString sCmp( sItem.copy( nPos + 1 )); | |||
465 | sItem = rCC.lowercase( sItem ); | |||
466 | ||||
467 | FindItem aPara( sName ); | |||
468 | ||||
469 | if( sCmp == "table" ) | |||
470 | { | |||
471 | sName = rCC.lowercase( sName ); | |||
472 | for( const SwFrameFormat* pFormat : *m_rDoc.GetTableFrameFormats() ) | |||
473 | { | |||
474 | if (!(lcl_FindTable(pFormat, &aPara))) | |||
475 | break; | |||
476 | } | |||
477 | if( aPara.pTableNd ) | |||
478 | { | |||
479 | rpRange.reset(new SwNodeRange( *aPara.pTableNd, 0, | |||
480 | *aPara.pTableNd->EndOfSectionNode(), 1 )); | |||
481 | return true; | |||
482 | } | |||
483 | } | |||
484 | else if( sCmp == "frame" ) | |||
485 | { | |||
486 | const SwFlyFrameFormat* pFlyFormat = m_rDoc.FindFlyByName( sName ); | |||
487 | if( pFlyFormat ) | |||
488 | { | |||
489 | SwNodeIndex* pIdx = const_cast<SwNodeIndex*>(pFlyFormat->GetContent().GetContentIdx()); | |||
490 | if( pIdx ) | |||
491 | { | |||
492 | SwNode* pNd = &pIdx->GetNode(); | |||
493 | if( !pNd->IsNoTextNode() ) | |||
494 | { | |||
495 | rpRange.reset(new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() )); | |||
496 | return true; | |||
497 | } | |||
498 | } | |||
499 | } | |||
500 | } | |||
501 | else if( sCmp == "region" ) | |||
502 | { | |||
503 | sItem = sName; // Is being dealt with further down! | |||
504 | bContinue = true; | |||
505 | } | |||
506 | else if( sCmp == "outline" ) | |||
507 | { | |||
508 | SwPosition aPos( SwNodeIndex( m_rDoc.GetNodes() )); | |||
509 | if (m_rDoc.GotoOutline(aPos, sName, nullptr)) | |||
510 | { | |||
511 | SwNode* pNd = &aPos.nNode.GetNode(); | |||
512 | const int nLvl = pNd->GetTextNode()->GetAttrOutlineLevel()-1; | |||
513 | ||||
514 | const SwOutlineNodes& rOutlNds = m_rDoc.GetNodes().GetOutLineNds(); | |||
515 | SwOutlineNodes::size_type nTmpPos; | |||
516 | (void)rOutlNds.Seek_Entry( pNd, &nTmpPos ); | |||
517 | rpRange.reset(new SwNodeRange( aPos.nNode, 0, aPos.nNode )); | |||
518 | ||||
519 | // look for the section's end, now | |||
520 | for( ++nTmpPos; | |||
521 | nTmpPos < rOutlNds.size() && | |||
522 | nLvl < rOutlNds[ nTmpPos ]->GetTextNode()-> | |||
523 | GetAttrOutlineLevel()-1; | |||
524 | ++nTmpPos ) | |||
525 | ; // there is no block | |||
526 | ||||
527 | if( nTmpPos < rOutlNds.size() ) | |||
528 | rpRange->aEnd = *rOutlNds[ nTmpPos ]; | |||
529 | else | |||
530 | rpRange->aEnd = m_rDoc.GetNodes().GetEndOfContent(); | |||
531 | return true; | |||
532 | } | |||
533 | } | |||
534 | ||||
535 | if( !bContinue ) | |||
536 | return false; | |||
537 | } | |||
538 | ||||
539 | // search for bookmarks and sections case sensitive at first. If nothing is found then try again case insensitive | |||
540 | bool bCaseSensitive = true; | |||
541 | while( true ) | |||
542 | { | |||
543 | ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*m_rDoc.getIDocumentMarkAccess(), sItem, bCaseSensitive); | |||
544 | if(pBkmk) | |||
545 | { | |||
546 | if(pBkmk->IsExpanded()) | |||
547 | rpPam = new SwPaM( | |||
548 | pBkmk->GetMarkPos(), | |||
549 | pBkmk->GetOtherMarkPos()); | |||
550 | return static_cast<bool>(rpPam); | |||
551 | } | |||
552 | ||||
553 | FindItem aPara( bCaseSensitive ? sItem : rCC.lowercase( sItem ) ); | |||
554 | ||||
555 | if( !m_rDoc.GetSections().empty() ) | |||
556 | { | |||
557 | for( const SwSectionFormat* pFormat : m_rDoc.GetSections() ) | |||
558 | { | |||
559 | if (!(lcl_FindSection(pFormat, &aPara, bCaseSensitive))) | |||
560 | break; | |||
561 | } | |||
562 | if( aPara.pSectNd ) | |||
563 | { | |||
564 | rpRange.reset(new SwNodeRange( *aPara.pSectNd, 1, | |||
565 | *aPara.pSectNd->EndOfSectionNode() )); | |||
566 | return true; | |||
567 | ||||
568 | } | |||
569 | } | |||
570 | if( !bCaseSensitive ) | |||
571 | break; | |||
572 | bCaseSensitive = false; | |||
573 | } | |||
574 | return false; | |||
575 | } | |||
576 | ||||
577 | ||||
578 | } | |||
579 | ||||
580 | ||||
581 | /* 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 | #ifndef INCLUDED_TOOLS_REF_HXX | ||||
20 | #define INCLUDED_TOOLS_REF_HXX | ||||
21 | |||||
22 | #include <sal/config.h> | ||||
23 | #include <cassert> | ||||
24 | #include <tools/toolsdllapi.h> | ||||
25 | #include <utility> | ||||
26 | |||||
27 | /** | ||||
28 | This implements similar functionality to boost::intrusive_ptr | ||||
29 | */ | ||||
30 | |||||
31 | namespace tools { | ||||
32 | |||||
33 | /** T must be a class that extends SvRefBase */ | ||||
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { | ||||
35 | public: | ||||
36 | SvRef(): pObj(nullptr) {} | ||||
37 | |||||
38 | SvRef(SvRef&& rObj) noexcept | ||||
39 | { | ||||
40 | pObj = rObj.pObj; | ||||
41 | rObj.pObj = nullptr; | ||||
42 | } | ||||
43 | |||||
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) | ||||
45 | { | ||||
46 | if (pObj != nullptr) pObj->AddNextRef(); | ||||
47 | } | ||||
48 | |||||
49 | SvRef(T * pObjP): pObj(pObjP) | ||||
50 | { | ||||
51 | if (pObj != nullptr) pObj->AddFirstRef(); | ||||
52 | } | ||||
53 | |||||
54 | ~SvRef() | ||||
55 | { | ||||
56 | if (pObj != nullptr) pObj->ReleaseRef(); | ||||
57 | } | ||||
58 | |||||
59 | void clear() | ||||
60 | { | ||||
61 | if (pObj != nullptr) { | ||||
62 | T * pRefObj = pObj; | ||||
63 | pObj = nullptr; | ||||
64 | pRefObj->ReleaseRef(); | ||||
65 | } | ||||
66 | } | ||||
67 | |||||
68 | SvRef & operator =(SvRef const & rObj) | ||||
69 | { | ||||
70 | if (rObj.pObj != nullptr) { | ||||
71 | rObj.pObj->AddNextRef(); | ||||
72 | } | ||||
73 | T * pRefObj = pObj; | ||||
74 | pObj = rObj.pObj; | ||||
75 | if (pRefObj != nullptr) { | ||||
76 | pRefObj->ReleaseRef(); | ||||
77 | } | ||||
78 | return *this; | ||||
79 | } | ||||
80 | |||||
81 | SvRef & operator =(SvRef && rObj) | ||||
82 | { | ||||
83 | if (pObj != nullptr) { | ||||
84 | pObj->ReleaseRef(); | ||||
85 | } | ||||
86 | pObj = rObj.pObj; | ||||
87 | rObj.pObj = nullptr; | ||||
88 | return *this; | ||||
89 | } | ||||
90 | |||||
91 | bool is() const { return pObj != nullptr; } | ||||
92 | |||||
93 | explicit operator bool() const { return is(); } | ||||
94 | |||||
95 | T * get() const { return pObj; } | ||||
96 | |||||
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } | ||||
98 | |||||
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } | ||||
100 | |||||
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } | ||||
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } | ||||
103 | |||||
104 | private: | ||||
105 | T * pObj; | ||||
106 | }; | ||||
107 | |||||
108 | /** | ||||
109 | * This implements similar functionality to std::make_shared. | ||||
110 | */ | ||||
111 | template<typename T, typename... Args> | ||||
112 | SvRef<T> make_ref(Args&& ... args) | ||||
113 | { | ||||
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); | ||||
115 | } | ||||
116 | |||||
117 | } | ||||
118 | |||||
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ | ||||
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase | ||||
121 | { | ||||
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* | ||||
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object | ||||
124 | unsigned int nRefCount : 31; | ||||
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields | ||||
126 | unsigned int bNoDelete : 1; | ||||
127 | |||||
128 | protected: | ||||
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; | ||||
130 | |||||
131 | public: | ||||
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} | ||||
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} | ||||
134 | |||||
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } | ||||
136 | |||||
137 | void RestoreNoDelete() | ||||
138 | { bNoDelete = 1; } | ||||
139 | |||||
140 | void AddNextRef() | ||||
141 | { | ||||
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); | ||||
143 | ++nRefCount; | ||||
144 | } | ||||
145 | |||||
146 | void AddFirstRef() | ||||
147 | { | ||||
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); | ||||
149 | if( bNoDelete ) | ||||
150 | bNoDelete = 0; | ||||
151 | ++nRefCount; | ||||
152 | } | ||||
153 | |||||
154 | void ReleaseRef() | ||||
155 | { | ||||
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); | ||||
157 | if( --nRefCount == 0 && !bNoDelete
| ||||
158 | { | ||||
159 | // I'm not sure about the original purpose of this line, but right now | ||||
160 | // it serves the purpose that anything that attempts to do an AddRef() | ||||
161 | // after an object is deleted will trip an assert. | ||||
162 | nRefCount = 1 << 30; | ||||
163 | delete this; | ||||
164 | } | ||||
165 | } | ||||
166 | |||||
167 | unsigned int GetRefCount() const | ||||
168 | { return nRefCount; } | ||||
169 | }; | ||||
170 | |||||
171 | template<typename T> | ||||
172 | class SvCompatWeakBase; | ||||
173 | |||||
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. | ||||
175 | */ | ||||
176 | template<typename T> | ||||
177 | class SvCompatWeakHdl final : public SvRefBase | ||||
178 | { | ||||
179 | friend class SvCompatWeakBase<T>; | ||||
180 | T* _pObj; | ||||
181 | |||||
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} | ||||
183 | |||||
184 | public: | ||||
185 | void ResetWeakBase( ) { _pObj = nullptr; } | ||||
186 | T* GetObj() { return _pObj; } | ||||
187 | }; | ||||
188 | |||||
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. | ||||
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. | ||||
191 | */ | ||||
192 | template<typename T> | ||||
193 | class SvCompatWeakBase | ||||
194 | { | ||||
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | ||||
196 | |||||
197 | public: | ||||
198 | /** Does not use initializer due to compiler warnings, | ||||
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. | ||||
200 | */ | ||||
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } | ||||
202 | |||||
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } | ||||
204 | |||||
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } | ||||
206 | }; | ||||
207 | |||||
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. | ||||
209 | */ | ||||
210 | template<typename T> | ||||
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef | ||||
212 | { | ||||
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | ||||
214 | public: | ||||
215 | SvCompatWeakRef( ) {} | ||||
216 | SvCompatWeakRef( T* pObj ) | ||||
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } | ||||
218 | #if defined(__COVERITY__) | ||||
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} | ||||
220 | #endif | ||||
221 | SvCompatWeakRef& operator = ( T * pObj ) | ||||
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } | ||||
223 | bool is() const | ||||
224 | { return _xHdl.is() && _xHdl->GetObj(); } | ||||
225 | explicit operator bool() const { return is(); } | ||||
226 | T* operator -> () const | ||||
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | ||||
228 | operator T* () const | ||||
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | ||||
230 | }; | ||||
231 | |||||
232 | #endif | ||||
233 | |||||
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |