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 <doc.hxx> 21 #include <IDocumentUndoRedo.hxx> 22 #include <IDocumentSettingAccess.hxx> 23 #include <IDocumentState.hxx> 24 #include <editsh.hxx> 25 #include <pam.hxx> 26 #include <ndtxt.hxx> 27 #include <docary.hxx> 28 #include <swundo.hxx> 29 #include <section.hxx> 30 #include <doctxm.hxx> 31 #include <edglbldc.hxx> 32 33 bool SwEditShell::IsGlobalDoc() const 34 { 35 return getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT); 36 } 37 38 void SwEditShell::SetGlblDocSaveLinks( bool bFlag ) 39 { 40 getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, bFlag); 41 if( !GetDoc()->getIDocumentState().IsModified() ) // Bug 57028 42 { 43 GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified(); 44 } 45 GetDoc()->getIDocumentState().SetModified(); 46 } 47 48 bool SwEditShell::IsGlblDocSaveLinks() const 49 { 50 return getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS); 51 } 52 53 void SwEditShell::GetGlobalDocContent( SwGlblDocContents& rArr ) const 54 { 55 rArr.clear(); 56 57 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) ) 58 return; 59 60 // then all linked areas on the topmost level 61 SwDoc* pMyDoc = GetDoc(); 62 const SwSectionFormats& rSectFormats = pMyDoc->GetSections(); 63 64 for( auto n = rSectFormats.size(); n; ) 65 { 66 const SwSection* pSect = rSectFormats[ --n ]->GetGlobalDocSection(); 67 if( pSect ) 68 { 69 std::unique_ptr<SwGlblDocContent> pNew; 70 switch( pSect->GetType() ) 71 { 72 case SectionType::ToxHeader: 73 break; // ignore 74 case SectionType::ToxContent: 75 assert( dynamic_cast<const SwTOXBaseSection*>( pSect) && "no TOXBaseSection!" ); 76 pNew.reset(new SwGlblDocContent( static_cast<const SwTOXBaseSection*>(pSect) )); 77 break; 78 79 default: 80 pNew.reset(new SwGlblDocContent( pSect )); 81 break; 82 } 83 if (pNew) 84 rArr.insert( std::move(pNew) ); 85 } 86 } 87 88 // and finally add the dummies (other text) 89 SwNode* pNd; 90 SwNodeOffset nSttIdx = pMyDoc->GetNodes().GetEndOfExtras().GetIndex() + 2; 91 for( SwGlblDocContents::size_type n = 0; n < rArr.size(); ++n ) 92 { 93 const SwGlblDocContent& rNew = *rArr[ n ]; 94 // Search from StartPos until rNew.DocPos for a content node. 95 // If one exists then a dummy entry is needed. 96 for( ; nSttIdx < rNew.GetDocPos(); ++nSttIdx ) 97 if( ( pNd = pMyDoc->GetNodes()[ nSttIdx ])->IsContentNode() 98 || pNd->IsSectionNode() || pNd->IsTableNode() ) 99 { 100 std::unique_ptr<SwGlblDocContent> pNew(new SwGlblDocContent( nSttIdx )); 101 if( rArr.insert( std::move(pNew) ).second ) 102 ++n; // to the next position 103 break; 104 } 105 106 // set StartPosition to the end 107 nSttIdx = pMyDoc->GetNodes()[ rNew.GetDocPos() ]->EndOfSectionIndex(); 108 ++nSttIdx; 109 } 110 111 // Should the end also be set? 112 if( !rArr.empty() ) 113 { 114 SwNodeOffset nNdEnd = pMyDoc->GetNodes().GetEndOfContent().GetIndex(); 115 for( ; nSttIdx < nNdEnd; ++nSttIdx ) 116 if( ( pNd = pMyDoc->GetNodes()[ nSttIdx ])->IsContentNode() 117 || pNd->IsSectionNode() || pNd->IsTableNode() ) 118 { 119 rArr.insert( std::make_unique<SwGlblDocContent>( nSttIdx ) ); 120 break; 121 } 122 } 123 else 124 { 125 std::unique_ptr<SwGlblDocContent> pNew(new SwGlblDocContent( 126 pMyDoc->GetNodes().GetEndOfExtras().GetIndex() + 2 )); 127 rArr.insert( std::move(pNew) ); 128 } 129 } 130 131 void SwEditShell::InsertGlobalDocContent( const SwGlblDocContent& rInsPos, 132 SwSectionData & rNew) 133 { 134 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) ) 135 return; 136 137 CurrShell aCurr( this ); 138 StartAllAction(); 139 140 SwPaM* pCursor = GetCursor(); 141 if( pCursor->GetNext() != pCursor || IsTableMode() ) 142 ClearMark(); 143 144 SwPosition& rPos = *pCursor->GetPoint(); 145 rPos.Assign( rInsPos.GetDocPos() ); 146 147 bool bEndUndo = false; 148 SwDoc* pMyDoc = GetDoc(); 149 SwTextNode *const pTextNd = rPos.GetNode().GetTextNode(); 150 if( !pTextNd ) 151 { 152 bEndUndo = true; 153 pMyDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr ); 154 rPos.Adjust(SwNodeOffset(-1)); 155 pMyDoc->getIDocumentContentOperations().AppendTextNode( rPos ); 156 pCursor->SetMark(); 157 } 158 159 InsertSection( rNew ); 160 161 if( bEndUndo ) 162 { 163 pMyDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr ); 164 } 165 EndAllAction(); 166 } 167 168 bool SwEditShell::InsertGlobalDocContent( const SwGlblDocContent& rInsPos, 169 const SwTOXBase& rTOX ) 170 { 171 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) ) 172 return false; 173 174 CurrShell aCurr( this ); 175 StartAllAction(); 176 177 SwPaM* pCursor = GetCursor(); 178 if( pCursor->GetNext() != pCursor || IsTableMode() ) 179 ClearMark(); 180 181 SwPosition& rPos = *pCursor->GetPoint(); 182 rPos.Assign(rInsPos.GetDocPos()); 183 184 bool bEndUndo = false; 185 SwDoc* pMyDoc = GetDoc(); 186 SwTextNode* pTextNd = rPos.GetNode().GetTextNode(); 187 if (!pTextNd || !pTextNd->GetText().getLength() || rPos.GetNodeIndex() + 1 == 188 pMyDoc->GetNodes().GetEndOfContent().GetIndex() ) 189 { 190 bEndUndo = true; 191 pMyDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr ); 192 rPos.Adjust(SwNodeOffset(-1)); 193 pMyDoc->getIDocumentContentOperations().AppendTextNode( rPos ); 194 } 195 196 InsertTableOf( rTOX ); 197 198 if( bEndUndo ) 199 { 200 pMyDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr ); 201 } 202 EndAllAction(); 203 204 return true; 205 } 206 207 bool SwEditShell::InsertGlobalDocContent( const SwGlblDocContent& rInsPos ) 208 { 209 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) ) 210 return false; 211 212 CurrShell aCurr( this ); 213 StartAllAction(); 214 215 SwPaM* pCursor = GetCursor(); 216 if( pCursor->GetNext() != pCursor || IsTableMode() ) 217 ClearMark(); 218 219 SwPosition& rPos = *pCursor->GetPoint(); 220 rPos.Assign(rInsPos.GetDocPos() - 1); 221 222 SwDoc* pMyDoc = GetDoc(); 223 pMyDoc->getIDocumentContentOperations().AppendTextNode( rPos ); 224 EndAllAction(); 225 return true; 226 } 227 228 void SwEditShell::DeleteGlobalDocContent( const SwGlblDocContents& rArr , 229 size_t nDelPos ) 230 { 231 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) ) 232 return; 233 234 CurrShell aCurr( this ); 235 StartAllAction(); 236 StartUndo( SwUndoId::START ); 237 238 SwPaM* pCursor = GetCursor(); 239 if( pCursor->GetNext() != pCursor || IsTableMode() ) 240 ClearMark(); 241 242 SwPosition& rPos = *pCursor->GetPoint(); 243 244 SwDoc* pMyDoc = GetDoc(); 245 const SwGlblDocContent& rDelPos = *rArr[ nDelPos ]; 246 SwNodeOffset nDelIdx = rDelPos.GetDocPos(); 247 if( 1 == rArr.size() ) 248 { 249 // we need at least one node! 250 rPos.Assign(nDelIdx - 1); 251 252 pMyDoc->getIDocumentContentOperations().AppendTextNode( rPos ); 253 ++nDelIdx; 254 } 255 256 switch( rDelPos.GetType() ) 257 { 258 case GLBLDOC_UNKNOWN: 259 { 260 rPos.Assign(nDelIdx); 261 pCursor->SetMark(); 262 if( ++nDelPos < rArr.size() ) 263 rPos.Assign(rArr[ nDelPos ]->GetDocPos(), -1); 264 else 265 rPos.Assign(pMyDoc->GetNodes().GetEndOfContent(), -1); 266 if( !pMyDoc->getIDocumentContentOperations().DelFullPara( *pCursor ) ) 267 Delete(false); 268 } 269 break; 270 271 case GLBLDOC_TOXBASE: 272 { 273 const SwTOXBaseSection* pTOX = static_cast<const SwTOXBaseSection*>(rDelPos.GetTOX()); 274 pMyDoc->DeleteTOX( *pTOX, true ); 275 } 276 break; 277 278 case GLBLDOC_SECTION: 279 { 280 SwSectionFormat* pSectFormat = const_cast<SwSectionFormat*>(rDelPos.GetSection()->GetFormat()); 281 pMyDoc->DelSectionFormat( pSectFormat, true ); 282 } 283 break; 284 } 285 286 EndUndo( SwUndoId::END ); 287 EndAllAction(); 288 } 289 290 bool SwEditShell::MoveGlobalDocContent( const SwGlblDocContents& rArr , 291 size_t nFromPos, size_t nToPos, 292 size_t nInsPos ) 293 { 294 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) || 295 nFromPos >= rArr.size() || nToPos > rArr.size() || 296 nInsPos > rArr.size() || nFromPos >= nToPos || 297 ( nFromPos <= nInsPos && nInsPos <= nToPos ) ) 298 return false; 299 300 CurrShell aCurr( this ); 301 StartAllAction(); 302 303 SwPaM* pCursor = GetCursor(); 304 if( pCursor->GetNext() != pCursor || IsTableMode() ) 305 ClearMark(); 306 307 SwDoc* pMyDoc = GetDoc(); 308 SwNodeRange aRg( pMyDoc->GetNodes(), rArr[ nFromPos ]->GetDocPos() ); 309 if( nToPos < rArr.size() ) 310 aRg.aEnd = rArr[ nToPos ]->GetDocPos(); 311 else 312 aRg.aEnd = pMyDoc->GetNodes().GetEndOfContent(); 313 314 SwNodeIndex aInsPos( pMyDoc->GetNodes() ); 315 if( nInsPos < rArr.size() ) 316 aInsPos = rArr[ nInsPos ]->GetDocPos(); 317 else 318 aInsPos = pMyDoc->GetNodes().GetEndOfContent(); 319 320 bool bRet = pMyDoc->getIDocumentContentOperations().MoveNodeRange( aRg, aInsPos.GetNode(), 321 SwMoveFlags::CREATEUNDOOBJ ); 322 323 EndAllAction(); 324 return bRet; 325 } 326 327 void SwEditShell::GotoGlobalDocContent( const SwGlblDocContent& rPos ) 328 { 329 if( !getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) ) 330 return; 331 332 CurrShell aCurr( this ); 333 SttCursorMove(); 334 335 SwPaM* pCursor = GetCursor(); 336 if( pCursor->GetNext() != pCursor || IsTableMode() ) 337 ClearMark(); 338 339 SwPosition& rCursorPos = *pCursor->GetPoint(); 340 rCursorPos.Assign(rPos.GetDocPos()); 341 342 SwDoc* pMyDoc = GetDoc(); 343 SwContentNode * pCNd = rCursorPos.GetNode().GetContentNode(); 344 if( !pCNd ) 345 pCNd = pMyDoc->GetNodes().GoNext( &rCursorPos ); 346 347 EndCursorMove(); 348 } 349 350 SwGlblDocContent::SwGlblDocContent( SwNodeOffset nPos ) 351 { 352 m_eType = GLBLDOC_UNKNOWN; 353 m_PTR.pTOX = nullptr; 354 m_nDocPos = nPos; 355 } 356 357 SwGlblDocContent::SwGlblDocContent( const SwTOXBaseSection* pTOX ) 358 { 359 m_eType = GLBLDOC_TOXBASE; 360 m_PTR.pTOX = pTOX; 361 362 const SwSectionNode* pSectNd = pTOX->GetFormat()->GetSectionNode(); 363 m_nDocPos = pSectNd ? pSectNd->GetIndex() : SwNodeOffset(0); 364 } 365 366 SwGlblDocContent::SwGlblDocContent( const SwSection* pSect ) 367 { 368 m_eType = GLBLDOC_SECTION; 369 m_PTR.pSect = pSect; 370 371 const SwSectionNode* pSectNd = pSect->GetFormat()->GetSectionNode(); 372 m_nDocPos = pSectNd ? pSectNd->GetIndex() : SwNodeOffset(0); 373 } 374 375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 376
