xref: /core/sw/source/core/edit/edglbldc.cxx (revision ada3cf7a)
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