/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _FRMTOOL_HXX
#define _FRMTOOL_HXX

#include <bf_svtools/bf_solar.h>

#include "swtypes.hxx"
#include "layfrm.hxx"
#include "frmatr.hxx"
#include "swcache.hxx"
class BigInt;
class OutputDevice;
namespace binfilter {

class SwPageFrm;
class SwFlyFrm;
class SwCntntFrm;
class SwFtnContFrm;
class SwDoc;
class SwAttrSet;
class SdrObject;

class SvxBrushItem;
class SdrMarkList;
class SwNodeIndex;

class SwPageDesc;
class SwCrsrShell;
class SwTxtFrm;

#if defined(MSC)
#define MA_FASTCALL __fastcall
#else
#define MA_FASTCALL
#endif

#define WEIT_WECH       LONG_MAX - 20000        //Initale Position der Flys.
#define BROWSE_HEIGHT   56700L * 10L                //10 Meter

#define GRFNUM_NO 0
#define GRFNUM_YES 1
#define GRFNUM_REPLACE 2

//Painten des Hintergrunds. Mit Brush oder Graphic.
// add 6th parameter to indicate that method should
//     consider background transparency, saved in the color of the brush item
void MA_FASTCALL DrawGraphic( const SvxBrushItem *, OutputDevice *,
      const SwRect &rOrg, const SwRect &rOut, const BYTE nGrfNum = GRFNUM_NO,
      const sal_Bool bConsiderBackgroundTransparency = sal_False );

// method to align graphic rectangle
// Created declaration here to avoid <extern> declarations
void SwAlignGrfRect( SwRect *pGrfRect, const OutputDevice &rOut );

SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart );
void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling );

//Nicht gleich die math.lib anziehen.
ULONG MA_FASTCALL SqRt( BigInt nX );

//CntntNodes besorgen, CntntFrms erzeugen und in den LayFrm haengen.
void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc, ULONG nIndex,
                 BOOL bPages = FALSE, ULONG nEndIndex = 0,
                 SwFrm *pPrv = 0 );

//Erzeugen der Frames fuer einen bestimmten Bereich, verwendet _InsertCnt
void MakeFrms();

//Um z.B. fuer Tabelleheadlines das Erzeugen der Flys in _InsertCnt zu unterbinden.
extern bool bDontCreateObjects;

//Fuer FlyCnts, siehe SwFlyAtCntFrm::MakeAll()
extern bool bSetCompletePaintOnInvalidate;

//Fuer Tabelleneinstellung per Tastatur.
long MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow );
long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm );  //MA_FLY_HEIGHT

//Neue Seite einsetzen
SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
                          BOOL bOdd, BOOL bInsertEmpty, BOOL bFtn,
                          SwFrm *pSibling );

//Flys bei der Seite anmelden.
void RegistFlys( SwPageFrm*, const SwLayoutFrm* );

//Benachrichtung des Fly Hintergrundes wenn Notwendig.
void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld );

void Notify_Background( SdrObject *pObj, SwPageFrm *pPage, const SwRect& rRect,
                        const PrepareHint eHint );

const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos );

BOOL Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj );

const SwFrm *FindKontext( const SwFrm *pFrm, USHORT nAdditionalKontextTyp );

BOOL IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm );

void MA_ParkCrsr( SwPageDesc *pDesc, SwCrsrShell &rSh );

const SwFrm * MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage );

// wird von SwCntntNode::GetFrm und von SwFlyFrm::GetFrm gerufen
SwFrm* GetFrmOfModify( SwModify&, USHORT nFrmType, const Point* = 0,
                        const SwPosition *pPos = 0,
                        const BOOL bCalcFrm = FALSE );

// #i11760# - method declaration <CalcCntnt(..)>
void CalcCntnt( SwLayoutFrm *pLay,
                bool bNoCalcFollow = false );


//Die Notify-Klassen merken sich im CTor die aktuellen Groessen und fuehren
//im DTor ggf. die notwendigen Benachrichtigungen durch.

class SwFrmNotify
{
protected:
    SwFrm *pFrm;
    const SwRect aFrm;
    const SwRect aPrt;
    SwTwips mnFlyAnchorOfst;
    SwTwips mnFlyAnchorOfstNoWrap;
    bool     bHadFollow;
    bool     bInvaKeep;
#ifdef ACCESSIBLE_LAYOUT
    bool     bValidSize;
#endif

public:
    SwFrmNotify( SwFrm *pFrm );
    ~SwFrmNotify();

    const SwRect &Frm() const { return aFrm; }
    const SwRect &Prt() const { return aPrt; }
    void SetInvaKeep() { bInvaKeep = TRUE; }
};

class SwLayNotify : public SwFrmNotify
{
    SwTwips  nHeightOfst;
    SwTwips  nWidthOfst;
    bool bLowersComplete;

    SwLayoutFrm *GetLay() { return (SwLayoutFrm*)pFrm; }
public:
    SwLayNotify( SwLayoutFrm *pLayFrm );
    ~SwLayNotify();

    void AddHeightOfst     ( SwTwips nAdd ) { nHeightOfst += nAdd; }
    void AddWidthOfst      ( SwTwips nAdd ) { nHeightOfst += nAdd; }
    void SubtractHeightOfst( SwTwips nSub ) { nWidthOfst -= nSub; }
    void SubtractWidthOfst ( SwTwips nSub ) { nWidthOfst -= nSub; }
    SwTwips GetHeightOfst() const { return nHeightOfst; }
    SwTwips GetWidthOfst()  const { return nWidthOfst; }
    void    ResetHeightOfst() { nHeightOfst = 0; }
    void    ResetWidthOfst()  { nWidthOfst = 0; }

    void SetLowersComplete( bool b ) { bLowersComplete = b; }
    bool IsLowersComplete()          { return bLowersComplete; }
};

class SwFlyNotify : public SwLayNotify
{
    SwPageFrm *pOldPage;
    const SwRect aFrmAndSpace;
    SwFlyFrm *GetFly() { return (SwFlyFrm*)pFrm; }
public:
    SwFlyNotify( SwFlyFrm *pFlyFrm );
    ~SwFlyNotify();

    SwPageFrm *GetOldPage() const { return pOldPage; }
};

class SwCntntNotify : public SwFrmNotify
{
    SwCntntFrm *GetCnt() { return (SwCntntFrm*)pFrm; }
public:
    SwCntntNotify( SwCntntFrm *pCntFrm );
    ~SwCntntNotify();
};

//SwBorderAttrs kapselt die Berechnung fuer die Randattribute inclusive
//Umrandung. Die Attribute und die errechneten Werte werden gecached.
//Neu: Die gesammte Klasse wird gecached.

//!!!Achtung: Wenn weitere Attribute gecached werden muss unbedingt die
//Methode Modify::Modify mitgepflegt werden!!!

// delete old method <SwBorderAttrs::CalcRight()> and
// the stuff that belongs to it.
class SwBorderAttrs : public SwCacheObj
{
    const SwAttrSet      &rAttrSet;
    const SvxULSpaceItem &rUL;
    const SvxLRSpaceItem &rLR;
    const SvxBoxItem     &rBox;
    const SvxShadowItem  &rShadow;
    const Size            aFrmSize;     //Die FrmSize

    BOOL bBorderDist    :1;             //Ist's ein Frm der auch ohne Linie
                                        //einen Abstand haben kann?

    //Mit den Folgenden Bools werden die gecache'ten Werte fuer UNgueltig
    //erklaert - bis sie einmal berechnet wurden.
    BOOL bTopLine       :1;
    BOOL bBottomLine    :1;
    BOOL bLeftLine      :1;
    BOOL bRightLine     :1;
    BOOL bTop           :1;
    BOOL bBottom        :1;
    BOOL bLine          :1;

    BOOL bIsLine        :1; //Umrandung an mind. einer Kante?

    BOOL bCacheGetLine        :1; //GetTopLine(), GetBottomLine() cachen?
    BOOL bCachedGetTopLine    :1; //GetTopLine() gecached?
    BOOL bCachedGetBottomLine :1; //GetBottomLine() gecached?
    // booleans indicating, if values <bJoinedWithPrev>
    //          and <bJoinedWithNext> are cached and valid.
    //          Caching depends on value of <bCacheGetLine>.
    mutable BOOL bCachedJoinedWithPrev :1;
    mutable BOOL bCachedJoinedWithNext :1;
    // booleans indicating, if borders are joined with previous/next frame.
    BOOL bJoinedWithPrev :1;
    BOOL bJoinedWithNext :1;

    //Die gecache'ten Werte, undefiniert bis sie einmal berechnet wurden.
    USHORT nTopLine,
           nBottomLine,
           nLeftLine,
           nRightLine,
           nTop,
           nBottom,
           nGetTopLine,
           nGetBottomLine;

    //Nur die Lines + Shadow errechnen.
    void _CalcTopLine();
    void _CalcBottomLine();
    void _CalcLeftLine();
    void _CalcRightLine();

    //Lines + Shadow + Abstaende
    void _CalcTop();
    void _CalcBottom();


    void _GetTopLine   ( const SwFrm *pFrm );
    void _GetBottomLine( const SwFrm *pFrm );

    // private methods to calculate cached values
    // <bJoinedWithPrev> and <bJoinedWithNext>.
    void _CalcJoinedWithPrev( const SwFrm& _rFrm );
    void _CalcJoinedWithNext( const SwFrm& _rFrm );

    // internal helper method for methods
    // <_CalcJoinedWithPrev> and <_CalcJoinedWithNext>.
    BOOL _JoinWithCmp( const SwFrm& _rCallerFrm,
                       const SwFrm& _rCmpFrm ) const;

     //Rechte und linke Linie sowie LRSpace gleich?
    // change name of 1st parameter - "rAttrs" -> "rCmpAttrs".
    BOOL CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
                       const SwFrm *pCaller,
                       const SwFrm *pCmp ) const;

public:
    DECL_FIXEDMEMPOOL_NEWDEL(SwBorderAttrs)

    SwBorderAttrs( const SwModify *pOwner, const SwFrm *pConstructor );
    ~SwBorderAttrs();

    inline const SwAttrSet      &GetAttrSet() const { return rAttrSet;  }
    inline const SvxULSpaceItem &GetULSpace() const { return rUL;       }
    inline const SvxLRSpaceItem &GetLRSpace() const { return rLR;       }
    inline const SvxBoxItem     &GetBox()     const { return rBox;      }
    inline const SvxShadowItem  &GetShadow()  const { return rShadow;   }

    inline USHORT CalcTopLine() const;
    inline USHORT CalcBottomLine() const;
    inline USHORT CalcLeftLine() const;
    inline USHORT CalcRightLine() const;
    inline USHORT CalcTop() const;
    inline USHORT CalcBottom() const;
           long CalcLeft( const SwFrm *pCaller ) const;
           long CalcRight( const SwFrm *pCaller ) const;


    inline const Size &GetSize()     const { return aFrmSize; }

    inline BOOL IsBorderDist() const { return bBorderDist; }

    //Sollen obere bzw. untere Umrandung fuer den Frm ausgewertet werden?
    inline USHORT GetTopLine   ( const SwFrm *pFrm ) const;
    inline USHORT GetBottomLine( const SwFrm *pFrm ) const;
    inline void   SetGetCacheLine( BOOL bNew ) const;
        // accessors for cached values <bJoinedWithPrev> and <bJoinedWithPrev>
    BOOL JoinedWithPrev( const SwFrm& _rFrm ) const;
    BOOL JoinedWithNext( const SwFrm& _rFrm ) const;
};

class SwBorderAttrAccess : public SwCacheAccess
{
    const SwFrm *pConstructor;      //opt: Zur weitergabe an SwBorderAttrs
protected:
    virtual SwCacheObj *NewObj();

public:
    SwBorderAttrAccess( SwCache &rCache, const SwFrm *pOwner );

    SwBorderAttrs *Get();
};

//---------------------------------------------------------------------
//Iterator fuer die DrawObjecte einer Seite. Die Objecte werden Nach ihrer
//Z-Order iteriert.
//Das iterieren ist nicht eben billig, denn fuer alle Operationen muss jeweils
//ueber das gesamte SortArray iteriert werden.
class SwOrderIter
{
    const SwPageFrm *pPage;
    const SdrObject *pCurrent;
    const bool bFlysOnly;
public:
    SwOrderIter( const SwPageFrm *pPage, bool bFlysOnly = TRUE );

    void             Current( const SdrObject *pNew ) { pCurrent = pNew; }
    const SdrObject *Current()    const { return pCurrent; }
    const SdrObject *operator()() const { return pCurrent; }
    const SdrObject *Bottom();
    const SdrObject *Next();
};


class StackHack
{
    static BYTE nCnt;
    static BOOL bLocked;
public:
    StackHack()
    {
        if ( ++StackHack::nCnt > 50 )
            StackHack::bLocked = TRUE;
    }
    ~StackHack()
    {
        if ( --StackHack::nCnt == 0 )
            StackHack::bLocked = FALSE;
    }

    static BOOL IsLocked()  { return StackHack::bLocked; }
    static BYTE Count()     { return StackHack::nCnt; }
};


//Sollen obere bzw. untere Umrandung fuer den Frm ausgewertet werden?
inline USHORT SwBorderAttrs::GetTopLine   ( const SwFrm *pFrm ) const
{
    if ( !bCachedGetTopLine )
        ((SwBorderAttrs*)this)->_GetTopLine( pFrm );
    return nGetTopLine;
}
inline USHORT SwBorderAttrs::GetBottomLine( const SwFrm *pFrm ) const
{
    if ( !bCachedGetBottomLine )
        ((SwBorderAttrs*)this)->_GetBottomLine( pFrm );
    return nGetBottomLine;
}
inline void SwBorderAttrs::SetGetCacheLine( BOOL bNew ) const
{
    ((SwBorderAttrs*)this)->bCacheGetLine = bNew;
    ((SwBorderAttrs*)this)->bCachedGetBottomLine =
    ((SwBorderAttrs*)this)->bCachedGetTopLine = FALSE;
        // invalidate cache for values <bJoinedWithPrev> and <bJoinedWithNext>.
    bCachedJoinedWithPrev = FALSE;
    bCachedJoinedWithNext = FALSE;
}

inline USHORT SwBorderAttrs::CalcTopLine() const
{
    if ( bTopLine )
        ((SwBorderAttrs*)this)->_CalcTopLine();
    return nTopLine;
}
inline USHORT SwBorderAttrs::CalcBottomLine() const
{
    if ( bBottomLine )
        ((SwBorderAttrs*)this)->_CalcBottomLine();
    return nBottomLine;
}
inline USHORT SwBorderAttrs::CalcLeftLine() const
{
    if ( bLeftLine )
        ((SwBorderAttrs*)this)->_CalcLeftLine();
    return nLeftLine;
}
inline USHORT SwBorderAttrs::CalcRightLine() const
{
    if ( bRightLine )
        ((SwBorderAttrs*)this)->_CalcRightLine();
    return nRightLine;
}
inline USHORT SwBorderAttrs::CalcTop() const
{
    if ( bTop )
        ((SwBorderAttrs*)this)->_CalcTop();
    return nTop;
}
inline USHORT SwBorderAttrs::CalcBottom() const
{
    if ( bBottom )
        ((SwBorderAttrs*)this)->_CalcBottom();
    return nBottom;
}
} //namespace binfilter
#endif  //_FRMTOOL_HXX

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