Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / crsr / crbm.cxx
blobe296bd50e8fefe1b7bc40e3f691a9b1d0207fa20
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <crsrsh.hxx>
21 #include <ndtxt.hxx>
22 #include <rootfrm.hxx>
23 #include <txtfrm.hxx>
24 #include <IMark.hxx>
25 #include <swcrsr.hxx>
26 #include <IDocumentMarkAccess.hxx>
27 #include <IDocumentSettingAccess.hxx>
29 namespace
31 struct CursorStateHelper
33 explicit CursorStateHelper(SwCursorShell const & rShell)
34 : m_pCursor(rShell.GetCursor())
35 , m_aSaveState(*m_pCursor)
36 { }
38 void SetCursorToMark(::sw::mark::IMark const * const pMark)
40 *(m_pCursor->GetPoint()) = pMark->GetMarkStart();
41 if(pMark->IsExpanded())
43 m_pCursor->SetMark();
44 *(m_pCursor->GetMark()) = pMark->GetMarkEnd();
48 /// returns true if the Cursor had been rolled back
49 bool RollbackIfIllegal()
51 if(m_pCursor->IsSelOvr(SwCursorSelOverFlags::CheckNodeSection
52 | SwCursorSelOverFlags::Toggle))
54 m_pCursor->DeleteMark();
55 m_pCursor->RestoreSavePos();
56 return true;
58 return false;
61 SwCursor* m_pCursor;
62 SwCursorSaveState m_aSaveState;
65 bool lcl_ReverseMarkOrderingByEnd(const ::sw::mark::IMark* pFirst,
66 const ::sw::mark::IMark* pSecond)
68 return pFirst->GetMarkEnd() > pSecond->GetMarkEnd();
71 bool lcl_IsInvisibleBookmark(const ::sw::mark::IMark* pMark)
73 return IDocumentMarkAccess::GetType(*pMark) != IDocumentMarkAccess::MarkType::BOOKMARK;
77 // at CurrentCursor.SPoint
78 ::sw::mark::IMark* SwCursorShell::SetBookmark(
79 const vcl::KeyCode& rCode,
80 const OUString& rName,
81 IDocumentMarkAccess::MarkType eMark)
83 StartAction();
84 ::sw::mark::IMark* pMark = getIDocumentMarkAccess()->makeMark(
85 *GetCursor(),
86 rName,
87 eMark, sw::mark::InsertMode::New);
88 ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
89 if(pBookmark)
91 pBookmark->SetKeyCode(rCode);
92 pBookmark->SetShortName(OUString());
94 EndAction();
95 return pMark;
97 // set CurrentCursor.SPoint
99 // at CurrentCursor.SPoint
100 ::sw::mark::IMark* SwCursorShell::SetBookmark2(
101 const vcl::KeyCode& rCode,
102 const OUString& rName,
103 bool bHide,
104 const OUString& rCondition)
106 StartAction();
107 ::sw::mark::IMark* pMark = getIDocumentMarkAccess()->makeMark(
108 *GetCursor(),
109 rName,
110 IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
111 ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
112 if (pBookmark)
114 pBookmark->SetKeyCode(rCode);
115 pBookmark->SetShortName(OUString());
116 pBookmark->Hide(bHide);
117 pBookmark->SetHideCondition(rCondition);
119 EndAction();
120 return pMark;
123 namespace sw {
125 bool IsMarkHidden(SwRootFrame const& rLayout, ::sw::mark::IMark const& rMark)
127 if (!rLayout.HasMergedParas())
129 return false;
131 SwNode const& rNode(rMark.GetMarkPos().GetNode());
132 SwTextNode const*const pTextNode(rNode.GetTextNode());
133 if (pTextNode == nullptr)
134 { // UNO_BOOKMARK may point to table node
135 return rNode.GetRedlineMergeFlag() == SwNode::Merge::Hidden;
137 SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(
138 pTextNode->getLayoutFrame(&rLayout)));
139 if (!pFrame)
141 return true;
143 if (rMark.IsExpanded())
145 SwTextFrame const*const pOtherFrame(static_cast<SwTextFrame const*>(
146 rMark.GetOtherMarkPos().GetNode().GetTextNode()->getLayoutFrame(&rLayout)));
147 return pFrame == pOtherFrame
148 && pFrame->MapModelToViewPos(rMark.GetMarkPos())
149 == pFrame->MapModelToViewPos(rMark.GetOtherMarkPos());
151 else
153 if (rMark.GetMarkPos().GetContentIndex() == pTextNode->Len())
154 { // at end of node: never deleted (except if node deleted)
155 return pTextNode->GetRedlineMergeFlag() == SwNode::Merge::Hidden;
157 else
158 { // check character following mark pos
159 return pFrame->MapModelToViewPos(rMark.GetMarkPos())
160 == pFrame->MapModelToView(pTextNode, rMark.GetMarkPos().GetContentIndex() + 1);
165 } // namespace sw
167 // set CurrentCursor.SPoint
168 bool SwCursorShell::GotoMark(const ::sw::mark::IMark* const pMark, bool bAtStart)
170 if (sw::IsMarkHidden(*GetLayout(), *pMark))
172 return false;
174 // watch Cursor-Moves
175 CursorStateHelper aCursorSt(*this);
176 if ( bAtStart )
177 *aCursorSt.m_pCursor->GetPoint() = pMark->GetMarkStart();
178 else
179 *aCursorSt.m_pCursor->GetPoint() = pMark->GetMarkEnd();
181 if(aCursorSt.RollbackIfIllegal()) return false;
183 UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
184 return true;
187 bool SwCursorShell::GotoMark(const ::sw::mark::IMark* const pMark)
189 if (sw::IsMarkHidden(*GetLayout(), *pMark))
191 return false;
193 // watch Cursor-Moves
194 CursorStateHelper aCursorSt(*this);
195 aCursorSt.SetCursorToMark(pMark);
197 if(aCursorSt.RollbackIfIllegal()) return false;
199 UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
200 return true;
203 bool SwCursorShell::GoNextBookmark()
205 IDocumentMarkAccess* pMarkAccess = getIDocumentMarkAccess();
206 std::vector<::sw::mark::IMark*> vCandidates;
207 remove_copy_if(
208 pMarkAccess->findFirstBookmarkStartsAfter(*GetCursor()->GetPoint()),
209 pMarkAccess->getBookmarksEnd(),
210 back_inserter(vCandidates),
211 &lcl_IsInvisibleBookmark);
213 // watch Cursor-Moves
214 CursorStateHelper aCursorSt(*this);
215 auto ppMark = vCandidates.begin();
216 for(; ppMark!=vCandidates.end(); ++ppMark)
218 if (sw::IsMarkHidden(*GetLayout(), **ppMark))
220 continue;
222 aCursorSt.SetCursorToMark(*ppMark);
223 if(!aCursorSt.RollbackIfIllegal())
224 break; // found legal move
226 if(ppMark==vCandidates.end())
228 SttEndDoc(false);
229 return false;
232 UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
233 return true;
236 bool SwCursorShell::GoPrevBookmark()
238 IDocumentMarkAccess* pMarkAccess = getIDocumentMarkAccess();
239 // candidates from which to choose the mark before
240 // no need to consider marks starting after rPos
241 std::vector<::sw::mark::IMark*> vCandidates;
242 remove_copy_if(
243 pMarkAccess->getBookmarksBegin(),
244 pMarkAccess->findFirstBookmarkStartsAfter(*GetCursor()->GetPoint()),
245 back_inserter(vCandidates),
246 &lcl_IsInvisibleBookmark);
247 sort(
248 vCandidates.begin(),
249 vCandidates.end(),
250 &lcl_ReverseMarkOrderingByEnd);
252 // watch Cursor-Moves
253 CursorStateHelper aCursorSt(*this);
254 auto ppMark = vCandidates.begin();
255 for(; ppMark!=vCandidates.end(); ++ppMark)
257 // ignoring those not ending before the Cursor
258 // (we were only able to eliminate those starting
259 // behind the Cursor by the upper_bound(..)
260 // above)
261 if(!((**ppMark).GetMarkEnd() < *GetCursor()->GetPoint()))
262 continue;
263 if (sw::IsMarkHidden(*GetLayout(), **ppMark))
265 continue;
267 aCursorSt.SetCursorToMark(*ppMark);
268 if(!aCursorSt.RollbackIfIllegal())
269 break; // found legal move
271 if(ppMark==vCandidates.end())
273 SttEndDoc(true);
274 return false;
277 UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
278 return true;
281 bool SwCursorShell::IsFormProtected()
283 return getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FORM);
286 ::sw::mark::IFieldmark* SwCursorShell::GetCurrentFieldmark()
288 // TODO: Refactor
289 SwPosition pos(*GetCursor()->Start());
290 return getIDocumentMarkAccess()->getInnerFieldmarkFor(pos);
293 sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter(bool bLoop)
295 SwPosition pos(*GetCursor()->GetPoint());
296 return getIDocumentMarkAccess()->getFieldmarkAfter(pos, bLoop);
299 sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore(bool bLoop)
301 SwPosition pos(*GetCursor()->GetPoint());
302 return getIDocumentMarkAccess()->getFieldmarkBefore(pos, bLoop);
305 bool SwCursorShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark)
307 if(pMark==nullptr) return false;
309 // watch Cursor-Moves
310 CursorStateHelper aCursorSt(*this);
311 aCursorSt.SetCursorToMark(pMark);
312 aCursorSt.m_pCursor->GetPoint()->AdjustContent(+1);
313 aCursorSt.m_pCursor->GetMark()->AdjustContent(-1);
315 if(aCursorSt.RollbackIfIllegal()) return false;
317 UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
318 return true;
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */