File: | home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx |
Warning: | line 1796, column 42 Called C++ object pointer is null |
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 <o3tl/any.hxx> | |||
22 | #include <svl/itemiter.hxx> | |||
23 | #include <vcl/imapobj.hxx> | |||
24 | #include <editeng/protitem.hxx> | |||
25 | #include <svx/svdogrp.hxx> | |||
26 | #include <svx/svdouno.hxx> | |||
27 | #include <tools/globname.hxx> | |||
28 | #include <sot/exchange.hxx> | |||
29 | #include <com/sun/star/form/FormButtonType.hpp> | |||
30 | #include <com/sun/star/beans/XPropertySet.hpp> | |||
31 | #include <com/sun/star/embed/XEmbeddedObject.hpp> | |||
32 | #include <comphelper/types.hxx> | |||
33 | #include <fmtanchr.hxx> | |||
34 | #include <fmtcntnt.hxx> | |||
35 | #include <fmtornt.hxx> | |||
36 | #include <fmturl.hxx> | |||
37 | #include <fmtfsize.hxx> | |||
38 | #include <docary.hxx> | |||
39 | #include <fesh.hxx> | |||
40 | #include <rootfrm.hxx> | |||
41 | #include <pagefrm.hxx> | |||
42 | #include <cntfrm.hxx> | |||
43 | #include <txtfrm.hxx> | |||
44 | #include <viewimp.hxx> | |||
45 | #include <viscrs.hxx> | |||
46 | #include <doc.hxx> | |||
47 | #include <IDocumentDrawModelAccess.hxx> | |||
48 | #include <IDocumentUndoRedo.hxx> | |||
49 | #include <IDocumentState.hxx> | |||
50 | #include <IDocumentLayoutAccess.hxx> | |||
51 | #include <dview.hxx> | |||
52 | #include <dflyobj.hxx> | |||
53 | #include <dcontact.hxx> | |||
54 | #include <frmfmt.hxx> | |||
55 | #include <flyfrm.hxx> | |||
56 | #include <ndtxt.hxx> | |||
57 | #include <swtable.hxx> | |||
58 | #include <ndgrf.hxx> | |||
59 | #include <flyfrms.hxx> | |||
60 | #include <fldbas.hxx> | |||
61 | #include <fmtfld.hxx> | |||
62 | #include <swundo.hxx> | |||
63 | #include <txatbase.hxx> | |||
64 | #include <frame.hxx> | |||
65 | #include <notxtfrm.hxx> | |||
66 | #include <HandleAnchorNodeChg.hxx> | |||
67 | #include <frmatr.hxx> | |||
68 | #include <fmtsrnd.hxx> | |||
69 | #include <ndole.hxx> | |||
70 | #include <fefly.hxx> | |||
71 | #include <fmtcnct.hxx> | |||
72 | #include <frameformats.hxx> | |||
73 | #include <textboxhelper.hxx> | |||
74 | ||||
75 | ||||
76 | using namespace ::com::sun::star; | |||
77 | ||||
78 | // Based on the request, changes to the specific layouts will be made, to | |||
79 | // fit to the format | |||
80 | static bool lcl_SetNewFlyPos( const SwNode& rNode, SwFormatAnchor& rAnchor, | |||
81 | const Point& rPt ) | |||
82 | { | |||
83 | bool bRet = false; | |||
84 | const SwStartNode* pStNode = rNode.FindFlyStartNode(); | |||
85 | if( pStNode ) | |||
86 | { | |||
87 | SwPosition aPos( *pStNode ); | |||
88 | rAnchor.SetAnchor( &aPos ); | |||
89 | bRet = true; | |||
90 | } | |||
91 | else | |||
92 | { | |||
93 | const SwContentNode *pCntNd = rNode.GetContentNode(); | |||
94 | std::pair<Point, bool> const tmp(rPt, false); | |||
95 | const SwContentFrame* pCFrame = pCntNd ? pCntNd->getLayoutFrame( | |||
96 | pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), | |||
97 | nullptr, &tmp) : nullptr; | |||
98 | const SwPageFrame *pPg = pCFrame ? pCFrame->FindPageFrame() : nullptr; | |||
99 | ||||
100 | rAnchor.SetPageNum( pPg ? pPg->GetPhyPageNum() : 1 ); | |||
101 | rAnchor.SetType( RndStdIds::FLY_AT_PAGE ); | |||
102 | } | |||
103 | return bRet; | |||
104 | } | |||
105 | ||||
106 | static bool lcl_FindAnchorPos( | |||
107 | SwDoc& rDoc, | |||
108 | const Point& rPt, | |||
109 | const SwFrame& rFrame, | |||
110 | SfxItemSet& rSet ) | |||
111 | { | |||
112 | bool bRet = true; | |||
113 | SwFormatAnchor aNewAnch( rSet.Get( RES_ANCHOR ) ); | |||
114 | RndStdIds nNew = aNewAnch.GetAnchorId(); | |||
115 | const SwFrame *pNewAnch; | |||
116 | ||||
117 | //determine new anchor | |||
118 | Point aTmpPnt( rPt ); | |||
119 | switch( nNew ) | |||
120 | { | |||
121 | case RndStdIds::FLY_AS_CHAR: // also include this? | |||
122 | case RndStdIds::FLY_AT_PARA: | |||
123 | case RndStdIds::FLY_AT_CHAR: // LAYER_IMPL | |||
124 | { | |||
125 | // starting from the upper-left corner of the Fly, | |||
126 | // search nearest ContentFrame | |||
127 | const SwFrame* pFrame = rFrame.IsFlyFrame() ? static_cast<const SwFlyFrame&>(rFrame).GetAnchorFrame() | |||
128 | : &rFrame; | |||
129 | pNewAnch = ::FindAnchor( pFrame, aTmpPnt ); | |||
130 | if( pNewAnch->IsProtected() ) | |||
131 | { | |||
132 | bRet = false; | |||
133 | break; | |||
134 | } | |||
135 | SwPosition aPos( pNewAnch->IsTextFrame() | |||
136 | ? *static_cast<SwTextFrame const*>(pNewAnch)->GetTextNodeForParaProps() | |||
137 | : *static_cast<const SwNoTextFrame*>(pNewAnch)->GetNode() ); | |||
138 | if ((RndStdIds::FLY_AT_CHAR == nNew) || (RndStdIds::FLY_AS_CHAR == nNew)) | |||
139 | { | |||
140 | // textnode should be found, as only in those | |||
141 | // a content bound frame can be anchored | |||
142 | SwCursorMoveState aState( CursorMoveState::SetOnlyText ); | |||
143 | aTmpPnt.setX(aTmpPnt.getX() - 1); // do not land in the fly! | |||
144 | if( !pNewAnch->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState ) ) | |||
145 | { | |||
146 | assert(pNewAnch->IsTextFrame())(static_cast <bool> (pNewAnch->IsTextFrame()) ? void (0) : __assert_fail ("pNewAnch->IsTextFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" , 146, __extension__ __PRETTY_FUNCTION__)); // because AT_CHAR/AS_CHAR | |||
147 | SwTextFrame const*const pTextFrame( | |||
148 | static_cast<SwTextFrame const*>(pNewAnch)); | |||
149 | if( pNewAnch->getFrameArea().Bottom() < aTmpPnt.Y() ) | |||
150 | { | |||
151 | aPos = pTextFrame->MapViewToModelPos(TextFrameIndex(0)); | |||
152 | } | |||
153 | else | |||
154 | { | |||
155 | aPos = pTextFrame->MapViewToModelPos( | |||
156 | TextFrameIndex(pTextFrame->GetText().getLength())); | |||
157 | } | |||
158 | } | |||
159 | else | |||
160 | { | |||
161 | if ( SwCursorShell::PosInsideInputField( aPos ) ) | |||
162 | { | |||
163 | aPos.nContent = SwCursorShell::StartOfInputFieldAtPos( aPos ); | |||
164 | } | |||
165 | } | |||
166 | } | |||
167 | aNewAnch.SetAnchor( &aPos ); | |||
168 | } | |||
169 | break; | |||
170 | ||||
171 | case RndStdIds::FLY_AT_FLY: // LAYER_IMPL | |||
172 | { | |||
173 | // starting from the upper-left corner of the Fly | |||
174 | // search nearest SwFlyFrame | |||
175 | SwCursorMoveState aState( CursorMoveState::SetOnlyText ); | |||
176 | SwPosition aPos( rDoc.GetNodes() ); | |||
177 | aTmpPnt.setX(aTmpPnt.getX() - 1); // do not land in the fly! | |||
178 | rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState ); | |||
179 | pNewAnch = ::FindAnchor( | |||
180 | aPos.nNode.GetNode().GetContentNode()->getLayoutFrame(rFrame.getRootFrame(), nullptr, nullptr), | |||
181 | aTmpPnt )->FindFlyFrame(); | |||
182 | ||||
183 | if( pNewAnch && &rFrame != pNewAnch && !pNewAnch->IsProtected() ) | |||
184 | { | |||
185 | aPos.nNode = *static_cast<const SwFlyFrame*>(pNewAnch)->GetFormat()->GetContent(). | |||
186 | GetContentIdx(); | |||
187 | aNewAnch.SetAnchor( &aPos ); | |||
188 | break; | |||
189 | } | |||
190 | } | |||
191 | ||||
192 | nNew = RndStdIds::FLY_AT_PAGE; | |||
193 | aNewAnch.SetType( nNew ); | |||
194 | [[fallthrough]]; | |||
195 | ||||
196 | case RndStdIds::FLY_AT_PAGE: | |||
197 | pNewAnch = rFrame.FindPageFrame(); | |||
198 | aNewAnch.SetPageNum( pNewAnch->GetPhyPageNum() ); | |||
199 | break; | |||
200 | ||||
201 | default: | |||
202 | OSL_ENSURE( false, "Wrong Id for new anchor." )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "202" ": "), "%s", "Wrong Id for new anchor."); } } while (false); | |||
203 | } | |||
204 | ||||
205 | rSet.Put( aNewAnch ); | |||
206 | return bRet; | |||
207 | } | |||
208 | ||||
209 | //! also used in unoframe.cxx | |||
210 | ||||
211 | bool sw_ChkAndSetNewAnchor( | |||
212 | const SwFlyFrame& rFly, | |||
213 | SfxItemSet& rSet ) | |||
214 | { | |||
215 | const SwFrameFormat& rFormat = *rFly.GetFormat(); | |||
216 | const SwFormatAnchor &rOldAnch = rFormat.GetAnchor(); | |||
217 | const RndStdIds nOld = rOldAnch.GetAnchorId(); | |||
218 | ||||
219 | RndStdIds nNew = rSet.Get( RES_ANCHOR ).GetAnchorId(); | |||
220 | ||||
221 | if( nOld == nNew ) | |||
222 | return false; | |||
223 | ||||
224 | SwDoc* pDoc = const_cast<SwDoc*>(rFormat.GetDoc()); | |||
225 | ||||
226 | #if OSL_DEBUG_LEVEL1 > 0 | |||
227 | OSL_ENSURE( !(nNew == RndStdIds::FLY_AT_PAGE &&do { if (true && (!(!(nNew == RndStdIds::FLY_AT_PAGE && (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) && pDoc->IsInHeaderFooter ( rOldAnch.GetContentAnchor()->nNode ))))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "230" ": "), "%s", "forbidden anchor change in Head/Foot." ); } } while (false) | |||
228 | (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) &&do { if (true && (!(!(nNew == RndStdIds::FLY_AT_PAGE && (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) && pDoc->IsInHeaderFooter ( rOldAnch.GetContentAnchor()->nNode ))))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "230" ": "), "%s", "forbidden anchor change in Head/Foot." ); } } while (false) | |||
229 | pDoc->IsInHeaderFooter( rOldAnch.GetContentAnchor()->nNode )),do { if (true && (!(!(nNew == RndStdIds::FLY_AT_PAGE && (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) && pDoc->IsInHeaderFooter ( rOldAnch.GetContentAnchor()->nNode ))))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "230" ": "), "%s", "forbidden anchor change in Head/Foot." ); } } while (false) | |||
230 | "forbidden anchor change in Head/Foot." )do { if (true && (!(!(nNew == RndStdIds::FLY_AT_PAGE && (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) && pDoc->IsInHeaderFooter ( rOldAnch.GetContentAnchor()->nNode ))))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "230" ": "), "%s", "forbidden anchor change in Head/Foot." ); } } while (false); | |||
231 | #endif | |||
232 | ||||
233 | return ::lcl_FindAnchorPos( *pDoc, rFly.getFrameArea().Pos(), rFly, rSet ); | |||
234 | } | |||
235 | ||||
236 | void SwFEShell::SelectFlyFrame( SwFlyFrame& rFrame ) | |||
237 | { | |||
238 | CurrShell aCurr( this ); | |||
239 | ||||
240 | // The frame is new, thus select it. | |||
241 | // !! Always select the frame, if it's not selected. | |||
242 | // - it could be a new "old" one because the anchor was changed | |||
243 | // - "old" frames have had to be selected previously otherwise they could | |||
244 | // not have been changed | |||
245 | // The frames should not be selected by the document position, because | |||
246 | // it should have been selected! | |||
247 | SwViewShellImp *pImpl = Imp(); | |||
248 | if( !GetWin() ) | |||
249 | return; | |||
250 | ||||
251 | OSL_ENSURE( rFrame.IsFlyFrame(), "SelectFlyFrame wants a Fly" )do { if (true && (!(rFrame.IsFlyFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "251" ": "), "%s", "SelectFlyFrame wants a Fly"); } } while (false); | |||
252 | ||||
253 | // nothing to be done if the Fly already was selected | |||
254 | if (GetSelectedFlyFrame() == &rFrame) | |||
255 | return; | |||
256 | ||||
257 | // assure the anchor is drawn | |||
258 | if( rFrame.IsFlyInContentFrame() && rFrame.GetAnchorFrame() ) | |||
259 | rFrame.GetAnchorFrame()->SetCompletePaint(); | |||
260 | ||||
261 | if( pImpl->GetDrawView()->AreObjectsMarked() ) | |||
262 | pImpl->GetDrawView()->UnmarkAll(); | |||
263 | ||||
264 | pImpl->GetDrawView()->MarkObj( rFrame.GetVirtDrawObj(), | |||
265 | pImpl->GetPageView() ); | |||
266 | ||||
267 | rFrame.SelectionHasChanged(this); | |||
268 | ||||
269 | KillPams(); | |||
270 | ClearMark(); | |||
271 | SelFlyGrabCursor(); | |||
272 | } | |||
273 | ||||
274 | // Get selected fly | |||
275 | SwFlyFrame* SwFEShell::GetSelectedFlyFrame() const | |||
276 | { | |||
277 | if ( Imp()->HasDrawView() ) | |||
278 | { | |||
279 | // A Fly is only accessible if it is selected | |||
280 | const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); | |||
281 | if( rMrkList.GetMarkCount() != 1 ) | |||
282 | return nullptr; | |||
283 | ||||
284 | SdrObject *pO = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); | |||
285 | ||||
286 | SwVirtFlyDrawObj *pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pO); | |||
287 | ||||
288 | return pFlyObj ? pFlyObj->GetFlyFrame() : nullptr; | |||
289 | } | |||
290 | return nullptr; | |||
291 | } | |||
292 | ||||
293 | // Get current fly in which the cursor is positioned | |||
294 | SwFlyFrame* SwFEShell::GetCurrFlyFrame(const bool bCalcFrame) const | |||
295 | { | |||
296 | SwContentFrame *pContent = GetCurrFrame(bCalcFrame); | |||
297 | return pContent ? pContent->FindFlyFrame() : nullptr; | |||
298 | } | |||
299 | ||||
300 | // Get selected fly, but if none Get current fly in which the cursor is positioned | |||
301 | SwFlyFrame* SwFEShell::GetSelectedOrCurrFlyFrame() const | |||
302 | { | |||
303 | SwFlyFrame *pFly = GetSelectedFlyFrame(); | |||
304 | if (pFly) | |||
305 | return pFly; | |||
306 | return GetCurrFlyFrame(); | |||
307 | } | |||
308 | ||||
309 | // Returns non-null pointer, if the current Fly could be anchored to another one (so it is inside) | |||
310 | const SwFrameFormat* SwFEShell::IsFlyInFly() | |||
311 | { | |||
312 | CurrShell aCurr( this ); | |||
313 | ||||
314 | if ( !Imp()->HasDrawView() ) | |||
315 | return nullptr; | |||
316 | ||||
317 | const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); | |||
318 | if ( !rMrkList.GetMarkCount() ) | |||
319 | { | |||
320 | SwFlyFrame *pFly = GetCurrFlyFrame(false); | |||
321 | if (!pFly) | |||
322 | return nullptr; | |||
323 | return pFly->GetFormat(); | |||
324 | } | |||
325 | else if ( rMrkList.GetMarkCount() != 1 || | |||
326 | !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) ) | |||
327 | return nullptr; | |||
328 | ||||
329 | SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); | |||
330 | ||||
331 | SwFrameFormat *pFormat = FindFrameFormat( pObj ); | |||
332 | if( pFormat && RndStdIds::FLY_AT_FLY == pFormat->GetAnchor().GetAnchorId() ) | |||
333 | { | |||
334 | const SwFrame* pFly; | |||
335 | if (SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj *>(pObj)) | |||
336 | { | |||
337 | pFly = pFlyObj->GetFlyFrame()->GetAnchorFrame(); | |||
338 | } | |||
339 | else | |||
340 | { | |||
341 | pFly = static_cast<SwDrawContact*>(GetUserCall(pObj))->GetAnchorFrame(pObj); | |||
342 | } | |||
343 | ||||
344 | OSL_ENSURE( pFly, "IsFlyInFly: Where's my anchor?" )do { if (true && (!(pFly))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "344" ": "), "%s", "IsFlyInFly: Where's my anchor?"); } } while (false); | |||
345 | OSL_ENSURE( pFly->IsFlyFrame(), "IsFlyInFly: Funny anchor!" )do { if (true && (!(pFly->IsFlyFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "345" ": "), "%s", "IsFlyInFly: Funny anchor!"); } } while (false); | |||
346 | return static_cast<const SwFlyFrame*>(pFly)->GetFormat(); | |||
347 | } | |||
348 | ||||
349 | Point aTmpPos = pObj->GetCurrentBoundRect().TopLeft(); | |||
350 | ||||
351 | SwFrame *pTextFrame; | |||
352 | { | |||
353 | SwCursorMoveState aState( CursorMoveState::SetOnlyText ); | |||
354 | SwNodeIndex aSwNodeIndex( GetDoc()->GetNodes() ); | |||
355 | SwPosition aPos( aSwNodeIndex ); | |||
356 | Point aPoint( aTmpPos ); | |||
357 | aPoint.setX(aPoint.getX() - 1); //do not land in the fly!! | |||
358 | GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState ); | |||
359 | // determine text frame by left-top-corner of object | |||
360 | SwContentNode *pNd = aPos.nNode.GetNode().GetContentNode(); | |||
361 | std::pair<Point, bool> const tmp(aTmpPos, false); | |||
362 | pTextFrame = pNd ? pNd->getLayoutFrame(GetLayout(), nullptr, &tmp) : nullptr; | |||
363 | } | |||
364 | const SwFrame *pTmp = pTextFrame ? ::FindAnchor(pTextFrame, aTmpPos) : nullptr; | |||
365 | const SwFlyFrame *pFly = pTmp ? pTmp->FindFlyFrame() : nullptr; | |||
366 | if( pFly ) | |||
367 | return pFly->GetFormat(); | |||
368 | return nullptr; | |||
369 | } | |||
370 | ||||
371 | void SwFEShell::SetFlyPos( const Point& rAbsPos ) | |||
372 | { | |||
373 | CurrShell aCurr( this ); | |||
374 | ||||
375 | // Determine reference point in document coordinates | |||
376 | SwFlyFrame *pFly = GetCurrFlyFrame(false); | |||
377 | if (!pFly) | |||
378 | return; | |||
379 | ||||
380 | //SwSaveHdl aSaveX( Imp() ); | |||
381 | ||||
382 | // Set an anchor starting from the absolute position for paragraph bound Flys | |||
383 | // Anchor and new RelPos will be calculated and set by the Fly | |||
384 | if ( pFly->IsFlyAtContentFrame() ) | |||
385 | { | |||
386 | if(pFly->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(pFly)->isTransformableSwFrame()) | |||
387 | { | |||
388 | // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used), | |||
389 | // we need to correct the absolute position (rAbsPos) which was created in | |||
390 | // transformed coordinates to untransformed state | |||
391 | TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(pFly)->getTransformableSwFrame()); | |||
392 | const SwRect aUntransformedFrameArea(pTransformableSwFrame->getUntransformedFrameArea()); | |||
393 | const Point aNewAbsPos( | |||
394 | rAbsPos.X() + aUntransformedFrameArea.Left() - pFly->getFrameArea().Left(), | |||
395 | rAbsPos.Y() + aUntransformedFrameArea.Top() - pFly->getFrameArea().Top()); | |||
396 | static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos(aNewAbsPos); | |||
397 | } | |||
398 | else | |||
399 | { | |||
400 | static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos ); | |||
401 | } | |||
402 | } | |||
403 | else | |||
404 | { | |||
405 | const SwFrame *pAnch = pFly->GetAnchorFrame(); | |||
406 | Point aOrient( pAnch->getFrameArea().Pos() ); | |||
407 | ||||
408 | if ( pFly->IsFlyInContentFrame() ) | |||
409 | aOrient.setX(rAbsPos.getX()); | |||
410 | ||||
411 | // calculate RelPos. | |||
412 | aOrient.setX(rAbsPos.getX() - aOrient.getX()); | |||
413 | aOrient.setY(rAbsPos.getY() - aOrient.getY()); | |||
414 | pFly->ChgRelPos( aOrient ); | |||
415 | } | |||
416 | CallChgLnk(); // call the AttrChangeNotify on the UI-side. | |||
417 | } | |||
418 | ||||
419 | Point SwFEShell::FindAnchorPos( const Point& rAbsPos, bool bMoveIt ) | |||
420 | { | |||
421 | Point aRet; | |||
422 | ||||
423 | CurrShell aCurr( this ); | |||
424 | ||||
425 | if ( !Imp()->HasDrawView() ) | |||
426 | return aRet; | |||
427 | ||||
428 | const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); | |||
429 | if ( rMrkList.GetMarkCount() != 1 || | |||
430 | !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) ) | |||
431 | return aRet; | |||
432 | ||||
433 | SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); | |||
434 | // #i28701# | |||
435 | SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj ); | |||
436 | SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat(); | |||
437 | const RndStdIds nAnchorId = rFormat.GetAnchor().GetAnchorId(); | |||
438 | ||||
439 | if ( RndStdIds::FLY_AS_CHAR == nAnchorId ) | |||
440 | return aRet; | |||
441 | ||||
442 | bool bFlyFrame = dynamic_cast<SwVirtFlyDrawObj *>(pObj) != nullptr; | |||
443 | ||||
444 | bool bTextBox = false; | |||
445 | if (rFormat.Which() == RES_DRAWFRMFMT) | |||
446 | { | |||
447 | bTextBox = SwTextBoxHelper::isTextBox(&rFormat, RES_DRAWFRMFMT); | |||
448 | } | |||
449 | ||||
450 | SwFlyFrame* pFly = nullptr; | |||
451 | const SwFrame* pFooterOrHeader = nullptr; | |||
452 | ||||
453 | if( bFlyFrame ) | |||
454 | { | |||
455 | // Calculate reference point in document coordinates | |||
456 | SwContentFrame *pContent = GetCurrFrame( false ); | |||
457 | if( !pContent ) | |||
458 | return aRet; | |||
459 | pFly = pContent->FindFlyFrame(); | |||
460 | if ( !pFly ) | |||
461 | return aRet; | |||
462 | const SwFrame* pOldAnch = pFly->GetAnchorFrame(); | |||
463 | if( !pOldAnch ) | |||
464 | return aRet; | |||
465 | if ( RndStdIds::FLY_AT_PAGE != nAnchorId ) | |||
466 | { | |||
467 | pFooterOrHeader = pContent->FindFooterOrHeader(); | |||
468 | } | |||
469 | } | |||
470 | else if (bTextBox) | |||
471 | { | |||
472 | auto pFlyFormat = dynamic_cast<const SwFlyFrameFormat*>( | |||
473 | SwTextBoxHelper::getOtherTextBoxFormat(&rFormat, RES_DRAWFRMFMT)); | |||
474 | if (pFlyFormat) | |||
475 | { | |||
476 | pFly = pFlyFormat->GetFrame(); | |||
477 | } | |||
478 | } | |||
479 | ||||
480 | // set <pFooterOrHeader> also for drawing | |||
481 | // objects, but not for control objects. | |||
482 | // Necessary for moving 'anchor symbol' at the user interface inside header/footer. | |||
483 | else if ( !::CheckControlLayer( pObj ) ) | |||
484 | { | |||
485 | SwContentFrame *pContent = GetCurrFrame( false ); | |||
486 | if( !pContent ) | |||
487 | return aRet; | |||
488 | pFooterOrHeader = pContent->FindFooterOrHeader(); | |||
489 | } | |||
490 | ||||
491 | // Search nearest SwFlyFrame starting from the upper-left corner | |||
492 | // of the fly | |||
493 | SwContentFrame *pTextFrame = nullptr; | |||
494 | { | |||
495 | SwCursorMoveState aState( CursorMoveState::SetOnlyText ); | |||
496 | SwPosition aPos( GetDoc()->GetNodes().GetEndOfExtras() ); | |||
497 | Point aTmpPnt( rAbsPos ); | |||
498 | GetLayout()->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState ); | |||
499 | if (aPos.nNode != GetDoc()->GetNodes().GetEndOfExtras().GetIndex() | |||
500 | && (nAnchorId != RndStdIds::FLY_AT_CHAR || !PosInsideInputField(aPos))) | |||
501 | { | |||
502 | SwContentNode* pCNode = aPos.nNode.GetNode().GetContentNode(); | |||
503 | assert(pCNode)(static_cast <bool> (pCNode) ? void (0) : __assert_fail ("pCNode", "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" , 503, __extension__ __PRETTY_FUNCTION__)); | |||
504 | pTextFrame = pCNode->getLayoutFrame(GetLayout(), &aPos, nullptr); | |||
505 | } | |||
506 | } | |||
507 | const SwFrame *pNewAnch = nullptr; | |||
508 | if( pTextFrame != nullptr ) | |||
509 | { | |||
510 | if ( RndStdIds::FLY_AT_PAGE == nAnchorId ) | |||
511 | { | |||
512 | pNewAnch = pTextFrame->FindPageFrame(); | |||
513 | } | |||
514 | else | |||
515 | { | |||
516 | pNewAnch = ::FindAnchor( pTextFrame, rAbsPos ); | |||
517 | ||||
518 | if( RndStdIds::FLY_AT_FLY == nAnchorId ) // LAYER_IMPL | |||
519 | { | |||
520 | pNewAnch = pNewAnch->FindFlyFrame(); | |||
521 | } | |||
522 | } | |||
523 | } | |||
524 | ||||
525 | if( pNewAnch && !pNewAnch->IsProtected() ) | |||
526 | { | |||
527 | const SwFlyFrame* pCheck = (bFlyFrame || bTextBox) ? pNewAnch->FindFlyFrame() : nullptr; | |||
528 | // If we land inside the frame, make sure | |||
529 | // that the frame does not land inside its own content | |||
530 | while( pCheck ) | |||
531 | { | |||
532 | if( pCheck == pFly ) | |||
533 | break; | |||
534 | const SwFrame *pTmp = pCheck->GetAnchorFrame(); | |||
535 | pCheck = pTmp ? pTmp->FindFlyFrame() : nullptr; | |||
536 | } | |||
537 | ||||
538 | // Do not switch from header/footer to another area, | |||
539 | // do not switch to a header/footer | |||
540 | if( !pCheck && | |||
541 | pFooterOrHeader == pNewAnch->FindFooterOrHeader() ) | |||
542 | { | |||
543 | aRet = pNewAnch->GetFrameAnchorPos( ::HasWrap( pObj ) ); | |||
544 | ||||
545 | if ( bMoveIt || (nAnchorId == RndStdIds::FLY_AT_CHAR) ) | |||
546 | { | |||
547 | SwFormatAnchor aAnch( rFormat.GetAnchor() ); | |||
548 | switch ( nAnchorId ) | |||
549 | { | |||
550 | case RndStdIds::FLY_AT_PARA: | |||
551 | { | |||
552 | SwPosition pos = *aAnch.GetContentAnchor(); | |||
553 | pos.nNode = pTextFrame->IsTextFrame() | |||
554 | ? *static_cast<SwTextFrame const*>(pTextFrame)->GetTextNodeForParaProps() | |||
555 | : *static_cast<const SwNoTextFrame*>(pTextFrame)->GetNode(); | |||
556 | pos.nContent.Assign(nullptr,0); | |||
557 | aAnch.SetAnchor( &pos ); | |||
558 | break; | |||
559 | } | |||
560 | case RndStdIds::FLY_AT_PAGE: | |||
561 | { | |||
562 | aAnch.SetPageNum( static_cast<const SwPageFrame*>(pNewAnch)-> | |||
563 | GetPhyPageNum() ); | |||
564 | break; | |||
565 | } | |||
566 | ||||
567 | case RndStdIds::FLY_AT_FLY: | |||
568 | { | |||
569 | SwPosition aPos( *static_cast<const SwFlyFrame*>(pNewAnch)->GetFormat()-> | |||
570 | GetContent().GetContentIdx() ); | |||
571 | aAnch.SetAnchor( &aPos ); | |||
572 | break; | |||
573 | } | |||
574 | ||||
575 | case RndStdIds::FLY_AT_CHAR: | |||
576 | { | |||
577 | SwPosition pos = *aAnch.GetContentAnchor(); | |||
578 | Point aTmpPnt( rAbsPos ); | |||
579 | if( pTextFrame->GetModelPositionForViewPoint( &pos, aTmpPnt ) ) | |||
580 | { | |||
581 | SwRect aTmpRect; | |||
582 | pTextFrame->GetCharRect( aTmpRect, pos ); | |||
583 | aRet = aTmpRect.Pos(); | |||
584 | } | |||
585 | else | |||
586 | { | |||
587 | pos = static_cast<SwTextFrame const*>(pTextFrame)->MapViewToModelPos(TextFrameIndex(0)); | |||
588 | } | |||
589 | aAnch.SetAnchor( &pos ); | |||
590 | break; | |||
591 | } | |||
592 | default: | |||
593 | break; | |||
594 | ||||
595 | } | |||
596 | ||||
597 | if( bMoveIt ) | |||
598 | { | |||
599 | StartAllAction(); | |||
600 | // --> handle change of anchor node: | |||
601 | // if count of the anchor frame also change, the fly frames have to be | |||
602 | // re-created. Thus, delete all fly frames except the <this> before the | |||
603 | // anchor attribute is change and re-create them afterwards. | |||
604 | { | |||
605 | std::unique_ptr<SwHandleAnchorNodeChg, o3tl::default_delete<SwHandleAnchorNodeChg>> pHandleAnchorNodeChg; | |||
606 | SwFlyFrameFormat* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat*>(&rFormat) ); | |||
607 | if ( pFlyFrameFormat ) | |||
608 | { | |||
609 | pHandleAnchorNodeChg.reset( | |||
610 | new SwHandleAnchorNodeChg( *pFlyFrameFormat, aAnch )); | |||
611 | } | |||
612 | rFormat.GetDoc()->SetAttr( aAnch, rFormat ); | |||
613 | if (SwTextBoxHelper::getOtherTextBoxFormat(&rFormat, RES_DRAWFRMFMT)) | |||
614 | { | |||
615 | SwTextBoxHelper::syncFlyFrameAttr(rFormat, rFormat.GetAttrSet()); | |||
616 | } | |||
617 | } | |||
618 | // #i28701# - no call of method | |||
619 | // <CheckCharRectAndTopOfLine()> for to-character anchored | |||
620 | // Writer fly frame needed. This method call can cause a | |||
621 | // format of the anchor frame, which is no longer intended. | |||
622 | // Instead clear the anchor character rectangle and | |||
623 | // the top of line values for all to-character anchored objects. | |||
624 | pAnchoredObj->ClearCharRectAndTopOfLine(); | |||
625 | EndAllAction(); | |||
626 | } | |||
627 | } | |||
628 | ||||
629 | SwRect aTmpRect( aRet, rAbsPos ); | |||
630 | if( aTmpRect.HasArea() ) | |||
631 | MakeVisible( aTmpRect ); | |||
632 | #if OSL_DEBUG_LEVEL1 > 0 | |||
633 | //TODO: That doesn't seem to be intended | |||
634 | if( COL_TRANSPARENT != GetOut()->GetLineColor() ) | |||
635 | { | |||
636 | OSL_FAIL( "Hey, Joe: Where's my Null Pen?" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "636" ": "), "%s", "Hey, Joe: Where's my Null Pen?"); } } while (false); | |||
637 | GetOut()->SetLineColor( COL_TRANSPARENT ); | |||
638 | } | |||
639 | #endif | |||
640 | } | |||
641 | } | |||
642 | ||||
643 | return aRet; | |||
644 | } | |||
645 | ||||
646 | const SwFrameFormat *SwFEShell::NewFlyFrame( const SfxItemSet& rSet, bool bAnchValid, | |||
647 | SwFrameFormat *pParent ) | |||
648 | { | |||
649 | CurrShell aCurr( this ); | |||
650 | StartAllAction(); | |||
651 | ||||
652 | SwPaM* pCursor = GetCursor(); | |||
653 | const Point aPt( GetCursorDocPos() ); | |||
654 | ||||
655 | SwSelBoxes aBoxes; | |||
656 | bool bMoveContent = true; | |||
657 | if( IsTableMode() ) | |||
658 | { | |||
659 | GetTableSel( *this, aBoxes ); | |||
660 | if( !aBoxes.empty() ) | |||
661 | { | |||
662 | // Cursor should be removed from the removal area. | |||
663 | // Always put it after/on the table; via the | |||
664 | // document position they will be set to the old | |||
665 | // position | |||
666 | ParkCursor( SwNodeIndex( *aBoxes[0]->GetSttNd() )); | |||
667 | ||||
668 | // #i127787# pCurrentCursor will be deleted in ParkCursor, | |||
669 | // we better get the current pCurrentCursor instead of working with the | |||
670 | // deleted one: | |||
671 | pCursor = GetCursor(); | |||
672 | } | |||
673 | else | |||
674 | bMoveContent = false; | |||
675 | } | |||
676 | else if( !pCursor->HasMark() && !pCursor->IsMultiSelection() ) | |||
677 | bMoveContent = false; | |||
678 | ||||
679 | const SwPosition& rPos = *pCursor->Start(); | |||
680 | ||||
681 | SwFormatAnchor& rAnch = const_cast<SwFormatAnchor&>(rSet.Get( RES_ANCHOR )); | |||
682 | RndStdIds eRndId = rAnch.GetAnchorId(); | |||
683 | switch( eRndId ) | |||
684 | { | |||
685 | case RndStdIds::FLY_AT_PAGE: | |||
686 | if( !rAnch.GetPageNum() ) //HotFix: Bug in UpdateByExample | |||
687 | rAnch.SetPageNum( 1 ); | |||
688 | break; | |||
689 | ||||
690 | case RndStdIds::FLY_AT_FLY: | |||
691 | case RndStdIds::FLY_AT_PARA: | |||
692 | case RndStdIds::FLY_AT_CHAR: | |||
693 | case RndStdIds::FLY_AS_CHAR: | |||
694 | if( !bAnchValid ) | |||
695 | { | |||
696 | if( RndStdIds::FLY_AT_FLY != eRndId ) | |||
697 | { | |||
698 | rAnch.SetAnchor( &rPos ); | |||
699 | } | |||
700 | else if( lcl_SetNewFlyPos( rPos.nNode.GetNode(), rAnch, aPt ) ) | |||
701 | { | |||
702 | eRndId = RndStdIds::FLY_AT_PAGE; | |||
703 | } | |||
704 | } | |||
705 | break; | |||
706 | ||||
707 | default: | |||
708 | OSL_ENSURE( false, "What is the purpose of this Fly?" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "708" ": "), "%s", "What is the purpose of this Fly?"); } } while (false); | |||
709 | break; | |||
710 | } | |||
711 | ||||
712 | SwFlyFrameFormat *pRet; | |||
713 | if( bMoveContent ) | |||
714 | { | |||
715 | GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSLAYFMT, nullptr ); | |||
716 | std::unique_ptr<SwFormatAnchor> pOldAnchor; | |||
717 | bool bHOriChgd = false, bVOriChgd = false; | |||
718 | std::shared_ptr<SwFormatVertOrient> aOldV; | |||
719 | std::shared_ptr<SwFormatHoriOrient> aOldH; | |||
720 | ||||
721 | if ( RndStdIds::FLY_AT_PAGE != eRndId ) | |||
722 | { | |||
723 | // First as with page link. Paragraph/character link on if | |||
724 | // everything was shifted. Then the position is valid! | |||
725 | // JP 13.05.98: if necessary also convert the horizontal/vertical | |||
726 | // orientation, to prevent correction during re-anchoring | |||
727 | pOldAnchor.reset(new SwFormatAnchor( rAnch )); | |||
728 | const_cast<SfxItemSet&>(rSet).Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, 1 ) ); | |||
729 | ||||
730 | const SfxPoolItem* pItem; | |||
731 | if( SfxItemState::SET == rSet.GetItemState( RES_HORI_ORIENT, false, &pItem ) | |||
732 | && text::HoriOrientation::NONE == static_cast<const SwFormatHoriOrient*>(pItem)->GetHoriOrient() ) | |||
733 | { | |||
734 | bHOriChgd = true; | |||
735 | aOldH.reset(static_cast<SwFormatHoriOrient*>(pItem->Clone())); | |||
736 | const_cast<SfxItemSet&>(rSet).Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT ) ); | |||
737 | } | |||
738 | if( SfxItemState::SET == rSet.GetItemState( RES_VERT_ORIENT, false, &pItem ) | |||
739 | && text::VertOrientation::NONE == static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() ) | |||
740 | { | |||
741 | bVOriChgd = true; | |||
742 | aOldV.reset(static_cast<SwFormatVertOrient*>(pItem->Clone())); | |||
743 | const_cast<SfxItemSet&>(rSet).Put( SwFormatVertOrient( 0, text::VertOrientation::TOP ) ); | |||
744 | } | |||
745 | } | |||
746 | ||||
747 | pRet = GetDoc()->MakeFlyAndMove( *pCursor, rSet, &aBoxes, pParent ); | |||
748 | ||||
749 | KillPams(); | |||
750 | ||||
751 | if( pOldAnchor ) | |||
752 | { | |||
753 | if( pRet ) | |||
754 | { | |||
755 | // calculate new position | |||
756 | // JP 24.03.97: also go via page links | |||
757 | // anchor should not lie in the shifted area | |||
758 | pRet->DelFrames(); | |||
759 | ||||
760 | const SwFrame* pAnch = ::FindAnchor( GetLayout(), aPt ); | |||
761 | SwPosition aPos( pAnch->IsTextFrame() | |||
762 | ? *static_cast<SwTextFrame const*>(pAnch)->GetTextNodeForParaProps() | |||
763 | : *static_cast<const SwNoTextFrame*>(pAnch)->GetNode() ); | |||
764 | ||||
765 | if ( RndStdIds::FLY_AS_CHAR == eRndId ) | |||
766 | { | |||
767 | assert(pAnch->IsTextFrame())(static_cast <bool> (pAnch->IsTextFrame()) ? void (0 ) : __assert_fail ("pAnch->IsTextFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" , 767, __extension__ __PRETTY_FUNCTION__)); | |||
768 | aPos = static_cast<SwTextFrame const*>(pAnch)->MapViewToModelPos(TextFrameIndex(0)); | |||
769 | } | |||
770 | pOldAnchor->SetAnchor( &aPos ); | |||
771 | ||||
772 | // shifting of table selection is not Undo-capable. therefore | |||
773 | // changing the anchors should not be recorded | |||
774 | bool const bDoesUndo = | |||
775 | GetDoc()->GetIDocumentUndoRedo().DoesUndo(); | |||
776 | SwUndoId nLastUndoId(SwUndoId::EMPTY); | |||
777 | if (bDoesUndo && | |||
778 | GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(nullptr, | |||
779 | & nLastUndoId)) | |||
780 | { | |||
781 | if (SwUndoId::INSLAYFMT == nLastUndoId) | |||
782 | { | |||
783 | GetDoc()->GetIDocumentUndoRedo().DoUndo(false); | |||
784 | } | |||
785 | } | |||
786 | ||||
787 | const_cast<SfxItemSet&>(rSet).Put( *pOldAnchor ); | |||
788 | ||||
789 | if( bHOriChgd ) | |||
790 | const_cast<SfxItemSet&>(rSet).Put( *aOldH ); | |||
791 | if( bVOriChgd ) | |||
792 | const_cast<SfxItemSet&>(rSet).Put( *aOldV ); | |||
793 | ||||
794 | GetDoc()->SetFlyFrameAttr( *pRet, const_cast<SfxItemSet&>(rSet) ); | |||
795 | GetDoc()->GetIDocumentUndoRedo().DoUndo(bDoesUndo); | |||
796 | } | |||
797 | } | |||
798 | GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSLAYFMT, nullptr ); | |||
799 | } | |||
800 | else | |||
801 | /* If called from a shell try to propagate an | |||
802 | existing adjust item from rPos to the content node of the | |||
803 | new frame. */ | |||
804 | pRet = GetDoc()->MakeFlySection( eRndId, &rPos, &rSet, pParent, true ); | |||
805 | ||||
806 | if( pRet ) | |||
807 | { | |||
808 | SwFlyFrame* pFrame = pRet->GetFrame( &aPt ); | |||
809 | if( pFrame ) | |||
810 | SelectFlyFrame( *pFrame ); | |||
811 | else | |||
812 | { | |||
813 | GetLayout()->SetAssertFlyPages(); | |||
814 | pRet = nullptr; | |||
815 | } | |||
816 | } | |||
817 | EndAllActionAndCall(); | |||
818 | ||||
819 | return pRet; | |||
820 | } | |||
821 | ||||
822 | void SwFEShell::Insert( const OUString& rGrfName, const OUString& rFltName, | |||
823 | const Graphic* pGraphic, | |||
824 | const SfxItemSet* pFlyAttrSet ) | |||
825 | { | |||
826 | SwFlyFrameFormat* pFormat = nullptr; | |||
827 | CurrShell aCurr( this ); | |||
828 | StartAllAction(); | |||
829 | SwShellCursor *pStartCursor = dynamic_cast<SwShellCursor*>(GetSwCursor()); | |||
830 | SwShellCursor *pCursor = pStartCursor; | |||
831 | do | |||
832 | { | |||
833 | if (!pCursor) | |||
834 | break; | |||
835 | ||||
836 | // Has the anchor not been set or been set incompletely? | |||
837 | if( pFlyAttrSet ) | |||
838 | { | |||
839 | const SfxPoolItem* pItem; | |||
840 | if( SfxItemState::SET == pFlyAttrSet->GetItemState( RES_ANCHOR, false, | |||
841 | &pItem ) ) | |||
842 | { | |||
843 | SwFormatAnchor* pAnchor = const_cast<SwFormatAnchor*>(static_cast<const SwFormatAnchor*>(pItem)); | |||
844 | switch( pAnchor->GetAnchorId()) | |||
845 | { | |||
846 | case RndStdIds::FLY_AT_PARA: | |||
847 | case RndStdIds::FLY_AT_CHAR: // LAYER_IMPL | |||
848 | case RndStdIds::FLY_AS_CHAR: | |||
849 | if( !pAnchor->GetContentAnchor() ) | |||
850 | { | |||
851 | pAnchor->SetAnchor( pCursor->GetPoint() ); | |||
852 | } | |||
853 | break; | |||
854 | case RndStdIds::FLY_AT_FLY: | |||
855 | if( !pAnchor->GetContentAnchor() ) | |||
856 | { | |||
857 | lcl_SetNewFlyPos( pCursor->GetNode(), | |||
858 | *pAnchor, GetCursorDocPos() ); | |||
859 | } | |||
860 | break; | |||
861 | case RndStdIds::FLY_AT_PAGE: | |||
862 | if( !pAnchor->GetPageNum() ) | |||
863 | { | |||
864 | pAnchor->SetPageNum( pCursor->GetPageNum( | |||
865 | true, &pCursor->GetPtPos() ) ); | |||
866 | } | |||
867 | break; | |||
868 | default : | |||
869 | break; | |||
870 | } | |||
871 | } | |||
872 | } | |||
873 | pFormat = GetDoc()->getIDocumentContentOperations().InsertGraphic( | |||
874 | *pCursor, rGrfName, | |||
875 | rFltName, pGraphic, | |||
876 | pFlyAttrSet, | |||
877 | nullptr, nullptr ); | |||
878 | OSL_ENSURE(pFormat, "IDocumentContentOperations::InsertGraphic failed.")do { if (true && (!(pFormat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "878" ": "), "%s", "IDocumentContentOperations::InsertGraphic failed." ); } } while (false); | |||
879 | ||||
880 | pCursor = pCursor->GetNext(); | |||
881 | } while( pCursor != pStartCursor ); | |||
882 | ||||
883 | EndAllAction(); | |||
884 | ||||
885 | if( !pFormat ) | |||
886 | return; | |||
887 | ||||
888 | const Point aPt( GetCursorDocPos() ); | |||
889 | SwFlyFrame* pFrame = pFormat->GetFrame( &aPt ); | |||
890 | ||||
891 | if( pFrame ) | |||
892 | { | |||
893 | // fdo#36681: Invalidate the content and layout to refresh | |||
894 | // the picture anchoring properly | |||
895 | SwPageFrame* pPageFrame = pFrame->FindPageFrameOfAnchor(); | |||
896 | pPageFrame->InvalidateFlyLayout(); | |||
897 | pPageFrame->InvalidateContent(); | |||
898 | ||||
899 | SelectFlyFrame( *pFrame ); | |||
900 | } | |||
901 | else | |||
902 | GetLayout()->SetAssertFlyPages(); | |||
903 | } | |||
904 | ||||
905 | SwFlyFrameFormat* SwFEShell::InsertObject( const svt::EmbeddedObjectRef& xObj, | |||
906 | SfxItemSet* pFlyAttrSet ) | |||
907 | { | |||
908 | SwFlyFrameFormat* pFormat = nullptr; | |||
909 | CurrShell aCurr( this ); | |||
910 | StartAllAction(); | |||
911 | { | |||
912 | for(const SwPaM& rPaM : GetCursor()->GetRingContainer()) | |||
913 | { | |||
914 | pFormat = GetDoc()->getIDocumentContentOperations().InsertEmbObject( | |||
915 | rPaM, xObj, pFlyAttrSet ); | |||
916 | OSL_ENSURE(pFormat, "IDocumentContentOperations::InsertEmbObject failed.")do { if (true && (!(pFormat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "916" ": "), "%s", "IDocumentContentOperations::InsertEmbObject failed." ); } } while (false); | |||
917 | } | |||
918 | } | |||
919 | EndAllAction(); | |||
920 | ||||
921 | if( pFormat ) | |||
922 | { | |||
923 | const Point aPt( GetCursorDocPos() ); | |||
924 | SwFlyFrame* pFrame = pFormat->GetFrame( &aPt ); | |||
925 | ||||
926 | if( pFrame ) | |||
927 | SelectFlyFrame( *pFrame ); | |||
928 | else | |||
929 | GetLayout()->SetAssertFlyPages(); | |||
930 | } | |||
931 | ||||
932 | return pFormat; | |||
933 | } | |||
934 | ||||
935 | void SwFEShell::InsertDrawObj( SdrObject& rDrawObj, | |||
936 | const Point& rInsertPosition ) | |||
937 | { | |||
938 | CurrShell aCurr( this ); | |||
939 | ||||
940 | SfxItemSet rFlyAttrSet( GetDoc()->GetAttrPool(), aFrameFormatSetRange ); | |||
941 | rFlyAttrSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PARA )); | |||
942 | // #i89920# | |||
943 | rFlyAttrSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) ); | |||
944 | rDrawObj.SetLayer( getIDocumentDrawModelAccess().GetHeavenId() ); | |||
945 | ||||
946 | // find anchor position | |||
947 | SwPaM aPam( mxDoc->GetNodes() ); | |||
948 | { | |||
949 | SwCursorMoveState aState( CursorMoveState::SetOnlyText ); | |||
950 | Point aTmpPt( rInsertPosition ); | |||
951 | GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmpPt, &aState ); | |||
952 | const SwFrame* pFrame = aPam.GetContentNode()->getLayoutFrame(GetLayout(), nullptr, nullptr); | |||
953 | const Point aRelPos( rInsertPosition.X() - pFrame->getFrameArea().Left(), | |||
954 | rInsertPosition.Y() - pFrame->getFrameArea().Top() ); | |||
955 | rDrawObj.SetRelativePos( aRelPos ); | |||
956 | ::lcl_FindAnchorPos( *GetDoc(), rInsertPosition, *pFrame, rFlyAttrSet ); | |||
957 | } | |||
958 | // insert drawing object into the document creating a new <SwDrawFrameFormat> instance | |||
959 | SwDrawFrameFormat* pFormat = GetDoc()->getIDocumentContentOperations().InsertDrawObj( aPam, rDrawObj, rFlyAttrSet ); | |||
960 | ||||
961 | // move object to visible layer | |||
962 | SwContact* pContact = static_cast<SwContact*>(rDrawObj.GetUserCall()); | |||
963 | if ( pContact ) | |||
964 | { | |||
965 | pContact->MoveObjToVisibleLayer( &rDrawObj ); | |||
966 | } | |||
967 | ||||
968 | if (pFormat) | |||
969 | { | |||
970 | pFormat->SetName(rDrawObj.GetName()); | |||
971 | // select drawing object | |||
972 | Imp()->GetDrawView()->MarkObj( &rDrawObj, Imp()->GetPageView() ); | |||
973 | } | |||
974 | else | |||
975 | { | |||
976 | GetLayout()->SetAssertFlyPages(); | |||
977 | } | |||
978 | } | |||
979 | ||||
980 | void SwFEShell::GetPageObjs( std::vector<SwFrameFormat*>& rFillArr ) | |||
981 | { | |||
982 | rFillArr.clear(); | |||
983 | ||||
984 | for( auto pFormat : *mxDoc->GetSpzFrameFormats() ) | |||
985 | { | |||
986 | if (RndStdIds::FLY_AT_PAGE == pFormat->GetAnchor().GetAnchorId()) | |||
987 | { | |||
988 | rFillArr.push_back( pFormat ); | |||
989 | } | |||
990 | } | |||
991 | } | |||
992 | ||||
993 | void SwFEShell::SetPageObjsNewPage( std::vector<SwFrameFormat*>& rFillArr ) | |||
994 | { | |||
995 | if( rFillArr.empty() ) | |||
996 | return; | |||
997 | ||||
998 | StartAllAction(); | |||
999 | StartUndo(); | |||
1000 | ||||
1001 | SwRootFrame* pTmpRootFrame = GetLayout(); | |||
1002 | sal_uInt16 nMaxPage = pTmpRootFrame->GetPageNum(); | |||
1003 | bool bTmpAssert = false; | |||
1004 | for( auto pFormat : rFillArr ) | |||
1005 | { | |||
1006 | if (mxDoc->GetSpzFrameFormats()->IsAlive(pFormat)) | |||
1007 | { | |||
1008 | // FlyFormat is still valid, therefore process | |||
1009 | ||||
1010 | SwFormatAnchor aNewAnchor( pFormat->GetAnchor() ); | |||
1011 | if (RndStdIds::FLY_AT_PAGE != aNewAnchor.GetAnchorId()) | |||
1012 | // Anchor has been changed, therefore: do not change! | |||
1013 | continue; | |||
1014 | sal_uInt16 nNewPage = aNewAnchor.GetPageNum() + 1; | |||
1015 | if (nNewPage > nMaxPage) | |||
1016 | { | |||
1017 | if ( RES_DRAWFRMFMT == pFormat->Which() ) | |||
1018 | pFormat->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS)); | |||
1019 | else | |||
1020 | pFormat->DelFrames(); | |||
1021 | bTmpAssert = true; | |||
1022 | } | |||
1023 | aNewAnchor.SetPageNum(nNewPage); | |||
1024 | mxDoc->SetAttr( aNewAnchor, *pFormat ); | |||
1025 | } | |||
1026 | } | |||
1027 | ||||
1028 | if( bTmpAssert ) | |||
1029 | pTmpRootFrame->SetAssertFlyPages(); | |||
1030 | ||||
1031 | EndUndo(); | |||
1032 | EndAllAction(); | |||
1033 | } | |||
1034 | ||||
1035 | // All attributes in the "baskets" will be filled with the attributes of the | |||
1036 | // current FlyFrames. Attributes which cannot be filled due to being at the | |||
1037 | // wrong place or which are ambiguous (multiple selections) will be removed. | |||
1038 | bool SwFEShell::GetFlyFrameAttr( SfxItemSet &rSet ) const | |||
1039 | { | |||
1040 | SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame(); | |||
1041 | if (!pFly) | |||
1042 | { | |||
1043 | OSL_ENSURE( false, "GetFlyFrameAttr, no Fly selected." )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1043" ": "), "%s", "GetFlyFrameAttr, no Fly selected.") ; } } while (false); | |||
1044 | return false; | |||
1045 | } | |||
1046 | ||||
1047 | CurrShell aCurr( const_cast<SwFEShell*>(this) ); | |||
1048 | ||||
1049 | if( !rSet.Set( pFly->GetFormat()->GetAttrSet() ) ) | |||
1050 | return false; | |||
1051 | ||||
1052 | // now examine all attributes. Remove forbidden attributes, then | |||
1053 | // get all remaining attributes and enter them | |||
1054 | const SfxPoolItem* pItem; | |||
1055 | if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false, &pItem ) ) | |||
1056 | { | |||
1057 | const SwFormatAnchor* pAnchor = static_cast<const SwFormatAnchor*>(pItem); | |||
1058 | RndStdIds eType = pAnchor->GetAnchorId(); | |||
1059 | ||||
1060 | if ( RndStdIds::FLY_AT_PAGE != eType ) | |||
1061 | { | |||
1062 | // OD 12.11.2003 #i22341# - content anchor of anchor item is needed. | |||
1063 | // Thus, don't overwrite anchor item by default constructed anchor item. | |||
1064 | if ( RndStdIds::FLY_AS_CHAR == eType ) | |||
1065 | { | |||
1066 | rSet.ClearItem( RES_OPAQUE ); | |||
1067 | rSet.ClearItem( RES_SURROUND ); | |||
1068 | } | |||
1069 | } | |||
1070 | } | |||
1071 | rSet.SetParent( pFly->GetFormat()->GetAttrSet().GetParent() ); | |||
1072 | // attributes must be removed | |||
1073 | rSet.ClearItem( RES_FILL_ORDER ); | |||
1074 | rSet.ClearItem( RES_CNTNT ); | |||
1075 | //MA: remove first (Template by example etc.) | |||
1076 | rSet.ClearItem( RES_CHAIN ); | |||
1077 | return true; | |||
1078 | } | |||
1079 | ||||
1080 | // Attributes of the current fly will change. | |||
1081 | bool SwFEShell::SetFlyFrameAttr( SfxItemSet& rSet ) | |||
1082 | { | |||
1083 | CurrShell aCurr( this ); | |||
1084 | bool bRet = false; | |||
1085 | ||||
1086 | if( rSet.Count() ) | |||
1087 | { | |||
1088 | SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame(); | |||
1089 | OSL_ENSURE(pFly, "SetFlyFrameAttr, no Fly selected.")do { if (true && (!(pFly))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1089" ": "), "%s", "SetFlyFrameAttr, no Fly selected.") ; } } while (false); | |||
1090 | if (pFly) | |||
1091 | { | |||
1092 | StartAllAction(); | |||
1093 | const Point aPt( pFly->getFrameArea().Pos() ); | |||
1094 | ||||
1095 | if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false )) | |||
1096 | sw_ChkAndSetNewAnchor( *pFly, rSet ); | |||
1097 | SwFlyFrameFormat* pFlyFormat = pFly->GetFormat(); | |||
1098 | ||||
1099 | if( GetDoc()->SetFlyFrameAttr( *pFlyFormat, rSet )) | |||
1100 | { | |||
1101 | bRet = true; | |||
1102 | SwFlyFrame* pFrame = pFlyFormat->GetFrame( &aPt ); | |||
1103 | if( pFrame ) | |||
1104 | SelectFlyFrame( *pFrame ); | |||
1105 | else | |||
1106 | GetLayout()->SetAssertFlyPages(); | |||
1107 | } | |||
1108 | ||||
1109 | EndAllActionAndCall(); | |||
1110 | } | |||
1111 | } | |||
1112 | return bRet; | |||
1113 | } | |||
1114 | ||||
1115 | SfxItemSet SwFEShell::makeItemSetFromFormatAnchor(SfxItemPool& rPool, const SwFormatAnchor &rAnchor) | |||
1116 | { | |||
1117 | // The set also includes VERT/HORI_ORIENT, because the align | |||
1118 | // shall be changed in FEShell::SetFlyFrameAttr/SetFlyFrameAnchor, | |||
1119 | // possibly as a result of the anchor change. | |||
1120 | SfxItemSet aSet(rPool, svl::Items<RES_VERT_ORIENT, RES_ANCHOR>{}); | |||
1121 | aSet.Put(rAnchor); | |||
1122 | return aSet; | |||
1123 | } | |||
1124 | ||||
1125 | bool SwFEShell::SetDrawingAttr( SfxItemSet& rSet ) | |||
1126 | { | |||
1127 | bool bRet = false; | |||
1128 | CurrShell aCurr( this ); | |||
1129 | if ( !rSet.Count() || | |||
1130 | !Imp()->HasDrawView() ) | |||
1131 | return bRet; | |||
1132 | ||||
1133 | const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); | |||
1134 | if ( rMrkList.GetMarkCount() != 1 ) | |||
1135 | return bRet; | |||
1136 | ||||
1137 | StartUndo(); | |||
1138 | SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); | |||
1139 | SwFrameFormat *pFormat = FindFrameFormat( pObj ); | |||
1140 | StartAllAction(); | |||
1141 | if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false )) | |||
1142 | { | |||
1143 | RndStdIds nNew = rSet.Get( RES_ANCHOR ).GetAnchorId(); | |||
1144 | if ( nNew != pFormat->GetAnchor().GetAnchorId() ) | |||
1145 | { | |||
1146 | ChgAnchor( nNew ); | |||
1147 | // #i26791# - clear anchor attribute in item set, | |||
1148 | // because method <ChgAnchor(..)> takes care of it. | |||
1149 | rSet.ClearItem( RES_ANCHOR ); | |||
1150 | } | |||
1151 | } | |||
1152 | ||||
1153 | if( GetDoc()->SetFlyFrameAttr( *pFormat, rSet )) | |||
1154 | { | |||
1155 | bRet = true; | |||
1156 | SelectObj( Point(), 0, pObj ); | |||
1157 | } | |||
1158 | EndAllActionAndCall(); | |||
1159 | EndUndo(); | |||
1160 | return bRet; | |||
1161 | } | |||
1162 | ||||
1163 | // Reset attributes contained in the set. | |||
1164 | void SwFEShell::ResetFlyFrameAttr( const SfxItemSet* pSet ) | |||
1165 | { | |||
1166 | CurrShell aCurr( this ); | |||
1167 | ||||
1168 | SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame(); | |||
1169 | OSL_ENSURE( pFly, "SetFlyFrameAttr, no Fly selected." )do { if (true && (!(pFly))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1169" ": "), "%s", "SetFlyFrameAttr, no Fly selected.") ; } } while (false); | |||
1170 | if( !pFly ) | |||
1171 | return; | |||
1172 | ||||
1173 | StartAllAction(); | |||
1174 | ||||
1175 | SfxItemIter aIter( *pSet ); | |||
1176 | for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) | |||
1177 | { | |||
1178 | if( !IsInvalidItem( pItem ) ) | |||
1179 | { | |||
1180 | sal_uInt16 nWhich = pItem->Which(); | |||
1181 | if( RES_ANCHOR != nWhich && RES_CHAIN != nWhich && RES_CNTNT != nWhich ) | |||
1182 | pFly->GetFormat()->ResetFormatAttr( nWhich ); | |||
1183 | } | |||
1184 | } | |||
1185 | ||||
1186 | EndAllActionAndCall(); | |||
1187 | GetDoc()->getIDocumentState().SetModified(); | |||
1188 | } | |||
1189 | ||||
1190 | // Returns frame-format if frame, otherwise 0 | |||
1191 | SwFrameFormat* SwFEShell::GetSelectedFrameFormat() const | |||
1192 | { | |||
1193 | SwFrameFormat* pRet = nullptr; | |||
1194 | SwLayoutFrame *pFly = GetSelectedFlyFrame(); | |||
1195 | if( pFly && ( pRet = static_cast<SwFrameFormat*>(pFly->GetFormat()->DerivedFrom()) ) == | |||
1196 | GetDoc()->GetDfltFrameFormat() ) | |||
1197 | pRet = nullptr; | |||
1198 | return pRet; | |||
1199 | } | |||
1200 | ||||
1201 | void SwFEShell::SetFrameFormat( SwFrameFormat *pNewFormat, bool bKeepOrient, Point const * pDocPos ) | |||
1202 | { | |||
1203 | SwFlyFrame *pFly = nullptr; | |||
1204 | if(pDocPos) | |||
1205 | { | |||
1206 | const SwFrameFormat* pFormat = GetFormatFromObj( *pDocPos ); | |||
1207 | ||||
1208 | if (const SwFlyFrameFormat* pFlyFormat = dynamic_cast<const SwFlyFrameFormat*>(pFormat)) | |||
1209 | pFly = pFlyFormat->GetFrame(); | |||
1210 | } | |||
1211 | else | |||
1212 | pFly = GetSelectedFlyFrame(); | |||
1213 | OSL_ENSURE( pFly, "SetFrameFormat: no frame" )do { if (true && (!(pFly))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1213" ": "), "%s", "SetFrameFormat: no frame"); } } while (false); | |||
1214 | if( !pFly ) | |||
1215 | return; | |||
1216 | ||||
1217 | StartAllAction(); | |||
1218 | CurrShell aCurr( this ); | |||
1219 | ||||
1220 | SwFlyFrameFormat* pFlyFormat = pFly->GetFormat(); | |||
1221 | const Point aPt( pFly->getFrameArea().Pos() ); | |||
1222 | ||||
1223 | std::unique_ptr<SfxItemSet> pSet; | |||
1224 | const SfxPoolItem* pItem; | |||
1225 | if( SfxItemState::SET == pNewFormat->GetItemState( RES_ANCHOR, false, &pItem )) | |||
1226 | { | |||
1227 | pSet.reset(new SfxItemSet( GetDoc()->GetAttrPool(), aFrameFormatSetRange )); | |||
1228 | pSet->Put( *pItem ); | |||
1229 | if( !sw_ChkAndSetNewAnchor( *pFly, *pSet )) | |||
1230 | { | |||
1231 | pSet.reset(); | |||
1232 | } | |||
1233 | } | |||
1234 | ||||
1235 | if( GetDoc()->SetFrameFormatToFly( *pFlyFormat, *pNewFormat, pSet.get(), bKeepOrient )) | |||
1236 | { | |||
1237 | SwFlyFrame* pFrame = pFlyFormat->GetFrame( &aPt ); | |||
1238 | if( pFrame ) | |||
1239 | SelectFlyFrame( *pFrame ); | |||
1240 | else | |||
1241 | GetLayout()->SetAssertFlyPages(); | |||
1242 | } | |||
1243 | pSet.reset(); | |||
1244 | ||||
1245 | EndAllActionAndCall(); | |||
1246 | } | |||
1247 | ||||
1248 | const SwFrameFormat* SwFEShell::GetFlyFrameFormat() const | |||
1249 | { | |||
1250 | const SwFlyFrame* pFly = GetSelectedOrCurrFlyFrame(); | |||
1251 | if (pFly) | |||
1252 | return pFly->GetFormat(); | |||
1253 | return nullptr; | |||
1254 | } | |||
1255 | ||||
1256 | SwFrameFormat* SwFEShell::GetFlyFrameFormat() | |||
1257 | { | |||
1258 | SwFlyFrame* pFly = GetSelectedOrCurrFlyFrame(); | |||
1259 | if (pFly) | |||
1260 | return pFly->GetFormat(); | |||
1261 | return nullptr; | |||
1262 | } | |||
1263 | ||||
1264 | SwRect SwFEShell::GetFlyRect() const | |||
1265 | { | |||
1266 | SwFlyFrame *pFly = GetCurrFlyFrame(false); | |||
1267 | if (!pFly) | |||
1268 | { | |||
1269 | SwRect aRect; | |||
1270 | return aRect; | |||
1271 | } | |||
1272 | else | |||
1273 | return pFly->getFrameArea(); | |||
1274 | } | |||
1275 | ||||
1276 | SwRect SwFEShell::GetObjRect() const | |||
1277 | { | |||
1278 | if( Imp()->HasDrawView() ) | |||
1279 | return Imp()->GetDrawView()->GetAllMarkedRect(); | |||
1280 | else | |||
1281 | { | |||
1282 | SwRect aRect; | |||
1283 | return aRect; | |||
1284 | } | |||
1285 | } | |||
1286 | ||||
1287 | void SwFEShell::SetObjRect( const SwRect& rRect ) | |||
1288 | { | |||
1289 | if ( Imp()->HasDrawView() ) | |||
1290 | { | |||
1291 | Imp()->GetDrawView()->SetAllMarkedRect( rRect.SVRect() ); | |||
1292 | CallChgLnk(); // call AttrChangeNotify on the UI-side. | |||
1293 | } | |||
1294 | } | |||
1295 | ||||
1296 | Size SwFEShell::RequestObjectResize( const SwRect &rRect, const uno::Reference < embed::XEmbeddedObject >& xObj ) | |||
1297 | { | |||
1298 | Size aResult; | |||
1299 | ||||
1300 | SwFlyFrame *pFly = FindFlyFrame( xObj ); | |||
1301 | if ( !pFly ) | |||
1302 | { | |||
1303 | aResult = rRect.SSize(); | |||
1304 | return aResult; | |||
1305 | } | |||
1306 | ||||
1307 | aResult = pFly->getFramePrintArea().SSize(); | |||
1308 | ||||
1309 | bool bPosProt = pFly->GetFormat()->GetProtect().IsPosProtected(); | |||
1310 | bool bSizeProt = pFly->GetFormat()->GetProtect().IsSizeProtected(); | |||
1311 | ||||
1312 | StartAllAction(); | |||
1313 | ||||
1314 | // MA we do not allow to clip the Fly, as the OLE server can | |||
1315 | // request various wishes. Clipping is done via the formatting. | |||
1316 | // Correct display is done by scaling. | |||
1317 | // Scaling is done by SwNoTextFrame::Format by calling | |||
1318 | // SwWrtShell::CalcAndSetScale() | |||
1319 | if ( rRect.SSize() != pFly->getFramePrintArea().SSize() && !bSizeProt ) | |||
1320 | { | |||
1321 | Size aSz( rRect.SSize() ); | |||
1322 | ||||
1323 | //JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size | |||
1324 | ||||
1325 | const SwFrame* pAnchor; | |||
1326 | const SwFormatFrameSize& rFrameSz = pFly->GetFormat()->GetFrameSize(); | |||
1327 | if (m_bCheckForOLEInCaption && | |||
1328 | 0 != rFrameSz.GetWidthPercent() && | |||
1329 | nullptr != (pAnchor = pFly->GetAnchorFrame()) && | |||
1330 | pAnchor->IsTextFrame() && | |||
1331 | !pAnchor->GetNext() && !pAnchor->GetPrev() && | |||
1332 | pAnchor->GetUpper()->IsFlyFrame()) | |||
1333 | { | |||
1334 | // search for a sequence field: | |||
1335 | sw::MergedAttrIter iter(*static_cast<SwTextFrame const*>(pAnchor)); | |||
1336 | for (SwTextAttr const* pHint = iter.NextAttr(); pHint; pHint = iter.NextAttr()) | |||
1337 | { | |||
1338 | const SfxPoolItem* pItem = &pHint->GetAttr(); | |||
1339 | if( RES_TXTATR_FIELD == pItem->Which() | |||
1340 | && SwFieldTypesEnum::Sequence == static_cast<const SwFormatField*>(pItem)->GetField()->GetTypeId() ) | |||
1341 | { | |||
1342 | // sequence field found | |||
1343 | SwFlyFrame* pChgFly = const_cast<SwFlyFrame*>(static_cast<const SwFlyFrame*>(pAnchor->GetUpper())); | |||
1344 | // calculate the changed size: | |||
1345 | // width must change, height can change | |||
1346 | Size aNewSz( aSz.Width() + pChgFly->getFrameArea().Width() - | |||
1347 | pFly->getFramePrintArea().Width(), aSz.Height() ); | |||
1348 | ||||
1349 | SwFrameFormat *pFormat = pChgFly->GetFormat(); | |||
1350 | SwFormatFrameSize aFrameSz( pFormat->GetFrameSize() ); | |||
1351 | aFrameSz.SetWidth( aNewSz.Width() ); | |||
1352 | if( SwFrameSize::Minimum != aFrameSz.GetHeightSizeType() ) | |||
1353 | { | |||
1354 | aNewSz.AdjustHeight(pChgFly->getFrameArea().Height() - | |||
1355 | pFly->getFramePrintArea().Height() ); | |||
1356 | if( std::abs( aNewSz.Height() - pChgFly->getFrameArea().Height()) > 1 ) | |||
1357 | aFrameSz.SetHeight( aNewSz.Height() ); | |||
1358 | } | |||
1359 | // via Doc for the Undo! | |||
1360 | pFormat->GetDoc()->SetAttr( aFrameSz, *pFormat ); | |||
1361 | break; | |||
1362 | } | |||
1363 | } | |||
1364 | } | |||
1365 | ||||
1366 | // set the new Size at the fly themself | |||
1367 | if ( !pFly->getFramePrintArea().IsEmpty() ) | |||
1368 | { | |||
1369 | aSz.AdjustWidth(pFly->getFrameArea().Width() - pFly->getFramePrintArea().Width() ); | |||
1370 | aSz.AdjustHeight(pFly->getFrameArea().Height()- pFly->getFramePrintArea().Height() ); | |||
1371 | } | |||
1372 | aResult = pFly->ChgSize( aSz ); | |||
1373 | ||||
1374 | // if the object changes, the contour is outside the object | |||
1375 | assert(pFly->Lower()->IsNoTextFrame())(static_cast <bool> (pFly->Lower()->IsNoTextFrame ()) ? void (0) : __assert_fail ("pFly->Lower()->IsNoTextFrame()" , "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" , 1375, __extension__ __PRETTY_FUNCTION__)); | |||
1376 | SwNoTextNode *pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetNoTextNode(); | |||
1377 | assert(pNd)(static_cast <bool> (pNd) ? void (0) : __assert_fail ("pNd" , "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" , 1377, __extension__ __PRETTY_FUNCTION__)); | |||
1378 | pNd->SetContour( nullptr ); | |||
1379 | ClrContourCache(); | |||
1380 | } | |||
1381 | ||||
1382 | // if only the size is to be adjusted, a position is transported with | |||
1383 | // allocated values | |||
1384 | Point aPt( pFly->getFramePrintArea().Pos() ); | |||
1385 | aPt += pFly->getFrameArea().Pos(); | |||
1386 | if ( rRect.Top() != LONG_MIN(-9223372036854775807L -1L) && rRect.Pos() != aPt && !bPosProt ) | |||
1387 | { | |||
1388 | aPt = rRect.Pos(); | |||
1389 | aPt.setX(aPt.getX() - pFly->getFramePrintArea().Left()); | |||
1390 | aPt.setY(aPt.getY() - pFly->getFramePrintArea().Top()); | |||
1391 | ||||
1392 | // in case of paragraph-bound Flys, starting from the new position, | |||
1393 | // a new anchor is to be set. The anchor and the new RelPos are | |||
1394 | // calculated by the Fly and set | |||
1395 | if( pFly->IsFlyAtContentFrame() ) | |||
1396 | static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( aPt ); | |||
1397 | else | |||
1398 | { | |||
1399 | const SwFrameFormat *pFormat = pFly->GetFormat(); | |||
1400 | const SwFormatVertOrient &rVert = pFormat->GetVertOrient(); | |||
1401 | const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient(); | |||
1402 | const long lXDiff = aPt.getX() - pFly->getFrameArea().Left(); | |||
1403 | const long lYDiff = aPt.getY() - pFly->getFrameArea().Top(); | |||
1404 | const Point aTmp( rHori.GetPos() + lXDiff, | |||
1405 | rVert.GetPos() + lYDiff ); | |||
1406 | pFly->ChgRelPos( aTmp ); | |||
1407 | } | |||
1408 | } | |||
1409 | ||||
1410 | SwFlyFrameFormat *pFlyFrameFormat = pFly->GetFormat(); | |||
1411 | OSL_ENSURE( pFlyFrameFormat, "fly frame format missing!" )do { if (true && (!(pFlyFrameFormat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1411" ": "), "%s", "fly frame format missing!"); } } while (false); | |||
1412 | if ( pFlyFrameFormat ) | |||
1413 | pFlyFrameFormat->SetLastFlyFramePrtRectPos( pFly->getFramePrintArea().Pos() ); //stores the value of last Prt rect | |||
1414 | ||||
1415 | EndAllAction(); | |||
1416 | ||||
1417 | return aResult; | |||
1418 | } | |||
1419 | ||||
1420 | SwFrameFormat* SwFEShell::WizardGetFly() | |||
1421 | { | |||
1422 | // do not search the Fly via the layout. Now we can delete a frame | |||
1423 | // without a valid layout. ( e.g. for the wizards ) | |||
1424 | SwFrameFormats& rSpzArr = *mxDoc->GetSpzFrameFormats(); | |||
1425 | if( !rSpzArr.empty() ) | |||
1426 | { | |||
1427 | SwNodeIndex& rCursorNd = GetCursor()->GetPoint()->nNode; | |||
1428 | if( rCursorNd.GetIndex() > mxDoc->GetNodes().GetEndOfExtras().GetIndex() ) | |||
1429 | // Cursor is in the body area! | |||
1430 | return nullptr; | |||
1431 | ||||
1432 | for( auto pFormat : rSpzArr ) | |||
1433 | { | |||
1434 | const SwNodeIndex* pIdx = pFormat->GetContent( false ).GetContentIdx(); | |||
1435 | SwStartNode* pSttNd; | |||
1436 | if( pIdx && | |||
1437 | nullptr != ( pSttNd = pIdx->GetNode().GetStartNode() ) && | |||
1438 | pSttNd->GetIndex() < rCursorNd.GetIndex() && | |||
1439 | rCursorNd.GetIndex() < pSttNd->EndOfSectionIndex() ) | |||
1440 | { | |||
1441 | // found: return immediately | |||
1442 | return pFormat; | |||
1443 | } | |||
1444 | } | |||
1445 | } | |||
1446 | return nullptr; | |||
1447 | } | |||
1448 | ||||
1449 | void SwFEShell::SetFlyName( const OUString& rName ) | |||
1450 | { | |||
1451 | SwLayoutFrame *pFly = GetSelectedFlyFrame(); | |||
1452 | if( pFly ) | |||
1453 | GetDoc()->SetFlyName( *static_cast<SwFlyFrameFormat*>(pFly->GetFormat()), rName ); | |||
1454 | else { | |||
1455 | OSL_ENSURE( false, "no FlyFrame selected" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1455" ": "), "%s", "no FlyFrame selected"); } } while ( false); | |||
1456 | } | |||
1457 | } | |||
1458 | ||||
1459 | OUString SwFEShell::GetFlyName() const | |||
1460 | { | |||
1461 | SwLayoutFrame *pFly = GetSelectedFlyFrame(); | |||
1462 | if( pFly ) | |||
1463 | return pFly->GetFormat()->GetName(); | |||
1464 | ||||
1465 | OSL_ENSURE( false, "no FlyFrame selected" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1465" ": "), "%s", "no FlyFrame selected"); } } while ( false); | |||
1466 | return OUString(); | |||
1467 | } | |||
1468 | ||||
1469 | uno::Reference < embed::XEmbeddedObject > SwFEShell::GetOleRef() const | |||
1470 | { | |||
1471 | uno::Reference < embed::XEmbeddedObject > xObj; | |||
1472 | SwFlyFrame * pFly = GetSelectedFlyFrame(); | |||
1473 | if (pFly && pFly->Lower() && pFly->Lower()->IsNoTextFrame()) | |||
1474 | { | |||
1475 | SwOLENode *pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetOLENode(); | |||
1476 | if (pNd) | |||
1477 | xObj = pNd->GetOLEObj().GetOleRef(); | |||
1478 | } | |||
1479 | return xObj; | |||
1480 | } | |||
1481 | ||||
1482 | OUString SwFEShell::GetUniqueGrfName() const | |||
1483 | { | |||
1484 | return GetDoc()->GetUniqueGrfName(); | |||
1485 | } | |||
1486 | ||||
1487 | const SwFrameFormat* SwFEShell::IsURLGrfAtPos( const Point& rPt, OUString* pURL, | |||
1488 | OUString *pTargetFrameName, | |||
1489 | OUString *pDescription ) const | |||
1490 | { | |||
1491 | if( !Imp()->HasDrawView() ) | |||
1492 | return nullptr; | |||
1493 | ||||
1494 | SdrPageView* pPV; | |||
1495 | const SwFrameFormat* pRet = nullptr; | |||
1496 | SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView()); | |||
1497 | ||||
1498 | const auto nOld = pDView->GetHitTolerancePixel(); | |||
1499 | pDView->SetHitTolerancePixel( 2 ); | |||
1500 | ||||
1501 | SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO); | |||
1502 | SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj); | |||
1503 | if (pFlyObj) | |||
1504 | { | |||
1505 | SwFlyFrame *pFly = pFlyObj->GetFlyFrame(); | |||
1506 | const SwFormatURL &rURL = pFly->GetFormat()->GetURL(); | |||
1507 | if( !rURL.GetURL().isEmpty() || rURL.GetMap() ) | |||
1508 | { | |||
1509 | bool bSetTargetFrameName = pTargetFrameName != nullptr; | |||
1510 | bool bSetDescription = pDescription != nullptr; | |||
1511 | if ( rURL.GetMap() ) | |||
1512 | { | |||
1513 | IMapObject *pObject = pFly->GetFormat()->GetIMapObject( rPt, pFly ); | |||
1514 | if ( pObject && !pObject->GetURL().isEmpty() ) | |||
1515 | { | |||
1516 | if( pURL ) | |||
1517 | *pURL = pObject->GetURL(); | |||
1518 | if ( bSetTargetFrameName && !pObject->GetTarget().isEmpty() ) | |||
1519 | { | |||
1520 | bSetTargetFrameName = false; | |||
1521 | *pTargetFrameName = pObject->GetTarget(); | |||
1522 | } | |||
1523 | if ( bSetDescription ) | |||
1524 | { | |||
1525 | bSetDescription = false; | |||
1526 | *pDescription = pObject->GetAltText(); | |||
1527 | } | |||
1528 | pRet = pFly->GetFormat(); | |||
1529 | } | |||
1530 | } | |||
1531 | else | |||
1532 | { | |||
1533 | if( pURL ) | |||
1534 | { | |||
1535 | *pURL = rURL.GetURL(); | |||
1536 | if( rURL.IsServerMap() ) | |||
1537 | { | |||
1538 | // append the relative pixel position !! | |||
1539 | Point aPt( rPt ); | |||
1540 | aPt -= pFly->getFrameArea().Pos(); | |||
1541 | // without MapMode-Offset, without Offset, o ... !!!!! | |||
1542 | aPt = GetOut()->LogicToPixel( | |||
1543 | aPt, MapMode( MapUnit::MapTwip ) ); | |||
1544 | *pURL = *pURL + "?" + OUString::number( aPt.getX() ) | |||
1545 | + "," + OUString::number(aPt.getY() ); | |||
1546 | } | |||
1547 | } | |||
1548 | pRet = pFly->GetFormat(); | |||
1549 | } | |||
1550 | if ( bSetTargetFrameName ) | |||
1551 | *pTargetFrameName = rURL.GetTargetFrameName(); | |||
1552 | if ( bSetDescription ) | |||
1553 | *pDescription = pFly->GetFormat()->GetName(); | |||
1554 | } | |||
1555 | } | |||
1556 | pDView->SetHitTolerancePixel( nOld ); | |||
1557 | return pRet; | |||
1558 | } | |||
1559 | ||||
1560 | const Graphic *SwFEShell::GetGrfAtPos( const Point &rPt, | |||
1561 | OUString &rName, bool &rbLink ) const | |||
1562 | { | |||
1563 | if( !Imp()->HasDrawView() ) | |||
1564 | return nullptr; | |||
1565 | ||||
1566 | SdrPageView* pPV; | |||
1567 | SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView()); | |||
1568 | ||||
1569 | SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV); | |||
1570 | SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj); | |||
1571 | if (pFlyObj) | |||
1572 | { | |||
1573 | SwFlyFrame *pFly = pFlyObj->GetFlyFrame(); | |||
1574 | if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() ) | |||
1575 | { | |||
1576 | SwGrfNode *const pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetGrfNode(); | |||
1577 | if ( pNd ) | |||
1578 | { | |||
1579 | if ( pNd->IsGrfLink() ) | |||
1580 | { | |||
1581 | // halfway ready graphic? | |||
1582 | ::sfx2::SvLinkSource* pLnkObj = pNd->GetLink()->GetObj(); | |||
1583 | if( pLnkObj && pLnkObj->IsPending() ) | |||
1584 | return nullptr; | |||
1585 | rbLink = true; | |||
1586 | } | |||
1587 | ||||
1588 | pNd->GetFileFilterNms( &rName, nullptr ); | |||
1589 | if ( rName.isEmpty() ) | |||
1590 | rName = pFly->GetFormat()->GetName(); | |||
1591 | return &pNd->GetGrf(true); | |||
1592 | } | |||
1593 | } | |||
1594 | } | |||
1595 | return nullptr; | |||
1596 | } | |||
1597 | ||||
1598 | const SwFrameFormat* SwFEShell::GetFormatFromObj( const Point& rPt, SwRect** pRectToFill ) const | |||
1599 | { | |||
1600 | SwFrameFormat* pRet = nullptr; | |||
1601 | ||||
1602 | if( Imp()->HasDrawView() ) | |||
1603 | { | |||
1604 | SdrPageView* pPView; | |||
1605 | ||||
1606 | SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView()); | |||
1607 | ||||
1608 | const auto nOld = pDView->GetHitTolerancePixel(); | |||
1609 | // tolerance for Drawing-SS | |||
1610 | pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 ); | |||
1611 | ||||
1612 | SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE); | |||
1613 | if (pObj) | |||
1614 | { | |||
1615 | // first check it: | |||
1616 | if (SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj)) | |||
1617 | pRet = pFlyObj->GetFormat(); | |||
1618 | else if ( pObj->GetUserCall() ) //not for group objects | |||
1619 | pRet = static_cast<SwDrawContact*>(pObj->GetUserCall())->GetFormat(); | |||
1620 | if(pRet && pRectToFill) | |||
1621 | **pRectToFill = pObj->GetCurrentBoundRect(); | |||
1622 | } | |||
1623 | pDView->SetHitTolerancePixel( nOld ); | |||
1624 | } | |||
1625 | return pRet; | |||
1626 | } | |||
1627 | ||||
1628 | // returns a format too, if the point is over the text of any fly | |||
1629 | const SwFrameFormat* SwFEShell::GetFormatFromAnyObj( const Point& rPt ) const | |||
1630 | { | |||
1631 | const SwFrameFormat* pRet = GetFormatFromObj( rPt ); | |||
1632 | if( !pRet || RES_FLYFRMFMT == pRet->Which() ) | |||
1633 | { | |||
1634 | SwPosition aPos( *GetCursor()->GetPoint() ); | |||
1635 | Point aPt( rPt ); | |||
1636 | GetLayout()->GetModelPositionForViewPoint( &aPos, aPt ); | |||
1637 | SwContentNode *pNd = aPos.nNode.GetNode().GetContentNode(); | |||
1638 | std::pair<Point, bool> const tmp(rPt, false); | |||
1639 | SwFrame* pFrame = pNd->getLayoutFrame(GetLayout(), nullptr, &tmp)->FindFlyFrame(); | |||
1640 | pRet = pFrame ? static_cast<SwLayoutFrame*>(pFrame)->GetFormat() : nullptr; | |||
1641 | } | |||
1642 | return pRet; | |||
1643 | } | |||
1644 | ||||
1645 | ObjCntType SwFEShell::GetObjCntType( const SdrObject& rObj ) | |||
1646 | { | |||
1647 | ObjCntType eType = OBJCNT_NONE; | |||
1648 | ||||
1649 | // investigate 'master' drawing object, if method | |||
1650 | // is called for a 'virtual' drawing object. | |||
1651 | const SdrObject* pInvestigatedObj; | |||
1652 | if (const SwDrawVirtObj* pDrawVirtObj = dynamic_cast<const SwDrawVirtObj*>( &rObj)) | |||
1653 | { | |||
1654 | pInvestigatedObj = &(pDrawVirtObj->GetReferencedObj()); | |||
1655 | } | |||
1656 | else | |||
1657 | { | |||
1658 | pInvestigatedObj = &rObj; | |||
1659 | } | |||
1660 | ||||
1661 | if( SdrInventor::FmForm == pInvestigatedObj->GetObjInventor() ) | |||
1662 | { | |||
1663 | eType = OBJCNT_CONTROL; | |||
1664 | uno::Reference< awt::XControlModel > xModel = | |||
1665 | static_cast<const SdrUnoObj&>(*pInvestigatedObj).GetUnoControlModel(); | |||
1666 | if( xModel.is() ) | |||
1667 | { | |||
1668 | uno::Any aVal; | |||
1669 | OUString sName("ButtonType"); | |||
1670 | uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY); | |||
1671 | ||||
1672 | uno::Reference< beans::XPropertySetInfo > xInfo = xSet->getPropertySetInfo(); | |||
1673 | if(xInfo->hasPropertyByName( sName )) | |||
1674 | { | |||
1675 | aVal = xSet->getPropertyValue( sName ); | |||
1676 | if( aVal.hasValue() && form::FormButtonType_URL == *o3tl::doAccess<form::FormButtonType>(aVal) ) | |||
1677 | eType = OBJCNT_URLBUTTON; | |||
1678 | } | |||
1679 | } | |||
1680 | } | |||
1681 | else if (const SwVirtFlyDrawObj *pFlyObj = dynamic_cast<const SwVirtFlyDrawObj*>(pInvestigatedObj)) | |||
1682 | { | |||
1683 | const SwFlyFrame *pFly = pFlyObj->GetFlyFrame(); | |||
1684 | if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() ) | |||
1685 | { | |||
1686 | if (static_cast<const SwNoTextFrame*>(pFly->Lower())->GetNode()->GetGrfNode()) | |||
1687 | eType = OBJCNT_GRF; | |||
1688 | else | |||
1689 | eType = OBJCNT_OLE; | |||
1690 | } | |||
1691 | else | |||
1692 | eType = OBJCNT_FLY; | |||
1693 | } | |||
1694 | else if ( dynamic_cast<const SdrObjGroup*>( pInvestigatedObj) != nullptr ) | |||
1695 | { | |||
1696 | SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(GetUserCall( pInvestigatedObj ) ) ); | |||
1697 | if ( !pDrawContact ) | |||
1698 | { | |||
1699 | OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing draw contact object" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1699" ": "), "%s", "<SwFEShell::GetObjCntType(..)> - missing draw contact object" ); } } while (false); | |||
1700 | eType = OBJCNT_NONE; | |||
1701 | } | |||
1702 | else | |||
1703 | { | |||
1704 | SwFrameFormat* pFrameFormat( pDrawContact->GetFormat() ); | |||
1705 | if ( !pFrameFormat ) | |||
1706 | { | |||
1707 | OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing frame format" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1707" ": "), "%s", "<SwFEShell::GetObjCntType(..)> - missing frame format" ); } } while (false); | |||
1708 | eType = OBJCNT_NONE; | |||
1709 | } | |||
1710 | else if ( RndStdIds::FLY_AS_CHAR != pFrameFormat->GetAnchor().GetAnchorId() ) | |||
1711 | { | |||
1712 | eType = OBJCNT_GROUPOBJ; | |||
1713 | } | |||
1714 | } | |||
1715 | } | |||
1716 | else | |||
1717 | eType = OBJCNT_SIMPLE; | |||
1718 | return eType; | |||
1719 | } | |||
1720 | ||||
1721 | ObjCntType SwFEShell::GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const | |||
1722 | { | |||
1723 | ObjCntType eType = OBJCNT_NONE; | |||
1724 | ||||
1725 | if( Imp()->HasDrawView() ) | |||
1726 | { | |||
1727 | SdrPageView* pPView; | |||
1728 | ||||
1729 | SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView()); | |||
1730 | ||||
1731 | const auto nOld = pDView->GetHitTolerancePixel(); | |||
1732 | // tolerance for Drawing-SS | |||
1733 | pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 ); | |||
1734 | ||||
1735 | SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE); | |||
1736 | if (pObj) | |||
1737 | { | |||
1738 | rpObj = pObj; | |||
1739 | eType = GetObjCntType( *rpObj ); | |||
1740 | } | |||
1741 | ||||
1742 | pDView->SetHitTolerancePixel( nOld ); | |||
1743 | } | |||
1744 | return eType; | |||
1745 | } | |||
1746 | ||||
1747 | ObjCntType SwFEShell::GetObjCntTypeOfSelection() const | |||
1748 | { | |||
1749 | ObjCntType eType = OBJCNT_NONE; | |||
1750 | ||||
1751 | if( Imp()->HasDrawView() ) | |||
1752 | { | |||
1753 | const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); | |||
1754 | for( size_t i = 0, nE = rMrkList.GetMarkCount(); i < nE; ++i ) | |||
1755 | { | |||
1756 | SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); | |||
1757 | if( !pObj ) | |||
1758 | continue; | |||
1759 | ObjCntType eTmp = GetObjCntType( *pObj ); | |||
1760 | if( !i ) | |||
1761 | { | |||
1762 | eType = eTmp; | |||
1763 | } | |||
1764 | else if( eTmp != eType ) | |||
1765 | { | |||
1766 | eType = OBJCNT_DONTCARE; | |||
1767 | // once DontCare, always DontCare! | |||
1768 | break; | |||
1769 | } | |||
1770 | } | |||
1771 | } | |||
1772 | return eType; | |||
1773 | } | |||
1774 | ||||
1775 | void SwFEShell::ReplaceSdrObj( const OUString& rGrfName, const Graphic* pGrf ) | |||
1776 | { | |||
1777 | CurrShell aCurr( this ); | |||
1778 | ||||
1779 | const SdrMarkList *pMrkList; | |||
1780 | if( !(Imp()->HasDrawView() && 1 == | |||
| ||||
1781 | ( pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList())->GetMarkCount()) ) | |||
1782 | return; | |||
1783 | ||||
1784 | SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); | |||
1785 | SwFrameFormat *pFormat = FindFrameFormat( pObj ); | |||
1786 | ||||
1787 | // store attributes, then set the graphic | |||
1788 | SfxItemSet aFrameSet( mxDoc->GetAttrPool(), | |||
1789 | pFormat->GetAttrSet().GetRanges() ); | |||
1790 | aFrameSet.Set( pFormat->GetAttrSet() ); | |||
1791 | ||||
1792 | // set size and position? | |||
1793 | if( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr ) | |||
1794 | { | |||
1795 | // then let's do it: | |||
1796 | const tools::Rectangle &rBound = pObj->GetSnapRect(); | |||
| ||||
1797 | Point aRelPos( pObj->GetRelativePos() ); | |||
1798 | ||||
1799 | const long nWidth = rBound.Right() - rBound.Left(); | |||
1800 | const long nHeight= rBound.Bottom() - rBound.Top(); | |||
1801 | aFrameSet.Put( SwFormatFrameSize( SwFrameSize::Minimum, | |||
1802 | std::max( nWidth, long(MINFLY23) ), | |||
1803 | std::max( nHeight, long(MINFLY23) ))); | |||
1804 | ||||
1805 | if( SfxItemState::SET != aFrameSet.GetItemState( RES_HORI_ORIENT )) | |||
1806 | aFrameSet.Put( SwFormatHoriOrient( aRelPos.getX(), text::HoriOrientation::NONE, text::RelOrientation::FRAME )); | |||
1807 | ||||
1808 | if( SfxItemState::SET != aFrameSet.GetItemState( RES_VERT_ORIENT )) | |||
1809 | aFrameSet.Put( SwFormatVertOrient( aRelPos.getY(), text::VertOrientation::NONE, text::RelOrientation::FRAME )); | |||
1810 | ||||
1811 | } | |||
1812 | ||||
1813 | pObj->GetOrdNum(); | |||
1814 | ||||
1815 | StartAllAction(); | |||
1816 | StartUndo(); | |||
1817 | ||||
1818 | // delete "Sdr-Object", insert the graphic instead | |||
1819 | DelSelectedObj(); | |||
1820 | ||||
1821 | GetDoc()->getIDocumentContentOperations().InsertGraphic( | |||
1822 | *GetCursor(), rGrfName, "", pGrf, &aFrameSet, nullptr, nullptr); | |||
1823 | ||||
1824 | EndUndo(); | |||
1825 | EndAllAction(); | |||
1826 | } | |||
1827 | ||||
1828 | static sal_uInt16 SwFormatGetPageNum(const SwFlyFrameFormat * pFormat) | |||
1829 | { | |||
1830 | OSL_ENSURE(pFormat != nullptr, "invalid argument")do { if (true && (!(pFormat != nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "1830" ": "), "%s", "invalid argument"); } } while (false ); | |||
1831 | ||||
1832 | SwFlyFrame * pFrame = pFormat->GetFrame(); | |||
1833 | ||||
1834 | sal_uInt16 aResult; | |||
1835 | ||||
1836 | if (pFrame != nullptr) | |||
1837 | aResult = pFrame->GetPhyPageNum(); | |||
1838 | else | |||
1839 | aResult = pFormat->GetAnchor().GetPageNum(); | |||
1840 | ||||
1841 | return aResult; | |||
1842 | } | |||
1843 | ||||
1844 | void SwFEShell::GetConnectableFrameFormats(SwFrameFormat & rFormat, | |||
1845 | const OUString & rReference, | |||
1846 | bool bSuccessors, | |||
1847 | std::vector< OUString > & aPrevPageVec, | |||
1848 | std::vector< OUString > & aThisPageVec, | |||
1849 | std::vector< OUString > & aNextPageVec, | |||
1850 | std::vector< OUString > & aRestVec) | |||
1851 | { | |||
1852 | StartAction(); | |||
1853 | ||||
1854 | SwFormatChain rChain = rFormat.GetChain(); | |||
1855 | SwFrameFormat * pOldChainNext = rChain.GetNext(); | |||
1856 | SwFrameFormat * pOldChainPrev = rChain.GetPrev(); | |||
1857 | ||||
1858 | if (pOldChainNext) | |||
1859 | mxDoc->Unchain(rFormat); | |||
1860 | ||||
1861 | if (pOldChainPrev) | |||
1862 | mxDoc->Unchain(*pOldChainPrev); | |||
1863 | ||||
1864 | const size_t nCnt = mxDoc->GetFlyCount(FLYCNTTYPE_FRM); | |||
1865 | ||||
1866 | /* potential successors resp. predecessors */ | |||
1867 | std::vector< const SwFrameFormat * > aTmpSpzArray; | |||
1868 | ||||
1869 | mxDoc->FindFlyByName(rReference); | |||
1870 | ||||
1871 | for (size_t n = 0; n < nCnt; ++n) | |||
1872 | { | |||
1873 | const SwFrameFormat & rFormat1 = *(mxDoc->GetFlyNum(n, FLYCNTTYPE_FRM)); | |||
1874 | ||||
1875 | /* | |||
1876 | pFormat is a potential successor of rFormat if it is chainable after | |||
1877 | rFormat. | |||
1878 | ||||
1879 | pFormat is a potential predecessor of rFormat if rFormat is chainable | |||
1880 | after pFormat. | |||
1881 | */ | |||
1882 | ||||
1883 | SwChainRet nChainState; | |||
1884 | ||||
1885 | if (bSuccessors) | |||
1886 | nChainState = mxDoc->Chainable(rFormat, rFormat1); | |||
1887 | else | |||
1888 | nChainState = mxDoc->Chainable(rFormat1, rFormat); | |||
1889 | ||||
1890 | if (nChainState == SwChainRet::OK) | |||
1891 | { | |||
1892 | aTmpSpzArray.push_back(&rFormat1); | |||
1893 | ||||
1894 | } | |||
1895 | ||||
1896 | } | |||
1897 | ||||
1898 | if (!aTmpSpzArray.empty()) | |||
1899 | { | |||
1900 | aPrevPageVec.clear(); | |||
1901 | aThisPageVec.clear(); | |||
1902 | aNextPageVec.clear(); | |||
1903 | aRestVec.clear(); | |||
1904 | ||||
1905 | /* number of page rFormat resides on */ | |||
1906 | sal_uInt16 nPageNum = SwFormatGetPageNum(static_cast<SwFlyFrameFormat *>(&rFormat)); | |||
1907 | ||||
1908 | for (const auto& rpFormat : aTmpSpzArray) | |||
1909 | { | |||
1910 | const OUString aString = rpFormat->GetName(); | |||
1911 | ||||
1912 | /* rFormat is not a valid successor or predecessor of | |||
1913 | itself */ | |||
1914 | if (aString != rReference && aString != rFormat.GetName()) | |||
1915 | { | |||
1916 | sal_uInt16 nNum1 = | |||
1917 | SwFormatGetPageNum(static_cast<const SwFlyFrameFormat *>(rpFormat)); | |||
1918 | ||||
1919 | if (nNum1 == nPageNum -1) | |||
1920 | aPrevPageVec.push_back(aString); | |||
1921 | else if (nNum1 == nPageNum) | |||
1922 | aThisPageVec.push_back(aString); | |||
1923 | else if (nNum1 == nPageNum + 1) | |||
1924 | aNextPageVec.push_back(aString); | |||
1925 | else | |||
1926 | aRestVec.push_back(aString); | |||
1927 | } | |||
1928 | } | |||
1929 | ||||
1930 | } | |||
1931 | ||||
1932 | if (pOldChainNext) | |||
1933 | mxDoc->Chain(rFormat, *pOldChainNext); | |||
1934 | ||||
1935 | if (pOldChainPrev) | |||
1936 | mxDoc->Chain(*pOldChainPrev, rFormat); | |||
1937 | ||||
1938 | EndAction(); | |||
1939 | } | |||
1940 | ||||
1941 | // #i73249# | |||
1942 | OUString SwFEShell::GetObjTitle() const | |||
1943 | { | |||
1944 | if ( Imp()->HasDrawView() ) | |||
1945 | { | |||
1946 | const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); | |||
1947 | if ( pMrkList->GetMarkCount() == 1 ) | |||
1948 | { | |||
1949 | const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); | |||
1950 | const SwFrameFormat* pFormat = FindFrameFormat( pObj ); | |||
1951 | if ( pFormat->Which() == RES_FLYFRMFMT ) | |||
1952 | { | |||
1953 | return static_cast<const SwFlyFrameFormat*>(pFormat)->GetObjTitle(); | |||
1954 | } | |||
1955 | return pObj->GetTitle(); | |||
1956 | } | |||
1957 | } | |||
1958 | ||||
1959 | return OUString(); | |||
1960 | } | |||
1961 | ||||
1962 | void SwFEShell::SetObjTitle( const OUString& rTitle ) | |||
1963 | { | |||
1964 | if ( !Imp()->HasDrawView() ) | |||
1965 | return; | |||
1966 | ||||
1967 | const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); | |||
1968 | if ( pMrkList->GetMarkCount() != 1 ) | |||
1969 | return; | |||
1970 | ||||
1971 | SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); | |||
1972 | SwFrameFormat* pFormat = FindFrameFormat( pObj ); | |||
1973 | if ( pFormat->Which() == RES_FLYFRMFMT ) | |||
1974 | { | |||
1975 | GetDoc()->SetFlyFrameTitle( dynamic_cast<SwFlyFrameFormat&>(*pFormat), | |||
1976 | rTitle ); | |||
1977 | } | |||
1978 | else | |||
1979 | { | |||
1980 | pObj->SetTitle( rTitle ); | |||
1981 | } | |||
1982 | } | |||
1983 | ||||
1984 | OUString SwFEShell::GetObjDescription() const | |||
1985 | { | |||
1986 | if ( Imp()->HasDrawView() ) | |||
1987 | { | |||
1988 | const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); | |||
1989 | if ( pMrkList->GetMarkCount() == 1 ) | |||
1990 | { | |||
1991 | const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); | |||
1992 | const SwFrameFormat* pFormat = FindFrameFormat( pObj ); | |||
1993 | if ( pFormat->Which() == RES_FLYFRMFMT ) | |||
1994 | { | |||
1995 | return dynamic_cast<const SwFlyFrameFormat&>(*pFormat).GetObjDescription(); | |||
1996 | } | |||
1997 | return pObj->GetDescription(); | |||
1998 | } | |||
1999 | } | |||
2000 | ||||
2001 | return OUString(); | |||
2002 | } | |||
2003 | ||||
2004 | void SwFEShell::SetObjDescription( const OUString& rDescription ) | |||
2005 | { | |||
2006 | if ( !Imp()->HasDrawView() ) | |||
2007 | return; | |||
2008 | ||||
2009 | const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); | |||
2010 | if ( pMrkList->GetMarkCount() != 1 ) | |||
2011 | return; | |||
2012 | ||||
2013 | SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); | |||
2014 | SwFrameFormat* pFormat = FindFrameFormat( pObj ); | |||
2015 | if ( pFormat->Which() == RES_FLYFRMFMT ) | |||
2016 | { | |||
2017 | GetDoc()->SetFlyFrameDescription(dynamic_cast<SwFlyFrameFormat&>(*pFormat), | |||
2018 | rDescription); | |||
2019 | } | |||
2020 | else | |||
2021 | { | |||
2022 | pObj->SetDescription( rDescription ); | |||
2023 | } | |||
2024 | } | |||
2025 | ||||
2026 | void SwFEShell::AlignFormulaToBaseline( const uno::Reference < embed::XEmbeddedObject >& xObj ) | |||
2027 | { | |||
2028 | #if OSL_DEBUG_LEVEL1 > 0 | |||
2029 | SvGlobalName aCLSID( xObj->getClassID() ); | |||
2030 | const bool bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 ); | |||
2031 | OSL_ENSURE( bStarMath, "AlignFormulaToBaseline should only be called for Math objects" )do { if (true && (!(bStarMath))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "2031" ": "), "%s", "AlignFormulaToBaseline should only be called for Math objects" ); } } while (false); | |||
2032 | ||||
2033 | if ( !bStarMath ) | |||
2034 | return; | |||
2035 | #endif | |||
2036 | ||||
2037 | SwFlyFrame * pFly = FindFlyFrame( xObj ); | |||
2038 | OSL_ENSURE( pFly , "No fly frame!" )do { if (true && (!(pFly))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "2038" ": "), "%s", "No fly frame!"); } } while (false); | |||
2039 | SwFrameFormat * pFrameFormat = pFly ? pFly->GetFormat() : nullptr; | |||
2040 | ||||
2041 | // baseline to baseline alignment should only be applied to formulas anchored as char | |||
2042 | if ( !pFly || !pFrameFormat || RndStdIds::FLY_AS_CHAR != pFrameFormat->GetAnchor().GetAnchorId() ) | |||
2043 | return; | |||
2044 | ||||
2045 | // get baseline from Math object | |||
2046 | uno::Any aBaseline; | |||
2047 | if( svt::EmbeddedObjectRef::TryRunningState( xObj ) ) | |||
2048 | { | |||
2049 | uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); | |||
2050 | if ( xSet.is() ) | |||
2051 | { | |||
2052 | try | |||
2053 | { | |||
2054 | aBaseline = xSet->getPropertyValue("BaseLine"); | |||
2055 | } | |||
2056 | catch ( uno::Exception& ) | |||
2057 | { | |||
2058 | OSL_FAIL( "Baseline could not be retrieved from Starmath!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "2058" ": "), "%s", "Baseline could not be retrieved from Starmath!" ); } } while (false); | |||
2059 | } | |||
2060 | } | |||
2061 | } | |||
2062 | ||||
2063 | sal_Int32 nBaseline = ::comphelper::getINT32(aBaseline); | |||
2064 | const MapMode aSourceMapMode( MapUnit::Map100thMM ); | |||
2065 | const MapMode aTargetMapMode( MapUnit::MapTwip ); | |||
2066 | nBaseline = OutputDevice::LogicToLogic( nBaseline, aSourceMapMode.GetMapUnit(), aTargetMapMode.GetMapUnit() ); | |||
2067 | ||||
2068 | OSL_ENSURE( nBaseline > 0, "Wrong value of Baseline while retrieving from Starmath!" )do { if (true && (!(nBaseline > 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "2068" ": "), "%s", "Wrong value of Baseline while retrieving from Starmath!" ); } } while (false); | |||
2069 | //nBaseline must be moved by aPrt position | |||
2070 | const SwFlyFrameFormat *pFlyFrameFormat = pFly->GetFormat(); | |||
2071 | OSL_ENSURE( pFlyFrameFormat, "fly frame format missing!" )do { if (true && (!(pFlyFrameFormat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fefly1.cxx" ":" "2071" ": "), "%s", "fly frame format missing!"); } } while (false); | |||
2072 | if ( pFlyFrameFormat ) | |||
2073 | nBaseline += pFlyFrameFormat->GetLastFlyFramePrtRectPos().Y(); | |||
2074 | ||||
2075 | const SwFormatVertOrient &rVert = pFrameFormat->GetVertOrient(); | |||
2076 | SwFormatVertOrient aVert( rVert ); | |||
2077 | aVert.SetPos( -nBaseline ); | |||
2078 | aVert.SetVertOrient( css::text::VertOrientation::NONE ); | |||
2079 | ||||
2080 | pFrameFormat->LockModify(); | |||
2081 | pFrameFormat->SetFormatAttr( aVert ); | |||
2082 | pFrameFormat->UnlockModify(); | |||
2083 | pFly->InvalidatePos(); | |||
2084 | ||||
2085 | } | |||
2086 | ||||
2087 | void SwFEShell::AlignAllFormulasToBaseline() | |||
2088 | { | |||
2089 | StartAllAction(); | |||
2090 | ||||
2091 | SwStartNode *pStNd; | |||
2092 | SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 ); | |||
2093 | while ( nullptr != (pStNd = aIdx.GetNode().GetStartNode()) ) | |||
2094 | { | |||
2095 | ++aIdx; | |||
2096 | SwOLENode *pOleNode = dynamic_cast< SwOLENode * >( &aIdx.GetNode() ); | |||
2097 | if ( pOleNode ) | |||
2098 | { | |||
2099 | const uno::Reference < embed::XEmbeddedObject > & xObj( pOleNode->GetOLEObj().GetOleRef() ); | |||
2100 | if (xObj.is()) | |||
2101 | { | |||
2102 | SvGlobalName aCLSID( xObj->getClassID() ); | |||
2103 | if ( SotExchange::IsMath( aCLSID ) ) | |||
2104 | AlignFormulaToBaseline( xObj ); | |||
2105 | } | |||
2106 | } | |||
2107 | ||||
2108 | aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 ); | |||
2109 | } | |||
2110 | ||||
2111 | EndAllAction(); | |||
2112 | } | |||
2113 | ||||
2114 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |