xref: /core/sw/source/uibase/uiview/view.cxx (revision c0936ba2)
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 <config_features.h>
21 
22 #include <stdlib.h>
23 #include <hintids.hxx>
24 #include <comphelper/string.hxx>
25 #include <o3tl/any.hxx>
26 #include <officecfg/Office/Common.hxx>
27 #include <vcl/graph.hxx>
28 #include <vcl/inputctx.hxx>
29 #include <svl/eitem.hxx>
30 #include <unotools/configmgr.hxx>
31 #include <unotools/lingucfg.hxx>
32 #include <unotools/useroptions.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <sfx2/objface.hxx>
36 #include <sfx2/request.hxx>
37 #include <sfx2/event.hxx>
38 #include <sfx2/infobar.hxx>
39 #include <svx/ruler.hxx>
40 #include <svx/srchdlg.hxx>
41 #include <svx/fmshell.hxx>
42 #include <svx/extrusionbar.hxx>
43 #include <svx/fontworkbar.hxx>
44 #include <svx/fmview.hxx>
45 #include <unotxvw.hxx>
46 #include <cmdid.h>
47 #include <svl/hint.hxx>
48 #include <swmodule.hxx>
49 #include <inputwin.hxx>
50 #include <uivwimp.hxx>
51 #include <edtwin.hxx>
52 #include <textsh.hxx>
53 #include <listsh.hxx>
54 #include <tabsh.hxx>
55 #include <grfsh.hxx>
56 #include <mediash.hxx>
57 #include <docsh.hxx>
58 #include <frmsh.hxx>
59 #include <olesh.hxx>
60 #include <drawsh.hxx>
61 #include <drawbase.hxx>
62 #include <drformsh.hxx>
63 #include <drwtxtsh.hxx>
64 #include <beziersh.hxx>
65 #include <navsh.hxx>
66 #include <globdoc.hxx>
67 #include <scroll.hxx>
68 #include <gloshdl.hxx>
69 #include <usrpref.hxx>
70 #include <srcview.hxx>
71 #include <strings.hrc>
72 #include <doc.hxx>
73 #include <IDocumentUndoRedo.hxx>
74 #include <IDocumentSettingAccess.hxx>
75 #include <IDocumentDrawModelAccess.hxx>
76 #include <DocumentFieldsManager.hxx>
77 #include <IDocumentState.hxx>
78 #include <IDocumentLayoutAccess.hxx>
79 #include <drawdoc.hxx>
80 #include <wdocsh.hxx>
81 #include <wrtsh.hxx>
82 #include <barcfg.hxx>
83 #include <pview.hxx>
84 #include <swdtflvr.hxx>
85 #include <prtopt.hxx>
86 #include <com/sun/star/frame/FrameSearchFlag.hpp>
87 #include <com/sun/star/frame/XLayoutManager.hpp>
88 #include <com/sun/star/scanner/ScannerContext.hpp>
89 #include <com/sun/star/scanner/XScannerManager2.hpp>
90 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
91 #include <com/sun/star/sdb/XDatabaseContext.hpp>
92 #include <com/sun/star/sdb/DatabaseContext.hpp>
93 #include <com/sun/star/sdbc/XDataSource.hpp>
94 #include <toolkit/helper/vclunohelper.hxx>
95 #include <sal/log.hxx>
96 
97 #include <formatclipboard.hxx>
98 #include <PostItMgr.hxx>
99 #include <annotsh.hxx>
100 #include <swruler.hxx>
101 
102 #include <com/sun/star/document/XDocumentProperties.hpp>
103 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
104 
105 #include <comphelper/propertyvalue.hxx>
106 #include <sfx2/lokhelper.hxx>
107 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
108 #include <svtools/embedhlp.hxx>
109 #include <tools/UnitConversion.hxx>
110 
111 using namespace ::com::sun::star;
112 using namespace ::com::sun::star::uno;
113 using namespace ::com::sun::star::lang;
114 using namespace ::com::sun::star::scanner;
115 using namespace ::com::sun::star::sdb;
116 using namespace ::com::sun::star::sdbc;
117 
118 #define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
119 
120 // Statics. OMG.
121 
122 bool bDocSzUpdated = true;
123 
124 SvxSearchItem*  SwView::s_pSrchItem   = nullptr;
125 
126 bool            SwView::s_bExtra      = false;
127 bool            SwView::s_bFound      = false;
128 bool            SwView::s_bJustOpened = false;
129 
130 std::unique_ptr<SearchAttrItemList>  SwView::s_xSearchList;
131 std::unique_ptr<SearchAttrItemList>  SwView::s_xReplaceList;
132 
133 SfxDispatcher &SwView::GetDispatcher()
134 {
135     return *GetViewFrame()->GetDispatcher();
136 }
137 
138 void SwView::ImpSetVerb( SelectionType nSelType )
139 {
140     bool bResetVerbs = m_bVerbsActive;
141     if ( !GetViewFrame()->GetFrame().IsInPlace() &&
142          (SelectionType::Ole|SelectionType::Graphic) & nSelType )
143     {
144         if ( m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE )
145         {
146             if ( nSelType & SelectionType::Ole )
147             {
148                 SetVerbs( GetWrtShell().GetOLEObject()->getSupportedVerbs() );
149                 m_bVerbsActive = true;
150                 bResetVerbs = false;
151             }
152         }
153     }
154     if ( bResetVerbs )
155     {
156         SetVerbs( Sequence< embed::VerbDescriptor >() );
157         m_bVerbsActive = false;
158     }
159 }
160 
161 // Called by the SwEditWin when it gets the focus.
162 
163 void SwView::GotFocus() const
164 {
165     // if we got the focus, and the form shell *is* on the top of the dispatcher
166     // stack, then we need to rebuild the stack (the form shell doesn't belong to
167     // the top then)
168     const SfxDispatcher& rDispatcher = const_cast< SwView* >( this )->GetDispatcher();
169     SfxShell* pTopShell = rDispatcher.GetShell( 0 );
170     FmFormShell* pAsFormShell = dynamic_cast<FmFormShell*>( pTopShell  );
171     if ( pAsFormShell )
172     {
173         pAsFormShell->ForgetActiveControl();
174         const_cast< SwView* >( this )->AttrChangedNotify(nullptr);
175     }
176     else if ( m_pPostItMgr )
177     {
178         SwAnnotationShell* pAsAnnotationShell = dynamic_cast<SwAnnotationShell*>( pTopShell  );
179         if ( pAsAnnotationShell )
180         {
181             m_pPostItMgr->SetActiveSidebarWin(nullptr);
182             const_cast< SwView* >( this )->AttrChangedNotify(nullptr);
183         }
184     }
185     if( GetWrtShellPtr() )
186     {
187         SwWrtShell& rWrtShell = GetWrtShell();
188         rWrtShell.GetDoc()->getIDocumentLayoutAccess().SetCurrentViewShell( GetWrtShellPtr() );
189         rWrtShell.GetDoc()->getIDocumentSettingAccess().set( DocumentSettingId::BROWSE_MODE,
190                                  rWrtShell.GetViewOptions()->getBrowseMode() );
191     }
192 }
193 
194 // called by the FormShell when a form control is focused. This is
195 // a request to put the form shell on the top of the dispatcher stack
196 
197 IMPL_LINK_NOARG(SwView, FormControlActivated, LinkParamNone*, void)
198 {
199     // if a form control has been activated, and the form shell is not on the top
200     // of the dispatcher stack, then we need to activate it
201     const SfxDispatcher& rDispatcher = GetDispatcher();
202     const SfxShell* pTopShell = rDispatcher.GetShell( 0 );
203     const FmFormShell* pAsFormShell = dynamic_cast<const FmFormShell*>( pTopShell  );
204     if ( !pAsFormShell )
205     {
206         // if we're editing text currently, cancel this
207         SdrView *pSdrView = m_pWrtShell ? m_pWrtShell->GetDrawView() : nullptr;
208         if ( pSdrView && pSdrView->IsTextEdit() )
209             pSdrView->SdrEndTextEdit( true );
210 
211         AttrChangedNotify(nullptr);
212     }
213 }
214 
215 IMPL_LINK_NOARG(SwView, ExchangeDatabaseHandler, weld::Button&, void)
216 {
217     GetDispatcher().Execute(FN_CHANGE_DBFIELD);
218 }
219 
220 namespace
221 {
222 uno::Reference<frame::XLayoutManager> getLayoutManager(const SfxViewFrame& rViewFrame)
223 {
224     uno::Reference<frame::XLayoutManager> xLayoutManager;
225     uno::Reference<beans::XPropertySet> xPropSet(rViewFrame.GetFrame().GetFrameInterface(),
226                                                  uno::UNO_QUERY);
227     if (xPropSet.is())
228     {
229         try
230         {
231             xLayoutManager.set(xPropSet->getPropertyValue("LayoutManager"), uno::UNO_QUERY);
232         }
233         catch (const Exception& e)
234         {
235             SAL_WARN("sw.ui", "Failure getting layout manager: " + e.Message);
236         }
237     }
238     return xLayoutManager;
239 }
240 }
241 
242 void SwView::ShowUIElement(const OUString& sElementURL) const
243 {
244     if (auto xLayoutManager = getLayoutManager(*GetViewFrame()))
245     {
246         if (!xLayoutManager->getElement(sElementURL).is())
247         {
248             xLayoutManager->createElement(sElementURL);
249             xLayoutManager->showElement(sElementURL);
250         }
251     }
252 }
253 
254 void SwView::SelectShell()
255 {
256     // Attention: Maintain the SelectShell for the WebView additionally
257 
258     if(m_bInDtor)
259         return;
260 
261     // Decision if the UpdateTable has to be called
262     bool bUpdateTable = false;
263     const SwFrameFormat* pCurTableFormat = m_pWrtShell->GetTableFormat();
264     if(pCurTableFormat && pCurTableFormat != m_pLastTableFormat)
265     {
266         bUpdateTable = true; // can only be executed later
267     }
268     m_pLastTableFormat = pCurTableFormat;
269 
270     //SEL_TBL and SEL_TBL_CELLS can be ORed!
271     SelectionType nNewSelectionType = m_pWrtShell->GetSelectionType()
272                                 & ~SelectionType::TableCell;
273 
274     if ( m_pFormShell && m_pFormShell->IsActiveControl() )
275         nNewSelectionType |= SelectionType::FormControl;
276 
277     if ( nNewSelectionType == m_nSelectionType )
278     {
279         GetViewFrame()->GetBindings().InvalidateAll( false );
280         if ( m_nSelectionType & SelectionType::Ole ||
281              m_nSelectionType & SelectionType::Graphic )
282             // For graphs and OLE the verb can be modified of course!
283             ImpSetVerb( nNewSelectionType );
284     }
285     else
286     {
287 
288         SfxDispatcher &rDispatcher = GetDispatcher();
289         SwToolbarConfigItem *pBarCfg = SW_MOD()->GetToolbarConfig();
290 
291         if ( m_pShell )
292         {
293             rDispatcher.Flush();        // Really erase all cached shells
294             //Remember to the old selection which toolbar was visible
295             ToolbarId eId = rDispatcher.GetObjectBarId(SFX_OBJECTBAR_OBJECT);
296             if (eId != ToolbarId::None)
297                 pBarCfg->SetTopToolbar(m_nSelectionType, eId);
298 
299             for ( sal_uInt16 i = 0; true; ++i )
300             {
301                 SfxShell *pSfxShell = rDispatcher.GetShell( i );
302                 if  (  dynamic_cast< const SwBaseShell *>( pSfxShell ) !=  nullptr
303                     || dynamic_cast< const SwDrawTextShell *>( pSfxShell ) !=  nullptr
304                     || dynamic_cast< const svx::ExtrusionBar*>( pSfxShell ) !=  nullptr
305                     || dynamic_cast< const svx::FontworkBar*>( pSfxShell ) !=  nullptr
306                     || dynamic_cast< const SwAnnotationShell *>( pSfxShell ) !=  nullptr
307                     )
308                 {
309                     rDispatcher.Pop( *pSfxShell, SfxDispatcherPopFlags::POP_DELETE );
310                 }
311                 else if ( dynamic_cast< const FmFormShell *>( pSfxShell ) !=  nullptr )
312                 {
313                     rDispatcher.Pop( *pSfxShell );
314                 }
315                 else
316                     break;
317             }
318         }
319 
320         bool bInitFormShell = false;
321         if (!m_pFormShell)
322         {
323             bInitFormShell = true;
324             m_pFormShell = new FmFormShell( this );
325             m_pFormShell->SetControlActivationHandler( LINK( this, SwView, FormControlActivated ) );
326             StartListening(*m_pFormShell);
327         }
328 
329         bool bSetExtInpCntxt = false;
330         m_nSelectionType = nNewSelectionType;
331         ShellMode eShellMode;
332 
333         if ( !( m_nSelectionType & SelectionType::FormControl ) )
334             rDispatcher.Push( *m_pFormShell );
335 
336         m_pShell = new SwNavigationShell( *this );
337         rDispatcher.Push( *m_pShell );
338 
339         if ( m_nSelectionType & SelectionType::Ole )
340         {
341             eShellMode = ShellMode::Object;
342             m_pShell = new SwOleShell( *this );
343             rDispatcher.Push( *m_pShell );
344         }
345         else if ( m_nSelectionType & SelectionType::Frame
346             || m_nSelectionType & SelectionType::Graphic)
347         {
348             eShellMode = ShellMode::Frame;
349             m_pShell = new SwFrameShell( *this );
350             rDispatcher.Push( *m_pShell );
351             if(m_nSelectionType & SelectionType::Graphic )
352             {
353                 eShellMode = ShellMode::Graphic;
354                 m_pShell = new SwGrfShell( *this );
355                 rDispatcher.Push( *m_pShell );
356             }
357         }
358         else if ( m_nSelectionType & SelectionType::DrawObject )
359         {
360             eShellMode = ShellMode::Draw;
361             m_pShell = new SwDrawShell( *this );
362             rDispatcher.Push( *m_pShell );
363 
364             if ( m_nSelectionType & SelectionType::Ornament )
365             {
366                 eShellMode = ShellMode::Bezier;
367                 m_pShell = new SwBezierShell( *this );
368                 rDispatcher.Push( *m_pShell );
369             }
370 #if HAVE_FEATURE_AVMEDIA
371             else if( m_nSelectionType & SelectionType::Media )
372             {
373                 eShellMode = ShellMode::Media;
374                 m_pShell = new SwMediaShell( *this );
375                 rDispatcher.Push( *m_pShell );
376             }
377 #endif
378             if (m_nSelectionType & SelectionType::ExtrudedCustomShape)
379             {
380                 eShellMode = ShellMode::ExtrudedCustomShape;
381                 m_pShell = new svx::ExtrusionBar(this);
382                 rDispatcher.Push( *m_pShell );
383             }
384             if (m_nSelectionType & SelectionType::FontWork)
385             {
386                 eShellMode = ShellMode::FontWork;
387                 m_pShell = new svx::FontworkBar(this);
388                 rDispatcher.Push( *m_pShell );
389             }
390         }
391         else if ( m_nSelectionType & SelectionType::DbForm )
392         {
393             eShellMode = ShellMode::DrawForm;
394             m_pShell = new SwDrawFormShell( *this );
395 
396             rDispatcher.Push( *m_pShell );
397         }
398         else if ( m_nSelectionType & SelectionType::DrawObjectEditMode )
399         {
400             bSetExtInpCntxt = true;
401             eShellMode = ShellMode::DrawText;
402             rDispatcher.Push( *(new SwBaseShell( *this )) );
403             m_pShell = new SwDrawTextShell( *this );
404             rDispatcher.Push( *m_pShell );
405         }
406         else if ( m_nSelectionType & SelectionType::PostIt )
407         {
408             eShellMode = ShellMode::PostIt;
409             m_pShell = new SwAnnotationShell( *this );
410             rDispatcher.Push( *m_pShell );
411         }
412         else
413         {
414             bSetExtInpCntxt = true;
415             eShellMode = ShellMode::Text;
416             if ( m_nSelectionType & SelectionType::NumberList )
417             {
418                 eShellMode = ShellMode::ListText;
419                 m_pShell = new SwListShell( *this );
420                 rDispatcher.Push( *m_pShell );
421             }
422             m_pShell = new SwTextShell(*this);
423             rDispatcher.Push( *m_pShell );
424             if ( m_nSelectionType & SelectionType::Table )
425             {
426                 eShellMode = eShellMode == ShellMode::ListText ? ShellMode::TableListText
427                                                         : ShellMode::TableText;
428                 m_pShell = new SwTableShell( *this );
429                 rDispatcher.Push( *m_pShell );
430             }
431         }
432 
433         if ( m_nSelectionType & SelectionType::FormControl )
434             rDispatcher.Push( *m_pFormShell );
435 
436         m_pViewImpl->SetShellMode(eShellMode);
437         ImpSetVerb( m_nSelectionType );
438 
439         if( !GetDocShell()->IsReadOnly() )
440         {
441             if( bSetExtInpCntxt && GetWrtShell().HasReadonlySel() )
442                 bSetExtInpCntxt = false;
443 
444             InputContext aCntxt( GetEditWin().GetInputContext() );
445             aCntxt.SetOptions( bSetExtInpCntxt
446                                 ? (aCntxt.GetOptions() |
447                                         ( InputContextFlags::Text |
448                                             InputContextFlags::ExtText ))
449                                 : (aCntxt.GetOptions() & ~
450                                         InputContextFlags( InputContextFlags::Text |
451                                             InputContextFlags::ExtText )) );
452             GetEditWin().SetInputContext( aCntxt );
453         }
454 
455         // Show Mail Merge toolbar initially for documents with Database fields
456         if (!m_bInitOnceCompleted
457             && (GetWrtShell().IsAnyDatabaseFieldInDoc()
458                 || !GetWrtShell().GetDBData().sDataSource.isEmpty()))
459             ShowUIElement("private:resource/toolbar/mailmerge");
460 
461         // Activate the toolbar to the new selection which also was active last time.
462         // Before a flush () must be, but does not affect the UI according to MBA and
463         // is not a performance problem.
464         // TODO/LATER: maybe now the Flush() command is superfluous?!
465         rDispatcher.Flush();
466 
467         Point aPnt = GetEditWin().OutputToScreenPixel(GetEditWin().GetPointerPosPixel());
468         aPnt = GetEditWin().PixelToLogic(aPnt);
469         GetEditWin().UpdatePointer(aPnt);
470 
471         SdrView* pDView = GetWrtShell().GetDrawView();
472         if ( bInitFormShell && pDView )
473             m_pFormShell->SetView(dynamic_cast<FmFormView*>( pDView) );
474 
475     }
476     // Opportune time for the communication with OLE objects?
477     if ( GetDocShell()->GetDoc()->IsOLEPrtNotifyPending() )
478         GetDocShell()->GetDoc()->PrtOLENotify( false );
479 
480     // now the table-update
481     if(bUpdateTable)
482         m_pWrtShell->UpdateTable();
483 
484     GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
485 
486     m_bInitOnceCompleted = true;
487 }
488 
489 // Interaction: AttrChangedNotify() and TimeoutHdl.
490 // No Update if actions are still open, since the cursor on the core side
491 // can be somewhere in no man's land.
492 // But since we can no longer supply status and we want instead lock
493 // the dispatcher.
494 
495 extern "C"
496 {
497     static int lcl_CmpIds( const void *pFirst, const void *pSecond)
498     {
499         return *static_cast<sal_uInt16 const *>(pFirst) - *static_cast<sal_uInt16 const *>(pSecond);
500     }
501 }
502 
503 IMPL_LINK_NOARG(SwView, AttrChangedNotify, LinkParamNone*, void)
504 {
505     if ( GetEditWin().IsChainMode() )
506         GetEditWin().SetChainMode( false );
507 
508     //Opt: Not if PaintLocked. During unlock a notify will be once more triggered.
509     if( !m_pWrtShell->IsPaintLocked() && !g_bNoInterrupt &&
510         GetDocShell()->IsReadOnly() )
511         CheckReadonlyState();
512 
513     if( !m_pWrtShell->IsPaintLocked() && !g_bNoInterrupt )
514         CheckReadonlySelection();
515 
516     if( !m_bAttrChgNotified )
517     {
518         if (m_pWrtShell->ActionPend() || g_bNoInterrupt ||
519              GetDispatcher().IsLocked() ||               //do not confuse the SFX
520              GetViewFrame()->GetBindings().IsInUpdate() )//do not confuse the SFX
521         {
522             m_bAttrChgNotified = true;
523             m_aTimer.Start();
524 
525             const SfxPoolItem *pItem;
526             if ( SfxItemState::SET != GetObjectShell()->GetMedium()->GetItemSet()->
527                                     GetItemState( SID_HIDDEN, false, &pItem ) ||
528                  !static_cast<const SfxBoolItem*>(pItem)->GetValue() )
529             {
530                 GetViewFrame()->GetBindings().ENTERREGISTRATIONS();
531                 m_bAttrChgNotifiedWithRegistrations = true;
532             }
533 
534         }
535         else
536             SelectShell();
537 
538     }
539 
540     // change ui if cursor is at a SwPostItField
541     if (m_pPostItMgr)
542     {
543         // only perform the code that is needed to determine, if at the
544         // actual cursor position is a post-it field
545         m_pPostItMgr->SetShadowState( m_pWrtShell->GetPostItFieldAtCursor() );
546     }
547 }
548 
549 IMPL_LINK_NOARG(SwView, TimeoutHdl, Timer *, void)
550 {
551     if (m_pWrtShell->ActionPend() || g_bNoInterrupt)
552     {
553         m_aTimer.Start();
554         return;
555     }
556 
557     if ( m_bAttrChgNotifiedWithRegistrations )
558     {
559         GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
560         m_bAttrChgNotifiedWithRegistrations = false;
561     }
562 
563     CheckReadonlyState();
564     CheckReadonlySelection();
565 
566     bool bOldUndo = m_pWrtShell->DoesUndo();
567     m_pWrtShell->DoUndo( false );
568     SelectShell();
569     m_pWrtShell->DoUndo( bOldUndo );
570     m_bAttrChgNotified = false;
571     GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
572 }
573 
574 void SwView::CheckReadonlyState()
575 {
576     SfxDispatcher &rDis = GetDispatcher();
577     // To be able to recognize if it is already disabled!
578     SfxItemState eStateRO, eStateProtAll;
579     const SfxPoolItem *pItem;
580     // Query the status from a slot which is only known to us.
581     // Otherwise the slot is known from other; like the BasicIde
582     eStateRO = rDis.QueryState( FN_INSERT_BOOKMARK, pItem );
583     eStateProtAll = rDis.QueryState( FN_EDIT_REGION, pItem );
584     bool bChgd = false;
585 
586     if ( !m_pWrtShell->IsCursorReadonly() )
587     {
588         static sal_uInt16 aROIds[] =
589         {
590             SID_DELETE,                 FN_BACKSPACE,               FN_SHIFT_BACKSPACE,
591             SID_UNDO,
592             SID_REDO,                   SID_REPEAT,                 SID_PASTE,
593             SID_PASTE_UNFORMATTED,      FN_PASTE_NESTED_TABLE,      FN_TABLE_PASTE_ROW_BEFORE,
594             FN_TABLE_PASTE_COL_BEFORE,  SID_PASTE_SPECIAL,          SID_SBA_BRW_INSERT,
595             SID_BACKGROUND_COLOR,       FN_INSERT_BOOKMARK,         SID_CHARMAP_CONTROL,
596             SID_CHARMAP,                SID_EMOJI_CONTROL,          FN_INSERT_SOFT_HYPHEN,
597             FN_INSERT_HARDHYPHEN,       FN_INSERT_HARD_SPACE,       FN_INSERT_NNBSP,
598             FN_INSERT_BREAK,            FN_INSERT_LINEBREAK,        FN_INSERT_COLUMN_BREAK,
599             FN_INSERT_BREAK_DLG,
600             FN_DELETE_SENT,             FN_DELETE_BACK_SENT,        FN_DELETE_WORD,
601             FN_DELETE_BACK_WORD,        FN_DELETE_LINE,             FN_DELETE_BACK_LINE,
602             FN_DELETE_PARA,             FN_DELETE_BACK_PARA,        FN_DELETE_WHOLE_LINE,
603             FN_CALCULATE,               FN_FORMAT_RESET,
604             FN_POSTIT,                  FN_JAVAEDIT,                SID_ATTR_PARA_ADJUST_LEFT,
605             SID_ATTR_PARA_ADJUST_RIGHT, SID_ATTR_PARA_ADJUST_CENTER,SID_ATTR_PARA_ADJUST_BLOCK,
606             SID_ATTR_PARA_LINESPACE_10, SID_ATTR_PARA_LINESPACE_15, SID_ATTR_PARA_LINESPACE_20,
607             SID_ATTR_CHAR_FONT,         SID_ATTR_CHAR_FONTHEIGHT,   SID_ATTR_CHAR_COLOR_BACKGROUND,
608             SID_ATTR_CHAR_COLOR_BACKGROUND_EXT,                     SID_ATTR_CHAR_COLOR_EXT,
609             SID_ATTR_CHAR_COLOR,        SID_ATTR_CHAR_WEIGHT,       SID_ATTR_CHAR_POSTURE,
610             SID_ATTR_CHAR_OVERLINE,
611             SID_ATTR_CHAR_UNDERLINE,    SID_ATTR_FLASH,             SID_ATTR_CHAR_STRIKEOUT,
612             SID_ULINE_VAL_SINGLE,       SID_ULINE_VAL_DOUBLE,       SID_ULINE_VAL_DOTTED,
613             SID_ATTR_CHAR_CONTOUR,      SID_ATTR_CHAR_SHADOWED,
614             SID_ATTR_CHAR_AUTOKERN,     SID_ATTR_CHAR_ESCAPEMENT,   FN_SET_SUPER_SCRIPT,
615             FN_SET_SUB_SCRIPT,          SID_ATTR_CHAR_CASEMAP,      SID_ATTR_CHAR_LANGUAGE,
616             SID_ATTR_CHAR_KERNING,      SID_CHAR_DLG,               SID_ATTR_CHAR_WORDLINEMODE,
617             FN_GROW_FONT_SIZE,          FN_SHRINK_FONT_SIZE,        FN_TXTATR_INET,
618             FN_FORMAT_DROPCAPS,         SID_ATTR_PARA_ADJUST,       SID_ATTR_PARA_LINESPACE,
619             SID_ATTR_PARA_SPLIT,        SID_ATTR_PARA_KEEP,         SID_ATTR_PARA_WIDOWS,
620             SID_ATTR_PARA_ORPHANS,
621             SID_ATTR_PARA_MODEL,        SID_PARA_DLG,
622             FN_SELECT_PARA,             SID_DEC_INDENT,
623             SID_INC_INDENT
624         };
625         static bool bFirst = true;
626         if ( bFirst )
627         {
628             qsort( static_cast<void*>(aROIds), SAL_N_ELEMENTS(aROIds), sizeof(sal_uInt16), lcl_CmpIds );
629             bFirst = false;
630         }
631         if ( SfxItemState::DISABLED == eStateRO )
632         {
633             rDis.SetSlotFilter( SfxSlotFilterState::ENABLED_READONLY, aROIds );
634             bChgd = true;
635         }
636     }
637     else if( m_pWrtShell->IsAllProtect() )
638     {
639         if ( SfxItemState::DISABLED == eStateProtAll )
640         {
641             static sal_uInt16 aAllProtIds[] = { SID_SAVEDOC, FN_EDIT_REGION };
642             static bool bAllProtFirst = true;
643             if ( bAllProtFirst )
644             {
645                 qsort( static_cast<void*>(aAllProtIds), SAL_N_ELEMENTS(aAllProtIds), sizeof(sal_uInt16), lcl_CmpIds );
646                 bAllProtFirst = false;
647             }
648             rDis.SetSlotFilter( SfxSlotFilterState::ENABLED_READONLY, aAllProtIds );
649             bChgd = true;
650         }
651     }
652     else if ( SfxItemState::DISABLED != eStateRO ||
653                 SfxItemState::DISABLED != eStateProtAll )
654     {
655         bChgd = true;
656         rDis.SetSlotFilter();
657     }
658     if ( bChgd )
659         GetViewFrame()->GetBindings().InvalidateAll(true);
660 }
661 
662 void SwView::CheckReadonlySelection()
663 {
664     SfxDisableFlags nDisableFlags = SfxDisableFlags::NONE;
665     SfxDispatcher &rDis = GetDispatcher();
666 
667     if( m_pWrtShell->HasReadonlySel() &&
668         ( !m_pWrtShell->GetDrawView() ||
669             !m_pWrtShell->GetDrawView()->GetMarkedObjectList().GetMarkCount() ))
670         nDisableFlags |= SfxDisableFlags::SwOnProtectedCursor;
671 
672     if( (SfxDisableFlags::SwOnProtectedCursor & nDisableFlags ) !=
673         (SfxDisableFlags::SwOnProtectedCursor & rDis.GetDisableFlags() ) )
674     {
675         // Additionally move at the Window the InputContext, so that
676         // in japanese / chinese versions the external input will be
677         // turned on or off. This but only if the correct shell is on
678         // the stack.
679         switch( m_pViewImpl->GetShellMode() )
680         {
681         case ShellMode::Text:
682         case ShellMode::ListText:
683         case ShellMode::TableText:
684         case ShellMode::TableListText:
685             {
686 // Temporary solution!!! Should set the font of the current insertion point
687 //         at each cursor movement, so outside of this "if". But TH does not
688 //         evaluates the font at this time and the "purchase" appears to me
689 //         as too expensive.
690 //         Moreover, we don't have a font, but only attributes from which the
691 //         text formatting and the correct font will be build together.
692 
693                 InputContext aCntxt( GetEditWin().GetInputContext() );
694                 aCntxt.SetOptions( SfxDisableFlags::SwOnProtectedCursor & nDisableFlags
695                                     ? (aCntxt.GetOptions() & ~
696                                             InputContextFlags( InputContextFlags::Text |
697                                                 InputContextFlags::ExtText ))
698                                     : (aCntxt.GetOptions() |
699                                             ( InputContextFlags::Text |
700                                                 InputContextFlags::ExtText )) );
701                 GetEditWin().SetInputContext( aCntxt );
702             }
703             break;
704         default:
705             ;
706         }
707 
708     }
709 
710     if( nDisableFlags != rDis.GetDisableFlags() )
711     {
712         rDis.SetDisableFlags( nDisableFlags );
713         GetViewFrame()->GetBindings().InvalidateAll( true );
714     }
715 }
716 
717 SwView::SwView( SfxViewFrame *_pFrame, SfxViewShell* pOldSh )
718     : SfxViewShell( _pFrame, SWVIEWFLAGS ),
719     m_nNewPage(USHRT_MAX),
720     m_nOldPageNum(0),
721     m_pNumRuleNodeFromDoc(nullptr),
722     m_pEditWin( VclPtr<SwEditWin>::Create( &_pFrame->GetWindow(), *this ) ),
723     m_pShell(nullptr),
724     m_pFormShell(nullptr),
725     m_pHScrollbar(nullptr),
726     m_pVScrollbar(nullptr),
727     m_pScrollFill(VclPtr<ScrollBarBox>::Create( &_pFrame->GetWindow(), WB_SIZEABLE )),
728     m_pVRuler(VclPtr<SvxRuler>::Create(&GetViewFrame()->GetWindow(), m_pEditWin,
729                             SvxRulerSupportFlags::TABS | SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL|
730                                 SvxRulerSupportFlags::BORDERS | SvxRulerSupportFlags::REDUCED_METRIC,
731                             GetViewFrame()->GetBindings(),
732                             WB_VSCROLL |  WB_EXTRAFIELD | WB_BORDER )),
733     m_pLastTableFormat(nullptr),
734     m_pFormatClipboard(new SwFormatClipboard()),
735     m_nSelectionType( SelectionType::All ),
736     m_nPageCnt(0),
737     m_nDrawSfxId( USHRT_MAX ),
738     m_nFormSfxId( USHRT_MAX ),
739     m_eFormObjKind(OBJ_NONE),
740     m_nLastPasteDestination( static_cast<SotExchangeDest>(0xFFFF) ),
741     m_nLeftBorderDistance( 0 ),
742     m_nRightBorderDistance( 0 ),
743     m_eLastSearchCommand( static_cast<SvxSearchCmd>(0xFFFF) ),
744     m_bWheelScrollInProgress(false),
745     m_bCenterCursor(false),
746     m_bTopCursor(false),
747     m_bTabColFromDoc(false),
748     m_bTabRowFromDoc(false),
749     m_bSetTabColFromDoc(false),
750     m_bSetTabRowFromDoc(false),
751     m_bAttrChgNotified(false),
752     m_bAttrChgNotifiedWithRegistrations(false),
753     m_bVerbsActive(false),
754     m_bDrawRotate(false),
755     m_bDrawSelMode(true),
756     m_bShowAtResize(true),
757     m_bInOuterResizePixel(false),
758     m_bInInnerResizePixel(false),
759     m_bPasteState(false),
760     m_bPasteSpecialState(false),
761     m_bInMailMerge(false),
762     m_bInDtor(false),
763     m_bOldShellWasPagePreview(false),
764     m_bIsPreviewDoubleClick(false),
765     m_bMakeSelectionVisible(false),
766     m_bForceChangesToolbar(true),
767     m_nLOKPageUpDownOffset(0)
768 {
769     static bool bRequestDoubleBuffering = getenv("VCL_DOUBLEBUFFERING_ENABLE");
770     if (bRequestDoubleBuffering)
771         m_pEditWin->RequestDoubleBuffering(true);
772 
773     // According to discussion with MBA and further
774     // investigations, no old SfxViewShell will be set as parameter <pOldSh>,
775     // if function "New Window" is performed to open an additional view beside
776     // an already existing one.
777     // If the view is switch from one to another, the 'old' view is given by
778     // parameter <pOldSh>.
779 
780     bDocSzUpdated = true;
781 
782     CreateScrollbar( true );
783     CreateScrollbar( false );
784 
785     m_pViewImpl.reset(new SwView_Impl(this));
786     SetName("View");
787     SetWindow( m_pEditWin );
788 
789     m_aTimer.SetTimeout( 120 );
790 
791     SwDocShell& rDocSh = dynamic_cast<SwDocShell&>(*_pFrame->GetObjectShell());
792     bool bOldModifyFlag = rDocSh.IsEnableSetModified();
793     if (bOldModifyFlag)
794         rDocSh.EnableSetModified( false );
795     // HACK: SwDocShell has some cached font info, VCL informs about font updates,
796     // but loading of docs with embedded fonts happens after SwDocShell is created
797     // but before SwEditWin (which handles the VCL event) is created. So update
798     // manually.
799     if (rDocSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS ))
800         rDocSh.UpdateFontList();
801     bool bWebDShell = dynamic_cast<const SwWebDocShell*>(&rDocSh) !=  nullptr;
802 
803     const SwMasterUsrPref *pUsrPref = SW_MOD()->GetUsrPref(bWebDShell);
804     SwViewOption aUsrPref( *pUsrPref);
805 
806     //! get lingu options without loading lingu DLL
807     SvtLinguOptions aLinguOpt;
808     SvtLinguConfig().GetOptions( aLinguOpt );
809     aUsrPref.SetOnlineSpell( aLinguOpt.bIsSpellAuto );
810 
811     bool bOldShellWasSrcView = false;
812 
813     // determine if there is an existing view for
814     // document
815     SfxViewShell* pExistingSh = nullptr;
816     if ( pOldSh )
817     {
818         pExistingSh = pOldSh;
819         // determine type of existing view
820         if (SwPagePreview* pPagePreview = dynamic_cast<SwPagePreview *>(pExistingSh))
821         {
822             m_sSwViewData = pPagePreview->GetPrevSwViewData();
823             m_sNewCursorPos = pPagePreview->GetNewCursorPos();
824             m_nNewPage = pPagePreview->GetNewPage();
825             m_bOldShellWasPagePreview = true;
826             m_bIsPreviewDoubleClick = !m_sNewCursorPos.isEmpty() || m_nNewPage != USHRT_MAX;
827         }
828         else if (dynamic_cast<const SwSrcView *>(pExistingSh) != nullptr)
829             bOldShellWasSrcView = true;
830     }
831 
832     SAL_INFO( "sw.ui", "before create WrtShell" );
833     if (SwView *pView = dynamic_cast<SwView*>(pExistingSh))
834     {
835         m_pWrtShell.reset(new SwWrtShell(*pView->m_pWrtShell, m_pEditWin, *this));
836     }
837     else if (SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(rDocSh.GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()))
838     {
839         m_pWrtShell.reset(new SwWrtShell(*pWrtShell, m_pEditWin, *this));
840     }
841     else
842     {
843         SwDoc& rDoc = *rDocSh.GetDoc();
844 
845         if( !bOldShellWasSrcView && bWebDShell && !m_bOldShellWasPagePreview )
846             aUsrPref.setBrowseMode( true );
847         else
848             aUsrPref.setBrowseMode( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) );
849 
850         //For the BrowseMode we do not assume a factor.
851         if( aUsrPref.getBrowseMode() && aUsrPref.GetZoomType() != SvxZoomType::PERCENT )
852         {
853             aUsrPref.SetZoomType( SvxZoomType::PERCENT );
854             aUsrPref.SetZoom( 100 );
855         }
856         if (rDocSh.IsPreview())
857         {
858             aUsrPref.SetZoomType( SvxZoomType::WHOLEPAGE );
859             aUsrPref.SetViewLayoutBookMode( false );
860             aUsrPref.SetViewLayoutColumns( 1 );
861         }
862         m_pWrtShell.reset(new SwWrtShell(rDoc, m_pEditWin, *this, &aUsrPref));
863         // creating an SwView from a SwPagePreview needs to
864         // add the SwViewShell to the ring of the other SwViewShell(s)
865         if(m_bOldShellWasPagePreview)
866         {
867             SwViewShell& rPreviewViewShell = *static_cast<SwPagePreview*>(pExistingSh)->GetViewShell();
868             m_pWrtShell->MoveTo(&rPreviewViewShell);
869             // to update the field command et.al. if necessary
870             const SwViewOption* pPreviewOpt = rPreviewViewShell.GetViewOptions();
871             if( pPreviewOpt->IsFieldName() != aUsrPref.IsFieldName() ||
872                     pPreviewOpt->IsShowHiddenField() != aUsrPref.IsShowHiddenField() ||
873                     pPreviewOpt->IsShowHiddenPara() != aUsrPref.IsShowHiddenPara() ||
874                     pPreviewOpt->IsShowHiddenChar() != aUsrPref.IsShowHiddenChar() )
875                 rPreviewViewShell.ApplyViewOptions(aUsrPref);
876             // reset design mode at draw view for form
877             // shell, if needed.
878             if ( static_cast<SwPagePreview*>(pExistingSh)->ResetFormDesignMode() &&
879                  m_pWrtShell->HasDrawView() )
880             {
881                 SdrView* pDrawView = m_pWrtShell->GetDrawView();
882                 pDrawView->SetDesignMode( static_cast<SwPagePreview*>(pExistingSh)->FormDesignModeToReset() );
883             }
884         }
885     }
886     SAL_INFO( "sw.ui", "after create WrtShell" );
887     m_pHRuler = VclPtr<SwCommentRuler>::Create(m_pWrtShell.get(), &GetViewFrame()->GetWindow(), m_pEditWin,
888                 SvxRulerSupportFlags::TABS |
889                 SvxRulerSupportFlags::PARAGRAPH_MARGINS |
890                 SvxRulerSupportFlags::BORDERS |
891                 SvxRulerSupportFlags::NEGATIVE_MARGINS|
892                 SvxRulerSupportFlags::REDUCED_METRIC,
893                 GetViewFrame()->GetBindings(),
894                 WB_STDRULER | WB_EXTRAFIELD | WB_BORDER);
895 
896     // assure that modified state of document
897     // isn't reset, if document is already modified.
898     const bool bIsDocModified = m_pWrtShell->GetDoc()->getIDocumentState().IsModified();
899 
900     // Thus among other things, the HRuler is not displayed in the read-only case.
901     aUsrPref.SetReadonly( m_pWrtShell->GetViewOptions()->IsReadonly() );
902 
903     // no margin for OLE!
904     Size aBrwsBorder;
905     if( SfxObjectCreateMode::EMBEDDED != rDocSh.GetCreateMode() )
906         aBrwsBorder = GetMargin();
907 
908     m_pWrtShell->SetBrowseBorder( aBrwsBorder );
909 
910     // In CTOR no shell changes may take place, which must be temporarily stored
911     // with the timer. Otherwise, the SFX removes them from the stack!
912     bool bOld = g_bNoInterrupt;
913     g_bNoInterrupt = true;
914 
915     m_pHRuler->SetActive();
916     m_pVRuler->SetActive();
917 
918     SfxViewFrame* pViewFrame = GetViewFrame();
919 
920     StartListening(*pViewFrame, DuplicateHandling::Prevent);
921     StartListening(rDocSh, DuplicateHandling::Prevent);
922 
923     // Set Zoom-factor from HRuler
924     Fraction aZoomFract( aUsrPref.GetZoom(), 100 );
925     m_pHRuler->SetZoom( aZoomFract );
926     m_pVRuler->SetZoom( aZoomFract );
927     m_pHRuler->SetDoubleClickHdl(LINK( this, SwView, ExecRulerClick ));
928     FieldUnit eMetric = pUsrPref->GetHScrollMetric();
929     m_pHRuler->SetUnit( eMetric );
930 
931     eMetric = pUsrPref->GetVScrollMetric();
932     m_pVRuler->SetUnit( eMetric );
933 
934     m_pHRuler->SetCharWidth( 371 );  // default character width
935     m_pVRuler->SetLineHeight( 551 );  // default line height
936 
937     // Set DocShell
938     m_xGlueDocShell.reset(new SwViewGlueDocShell(*this, rDocSh));
939     m_pPostItMgr.reset(new SwPostItMgr(this));
940 
941     // Check and process the DocSize. Via the handler, the shell could not
942     // be found, because the shell is not known in the SFX management
943     // within the CTOR phase.
944     DocSzChgd( m_pWrtShell->GetDocSize() );
945 
946         // Set AttrChangedNotify link
947     m_pWrtShell->SetChgLnk(LINK(this, SwView, AttrChangedNotify));
948 
949     if (rDocSh.GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
950         !rDocSh.GetVisArea(ASPECT_CONTENT).IsEmpty())
951         SetVisArea(rDocSh.GetVisArea(ASPECT_CONTENT),false);
952 
953     SAL_WARN_IF(
954         officecfg::Office::Common::Undo::Steps::get() <= 0,
955         "sw.ui", "/org.openoffice.Office.Common/Undo/Steps <= 0");
956     if (!utl::ConfigManager::IsFuzzing() && 0 < officecfg::Office::Common::Undo::Steps::get())
957     {
958         m_pWrtShell->DoUndo();
959     }
960 
961     const bool bBrowse = m_pWrtShell->GetViewOptions()->getBrowseMode();
962     // Disable "multiple window"
963     SetNewWindowAllowed(!bBrowse);
964     // End of disabled multiple window
965 
966     m_bVScrollbarEnabled = aUsrPref.IsViewVScrollBar();
967     m_bHScrollbarEnabled = aUsrPref.IsViewHScrollBar();
968     m_pHScrollbar->SetAuto(bBrowse);
969     if( aUsrPref.IsViewHRuler() )
970         CreateTab();
971     if( aUsrPref.IsViewVRuler() )
972         CreateVRuler();
973 
974     m_pWrtShell->SetUIOptions( aUsrPref );
975     m_pWrtShell->SetReadOnlyAvailable( aUsrPref.IsCursorInProtectedArea() );
976     m_pWrtShell->ApplyAccessibilityOptions(SW_MOD()->GetAccessibilityOptions());
977 
978     if( m_pWrtShell->GetDoc()->getIDocumentState().IsUpdateExpField() )
979     {
980         if (m_pWrtShell->GetDoc()->GetDocumentFieldsManager().containsUpdatableFields())
981         {
982             CurrShell aCurr(m_pWrtShell.get());
983             m_pWrtShell->StartAction();
984             m_pWrtShell->CalcLayout();
985             m_pWrtShell->GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
986             m_pWrtShell->EndAction();
987         }
988         m_pWrtShell->GetDoc()->getIDocumentState().SetUpdateExpFieldStat( false );
989     }
990 
991     // Update all tables if necessary:
992     if( m_pWrtShell->GetDoc()->IsUpdateTOX() )
993     {
994         SfxRequest aSfxRequest( FN_UPDATE_TOX, SfxCallMode::SLOT, GetPool() );
995         Execute( aSfxRequest );
996         m_pWrtShell->GetDoc()->SetUpdateTOX( false );     // reset again
997         m_pWrtShell->SttEndDoc(true);
998     }
999 
1000     // No ResetModified, if there is already a view to this doc.
1001     SfxViewFrame* pVFrame = GetViewFrame();
1002     SfxViewFrame* pFirst = SfxViewFrame::GetFirst(&rDocSh);
1003     // Currently(360) the view is registered firstly after the CTOR,
1004     // the following expression is also working if this changes.
1005     // If the modification cannot be canceled by undo, then do NOT set
1006     // the modify back.
1007     // no reset of modified state, if document
1008     // was already modified.
1009     if (!m_pWrtShell->GetDoc()->GetIDocumentUndoRedo().IsUndoNoResetModified() &&
1010          ( !pFirst || pFirst == pVFrame ) &&
1011          !bIsDocModified )
1012     {
1013         m_pWrtShell->ResetModified();
1014     }
1015 
1016     g_bNoInterrupt = bOld;
1017 
1018     // If a new GlobalDoc will be created, the navigator will also be generated.
1019     if( dynamic_cast<const SwGlobalDocShell*>(&rDocSh) != nullptr &&
1020         !pVFrame->GetChildWindow( SID_NAVIGATOR ))
1021     {
1022         SfxBoolItem aNavi(SID_NAVIGATOR, true);
1023         GetDispatcher().ExecuteList(SID_NAVIGATOR, SfxCallMode::ASYNCHRON, { &aNavi });
1024     }
1025 
1026     uno::Reference< frame::XFrame >  xFrame = pVFrame->GetFrame().GetFrameInterface();
1027 
1028     uno::Reference< frame::XFrame >  xBeamerFrame = xFrame->findFrame(
1029             "_beamer", frame::FrameSearchFlag::CHILDREN);
1030     if(xBeamerFrame.is())
1031     {
1032         SwDBData aData = m_pWrtShell->GetDBData();
1033         SwModule::ShowDBObj( *this, aData );
1034     }
1035 
1036     // has anybody calls the attrchanged handler in the constructor?
1037     if( m_bAttrChgNotifiedWithRegistrations )
1038     {
1039         GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
1040         if( m_aTimer.IsActive() )
1041             m_aTimer.Stop();
1042     }
1043 
1044     m_aTimer.SetInvokeHandler(LINK(this, SwView, TimeoutHdl));
1045     m_aTimer.SetDebugName( "sw::SwView m_aTimer" );
1046     m_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations = false;
1047     if (bOldModifyFlag)
1048         rDocSh.EnableSetModified();
1049     InvalidateBorder();
1050 
1051     if( !m_pHScrollbar->IsVisible( true ) )
1052         ShowHScrollbar( false );
1053     if( !m_pVScrollbar->IsVisible( true ) )
1054         ShowVScrollbar( false );
1055 
1056     GetViewFrame()->GetWindow().AddChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
1057 }
1058 
1059 SwViewGlueDocShell::SwViewGlueDocShell(SwView& rView, SwDocShell& rDocSh)
1060     : m_rView(rView)
1061 {
1062     // Set DocShell
1063     rDocSh.SetView(&m_rView);
1064     SW_MOD()->SetView(&m_rView);
1065 }
1066 
1067 SwViewGlueDocShell::~SwViewGlueDocShell()
1068 {
1069     SwDocShell* pDocSh = m_rView.GetDocShell();
1070     if (pDocSh && pDocSh->GetView() == &m_rView)
1071         pDocSh->SetView(nullptr);
1072     if (SW_MOD()->GetView() == &m_rView)
1073         SW_MOD()->SetView(nullptr);
1074 }
1075 
1076 SwView::~SwView()
1077 {
1078     // Notify other LOK views that we are going away.
1079     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", "false");
1080     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
1081     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
1082 
1083     // Need to remove activated field's button before disposing EditWin.
1084     GetWrtShell().getIDocumentMarkAccess()->ClearFieldActivation();
1085 
1086     GetViewFrame()->GetWindow().RemoveChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
1087     m_pPostItMgr.reset();
1088 
1089     m_bInDtor = true;
1090     m_pEditWin->Hide(); // prevent problems with painting
1091 
1092     // Set pointer in SwDocShell to the view again
1093     m_xGlueDocShell.reset();
1094 
1095     if( m_aTimer.IsActive() && m_bAttrChgNotifiedWithRegistrations )
1096         GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
1097 
1098     // the last view must end the text edit
1099     SdrView *pSdrView = m_pWrtShell ? m_pWrtShell->GetDrawView() : nullptr;
1100     if( pSdrView && pSdrView->IsTextEdit() )
1101         pSdrView->SdrEndTextEdit( true );
1102 
1103     SetWindow( nullptr );
1104 
1105     m_pViewImpl->Invalidate();
1106     EndListening(*GetViewFrame());
1107     EndListening(*GetDocShell());
1108     m_pScrollFill.disposeAndClear();
1109     m_pWrtShell.reset(); // reset here so that it is not accessible by the following dtors.
1110     m_pHScrollbar.disposeAndClear();
1111     m_pVScrollbar.disposeAndClear();
1112     m_pHRuler.disposeAndClear();
1113     m_pVRuler.disposeAndClear();
1114     m_pGlosHdl.reset();
1115     m_pViewImpl.reset();
1116 
1117     // If this was enabled in the ctor for the frame, then disable it here.
1118     static bool bRequestDoubleBuffering = getenv("VCL_DOUBLEBUFFERING_ENABLE");
1119     if (bRequestDoubleBuffering)
1120         m_pEditWin->RequestDoubleBuffering(false);
1121     m_pEditWin.disposeAndClear();
1122 
1123     m_pFormatClipboard.reset();
1124 }
1125 
1126 SwDocShell* SwView::GetDocShell()
1127 {
1128     SfxObjectShell* pDocShell = GetViewFrame()->GetObjectShell();
1129     return dynamic_cast<SwDocShell*>( pDocShell );
1130 }
1131 
1132 // Remember CursorPos
1133 
1134 void SwView::WriteUserData( OUString &rUserData, bool bBrowse )
1135 {
1136     // The browse flag will be passed from Sfx when documents are browsed
1137     // (not to be confused with the BrowseMode).
1138     // Then that stored data are not persistent!
1139 
1140     const SwRect& rRect = m_pWrtShell->GetCharRect();
1141     const tools::Rectangle& rVis = GetVisArea();
1142 
1143     rUserData = OUString::number( rRect.Left() );
1144     rUserData += ";";
1145     rUserData += OUString::number( rRect.Top() );
1146     rUserData += ";";
1147     rUserData += OUString::number( m_pWrtShell->GetViewOptions()->GetZoom() );
1148     rUserData += ";";
1149     rUserData += OUString::number( rVis.Left() );
1150     rUserData += ";";
1151     rUserData += OUString::number( rVis.Top() );
1152     rUserData += ";";
1153     rUserData += OUString::number( bBrowse ? SAL_MIN_INT32 : rVis.Right());
1154     rUserData += ";";
1155     rUserData += OUString::number( bBrowse ? SAL_MIN_INT32 : rVis.Bottom());
1156     rUserData += ";";
1157     rUserData += OUString::number(
1158             static_cast<sal_uInt16>(m_pWrtShell->GetViewOptions()->GetZoomType()));//eZoom;
1159     rUserData += ";";
1160     rUserData += FrameTypeFlags::NONE == m_pWrtShell->GetSelFrameType() ? OUStringLiteral(u"0") : OUStringLiteral(u"1");
1161 }
1162 
1163 // Set CursorPos
1164 
1165 static bool lcl_IsOwnDocument( SwView& rView )
1166 {
1167     uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1168         rView.GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
1169     uno::Reference<document::XDocumentProperties> xDocProps
1170         = xDPS->getDocumentProperties();
1171     OUString Created = xDocProps->getAuthor();
1172     OUString Changed = xDocProps->getModifiedBy();
1173     OUString FullName = SW_MOD()->GetUserOptions().GetFullName();
1174     return !FullName.isEmpty()
1175            && (Changed == FullName || (Changed.isEmpty() && Created == FullName));
1176 }
1177 
1178 void SwView::ReadUserData( const OUString &rUserData, bool bBrowse )
1179 {
1180     if ( !(rUserData.indexOf(';')>=0 && // more than one token
1181         // For document without layout only in the onlinelayout or
1182         // while forward/backward
1183          (!m_pWrtShell->IsNewLayout() || m_pWrtShell->GetViewOptions()->getBrowseMode() || bBrowse)) )
1184         return;
1185 
1186     bool bIsOwnDocument = lcl_IsOwnDocument( *this );
1187 
1188     CurrShell aCurr(m_pWrtShell.get());
1189 
1190     sal_Int32 nPos = 0;
1191 
1192     // No it is *not* a good idea to call GetToken within Point constr. immediately,
1193     // because which parameter is evaluated first?
1194     tools::Long nX = rUserData.getToken( 0, ';', nPos ).toInt32(),
1195          nY = rUserData.getToken( 0, ';', nPos ).toInt32();
1196     Point aCursorPos( nX, nY );
1197 
1198     sal_uInt16 nZoomFactor =
1199         static_cast< sal_uInt16 >( rUserData.getToken(0, ';', nPos ).toInt32() );
1200 
1201     tools::Long nLeft  = rUserData.getToken(0, ';', nPos ).toInt32(),
1202          nTop   = rUserData.getToken(0, ';', nPos ).toInt32(),
1203          nRight = rUserData.getToken(0, ';', nPos ).toInt32(),
1204          nBottom= rUserData.getToken(0, ';', nPos ).toInt32();
1205 
1206     const tools::Long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
1207     if ( nBottom > (m_pWrtShell->GetDocSize().Height()+nAdd) )
1208         return;
1209 
1210     m_pWrtShell->EnableSmooth( false );
1211 
1212     const tools::Rectangle aVis( nLeft, nTop, nRight, nBottom );
1213 
1214     sal_Int32 nOff = 0;
1215     SvxZoomType eZoom;
1216     if( !m_pWrtShell->GetViewOptions()->getBrowseMode() )
1217         eZoom = static_cast<SvxZoomType>(static_cast<sal_uInt16>(rUserData.getToken(nOff, ';', nPos ).toInt32()));
1218     else
1219     {
1220         eZoom = SvxZoomType::PERCENT;
1221         ++nOff;
1222     }
1223 
1224     bool bSelectObj = (0 != rUserData.getToken( nOff, ';', nPos ).toInt32())
1225                         && m_pWrtShell->IsObjSelectable( aCursorPos );
1226 
1227     // restore editing position
1228     m_pViewImpl->SetRestorePosition(aCursorPos, bSelectObj);
1229     // set flag value to avoid macro execution.
1230     bool bSavedFlagValue = m_pWrtShell->IsMacroExecAllowed();
1231     m_pWrtShell->SetMacroExecAllowed( false );
1232 // os: changed: The user data has to be read if the view is switched back from page preview
1233 // go to the last editing position when opening own files
1234     if(m_bOldShellWasPagePreview || bIsOwnDocument)
1235     {
1236         m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
1237         if( bSelectObj )
1238         {
1239             m_pWrtShell->SelectObj( aCursorPos );
1240             m_pWrtShell->EnterSelFrameMode( &aCursorPos );
1241         }
1242     }
1243 
1244     // reset flag value
1245     m_pWrtShell->SetMacroExecAllowed( bSavedFlagValue );
1246 
1247     // set visible area before applying
1248     // information from print preview. Otherwise, the applied information
1249     // is lost.
1250 // os: changed: The user data has to be read if the view is switched back from page preview
1251 // go to the last editing position when opening own files
1252     if(m_bOldShellWasPagePreview || bIsOwnDocument )
1253     {
1254         if ( bBrowse )
1255             SetVisArea( aVis.TopLeft() );
1256         else
1257             SetVisArea( aVis );
1258     }
1259 
1260     //apply information from print preview - if available
1261     if( !m_sNewCursorPos.isEmpty() )
1262     {
1263         sal_Int32 nIdx{ 0 };
1264         const tools::Long nXTmp = m_sNewCursorPos.getToken( 0, ';', nIdx ).toInt32();
1265         const tools::Long nYTmp = m_sNewCursorPos.getToken( 0, ';', nIdx ).toInt32();
1266         Point aCursorPos2( nXTmp, nYTmp );
1267         bSelectObj = m_pWrtShell->IsObjSelectable( aCursorPos2 );
1268 
1269         m_pWrtShell->SwCursorShell::SetCursor( aCursorPos2 );
1270         if( bSelectObj )
1271         {
1272             m_pWrtShell->SelectObj( aCursorPos2 );
1273             m_pWrtShell->EnterSelFrameMode( &aCursorPos2 );
1274         }
1275         m_pWrtShell->MakeSelVisible();
1276         m_sNewCursorPos.clear();
1277     }
1278     else if(USHRT_MAX != m_nNewPage)
1279     {
1280         m_pWrtShell->GotoPage(m_nNewPage, true);
1281         m_nNewPage = USHRT_MAX;
1282     }
1283 
1284     SelectShell();
1285 
1286     m_pWrtShell->StartAction();
1287     const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
1288     if( pVOpt->GetZoom() != nZoomFactor || pVOpt->GetZoomType() != eZoom )
1289         SetZoom( eZoom, nZoomFactor);
1290 
1291     m_pWrtShell->LockView( true );
1292     m_pWrtShell->EndAction();
1293     m_pWrtShell->LockView( false );
1294     m_pWrtShell->EnableSmooth( true );
1295 }
1296 
1297 void SwView::ReadUserDataSequence ( const uno::Sequence < beans::PropertyValue >& rSequence )
1298 {
1299     if(GetDocShell()->IsPreview()||m_bIsPreviewDoubleClick)
1300         return;
1301     bool bIsOwnDocument = lcl_IsOwnDocument( *this );
1302 
1303     CurrShell aCurr(m_pWrtShell.get());
1304     const SwRect& rRect = m_pWrtShell->GetCharRect();
1305     const tools::Rectangle &rVis = GetVisArea();
1306     const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
1307 
1308     sal_Int64 nX = rRect.Left(), nY = rRect.Top(), nLeft = rVis.Left(), nTop = rVis.Top();
1309     sal_Int64 nRight = nLeft;
1310     sal_Int64 nBottom = LONG_MIN;
1311     sal_Int16 nZoomType = static_cast< sal_Int16 >(pVOpt->GetZoomType());
1312     sal_Int16 nZoomFactor = static_cast < sal_Int16 > (pVOpt->GetZoom());
1313     bool bViewLayoutBookMode = pVOpt->IsViewLayoutBookMode();
1314     sal_Int16 nViewLayoutColumns = pVOpt->GetViewLayoutColumns();
1315 
1316     bool bSelectedFrame = ( m_pWrtShell->GetSelFrameType() != FrameTypeFlags::NONE ),
1317              bGotVisibleLeft = false,
1318              bGotVisibleTop = false, bGotVisibleRight = false,
1319              bGotVisibleBottom = false, bGotZoomType = false,
1320              bGotZoomFactor = false, bGotIsSelectedFrame = false,
1321              bGotViewLayoutColumns = false, bGotViewLayoutBookMode = false,
1322              bBrowseMode = false, bGotBrowseMode = false;
1323 
1324     for (const beans::PropertyValue& rValue : rSequence)
1325     {
1326         if ( rValue.Name == "ViewLeft" )
1327         {
1328            rValue.Value >>= nX;
1329            nX = convertMm100ToTwip( nX );
1330         }
1331         else if ( rValue.Name == "ViewTop" )
1332         {
1333            rValue.Value >>= nY;
1334            nY = convertMm100ToTwip( nY );
1335         }
1336         else if ( rValue.Name == "VisibleLeft" )
1337         {
1338            rValue.Value >>= nLeft;
1339            nLeft = convertMm100ToTwip( nLeft );
1340            bGotVisibleLeft = true;
1341         }
1342         else if ( rValue.Name == "VisibleTop" )
1343         {
1344            rValue.Value >>= nTop;
1345            nTop = convertMm100ToTwip( nTop );
1346            bGotVisibleTop = true;
1347         }
1348         else if ( rValue.Name == "VisibleRight" )
1349         {
1350            rValue.Value >>= nRight;
1351            nRight = convertMm100ToTwip( nRight );
1352            bGotVisibleRight = true;
1353         }
1354         else if ( rValue.Name == "VisibleBottom" )
1355         {
1356            rValue.Value >>= nBottom;
1357            nBottom = convertMm100ToTwip( nBottom );
1358            bGotVisibleBottom = true;
1359         }
1360         else if ( rValue.Name == "ZoomType" )
1361         {
1362            rValue.Value >>= nZoomType;
1363            bGotZoomType = true;
1364         }
1365         else if ( rValue.Name == "ZoomFactor" )
1366         {
1367            rValue.Value >>= nZoomFactor;
1368            bGotZoomFactor = true;
1369         }
1370         else if ( rValue.Name == "ViewLayoutColumns" )
1371         {
1372            rValue.Value >>= nViewLayoutColumns;
1373            bGotViewLayoutColumns = true;
1374         }
1375         else if ( rValue.Name == "ViewLayoutBookMode" )
1376         {
1377            bViewLayoutBookMode = *o3tl::doAccess<bool>(rValue.Value);
1378            bGotViewLayoutBookMode = true;
1379         }
1380         else if ( rValue.Name == "IsSelectedFrame" )
1381         {
1382            rValue.Value >>= bSelectedFrame;
1383            bGotIsSelectedFrame = true;
1384         }
1385         else if (rValue.Name == "ShowOnlineLayout")
1386         {
1387            rValue.Value >>= bBrowseMode;
1388            bGotBrowseMode = true;
1389         }
1390         // Fallback to common SdrModel processing
1391         else
1392            GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->ReadUserDataSequenceValue(&rValue);
1393     }
1394     if (bGotBrowseMode)
1395     {
1396         // delegate further
1397         GetViewImpl()->GetUNOObject_Impl()->getViewSettings()->setPropertyValue("ShowOnlineLayout", uno::Any(bBrowseMode));
1398     }
1399 
1400     SelectShell();
1401 
1402     if (!bGotVisibleBottom)
1403         return;
1404 
1405     Point aCursorPos( nX, nY );
1406     const tools::Long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
1407     if (nBottom > (m_pWrtShell->GetDocSize().Height()+nAdd) )
1408         return;
1409 
1410     m_pWrtShell->EnableSmooth( false );
1411     const tools::Rectangle aVis( nLeft, nTop, nRight, nBottom );
1412 
1413     SvxZoomType eZoom;
1414     if ( !m_pWrtShell->GetViewOptions()->getBrowseMode() )
1415         eZoom = static_cast < SvxZoomType > ( nZoomType );
1416     else
1417     {
1418         eZoom = SvxZoomType::PERCENT;
1419     }
1420     if (bGotIsSelectedFrame)
1421     {
1422         bool bSelectObj = bSelectedFrame && m_pWrtShell->IsObjSelectable( aCursorPos );
1423 
1424         // set flag value to avoid macro execution.
1425         bool bSavedFlagValue = m_pWrtShell->IsMacroExecAllowed();
1426         m_pWrtShell->SetMacroExecAllowed( false );
1427 // os: changed: The user data has to be read if the view is switched back from page preview
1428 // go to the last editing position when opening own files
1429         m_pViewImpl->SetRestorePosition(aCursorPos, bSelectObj);
1430         if(m_bOldShellWasPagePreview|| bIsOwnDocument)
1431         {
1432             m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
1433 
1434             // Update the shell to toggle Header/Footer edit if needed
1435             bool bInHeader = true;
1436             if ( m_pWrtShell->IsInHeaderFooter( &bInHeader ) )
1437             {
1438                 if ( !bInHeader )
1439                 {
1440                     m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Footer, true );
1441                     m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Header, false );
1442                 }
1443                 else
1444                 {
1445                     m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Header, true );
1446                     m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
1447                 }
1448 
1449                 // Force repaint
1450                 m_pWrtShell->GetWin()->Invalidate();
1451             }
1452             if ( m_pWrtShell->IsInHeaderFooter() != m_pWrtShell->IsHeaderFooterEdit() )
1453                 m_pWrtShell->ToggleHeaderFooterEdit();
1454 
1455             if( bSelectObj )
1456             {
1457                 m_pWrtShell->SelectObj( aCursorPos );
1458                 m_pWrtShell->EnterSelFrameMode( &aCursorPos );
1459             }
1460         }
1461 
1462         // reset flag value
1463         m_pWrtShell->SetMacroExecAllowed( bSavedFlagValue );
1464     }
1465 
1466     // Set ViewLayoutSettings
1467     const bool bSetViewLayoutSettings = bGotViewLayoutColumns && bGotViewLayoutBookMode &&
1468                                         ( pVOpt->GetViewLayoutColumns() != nViewLayoutColumns || pVOpt->IsViewLayoutBookMode() != bViewLayoutBookMode );
1469 
1470     const bool bSetViewSettings = bGotZoomType && bGotZoomFactor &&
1471                                   ( pVOpt->GetZoom() != nZoomFactor || pVOpt->GetZoomType() != eZoom );
1472 
1473     // In case we have a 'fixed' view layout of 2 or more columns,
1474     // we have to apply the view options *before* starting the action.
1475     // Otherwise the SetZoom function cannot work correctly, because
1476     // the view layout hasn't been calculated.
1477     const bool bZoomNeedsViewLayout = bSetViewLayoutSettings &&
1478                                       1 < nViewLayoutColumns &&
1479                                       bSetViewSettings &&
1480                                       eZoom != SvxZoomType::PERCENT;
1481 
1482     if ( !bZoomNeedsViewLayout )
1483         m_pWrtShell->StartAction();
1484 
1485     if ( bSetViewLayoutSettings )
1486         SetViewLayout( nViewLayoutColumns, bViewLayoutBookMode, true );
1487 
1488     if ( bZoomNeedsViewLayout )
1489         m_pWrtShell->StartAction();
1490 
1491     if ( bSetViewSettings )
1492         SetZoom( eZoom, nZoomFactor, true );
1493 
1494 // os: changed: The user data has to be read if the view is switched back from page preview
1495 // go to the last editing position when opening own files
1496     if(m_bOldShellWasPagePreview||bIsOwnDocument)
1497     {
1498         if ( bGotVisibleLeft && bGotVisibleTop )
1499         {
1500             Point aTopLeft(aVis.TopLeft());
1501             // make sure the document is still centered
1502             const SwTwips lBorder = IsDocumentBorder() ? DOCUMENTBORDER : 2 * DOCUMENTBORDER;
1503             SwTwips nEditWidth = GetEditWin().GetOutputSize().Width();
1504             if(nEditWidth > (m_aDocSz.Width() + lBorder ))
1505                 aTopLeft.setX( ( m_aDocSz.Width() + lBorder - nEditWidth  ) / 2 );
1506             else
1507             {
1508                 //check if the values are possible
1509                 tools::Long nXMax = m_pHScrollbar->GetRangeMax() - m_pHScrollbar->GetVisibleSize();
1510                 if( aTopLeft.X() > nXMax )
1511                     aTopLeft.setX( nXMax < 0 ? 0 : nXMax );
1512             }
1513             SetVisArea( aTopLeft );
1514         }
1515         else if (bGotVisibleLeft && bGotVisibleTop && bGotVisibleRight && bGotVisibleBottom )
1516             SetVisArea( aVis );
1517     }
1518 
1519     m_pWrtShell->LockView( true );
1520     m_pWrtShell->EndAction();
1521     m_pWrtShell->LockView( false );
1522     m_pWrtShell->EnableSmooth( true );
1523 
1524 }
1525 
1526 void SwView::WriteUserDataSequence ( uno::Sequence < beans::PropertyValue >& rSequence )
1527 {
1528     const SwRect& rRect = m_pWrtShell->GetCharRect();
1529     const tools::Rectangle& rVis = GetVisArea();
1530 
1531     std::vector<beans::PropertyValue> aVector;
1532 
1533     sal_uInt16 nViewID( GetViewFrame()->GetCurViewId());
1534     aVector.push_back(comphelper::makePropertyValue("ViewId", "view" + OUString::number(nViewID)));
1535 
1536     aVector.push_back(comphelper::makePropertyValue("ViewLeft", convertTwipToMm100 ( rRect.Left() )));
1537 
1538     aVector.push_back(comphelper::makePropertyValue("ViewTop", convertTwipToMm100 ( rRect.Top() )));
1539 
1540     auto visibleLeft = convertTwipToMm100 ( rVis.Left() );
1541     aVector.push_back(comphelper::makePropertyValue("VisibleLeft", visibleLeft));
1542 
1543     auto visibleTop = convertTwipToMm100 ( rVis.Top() );
1544     aVector.push_back(comphelper::makePropertyValue("VisibleTop", visibleTop));
1545 
1546     auto visibleRight = rVis.IsWidthEmpty() ? visibleLeft : convertTwipToMm100 ( rVis.Right() );
1547     aVector.push_back(comphelper::makePropertyValue("VisibleRight", visibleRight));
1548 
1549     auto visibleBottom = rVis.IsHeightEmpty() ? visibleTop : convertTwipToMm100 ( rVis.Bottom() );
1550     aVector.push_back(comphelper::makePropertyValue("VisibleBottom", visibleBottom));
1551 
1552     const sal_Int16 nZoomType = static_cast< sal_Int16 >(m_pWrtShell->GetViewOptions()->GetZoomType());
1553     aVector.push_back(comphelper::makePropertyValue("ZoomType", nZoomType));
1554 
1555     const sal_Int16 nViewLayoutColumns = static_cast< sal_Int16 >(m_pWrtShell->GetViewOptions()->GetViewLayoutColumns());
1556     aVector.push_back(comphelper::makePropertyValue("ViewLayoutColumns", nViewLayoutColumns));
1557 
1558     aVector.push_back(comphelper::makePropertyValue("ViewLayoutBookMode", m_pWrtShell->GetViewOptions()->IsViewLayoutBookMode()));
1559 
1560     aVector.push_back(comphelper::makePropertyValue("ZoomFactor", static_cast < sal_Int16 > (m_pWrtShell->GetViewOptions()->GetZoom())));
1561 
1562     aVector.push_back(comphelper::makePropertyValue("IsSelectedFrame", FrameTypeFlags::NONE != m_pWrtShell->GetSelFrameType()));
1563 
1564     rSequence = comphelper::containerToSequence(aVector);
1565 
1566     // Common SdrModel processing
1567     GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->WriteUserDataSequence(rSequence);
1568 }
1569 
1570 void SwView::ShowCursor( bool bOn )
1571 {
1572     //don't scroll the cursor into the visible area
1573     bool bUnlockView = !m_pWrtShell->IsViewLocked();
1574     m_pWrtShell->LockView( true );    //lock visible section
1575 
1576     if( !bOn )
1577         m_pWrtShell->HideCursor();
1578     else if( !m_pWrtShell->IsFrameSelected() && !m_pWrtShell->IsObjSelected() )
1579         m_pWrtShell->ShowCursor();
1580 
1581     if( bUnlockView )
1582         m_pWrtShell->LockView( false );
1583 }
1584 
1585 ErrCode SwView::DoVerb(sal_Int32 nVerb)
1586 {
1587     if ( !GetViewFrame()->GetFrame().IsInPlace() )
1588     {
1589         SwWrtShell &rSh = GetWrtShell();
1590         const SelectionType nSel = rSh.GetSelectionType();
1591         if ( nSel & SelectionType::Ole )
1592             rSh.LaunchOLEObj( nVerb );
1593     }
1594     return ERRCODE_NONE;
1595 }
1596 
1597 //   only return true for a text selection
1598 
1599 bool SwView::HasSelection( bool  bText ) const
1600 {
1601     return bText ? GetWrtShell().SwCursorShell::HasSelection()
1602                  : GetWrtShell().HasSelection();
1603 }
1604 
1605 OUString SwView::GetSelectionText( bool bCompleteWrds )
1606 {
1607     return GetSelectionTextParam( bCompleteWrds, true );
1608 }
1609 
1610 OUString SwView::GetSelectionTextParam( bool bCompleteWrds, bool bEraseTrail )
1611 {
1612     OUString sReturn;
1613     if( bCompleteWrds && !GetWrtShell().HasSelection() )
1614         GetWrtShell().SelWrd();
1615 
1616     GetWrtShell().GetSelectedText( sReturn );
1617     if( bEraseTrail )
1618         sReturn = comphelper::string::stripEnd(sReturn, ' ');
1619     return sReturn;
1620 }
1621 
1622 SwGlossaryHdl* SwView::GetGlosHdl()
1623 {
1624     if(!m_pGlosHdl)
1625         m_pGlosHdl.reset(new SwGlossaryHdl(GetViewFrame(), m_pWrtShell.get()));
1626     return m_pGlosHdl.get();
1627 }
1628 
1629 void SwView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1630 {
1631     bool bCallBase = true;
1632     if(auto pChangedHint = dynamic_cast<const FmDesignModeChangedHint*>(&rHint))
1633     {
1634         bool bDesignMode = pChangedHint->GetDesignMode();
1635         if (!bDesignMode && GetDrawFuncPtr())
1636         {
1637             GetDrawFuncPtr()->Deactivate();
1638             SetDrawFuncPtr(nullptr);
1639             LeaveDrawCreate();
1640             AttrChangedNotify(nullptr);
1641         }
1642     }
1643     else
1644     {
1645         if (auto pSfxEventHint = dynamic_cast<const SfxEventHint*>(&rHint))
1646         {
1647             switch( pSfxEventHint->GetEventId() )
1648             {
1649                 case SfxEventHintId::CreateDoc:
1650                 case SfxEventHintId::OpenDoc:
1651                 {
1652                     OUString sDataSourceName = GetDataSourceName();
1653                     if ( !sDataSourceName.isEmpty() && !IsDataSourceAvailable(sDataSourceName))
1654                         AppendDataSourceInfobar();
1655                 }
1656                 break;
1657                 default:
1658                     break;
1659             }
1660         }
1661 
1662         SfxHintId nId = rHint.GetId();
1663 
1664         switch ( nId )
1665         {
1666             // sub shells will be destroyed by the
1667             // dispatcher, if the view frame is dying. Thus, reset member <pShell>.
1668             case SfxHintId::Dying:
1669                 {
1670                     if ( &rBC == GetViewFrame() )
1671                     {
1672                         ResetSubShell();
1673                     }
1674                 }
1675                 break;
1676             case SfxHintId::ModeChanged:
1677                 {
1678                     // Modal mode change-over?
1679                     bool bModal = GetDocShell()->IsInModalMode();
1680                     m_pHRuler->SetActive( !bModal );
1681                     m_pVRuler->SetActive( !bModal );
1682                 }
1683 
1684                 [[fallthrough]];
1685 
1686             case SfxHintId::TitleChanged:
1687                 if ( GetDocShell()->IsReadOnly() != GetWrtShell().GetViewOptions()->IsReadonly() )
1688                 {
1689                     SwWrtShell &rSh = GetWrtShell();
1690                     rSh.SetReadonlyOption( GetDocShell()->IsReadOnly() );
1691 
1692                     if ( rSh.GetViewOptions()->IsViewVRuler() )
1693                         CreateVRuler();
1694                     else
1695                         KillVRuler();
1696                     if ( rSh.GetViewOptions()->IsViewHRuler() )
1697                         CreateTab();
1698                     else
1699                         KillTab();
1700                     bool bReadonly = GetDocShell()->IsReadOnly();
1701                     // if document is to be opened in alive-mode then this has to be
1702                     // regarded while switching from readonly-mode to edit-mode
1703                     if( !bReadonly )
1704                     {
1705                         SwDrawModel * pDrawDoc = GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1706                         if (pDrawDoc)
1707                         {
1708                             if( !pDrawDoc->GetOpenInDesignMode() )
1709                                 break;// don't touch the design mode
1710                         }
1711                     }
1712                     SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadonly);
1713                     GetDispatcher().ExecuteList(SID_FM_DESIGN_MODE,
1714                             SfxCallMode::ASYNCHRON, { &aItem });
1715                 }
1716                 break;
1717 
1718             case SfxHintId::SwDrawViewsCreated:
1719                 {
1720                     bCallBase = false;
1721                     if ( GetFormShell() )
1722                     {
1723                         GetFormShell()->SetView(dynamic_cast<FmFormView*>(GetWrtShell().GetDrawView()));
1724                         SfxBoolItem aItem( SID_FM_DESIGN_MODE, !GetDocShell()->IsReadOnly());
1725                         GetDispatcher().ExecuteList(SID_FM_DESIGN_MODE,
1726                                 SfxCallMode::SYNCHRON, { &aItem });
1727                     }
1728                 }
1729                 break;
1730             case SfxHintId::RedlineChanged:
1731                 {
1732                     static sal_uInt16 const aSlotRedLine[] = {
1733                         FN_REDLINE_ACCEPT_DIRECT,
1734                         FN_REDLINE_REJECT_DIRECT,
1735                         FN_REDLINE_NEXT_CHANGE,
1736                         FN_REDLINE_PREV_CHANGE,
1737                         FN_REDLINE_ACCEPT_ALL,
1738                         FN_REDLINE_REJECT_ALL,
1739                         0
1740                     };
1741                     GetViewFrame()->GetBindings().Invalidate(aSlotRedLine);
1742                 }
1743                 break;
1744             default: break;
1745         }
1746     }
1747 
1748     if ( bCallBase )
1749         SfxViewShell::Notify(rBC, rHint);
1750 }
1751 
1752 #if defined(_WIN32) || defined UNX
1753 
1754 void SwView::ScannerEventHdl()
1755 {
1756     uno::Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
1757     if( xScanMgr.is() )
1758     {
1759         const ScannerContext    aContext( xScanMgr->getAvailableScanners().getConstArray()[ 0 ] );
1760         const ScanError         eError = xScanMgr->getError( aContext );
1761 
1762         if( ScanError_ScanErrorNone == eError )
1763         {
1764             const uno::Reference< awt::XBitmap > xBitmap( xScanMgr->getBitmap( aContext ) );
1765 
1766             if( xBitmap.is() )
1767             {
1768                 const BitmapEx aScanBmp( VCLUnoHelper::GetBitmap( xBitmap ) );
1769 
1770                 if( !aScanBmp.IsEmpty() )
1771                 {
1772                     Graphic aGrf(aScanBmp);
1773                     m_pWrtShell->Insert( OUString(), OUString(), aGrf );
1774                 }
1775             }
1776         }
1777     }
1778     SfxBindings& rBind = GetViewFrame()->GetBindings();
1779     rBind.Invalidate( SID_TWAIN_SELECT );
1780     rBind.Invalidate( SID_TWAIN_TRANSFER );
1781 }
1782 #endif
1783 
1784 void    SwView::StopShellTimer()
1785 {
1786     if(m_aTimer.IsActive())
1787     {
1788         m_aTimer.Stop();
1789         if ( m_bAttrChgNotifiedWithRegistrations )
1790         {
1791             GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
1792             m_bAttrChgNotifiedWithRegistrations = false;
1793         }
1794         SelectShell();
1795         m_bAttrChgNotified = false;
1796     }
1797 }
1798 
1799 bool SwView::PrepareClose( bool bUI )
1800 {
1801     SfxViewFrame* pVFrame = GetViewFrame();
1802     pVFrame->SetChildWindow( SwInputChild::GetChildWindowId(), false );
1803     if( pVFrame->GetDispatcher()->IsLocked() )
1804         pVFrame->GetDispatcher()->Lock(false);
1805 
1806     if ( m_pFormShell && !m_pFormShell->PrepareClose( bUI ) )
1807     {
1808         return false;
1809     }
1810     return SfxViewShell::PrepareClose( bUI );
1811 }
1812 
1813 // status methods for clipboard.
1814 // Status changes now notified from the clipboard.
1815 bool SwView::IsPasteAllowed()
1816 {
1817     SotExchangeDest nPasteDestination = SwTransferable::GetSotDestination( *m_pWrtShell );
1818     if( m_nLastPasteDestination != nPasteDestination )
1819     {
1820         TransferableDataHelper aDataHelper(
1821                         TransferableDataHelper::CreateFromSystemClipboard(
1822                                                         &GetEditWin()) );
1823         if( aDataHelper.GetXTransferable().is() )
1824         {
1825             m_bPasteState = SwTransferable::IsPaste( *m_pWrtShell, aDataHelper );
1826             m_bPasteSpecialState = SwTransferable::IsPasteSpecial(
1827                                                     *m_pWrtShell, aDataHelper );
1828         }
1829         else
1830             m_bPasteState = m_bPasteSpecialState = false;
1831 
1832         if( static_cast<SotExchangeDest>(0xFFFF) == m_nLastPasteDestination )  // the init value
1833             m_pViewImpl->AddClipboardListener();
1834         m_nLastPasteDestination = nPasteDestination;
1835     }
1836     return m_bPasteState;
1837 }
1838 
1839 bool SwView::IsPasteSpecialAllowed()
1840 {
1841     if ( m_pFormShell && m_pFormShell->IsActiveControl() )
1842         return false;
1843 
1844     SotExchangeDest nPasteDestination = SwTransferable::GetSotDestination( *m_pWrtShell );
1845     if( m_nLastPasteDestination != nPasteDestination )
1846     {
1847         TransferableDataHelper aDataHelper(
1848                         TransferableDataHelper::CreateFromSystemClipboard(
1849                                                         &GetEditWin()) );
1850         if( aDataHelper.GetXTransferable().is() )
1851         {
1852             m_bPasteState = SwTransferable::IsPaste( *m_pWrtShell, aDataHelper );
1853             m_bPasteSpecialState = SwTransferable::IsPasteSpecial(
1854                                                     *m_pWrtShell, aDataHelper );
1855         }
1856         else
1857             m_bPasteState = m_bPasteSpecialState = false;
1858 
1859         if( static_cast<SotExchangeDest>(0xFFFF) == m_nLastPasteDestination )  // the init value
1860             m_pViewImpl->AddClipboardListener();
1861     }
1862     return m_bPasteSpecialState;
1863 }
1864 
1865 bool SwView::IsPasteSpreadsheet(bool bHasOwnTableCopied)
1866 {
1867     TransferableDataHelper aDataHelper(
1868                         TransferableDataHelper::CreateFromSystemClipboard(
1869                                                         &GetEditWin()) );
1870     if( aDataHelper.GetXTransferable().is() )
1871     {
1872         if (bHasOwnTableCopied && SwTransferable::IsPasteOwnFormat( aDataHelper ))
1873             return true;
1874         return aDataHelper.HasFormat( SotClipboardFormatId::SYLK ) || aDataHelper.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS );
1875     }
1876     return false;
1877 }
1878 
1879 void SwView::NotifyDBChanged()
1880 {
1881     GetViewImpl()->GetUNOObject_Impl()->NotifyDBChanged();
1882 }
1883 
1884 // Printing
1885 
1886 SfxObjectShellLock SwView::CreateTmpSelectionDoc()
1887 {
1888     SwXTextView *const pTempImpl = GetViewImpl()->GetUNOObject_Impl();
1889     return pTempImpl->BuildTmpSelectionDoc();
1890 }
1891 
1892 void SwView::AddTransferable(SwTransferable& rTransferable)
1893 {
1894     GetViewImpl()->AddTransferable(rTransferable);
1895 }
1896 
1897 tools::Rectangle SwView::getLOKVisibleArea() const
1898 {
1899     SwViewShell* pVwSh = GetWrtShellPtr();
1900     if (pVwSh)
1901         return pVwSh->getLOKVisibleArea();
1902     else
1903         return tools::Rectangle();
1904 }
1905 
1906 OUString SwView::GetDataSourceName() const
1907 {
1908     uno::Reference<lang::XMultiServiceFactory> xFactory(GetDocShell()->GetModel(), uno::UNO_QUERY);
1909     uno::Reference<beans::XPropertySet> xSettings(
1910         xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
1911     OUString sDataSourceName = "";
1912     xSettings->getPropertyValue("CurrentDatabaseDataSource") >>= sDataSourceName;
1913 
1914     return sDataSourceName;
1915 }
1916 
1917 bool SwView::IsDataSourceAvailable(const OUString sDataSourceName)
1918 {
1919     uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1920     Reference< XDatabaseContext> xDatabaseContext = DatabaseContext::create(xContext);
1921 
1922     return xDatabaseContext->hasByName(sDataSourceName);
1923 }
1924 
1925 void SwView::AppendDataSourceInfobar()
1926 {
1927     auto pInfoBar = GetViewFrame()->AppendInfoBar("datasource", "",
1928                                   SwResId(STR_DATASOURCE_NOT_AVAILABLE),
1929                                   InfobarType::WARNING);
1930     if (!pInfoBar)
1931         return;
1932 
1933     weld::Button& rBtn = pInfoBar->addButton();
1934     rBtn.set_label(SwResId(STR_EXCHANGE_DATABASE));
1935     rBtn.connect_clicked(LINK(this, SwView, ExchangeDatabaseHandler));
1936 }
1937 
1938 namespace sw {
1939 
1940 void InitPrintOptionsFromApplication(SwPrintData & o_rData, bool const bWeb)
1941 {
1942     o_rData = *SW_MOD()->GetPrtOptions(bWeb);
1943 }
1944 
1945 } // namespace sw
1946 
1947 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1948