summaryrefslogtreecommitdiffstats
path: root/sw/source/core/inc/rootfrm.hxx
blob: 3d00fe1cc2260ac03ce9f0424ac58a0086606dd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_SW_SOURCE_CORE_INC_ROOTFRM_HXX
#define INCLUDED_SW_SOURCE_CORE_INC_ROOTFRM_HXX

#include "layfrm.hxx"
#include <viewsh.hxx>
#include <doc.hxx>
#include <IDocumentTimerAccess.hxx>
#include <o3tl/typed_flags_set.hxx>
#include <set>
#include <vector>

class SwContentFrame;
class SdrPage;
class SwFrameFormat;
class SwPaM;
class SwCursor;
class SwShellCursor;
class SwTableCursor;
class SwLayVout;
class SwViewOption;
class SwSelectionList;
struct SwPosition;
struct SwCursorMoveState;

namespace sw {
    enum class RedlineMode
    {
        Shown, Hidden
    };

    enum class FieldmarkMode { ShowCommand = 1, ShowResult = 2, ShowBoth = 3 };
};

enum class SwInvalidateFlags
{
    Size      = 0x01,
    PrtArea   = 0x02,
    Pos       = 0x04,
    Table     = 0x08,
    Section   = 0x10,
    LineNum   = 0x20,
    Direction = 0x40,
};

namespace o3tl
{
    template<> struct typed_flags<SwInvalidateFlags> : is_typed_flags<SwInvalidateFlags, 0x7f> {};
};

enum class SwRemoveResult
{
    Next,
    Prev
};

using SwCurrShells = std::set<CurrShell*>;

class SwSectionFrame;
using SwDestroyList = o3tl::sorted_vector<SwSectionFrame*>;

/// The root element of a Writer document layout. Lower frames are expected to
/// be SwPageFrame instances.
class SW_DLLPUBLIC SwRootFrame final : public SwLayoutFrame
{
    // Needs to disable the Superfluous temporarily
    friend void AdjustSizeChgNotify( SwRootFrame *pRoot );

    // Maintains the mpLastPage (Cut() and Paste() of SwPageFrame
    friend inline void SetLastPage( SwPageFrame* );

    // For creating and destroying of the virtual output device manager
    friend void FrameInit(); // Creates s_pVout
    friend void FrameFinit(); // Destroys s_pVout

    std::vector<SwRect> maPageRects;// returns the current rectangle for each page frame
                                    // the rectangle is extended to the top/bottom/left/right
                                    // for pages located at the outer margins
    SwRect  maPagesArea;            // the area covered by the pages
    tools::Long    mnViewWidth;            // the current page layout bases on this view width
    sal_uInt16  mnColumns;          // the current page layout bases on this number of columns
    bool    mbBookMode;             // the current page layout is in book view
    bool    mbSidebarChanged;       // the notes sidebar state has changed

    bool    mbNeedGrammarCheck;     // true when sth needs to be checked (not necessarily started yet!)

    static SwLayVout     *s_pVout;
    static bool           s_isInPaint; // Protection against double Paints
    static bool           s_isNoVirDev;// No virt. Device for SystemPaints

    /// Width of the HTML / Web document if not defined otherwise: 20cm.
    static constexpr sal_Int64 MIN_BROWSE_WIDTH = o3tl::toTwips(20000, o3tl::Length::mm100);

    bool    mbCheckSuperfluous   :1; // Search for empty Pages?
    bool    mbIdleFormat         :1; // Trigger Idle Formatter?
    bool    mbBrowseWidthValid   :1; // Is mnBrowseWidth valid?
    bool    mbTurboAllowed       :1;
    bool    mbAssertFlyPages     :1; // Insert more Pages for Flys if needed?
    bool    mbTableUpdateInProgress : 1; // tdf#139426 to allow suppression of AssertFlyPages during TableUpdate
    bool    mbIsVirtPageNum      :1; // Do we have a virtual pagenumber?
    bool    mbIsNewLayout        :1; // Layout loaded or newly created
    bool    mbCallbackActionEnabled:1; // No Action in Notification desired
                                      // @see dcontact.cxx, ::Changed()
    bool    mbLayoutFreezed;
    bool    mbHideRedlines;
    sw::FieldmarkMode m_FieldmarkMode;

    /**
     * For BrowseMode
     * mnBrowseWidth is the outer margin of the object most to the right.
     * The page's right edge should not be smaller than this value.
     */
    tools::Long    mnBrowseWidth;

    /// If we only have to format one ContentFrame, its in mpTurbo
    const SwContentFrame *mpTurbo;

    /// We should not need to always struggle to find the last page, so store it here
    SwPageFrame *mpLastPage;

    /** [ Comment from the original StarOffice checkin ]:
     * The root takes care of the shell access. Via the document
     * it should be possible to get at the root frame, and thus always
     * have access to the shell.
     * the pointer mpCurrShell is the pointer to any of the shells for
     * the document.
     * Because sometimes it matters which shell is used, it is necessary to
     * know the active shell.
     * this is approximated by setting the pointer mpCurrShell when a
     * shell gets the focus (FEShell). Additionally the pointer will be
     * set temporarily by SwCurrShell typically via  CurrShell
     * The class can be found in the SwViewShell. These object can
     * be created nested (also for different kinds of Shells). They are
     * collected into the Array mpCurrShells.
     * Furthermore it can happen that a shell is activated while a curshell
     * object is still 'active'. This one will be entered into mpWaitingCurrShell
     * and will be activated by the last d'tor of CurrShell.
     * One other problem is the destruction of a shell while it is active.
     * The pointer mpCurrShell is then reset to an arbitrary other shell.
     * If at the time of the destruction of a shell, which is still referenced
     * by a curshell object, that will be cleaned up as well.
     */
    friend class CurrShell;
    friend void SetShell( SwViewShell *pSh );
    friend void InitCurrShells( SwRootFrame *pRoot );
    SwViewShell *mpCurrShell;
    SwViewShell *mpWaitingCurrShell;
    std::unique_ptr<SwCurrShells> mpCurrShells;

    /// One Page per DrawModel per Document; is always the size of the Root
    SdrPage *mpDrawPage;

    std::unique_ptr<SwDestroyList> mpDestroy;

    sal_uInt16  mnPhyPageNums; /// Page count
    sal_uInt16 mnAccessibleShells; // Number of accessible shells

    void ImplCalcBrowseWidth();
    void ImplInvalidateBrowseWidth();

    void DeleteEmptySct_(); // Destroys the registered SectionFrames
    void RemoveFromList_( SwSectionFrame* pSct ); // Removes SectionFrames from the Delete List

    virtual void DestroyImpl() override;
    virtual ~SwRootFrame() override;

    virtual void MakeAll(vcl::RenderContext* pRenderContext) override;

public:

    /// Remove MasterObjects from the Page (called by the ctors)
    static void RemoveMasterObjs( SdrPage *pPg );

    void AllCheckPageDescs() const;
    void AllInvalidateAutoCompleteWords() const;
    void AllAddPaintRect() const;
    void AllRemoveFootnotes() ;
    void AllInvalidateSmartTagsOrSpelling(bool bSmartTags) const;

    /// Output virtual Device (e.g. for animations)
    static bool FlushVout();

    /// Save Clipping if exactly the ClipRect is outputted
    static bool HasSameRect( const SwRect& rRect );

    SwRootFrame( SwFrameFormat*, SwViewShell* );
    void Init(SwFrameFormat*);

    SwViewShell *GetCurrShell() const { return mpCurrShell; }
    void DeRegisterShell( SwViewShell *pSh );

    /**
     * Set up Start-/EndAction for all Shells on an as high as possible
     * (Shell section) level.
     * For the StarONE binding, which does not know the Shells directly.
     * The ChangeLinkd of the CursorShell (UI notifications) is called
     * automatically in the EndAllAction.
     */
    void StartAllAction();
    void EndAllAction( bool bVirDev = false );

    /**
     * Certain UNO Actions (e.g. table cursor) require that all Actions are reset temporarily
     * In order for that to work, every SwViewShell needs to remember its old Action counter
     */
    void UnoRemoveAllActions();
    void UnoRestoreAllActions();

    const SdrPage* GetDrawPage() const { return mpDrawPage; }
          SdrPage* GetDrawPage()       { return mpDrawPage; }
          void     SetDrawPage( SdrPage* pNew ){ mpDrawPage = pNew; }

    virtual bool  GetModelPositionForViewPoint( SwPosition *, Point&,
                               SwCursorMoveState* = nullptr, bool bTestBackground = false ) const override;

    virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&,
                        SwPrintData const*const pPrintData = nullptr ) const override;
    virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) override;
    virtual SwTwips GrowFrame  ( SwTwips, bool bTst = false, bool bInfo = false ) override;
#ifdef DBG_UTIL
    virtual void Cut() override;
    virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) override;
#endif

    virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const override;

    Point  GetNextPrevContentPos( const Point &rPoint, bool bNext ) const;

    virtual Size ChgSize( const Size& aNewSize ) override;

    void SetIdleFlags()
    {
        mbIdleFormat = true;

        SwViewShell* pCurrShell = GetCurrShell();
        // May be NULL if called from SfxBaseModel::dispose
        // (this happens in the build test 'rtfexport').
        if (pCurrShell != nullptr)
            pCurrShell->GetDoc()->getIDocumentTimerAccess().StartIdling();
    }
    bool IsIdleFormat()  const { return mbIdleFormat; }
    void ResetIdleFormat()     { mbIdleFormat = false; }

    bool IsNeedGrammarCheck() const         { return mbNeedGrammarCheck; }
    void SetNeedGrammarCheck( bool bVal )
    {
        mbNeedGrammarCheck = bVal;

        if ( bVal )
        {
            SwViewShell* pCurrShell = GetCurrShell();
            // May be NULL if called from SfxBaseModel::dispose
            // (this happens in the build test 'rtfexport').
            if (pCurrShell != nullptr)
                pCurrShell->GetDoc()->getIDocumentTimerAccess().StartIdling();
        }
    }

    /// Makes sure that all requested page-bound Flys find a Page
    void SetAssertFlyPages() { mbAssertFlyPages = true; }
    void AssertFlyPages();
    bool IsAssertFlyPages() const { return mbAssertFlyPages; }

    void SetTableUpdateInProgress(bool bValue) { mbTableUpdateInProgress = bValue; }
    bool IsTableUpdateInProgress() const { return mbTableUpdateInProgress; }

    /**
     * Makes sure that, starting from the passed Page, all page-bound Frames
     * are on the right Page (pagenumber).
     */
    static void AssertPageFlys( SwPageFrame * );

    /// Invalidate all Content, Size or PrtArea
    void InvalidateAllContent( SwInvalidateFlags nInvalidate );

    /**
     * Invalidate/re-calculate the position of all floating
     * screen objects (Writer fly frames and drawing objects), which are
     * anchored to paragraph or to character.
    */
    void InvalidateAllObjPos();

    /// Remove superfluous Pages
    void SetSuperfluous()      { mbCheckSuperfluous = true; }
    bool IsSuperfluous() const { return mbCheckSuperfluous; }
    void RemoveSuperfluous();

    /**
     * Query/set the current Page and the collective Page count
     * We'll format as much as necessary
     */
    sal_uInt16  GetCurrPage( const SwPaM* ) const;
    sal_uInt16  SetCurrPage( SwCursor*, sal_uInt16 nPageNum );
    Point   GetPagePos( sal_uInt16 nPageNum ) const;
    sal_uInt16  GetPageNum() const      { return mnPhyPageNums; }
    void    DecrPhyPageNums()       { --mnPhyPageNums; }
    void    IncrPhyPageNums()       { ++mnPhyPageNums; }
    bool    IsVirtPageNum() const   { return mbIsVirtPageNum; }
    inline  void SetVirtPageNum( const bool bOf ) const;
    bool    IsDummyPage( sal_uInt16 nPageNum ) const;

    /**
     * Point rPt: The point that should be used to find the page
     * Size pSize: If given, we return the (first) page that overlaps with the
     * rectangle defined by rPt and pSize
     * bool bExtend: Extend each page to the left/right/top/bottom up to the
     * next page margin
     */
    const SwPageFrame* GetPageAtPos( const Point& rPt, const Size* pSize = nullptr, bool bExtend = false ) const;

    /**
    * Point rPt: The point to test
    * @returns true: if rPt is between top/bottom margins of two pages
    *                in hide-whitespace, rPt can be near the gap, but
    *                not strictly between pages (in a page) as gap is small.
    * @returns false: if rPt is in a page or not strictly between two pages
    */
    bool IsBetweenPages(const Point& rPt) const;

    void CalcFrameRects( SwShellCursor& );

    /**
     * Calculates the cells included from the current selection
     *
     * @returns false: There was no result because of an invalid layout
     * @returns true: Everything worked fine.
     */
    bool MakeTableCursors( SwTableCursor& );

    void DisallowTurbo()  const { const_cast<SwRootFrame*>(this)->mbTurboAllowed = false; }
    void ResetTurboFlag() const { const_cast<SwRootFrame*>(this)->mbTurboAllowed = true; }
    bool IsTurboAllowed() const { return mbTurboAllowed; }
    void SetTurbo( const SwContentFrame *pContent ) { mpTurbo = pContent; }
    void ResetTurbo() { mpTurbo = nullptr; }
    const SwContentFrame *GetTurbo() const { return mpTurbo; }

    /// Update the footnote numbers of all Pages
    void UpdateFootnoteNums(); // Only for page by page numbering!

    /// Remove all footnotes (but no references)
    void RemoveFootnotes( SwPageFrame *pPage = nullptr, bool bPageOnly = false,
                     bool bEndNotes = false );
    void CheckFootnotePageDescs( bool bEndNote );

    const SwPageFrame *GetLastPage() const { return mpLastPage; }
          SwPageFrame *GetLastPage()       { return mpLastPage; }

    static bool IsInPaint() { return s_isInPaint; }

    static void SetNoVirDev(const bool bNew) { s_isNoVirDev = bNew; }

    inline tools::Long GetBrowseWidth() const;
    inline void InvalidateBrowseWidth();

    bool IsNewLayout() const { return mbIsNewLayout; }
    void ResetNewLayout()    { mbIsNewLayout = false;}

    /**
     * Empty SwSectionFrames are registered here for deletion and
     * destroyed later on or deregistered.
     */
    void InsertEmptySct( SwSectionFrame* pDel );
    void DeleteEmptySct() { if( mpDestroy ) DeleteEmptySct_(); }
    void RemoveFromList( SwSectionFrame* pSct ) { if( mpDestroy ) RemoveFromList_( pSct ); }
#ifdef DBG_UTIL
    bool IsInDelList( SwSectionFrame* pSct ) const;
#endif

    void SetCallbackActionEnabled( bool b ) { mbCallbackActionEnabled = b; }
    bool IsCallbackActionEnabled() const    { return mbCallbackActionEnabled; }

    bool IsAnyShellAccessible() const { return mnAccessibleShells > 0; }
    void AddAccessibleShell() { ++mnAccessibleShells; }
    void RemoveAccessibleShell() { --mnAccessibleShells; }

    /**
     * Get page frame by physical page number
     * looping through the lowers, which are page frame, in order to find the
     * page frame with the given physical page number.
     * if no page frame is found, 0 is returned.
     * Note: Empty page frames are also returned.
     *
     * @param _nPageNum: physical page number of page frame to be searched and
     *                   returned.
     *
     * @return pointer to the page frame with the given physical page number
    */
    SwPageFrame* GetPageByPageNum( sal_uInt16 _nPageNum ) const;

    void CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea );
    bool IsLeftToRightViewLayout() const;
    const SwRect& GetPagesArea() const { return maPagesArea; }
    void SetSidebarChanged() { mbSidebarChanged = true; }

    bool IsLayoutFreezed() const { return mbLayoutFreezed; }
    void FreezeLayout( bool freeze ) { mbLayoutFreezed = freeze; }

    void RemovePage( SwPageFrame **pDel, SwRemoveResult eResult );

    /**
     * Replacement for sw::DocumentRedlineManager::GetRedlineFlags()
     * (this is layout-level redline hiding).
     */
    bool IsHideRedlines() const { return mbHideRedlines; }
    void SetHideRedlines(bool);
    sw::FieldmarkMode GetFieldmarkMode() const { return m_FieldmarkMode; }
    void SetFieldmarkMode(sw::FieldmarkMode);
    bool HasMergedParas() const {
        return IsHideRedlines() || GetFieldmarkMode() != sw::FieldmarkMode::ShowBoth;
    }
};

inline tools::Long SwRootFrame::GetBrowseWidth() const
{
    if ( !mbBrowseWidthValid )
        const_cast<SwRootFrame*>(this)->ImplCalcBrowseWidth();
    return mnBrowseWidth;
}

inline void SwRootFrame::InvalidateBrowseWidth()
{
    if ( mbBrowseWidthValid )
        ImplInvalidateBrowseWidth();
}

inline  void SwRootFrame::SetVirtPageNum( const bool bOf) const
{
    const_cast<SwRootFrame*>(this)->mbIsVirtPageNum = bOf;
}

/// helper class to disable creation of an action by a callback event
/// in particular, change event from a drawing object (SwDrawContact::Changed())
class DisableCallbackAction
{
    private:
        SwRootFrame & m_rRootFrame;
        bool m_bOldCallbackActionState;

    public:
        explicit DisableCallbackAction(SwRootFrame & rRootFrame)
            : m_rRootFrame(rRootFrame)
            , m_bOldCallbackActionState(rRootFrame.IsCallbackActionEnabled())
        {
            m_rRootFrame.SetCallbackActionEnabled(false);
        }

        ~DisableCallbackAction()
        {
            m_rRootFrame.SetCallbackActionEnabled(m_bOldCallbackActionState);
        }
};

#endif // INCLUDED_SW_SOURCE_CORE_INC_ROOTFRM_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */