blob: b38c3635b02bfb158d329c9d06a84b5f13bbeffa [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <tools/list.hxx>
#include <svx/svdobj.hxx>
#include <init.hxx>
#include <fesh.hxx>
#include <pagefrm.hxx>
#include <rootfrm.hxx>
#include <cntfrm.hxx>
#include <doc.hxx>
#include <frmtool.hxx>
#include <swtable.hxx>
#include <viewimp.hxx>
#include <dview.hxx>
#include <flyfrm.hxx>
#include <node.hxx>
#include <pam.hxx>
#include <sectfrm.hxx>
#include <fmtpdsc.hxx>
#include <fmtsrnd.hxx>
#include <fmtcntnt.hxx>
#include <tabfrm.hxx>
#include <cellfrm.hxx>
#include <flyfrms.hxx>
#include <txtfrm.hxx> // SwTxtFrm
#include <mdiexp.hxx>
#include <edimp.hxx>
#include <pagedesc.hxx>
#include <fmtanchr.hxx>
// OD 29.10.2003 #113049#
#include <environmentofanchoredobject.hxx>
// OD 12.11.2003 #i22341#
#include <ndtxt.hxx>
// OD 27.11.2003 #112045#
#include <dflyobj.hxx>
// OD 2004-03-29 #i26791#
#include <dcontact.hxx>
using namespace com::sun::star;
TYPEINIT1(SwFEShell,SwEditShell)
/***********************************************************************
#* Class : SwFEShell
#* Methode : EndAllActionAndCall()
#*
#* Datum : MA 03. May. 93
#* Update : MA 31. Oct. 95
#***********************************************************************/
void SwFEShell::EndAllActionAndCall()
{
ViewShell *pTmp = this;
do {
if( pTmp->IsA( TYPE(SwCrsrShell) ) )
{
((SwFEShell*)pTmp)->EndAction();
((SwFEShell*)pTmp)->CallChgLnk();
}
else
pTmp->EndAction();
} while( this != ( pTmp = (ViewShell*)pTmp->GetNext() ));
}
/***********************************************************************
#* Class : SwFEShell
#* Methode : GetCntntPos
#* Beschreibung: Ermitteln des Cntnt's der dem Punkt am naechsten liegt
#* Datum : MA 02. Jun. 92
#* Update : MA 02. May. 95
#***********************************************************************/
Point SwFEShell::GetCntntPos( const Point& rPoint, sal_Bool bNext ) const
{
SET_CURR_SHELL( (ViewShell*)this );
return GetLayout()->GetNextPrevCntntPos( rPoint, bNext );
}
const SwRect& SwFEShell::GetAnyCurRect( CurRectType eType, const Point* pPt,
const uno::Reference < embed::XEmbeddedObject >& xObj ) const
{
const SwFrm *pFrm = Imp()->HasDrawView()
? ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
(ViewShell*)this)
: 0;
if( !pFrm )
{
if( pPt )
{
SwPosition aPos( *GetCrsr()->GetPoint() );
Point aPt( *pPt );
GetLayout()->GetCrsrOfst( &aPos, aPt );
SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
}
else
{
const bool bOldCallbackActionEnabled = GetLayout()->IsCallbackActionEnabled();
if( bOldCallbackActionEnabled )
GetLayout()->SetCallbackActionEnabled( sal_False );
pFrm = GetCurrFrm();
if( bOldCallbackActionEnabled )
GetLayout()->SetCallbackActionEnabled( sal_True );
}
}
if( !pFrm )
return GetLayout()->Frm();
sal_Bool bFrm = sal_True;
switch ( eType )
{
case RECT_PAGE_PRT: bFrm = sal_False; /* no break */
case RECT_PAGE : pFrm = pFrm->FindPageFrm();
break;
case RECT_PAGE_CALC: pFrm->Calc();
pFrm = pFrm->FindPageFrm();
pFrm->Calc();
break;
case RECT_FLY_PRT_EMBEDDED: bFrm = sal_False; /* no break */
case RECT_FLY_EMBEDDED: pFrm = xObj.is() ? FindFlyFrm( xObj )
: pFrm->IsFlyFrm()
? pFrm
: pFrm->FindFlyFrm();
break;
case RECT_OUTTABSECTION_PRT:
case RECT_OUTTABSECTION : if( pFrm->IsInTab() )
pFrm = pFrm->FindTabFrm();
else {
ASSERT( sal_False, "Missing Table" );
}
/* KEIN BREAK */
case RECT_SECTION_PRT:
case RECT_SECTION: if( pFrm->IsInSct() )
pFrm = pFrm->FindSctFrm();
else {
ASSERT( sal_False, "Missing section" );
}
if( RECT_OUTTABSECTION_PRT == eType ||
RECT_SECTION_PRT == eType )
bFrm = sal_False;
break;
case RECT_HEADERFOOTER_PRT: bFrm = sal_False; /* no break */
case RECT_HEADERFOOTER: if( 0 == (pFrm = pFrm->FindFooterOrHeader()) )
return GetLayout()->Frm();
break;
case RECT_PAGES_AREA: return GetLayout()->GetPagesArea();
default: break;
}
return bFrm ? pFrm->Frm() : pFrm->Prt();
}
sal_uInt16 SwFEShell::GetPageNumber( const Point &rPoint ) const
{
const SwFrm *pPage = GetLayout()->Lower();
while ( pPage && !pPage->Frm().IsInside( rPoint ) )
pPage = pPage->GetNext();
if ( pPage )
return ((const SwPageFrm*)pPage)->GetPhyPageNum();
else
return 0;
}
sal_Bool SwFEShell::GetPageNumber( long nYPos, sal_Bool bAtCrsrPos, sal_uInt16& rPhyNum, sal_uInt16& rVirtNum, String &rDisplay) const
{
const SwFrm *pPage;
if ( bAtCrsrPos ) //Seite vom Crsr besorgen
{
pPage = GetCurrFrm( sal_False );
if ( pPage )
pPage = pPage->FindPageFrm();
}
else if ( nYPos > -1 ) //Seite ueber die Positon ermitteln
{
pPage = GetLayout()->Lower();
while( pPage && (pPage->Frm().Bottom() < nYPos ||
nYPos < pPage->Frm().Top() ) )
pPage = pPage->GetNext();
}
else //Die erste sichtbare Seite
{
pPage = Imp()->GetFirstVisPage();
if ( pPage && ((SwPageFrm*)pPage)->IsEmptyPage() )
pPage = pPage->GetNext();
}
if( pPage )
{
rPhyNum = ((const SwPageFrm*)pPage)->GetPhyPageNum();
rVirtNum = ((const SwPageFrm*)pPage)->GetVirtPageNum();
const SvxNumberType& rNum = ((const SwPageFrm*)pPage)->GetPageDesc()->GetNumType();
rDisplay = rNum.GetNumStr( rVirtNum );
}
return 0 != pPage;
}
/*************************************************************************
|*
|* SwFEShell::IsDirectlyInSection()
|*
|* Hack for OS:
|*
*************************************************************************/
bool SwFEShell::IsDirectlyInSection() const
{
SwFrm* pFrm = GetCurrFrm( sal_False );
return pFrm && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm();
}
/*************************************************************************
|*
|* SwFEShell::GetFrmType()
|*
|* Ersterstellung MA 12. Jan. 93
|* Letzte Aenderung AMA 25. Nov. 98
|*
*************************************************************************/
sal_uInt16 SwFEShell::GetFrmType( const Point *pPt, sal_Bool bStopAtFly ) const
{
sal_uInt16 nReturn = FRMTYPE_NONE;
const SwFrm *pFrm;
if ( pPt )
{
SwPosition aPos( *GetCrsr()->GetPoint() );
Point aPt( *pPt );
GetLayout()->GetCrsrOfst( &aPos, aPt );
SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
}
else
pFrm = GetCurrFrm( sal_False );
while ( pFrm )
{
switch ( pFrm->GetType() )
{
case FRM_COLUMN: if( pFrm->GetUpper()->IsSctFrm() )
{
// Check, if isn't not only a single column
// from a section with footnotes at the end.
if( pFrm->GetNext() || pFrm->GetPrev() )
// Sectioncolumns
nReturn |= ( nReturn & FRMTYPE_TABLE ) ?
FRMTYPE_COLSECTOUTTAB : FRMTYPE_COLSECT;
}
else // nur Seiten und Rahmenspalten
nReturn |= FRMTYPE_COLUMN;
break;
case FRM_PAGE: nReturn |= FRMTYPE_PAGE;
if( ((SwPageFrm*)pFrm)->IsFtnPage() )
nReturn |= FRMTYPE_FTNPAGE;
break;
case FRM_HEADER: nReturn |= FRMTYPE_HEADER; break;
case FRM_FOOTER: nReturn |= FRMTYPE_FOOTER; break;
case FRM_BODY: if( pFrm->GetUpper()->IsPageFrm() ) // nicht bei ColumnFrms
nReturn |= FRMTYPE_BODY;
break;
case FRM_FTN: nReturn |= FRMTYPE_FOOTNOTE; break;
case FRM_FLY: if( ((SwFlyFrm*)pFrm)->IsFlyLayFrm() )
nReturn |= FRMTYPE_FLY_FREE;
else if ( ((SwFlyFrm*)pFrm)->IsFlyAtCntFrm() )
nReturn |= FRMTYPE_FLY_ATCNT;
else
{
ASSERT( ((SwFlyFrm*)pFrm)->IsFlyInCntFrm(),
"Neuer Rahmentyp?" );
nReturn |= FRMTYPE_FLY_INCNT;
}
nReturn |= FRMTYPE_FLY_ANY;
if( bStopAtFly )
return nReturn;
break;
case FRM_TAB:
case FRM_ROW:
case FRM_CELL: nReturn |= FRMTYPE_TABLE; break;
default: /* do nothing */ break;
}
if ( pFrm->IsFlyFrm() )
pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
else
pFrm = pFrm->GetUpper();
}
return nReturn;
}
/*************************************************************************
|*
|* SwFEShell::ShLooseFcs(), ShGetFcs()
|*
|* Ersterstellung MA 10. May. 93
|* Letzte Aenderung MA 09. Sep. 98
|*
*************************************************************************/
void SwFEShell::ShGetFcs( sal_Bool bUpdate )
{
::SetShell( this );
SwCrsrShell::ShGetFcs( bUpdate );
if ( HasDrawView() )
{
Imp()->GetDrawView()->showMarkHandles();
if ( Imp()->GetDrawView()->AreObjectsMarked() )
FrameNotify( this, FLY_DRAG_START );
}
}
void SwFEShell::ShLooseFcs()
{
SwCrsrShell::ShLooseFcs();
if ( HasDrawView() && Imp()->GetDrawView()->AreObjectsMarked() )
{
Imp()->GetDrawView()->hideMarkHandles();
FrameNotify( this, FLY_DRAG_END );
}
// ::ResetShell();
}
/*************************************************************************
|*
|* SwFEShell::GetPhyPageNum()
|* SwFEShell::GetVirtPageNum()
|*
|* Ersterstellung OK 07.07.93 08:20
|* Letzte Aenderung MA 03. Jan. 94
|*
*************************************************************************/
sal_uInt16 SwFEShell::GetPhyPageNum()
{
SwFrm *pFrm = GetCurrFrm();
if ( pFrm )
return pFrm->GetPhyPageNum();
return 0;
}
sal_uInt16 SwFEShell::GetVirtPageNum( const sal_Bool bCalcFrm )
{
SwFrm *pFrm = GetCurrFrm( bCalcFrm );
if ( pFrm )
return pFrm->GetVirtPageNum();
return 0;
}
/*************************************************************************
|*
|* void lcl_SetAPageOffset()
|* void SwFEShell::SetNewPageOffset()
|* void SwFEShell::SetPageOffset()
|* sal_uInt16 SwFEShell::GetPageOffset() const
|*
|* Ersterstellung OK 07.07.93 08:20
|* Letzte Aenderung MA 30. Mar. 95
|*
*************************************************************************/
void lcl_SetAPageOffset( sal_uInt16 nOffset, SwPageFrm* pPage, SwFEShell* pThis )
{
pThis->StartAllAction();
ASSERT( pPage->FindFirstBodyCntnt(),
"SwFEShell _SetAPageOffset() ohne CntntFrm" );
SwFmtPageDesc aDesc( pPage->GetPageDesc() );
aDesc.SetNumOffset( nOffset );
SwFrm *pFrm = pThis->GetCurrFrm( sal_False );
if ( pFrm->IsInTab() )
pThis->GetDoc()->SetAttr( aDesc, *pFrm->FindTabFrm()->GetFmt() );
else
{
pThis->GetDoc()->InsertPoolItem( *pThis->GetCrsr(), aDesc, 0 );
}
pThis->EndAllAction();
}
void SwFEShell::SetNewPageOffset( sal_uInt16 nOffset )
{
GetLayout()->SetVirtPageNum( sal_True );
const SwPageFrm *pPage = GetCurrFrm( sal_False )->FindPageFrm();
lcl_SetAPageOffset( nOffset, (SwPageFrm*)pPage, this );
}
void SwFEShell::SetPageOffset( sal_uInt16 nOffset )
{
const SwPageFrm *pPage = GetCurrFrm( sal_False )->FindPageFrm();
const SwRootFrm* pDocLayout = GetLayout();
while ( pPage )
{
const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
if ( pFlow )
{
if ( pFlow->IsInTab() )
pFlow = pFlow->FindTabFrm();
const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
if ( rPgDesc.GetNumOffset() )
{
pDocLayout->SetVirtPageNum( sal_True );
lcl_SetAPageOffset( nOffset, (SwPageFrm*)pPage, this );
break;
}
}
pPage = (SwPageFrm*)pPage->GetPrev();
}
}
sal_uInt16 SwFEShell::GetPageOffset() const
{
const SwPageFrm *pPage = GetCurrFrm()->FindPageFrm();
while ( pPage )
{
const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
if ( pFlow )
{
if ( pFlow->IsInTab() )
pFlow = pFlow->FindTabFrm();
const sal_uInt16 nOffset = pFlow->GetAttrSet()->GetPageDesc().GetNumOffset();
if ( nOffset )
return nOffset;
}
pPage = (SwPageFrm*)pPage->GetPrev();
}
return 0;
}
/*************************************************************************
|*
|* SwFEShell::InsertLabel()
|*
|* Ersterstellung MA 10. Feb. 94
|* Letzte Aenderung MA 10. Feb. 94
|*
*************************************************************************/
void SwFEShell::InsertLabel( const SwLabelType eType, const String &rTxt, const String& rSeparator,
const String& rNumberSeparator,
const sal_Bool bBefore, const sal_uInt16 nId,
const String& rCharacterStyle,
const sal_Bool bCpyBrd )
{
//NodeIndex der CrsrPosition besorgen, den Rest kann das Dokument
//selbst erledigen.
SwCntntFrm *pCnt = LTYPE_DRAW==eType ? 0 : GetCurrFrm( sal_False );
if( LTYPE_DRAW==eType || pCnt )
{
StartAllAction();
sal_uLong nIdx = 0;
SwFlyFrmFmt* pFlyFmt = 0;
switch( eType )
{
case LTYPE_OBJECT:
case LTYPE_FLY:
if( pCnt->IsInFly() )
{
//Bei Flys den Index auf den StartNode herunterreichen.
nIdx = pCnt->FindFlyFrm()->
GetFmt()->GetCntnt().GetCntntIdx()->GetIndex();
//warum?? Bug 61913 ParkCrsr( GetCrsr()->GetPoint()->nNode );
}
break;
case LTYPE_TABLE:
if( pCnt->IsInTab() )
{
//Bei Tabellen den Index auf den TblNode herunterreichen.
const SwTable& rTbl = *pCnt->FindTabFrm()->GetTable();
nIdx = rTbl.GetTabSortBoxes()[ 0 ]
->GetSttNd()->FindTableNode()->GetIndex();
}
break;
case LTYPE_DRAW:
if( Imp()->GetDrawView() )
{
SwDrawView *pDView = Imp()->GetDrawView();
const SdrMarkList& rMrkList = pDView->GetMarkedObjectList();
StartUndo();
// OD 27.11.2003 #112045# - copy marked drawing objects to
// local list to perform the corresponding action for each object
std::vector<SdrObject*> aDrawObjs;
{
for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
{
SdrObject* pDrawObj = rMrkList.GetMark(i)->GetMarkedSdrObj();
if( pDrawObj )
aDrawObjs.push_back( pDrawObj );
}
}
// loop on marked drawing objects
while ( !aDrawObjs.empty() )
{
SdrObject* pDrawObj = aDrawObjs.back();
if ( !pDrawObj->ISA(SwVirtFlyDrawObj) &&
!pDrawObj->ISA(SwFlyDrawObj) )
{
SwFlyFrmFmt *pFmt =
GetDoc()->InsertDrawLabel( rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, *pDrawObj );
if( !pFlyFmt )
pFlyFmt = pFmt;
}
aDrawObjs.pop_back();
}
EndUndo();
}
break;
default:
ASSERT( !this, "Crsr weder in Tabelle noch in Fly." );
}
if( nIdx )
pFlyFmt = GetDoc()->InsertLabel( eType, rTxt, rSeparator, rNumberSeparator, bBefore, nId,
nIdx, rCharacterStyle, bCpyBrd );
SwFlyFrm* pFrm;
const Point aPt( GetCrsrDocPos() );
if( pFlyFmt && 0 != ( pFrm = pFlyFmt->GetFrm( &aPt )))
SelectFlyFrm( *pFrm, sal_True );
EndAllActionAndCall();
}
}
/***********************************************************************
#* Class : SwFEShell
#* Methoden : Sort
#* Datum : ??
#* Update : ??
#***********************************************************************/
sal_Bool SwFEShell::Sort(const SwSortOptions& rOpt)
{
if( !HasSelection() )
return sal_False;
SET_CURR_SHELL( this );
sal_Bool bRet;
StartAllAction();
if(IsTableMode())
{
// Tabelle sortieren
// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
SwFrm *pFrm = GetCurrFrm( sal_False );
ASSERT( pFrm->FindTabFrm(), "Crsr nicht in Tabelle." );
// lasse ueber das Layout die Boxen suchen
SwSelBoxes aBoxes;
GetTblSel(*this, aBoxes);
// die Crsr muessen noch aus dem Loesch Bereich entfernt
// werden. Setze sie immer hinter/auf die Tabelle; ueber die
// Dokument-Position werden sie dann immer an die alte Position gesetzt.
while( !pFrm->IsCellFrm() )
pFrm = pFrm->GetUpper();
{
/* #107993# ParkCursor->ParkCursorTab */
ParkCursorInTab();
}
// Sorting am Dokument aufrufen
bRet = pDoc->SortTbl(aBoxes, rOpt);
}
else
{
// Text sortieren und nichts anderes
FOREACHPAM_START(this)
SwPaM* pPam = PCURCRSR;
SwPosition* pStart = pPam->Start();
SwPosition* pEnd = pPam->End();
SwNodeIndex aPrevIdx( pStart->nNode, -1 );
sal_uLong nOffset = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
xub_StrLen nCntStt = pStart->nContent.GetIndex();
// Das Sortieren
bRet = pDoc->SortText(*pPam, rOpt);
// Selektion wieder setzen
pPam->DeleteMark();
pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
SwCntntNode* pCNd = pPam->GetCntntNode();
xub_StrLen nLen = pCNd->Len();
if( nLen > nCntStt )
nLen = nCntStt;
pPam->GetPoint()->nContent.Assign(pCNd, nLen );
pPam->SetMark();
pPam->GetPoint()->nNode += nOffset;
pCNd = pPam->GetCntntNode();
pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
FOREACHPAM_END()
}
EndAllAction();
return bRet;
}
/*************************************************************************
|*
|* SwFEShell::GetCurColNum(), _GetColNum()
|*
|* Ersterstellung MA 03. Feb. 95
|* Letzte Aenderung MA 20. Apr. 95
|
|*************************************************************************/
sal_uInt16 SwFEShell::_GetCurColNum( const SwFrm *pFrm,
SwGetCurColNumPara* pPara ) const
{
sal_uInt16 nRet = 0;
while ( pFrm )
{
pFrm = pFrm->GetUpper();
if( pFrm && pFrm->IsColumnFrm() )
{
const SwFrm *pCurFrm = pFrm;
do {
++nRet;
pFrm = pFrm->GetPrev();
} while ( pFrm );
if( pPara )
{
// dann suche mal das Format, was diese Spaltigkeit bestimmt
pFrm = pCurFrm->GetUpper();
while( pFrm )
{
if( ( FRM_PAGE | FRM_FLY | FRM_SECTION ) & pFrm->GetType() )
{
pPara->pFrmFmt = ((SwLayoutFrm*)pFrm)->GetFmt();
pPara->pPrtRect = &pFrm->Prt();
pPara->pFrmRect = &pFrm->Frm();
break;
}
pFrm = pFrm->GetUpper();
}
if( !pFrm )
{
pPara->pFrmFmt = 0;
pPara->pPrtRect = 0;
pPara->pFrmRect = 0;
}
}
break;
}
}
return nRet;
}
sal_uInt16 SwFEShell::GetCurColNum( SwGetCurColNumPara* pPara ) const
{
ASSERT( GetCurrFrm(), "Crsr geparkt?" );
return _GetCurColNum( GetCurrFrm(), pPara );
}
sal_uInt16 SwFEShell::GetCurOutColNum( SwGetCurColNumPara* pPara ) const
{
sal_uInt16 nRet = 0;
SwFrm* pFrm = GetCurrFrm();
ASSERT( pFrm, "Crsr geparkt?" );
if( pFrm )
{
pFrm = pFrm->IsInTab() ? (SwFrm*)pFrm->FindTabFrm()
: (SwFrm*)pFrm->FindSctFrm();
ASSERT( pFrm, "No Tab, no Sect" );
if( pFrm )
nRet = _GetCurColNum( pFrm, pPara );
}
return nRet;
}
SwFEShell::SwFEShell( SwDoc& rDoc, Window *pWindow, const SwViewOption *pOptions )
: SwEditShell( rDoc, pWindow, pOptions ),
pChainFrom( 0 ), pChainTo( 0 ), bCheckForOLEInCaption( sal_False )
{
}
SwFEShell::SwFEShell( SwEditShell& rShell, Window *pWindow )
: SwEditShell( rShell, pWindow ),
pChainFrom( 0 ), pChainTo( 0 ), bCheckForOLEInCaption( sal_False )
{
}
SwFEShell::~SwFEShell()
{
delete pChainFrom;
delete pChainTo;
}
// OD 18.09.2003 #i17567#, #108749#, #110354# - adjustments for allowing
// negative vertical positions for fly frames anchored to paragraph/to character.
// OD 06.11.2003 #i22305# - adjustments for option 'Follow text flow'
// for to frame anchored objects.
// OD 12.11.2003 #i22341# - adjustments for vertical alignment at top of line
// for to character anchored objects.
void SwFEShell::CalcBoundRect( SwRect& _orRect,
const RndStdIds _nAnchorId,
const sal_Int16 _eHoriRelOrient,
const sal_Int16 _eVertRelOrient,
const SwPosition* _pToCharCntntPos,
const bool _bFollowTextFlow,
bool _bMirror,
Point* _opRef,
Size* _opPercent ) const
{
const SwFrm* pFrm;
const SwFlyFrm* pFly;
if( _opRef )
{
pFrm = GetCurrFrm();
if( 0 != ( pFly = pFrm->FindFlyFrm() ) )
pFrm = pFly->GetAnchorFrm();
}
else
{
pFly = FindFlyFrm();
pFrm = pFly ? pFly->GetAnchorFrm() : GetCurrFrm();
}
sal_Bool bWrapThrough = sal_False;
if ( pFly )
{
SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)pFly->GetFmt();
const SwFmtSurround& rSurround = pFmt->GetSurround();
bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
}
const SwPageFrm* pPage = pFrm->FindPageFrm();
_bMirror = _bMirror && !pPage->OnRightPage();
Point aPos;
bool bVertic = false;
sal_Bool bRTL = sal_False;
// --> OD 2009-09-01 #mongolianlayout#
bool bVerticalL2R = false;
// <--
if ((FLY_AT_PAGE == _nAnchorId) || (FLY_AT_FLY == _nAnchorId)) // LAYER_IMPL
{
const SwFrm* pTmp = pFrm;
// OD 06.11.2003 #i22305#
if ((FLY_AT_PAGE == _nAnchorId) ||
((FLY_AT_FLY == _nAnchorId) && !_bFollowTextFlow))
{
pFrm = pPage;
}
else
{
pFrm = pFrm->FindFlyFrm();
}
if ( !pFrm )
pFrm = pTmp;
_orRect = pFrm->Frm();
SWRECTFN( pFrm )
bRTL = pFrm->IsRightToLeft();
if ( bRTL )
aPos = pFrm->Frm().TopRight();
else
aPos = (pFrm->Frm().*fnRect->fnGetPos)();
// --> OD 2009-09-01 #mongolianlayout#
if( bVert || bVertL2R )
// <--
{
// --> OD 2009-09-01 #mongolianlayout#
bVertic = bVert ? true : false;
bVerticalL2R = bVertL2R ? true : false;
// <--
_bMirror = false; // no mirroring in vertical environment
switch ( _eHoriRelOrient )
{
case text::RelOrientation::PAGE_RIGHT:
case text::RelOrientation::FRAME_RIGHT: aPos.Y() += pFrm->Prt().Height();
// no break!
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA: aPos.Y() += pFrm->Prt().Top(); break;
default: break;
}
}
else if ( _bMirror )
{
switch ( _eHoriRelOrient )
{
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Width();
// kein break
case text::RelOrientation::PAGE_RIGHT:
case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Left(); break;
default: aPos.X() += pFrm->Frm().Width();
}
}
else if ( bRTL )
{
switch ( _eHoriRelOrient )
{
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Width();
// kein break!
case text::RelOrientation::PAGE_LEFT:
case text::RelOrientation::FRAME_LEFT: aPos.X() += pFrm->Prt().Left() -
pFrm->Frm().Width(); break;
default: break;
}
}
else
{
switch ( _eHoriRelOrient )
{
case text::RelOrientation::PAGE_RIGHT:
case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Width();
// kein break!
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Left(); break;
default:break;
}
}
// --> OD 2009-09-01 #mongolianlayout#
if ( bVert && !bVertL2R )
// <--
{
switch ( _eVertRelOrient )
{
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA:
{
aPos.X() -= pFrm->GetRightMargin();
}
break;
}
}
// --> OD 2009-09-01 #mongolianlayout#
else if ( bVertL2R )
{
switch ( _eVertRelOrient )
{
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA:
{
aPos.X() += pFrm->GetLeftMargin();
}
break;
}
}
// <--
else
{
switch ( _eVertRelOrient )
{
case text::RelOrientation::PRINT_AREA:
case text::RelOrientation::PAGE_PRINT_AREA:
{
if ( pFrm->IsPageFrm() )
{
aPos.Y() =
static_cast<const SwPageFrm*>(pFrm)->PrtWithoutHeaderAndFooter().Top();
}
else
{
aPos.Y() += pFrm->Prt().Top();
}
}
break;
}
}
// <--
if ( _opPercent )
*_opPercent = pFrm->Prt().SSize();
}
else
{
const SwFrm* pUpper = ( pFrm->IsPageFrm() || pFrm->IsFlyFrm() ) ?
pFrm : pFrm->GetUpper();
SWRECTFN( pUpper );
if ( _opPercent )
*_opPercent = pUpper->Prt().SSize();
bRTL = pFrm->IsRightToLeft();
if ( bRTL )
aPos = pFrm->Frm().TopRight();
else
aPos = (pFrm->Frm().*fnRect->fnGetPos)();
// OD 08.09.2003 #i17567#, #108749#, #110354# - allow negative positions
// for fly frames anchor to paragraph/to character.
if ((_nAnchorId == FLY_AT_PARA) || (_nAnchorId == FLY_AT_CHAR))
{
// The rectangle, the fly frame can be positioned in, is determined
// horizontally by the frame area of the horizontal environment
// and vertically by the printing area of the vertical environment,
// if the object follows the text flow, or by the frame area of the
// vertical environment, if the object doesn't follow the text flow.
// OD 29.10.2003 #113049# - new class <SwEnvironmentOfAnchoredObject>
objectpositioning::SwEnvironmentOfAnchoredObject aEnvOfObj(
_bFollowTextFlow );
const SwLayoutFrm& rHoriEnvironLayFrm =
aEnvOfObj.GetHoriEnvironmentLayoutFrm( *pFrm );
const SwLayoutFrm& rVertEnvironLayFrm =
aEnvOfObj.GetVertEnvironmentLayoutFrm( *pFrm );
SwRect aHoriEnvironRect( rHoriEnvironLayFrm.Frm() );
SwRect aVertEnvironRect;
if ( _bFollowTextFlow )
{
aVertEnvironRect = rVertEnvironLayFrm.Prt();
aVertEnvironRect.Pos() += rVertEnvironLayFrm.Frm().Pos();
// OD 19.09.2003 #i18732# - adjust vertical 'virtual' anchor position
// (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned
// to page areas.
if ( _eVertRelOrient == text::RelOrientation::PAGE_FRAME || _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
{
// --> OD 2009-09-01 #mongolianlayout#
if ( bVert && !bVertL2R )
// <--
{
aPos.X() = aVertEnvironRect.Right();
}
// --> OD 2009-09-01 #mongolianlayout#
else if ( bVertL2R )
{
aPos.X() = aVertEnvironRect.Left();
}
else
{
aPos.Y() = aVertEnvironRect.Top();
}
}
}
else
{
ASSERT( rVertEnvironLayFrm.IsPageFrm(),
"<SwFEShell::CalcBoundRect(..)> - not following text flow, but vertical environment *not* page!" );
aVertEnvironRect = rVertEnvironLayFrm.Frm();
// OD 19.09.2003 #i18732# - adjustment vertical 'virtual' anchor position
// (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned
// to page areas.
if ( _eVertRelOrient == text::RelOrientation::PAGE_FRAME || _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
{
// --> OD 2009-09-01 #mongolianlayout#
if ( bVert && !bVertL2R )
// <--
{
aPos.X() = aVertEnvironRect.Right();
if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
{
aPos.X() -= rVertEnvironLayFrm.GetRightMargin();
}
}
// --> OD 2009-09-01 #mongolianlayout#
else if ( bVertL2R )
{
aPos.X() = aVertEnvironRect.Left();
if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
{
aPos.X() += rVertEnvironLayFrm.GetLeftMargin();
}
}
// <--
else
{
aPos.Y() = aVertEnvironRect.Top();
if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
{
aPos.Y() += rVertEnvironLayFrm.GetTopMargin();
// add height of page header
const SwFrm* pTmpFrm = rVertEnvironLayFrm.Lower();
if ( pTmpFrm->IsHeaderFrm() )
{
aPos.Y() += pTmpFrm->Frm().Height();
}
}
}
}
}
// OD 12.11.2003 #i22341# - adjust vertical 'virtual' anchor position
// (<aPos.Y()> respectively <aPos.X()>), if object is anchored to
// character and vertical aligned at character or top of line
// --> OD 2005-12-29 #125800#
// <pFrm>, which is the anchor frame or the proposed anchor frame,
// doesn't have to be a text frame (e.g. edit a to-page anchored
// fly frame). Thus, assure this.
const SwTxtFrm* pTxtFrm( dynamic_cast<const SwTxtFrm*>(pFrm) );
if ( pTxtFrm &&
(_nAnchorId == FLY_AT_CHAR) &&
( _eVertRelOrient == text::RelOrientation::CHAR ||
_eVertRelOrient == text::RelOrientation::TEXT_LINE ) )
{
SwTwips nTop = 0L;
if ( _eVertRelOrient == text::RelOrientation::CHAR )
{
SwRect aChRect;
if ( _pToCharCntntPos )
{
pTxtFrm->GetAutoPos( aChRect, *_pToCharCntntPos );
}
else
{
// No content position provided. Thus, use a default one.
SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) );
pTxtFrm->GetAutoPos( aChRect, aDefaultCntntPos );
}
nTop = (aChRect.*fnRect->fnGetBottom)();
}
else
{
if ( _pToCharCntntPos )
{
pTxtFrm->GetTopOfLine( nTop, *_pToCharCntntPos );
}
else
{
// No content position provided. Thus, use a default one.
SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) );
pTxtFrm->GetTopOfLine( nTop, aDefaultCntntPos );
}
}
// --> OD 2009-09-01 #mongolianlayout#
if ( bVert || bVertL2R )
{
aPos.X() = nTop;
}
// <--
else
{
aPos.Y() = nTop;
}
}
// --> OD 2004-10-05 #i26945# - adjust horizontal 'virtual' anchor
// position (<aPos.X()> respectively <aPos.Y()>), if object is
// anchored to character and horizontal aligned at character.
if ( pTxtFrm &&
(_nAnchorId == FLY_AT_CHAR) &&
_eHoriRelOrient == text::RelOrientation::CHAR )
{
SwTwips nLeft = 0L;
SwRect aChRect;
if ( _pToCharCntntPos )
{
pTxtFrm->GetAutoPos( aChRect, *_pToCharCntntPos );
}
else
{
// No content position provided. Thus, use a default one.
SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) );
pTxtFrm->GetAutoPos( aChRect, aDefaultCntntPos );
}
nLeft = (aChRect.*fnRect->fnGetLeft)();
// --> OD 2009-09-01 #mongolianlayout#
if ( bVert || bVertL2R )
{
aPos.Y() = nLeft;
}
// <--
else
{
aPos.X() = nLeft;
}
}
// <--
// --> OD 2009-09-01 #mongolianlayout#
if ( bVert || bVertL2R )
// <--
{
_orRect = SwRect( aVertEnvironRect.Left(),
aHoriEnvironRect.Top(),
aVertEnvironRect.Width(),
aHoriEnvironRect.Height() );
}
else
{
_orRect = SwRect( aHoriEnvironRect.Left(),
aVertEnvironRect.Top(),
aHoriEnvironRect.Width(),
aVertEnvironRect.Height() );
}
}
else
{
if( _opRef && pFly && pFly->IsFlyInCntFrm() )
*_opRef = ( (SwFlyInCntFrm*)pFly )->GetRefPoint();
_orRect = pUpper->Frm();
if( !pUpper->IsBodyFrm() )
{
_orRect += pUpper->Prt().Pos();
_orRect.SSize( pUpper->Prt().SSize() );
if ( pUpper->IsCellFrm() )//MA_FLY_HEIGHT
{
const SwFrm* pTab = pUpper->FindTabFrm();
long nBottom = (pTab->GetUpper()->*fnRect->fnGetPrtBottom)();
(_orRect.*fnRect->fnSetBottom)( nBottom );
}
}
// bei zeichengebundenen lieber nur 90% der Hoehe ausnutzen
{
// --> OD 2009-09-01 #mongolianlayout#
if( bVert || bVertL2R )
// <--
_orRect.Width( (_orRect.Width()*9)/10 );
else
_orRect.Height( (_orRect.Height()*9)/10 );
}
}
const SwTwips nBaseOfstForFly = ( pFrm->IsTxtFrm() && pFly ) ?
((SwTxtFrm*)pFrm)->GetBaseOfstForFly( !bWrapThrough ) :
0;
// --> OD 2009-09-01 #mongolianlayout#
if( bVert || bVertL2R )
// <--
{
// --> OD 2009-09-01 #mongolianlayout#
bVertic = bVert ? true : false;
bVerticalL2R = bVertL2R ? true : false;
// <--
_bMirror = false;
switch ( _eHoriRelOrient )
{
case text::RelOrientation::FRAME_RIGHT:
{
aPos.Y() += pFrm->Prt().Height();
aPos += (pFrm->Prt().*fnRect->fnGetPos)();
break;
}
case text::RelOrientation::PRINT_AREA:
{
aPos += (pFrm->Prt().*fnRect->fnGetPos)();
aPos.Y() += nBaseOfstForFly;
break;
}
case text::RelOrientation::PAGE_RIGHT:
{
aPos.Y() = pPage->Frm().Top() + pPage->Prt().Bottom();
break;
}
case text::RelOrientation::PAGE_PRINT_AREA:
{
aPos.Y() = pPage->Frm().Top() + pPage->Prt().Top();
break;
}
case text::RelOrientation::PAGE_LEFT:
case text::RelOrientation::PAGE_FRAME:
{
aPos.Y() = pPage->Frm().Top();
break;
}
case text::RelOrientation::FRAME:
{
aPos.Y() += nBaseOfstForFly;
break;
}
default: break;
}
}
else if( _bMirror )
{
switch ( _eHoriRelOrient )
{
case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Left(); break;
case text::RelOrientation::FRAME:
case text::RelOrientation::FRAME_LEFT: aPos.X() += pFrm->Frm().Width(); break;
case text::RelOrientation::PRINT_AREA: aPos.X() += pFrm->Prt().Right(); break;
case text::RelOrientation::PAGE_LEFT:
case text::RelOrientation::PAGE_FRAME: aPos.X() = pPage->Frm().Right(); break;
case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() = pPage->Frm().Left()
+ pPage->Prt().Left(); break;
default: break;
}
}
else if ( bRTL )
{
switch ( _eHoriRelOrient )
{
case text::RelOrientation::FRAME_LEFT:
aPos.X() = pFrm->Frm().Left() +
pFrm->Prt().Left();
break;
case text::RelOrientation::PRINT_AREA:
aPos.X() = pFrm->Frm().Left() + pFrm->Prt().Left() +
pFrm->Prt().Width();
aPos.X() += nBaseOfstForFly;
break;
case text::RelOrientation::PAGE_LEFT:
aPos.X() = pPage->Frm().Left() + pPage->Prt().Left();
break;
case text::RelOrientation::PAGE_PRINT_AREA:
aPos.X() = pPage->Frm().Left() + pPage->Prt().Left() +
pPage->Prt().Width() ;
break;
case text::RelOrientation::PAGE_RIGHT:
case text::RelOrientation::PAGE_FRAME:
aPos.X() = pPage->Frm().Right();
break;
case text::RelOrientation::FRAME:
aPos.X() += nBaseOfstForFly;
break;
default: break;
}
}
else
{
switch ( _eHoriRelOrient )
{
case text::RelOrientation::FRAME_RIGHT:
aPos.X() += pFrm->Prt().Width();
aPos += pFrm->Prt().Pos();
break;
case text::RelOrientation::PRINT_AREA:
aPos += pFrm->Prt().Pos();
aPos.X() += nBaseOfstForFly;
break;
case text::RelOrientation::PAGE_RIGHT:
aPos.X() = pPage->Frm().Left() + pPage->Prt().Right();
break;
case text::RelOrientation::PAGE_PRINT_AREA:
aPos.X() = pPage->Frm().Left() + pPage->Prt().Left();
break;
case text::RelOrientation::PAGE_LEFT:
case text::RelOrientation::PAGE_FRAME:
aPos.X() = pPage->Frm().Left();
break;
case text::RelOrientation::FRAME:
aPos.X() += nBaseOfstForFly;
break;
default: break;
}
}
}
if( !_opRef )
{
if( bVertic && !bVerticalL2R )
_orRect.Pos( aPos.X() - _orRect.Width() - _orRect.Left(), _orRect.Top() - aPos.Y() );
// --> OD 2009-09-01 #mongolianlayout#
else if( bVerticalL2R )
_orRect.Pos( _orRect.Left() - aPos.X(), _orRect.Top() - aPos.Y() );
// <--
else if ( bRTL )
_orRect.Pos( - ( _orRect.Right() - aPos.X() ), _orRect.Top() - aPos.Y() );
else
_orRect.Pos( _orRect.Left() - aPos.X(), _orRect.Top() - aPos.Y() );
if( _bMirror )
_orRect.Pos( -_orRect.Right(), _orRect.Top() );
}
}
Size SwFEShell::GetGraphicDefaultSize() const
{
Size aRet;
SwFlyFrm *pFly = FindFlyFrm();
if ( pFly )
{
// --> OD 2004-09-24 #i32951# - due to issue #i28701# no format of a
// newly inserted Writer fly frame or its anchor frame is performed
// any more. Thus, it could be possible (e.g. on insert of a horizontal
// line) that the anchor frame isn't formatted and its printing area
// size is (0,0). If this is the case the printing area of the upper
// of the anchor frame is taken.
const SwFrm* pAnchorFrm = pFly->GetAnchorFrm();
aRet = pAnchorFrm->Prt().SSize();
if ( aRet.Width() == 0 && aRet.Height() == 0 &&
pAnchorFrm->GetUpper() )
{
aRet = pAnchorFrm->GetUpper()->Prt().SSize();
}
// <--
SwRect aBound;
CalcBoundRect( aBound, pFly->GetFmt()->GetAnchor().GetAnchorId());
if ( pFly->GetAnchorFrm()->IsVertical() )
aRet.Width() = aBound.Width();
else
aRet.Height() = aBound.Height();
}
return aRet;
}
/* -----------------------------12.08.2002 12:51------------------------------
---------------------------------------------------------------------------*/
// --> OD 2009-08-31 #mongolianlayou#
// add output parameter <bVertL2R>
sal_Bool SwFEShell::IsFrmVertical(const sal_Bool bEnvironment, sal_Bool& bRTL, sal_Bool& bVertL2R) const
{
sal_Bool bVert = sal_False;
bRTL = sal_False;
bVertL2R = sal_False;
if ( Imp()->HasDrawView() )
{
const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
if( rMrkList.GetMarkCount() != 1 )
return bVert;
SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
// --> OD 2006-01-06 #123831# - make code robust:
if ( !pObj )
{
ASSERT( false,
"<SwFEShell::IsFrmVertical(..)> - missing SdrObject instance in marked object list -> This is a serious situation, please inform OD" );
return bVert;
}
// <--
// OD 2004-03-29 #i26791#
SwContact* pContact = static_cast<SwContact*>(GetUserCall( pObj ));
// --> OD 2006-01-06 #123831# - make code robust:
if ( !pContact )
{
ASSERT( false,
"<SwFEShell::IsFrmVertical(..)> - missing SwContact instance at marked object -> This is a serious situation, please inform OD" );
return bVert;
}
// <--
const SwFrm* pRef = pContact->GetAnchoredObj( pObj )->GetAnchorFrm();
// --> OD 2006-01-06 #123831# - make code robust:
if ( !pRef )
{
ASSERT( false,
"<SwFEShell::IsFrmVertical(..)> - missing anchor frame at marked object -> This is a serious situation, please inform OD" );
return bVert;
}
// <--
if ( pObj->ISA(SwVirtFlyDrawObj) && !bEnvironment )
pRef = static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm();
bVert = pRef->IsVertical();
bRTL = pRef->IsRightToLeft();
bVertL2R = pRef->IsVertLR();
}
return bVert;
}
// <--
void SwFEShell::MoveObjectIfActive( svt::EmbeddedObjectRef&, const Point& )
{
// does not do anything, only avoids crash if the method is used for wrong shell
}