1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
22 #include <com/sun/star/i18n/ScriptType.hpp>
23 #include <fmtcntnt.hxx>
24 #include <txatbase.hxx>
34 #include <fmtfsize.hxx>
37 #include <breakit.hxx>
39 #include<vcl/window.hxx>
42 SwCallLink::SwCallLink( SwCrsrShell
& rSh
, sal_uLong nAktNode
, xub_StrLen nAktCntnt
,
43 sal_uInt8 nAktNdTyp
, long nLRPos
, bool bAktSelection
)
44 : rShell( rSh
), nNode( nAktNode
), nCntnt( nAktCntnt
),
45 nNdTyp( nAktNdTyp
), nLeftFrmPos( nLRPos
),
46 bHasSelection( bAktSelection
)
51 SwCallLink::SwCallLink( SwCrsrShell
& rSh
)
54 // remember SPoint-values of current cursor
55 SwPaM
* pCrsr
= rShell
.IsTableMode() ? rShell
.GetTblCrs() : rShell
.GetCrsr();
56 SwNode
& rNd
= pCrsr
->GetPoint()->nNode
.GetNode();
57 nNode
= rNd
.GetIndex();
58 nCntnt
= pCrsr
->GetPoint()->nContent
.GetIndex();
59 nNdTyp
= rNd
.GetNodeType();
60 bHasSelection
= ( *pCrsr
->GetPoint() != *pCrsr
->GetMark() );
63 nLeftFrmPos
= SwCallLink::getLayoutFrm( rShell
.GetLayout(), (SwTxtNode
&)rNd
, nCntnt
,
64 !rShell
.ActionPend() );
69 // A special treatment for SwFeShell:
70 // When deleting the header/footer, footnotes SwFeShell sets the
71 // Cursor to NULL (Node + Content).
72 // If the Cursor is not on a CntntNode (ContentNode) this fact gets
74 if( ND_CONTENTNODE
& nNdTyp
)
79 static void lcl_notifyRow(const SwCntntNode
* pNode
, SwCrsrShell
& rShell
)
83 SwFrm
*myFrm
= pNode
->getLayoutFrm( rShell
.GetLayout() );
86 // We need to emulated a change of the row height in order
87 // to have the complete row redrawn
88 SwRowFrm
* pRow
= myFrm
->FindRowFrm();
91 const SwTableLine
* pLine
= pRow
->GetTabLine( );
92 // Avoid redrawing the complete row if there are no nested tables
93 bool bHasTable
= false;
94 SwFrm
*pCell
= pRow
->GetLower();
95 for (; pCell
&& !bHasTable
; pCell
= pCell
->GetNext())
97 SwFrm
*pContent
= pCell
->GetLower();
98 for (; pContent
&& !bHasTable
; pContent
= pContent
->GetNext())
99 if (pContent
->GetType() == FRM_TAB
)
104 SwFmtFrmSize pSize
= pLine
->GetFrmFmt()->GetFrmSize();
105 pRow
->ModifyNotification(NULL
, &pSize
);
112 SwCallLink::~SwCallLink()
114 if( !nNdTyp
|| !rShell
.bCallChgLnk
) // see ctor
117 // If travelling over Nodes check formats and register them anew at the
119 SwPaM
* pCurCrsr
= rShell
.IsTableMode() ? rShell
.GetTblCrs() : rShell
.GetCrsr();
120 SwCntntNode
* pCNd
= pCurCrsr
->GetCntntNode();
124 lcl_notifyRow(pCNd
, rShell
);
126 const SwDoc
*pDoc
=rShell
.GetDoc();
127 const SwCntntNode
*pNode
= NULL
;
128 if ( ( pDoc
!= NULL
&& nNode
< pDoc
->GetNodes( ).Count( ) ) )
130 pNode
= pDoc
->GetNodes()[nNode
]->GetCntntNode();
132 lcl_notifyRow(pNode
, rShell
);
134 xub_StrLen nCmp
, nAktCntnt
= pCurCrsr
->GetPoint()->nContent
.GetIndex();
135 sal_uInt16 nNdWhich
= pCNd
->GetNodeType();
136 sal_uLong nAktNode
= pCurCrsr
->GetPoint()->nNode
.GetIndex();
138 // Register the Shell as dependent at the current Node. By doing this all
139 // attribute changes can be signaled over the link.
140 pCNd
->Add( &rShell
);
142 if( nNdTyp
!= nNdWhich
|| nNode
!= nAktNode
)
144 // Every time a switch between nodes occurs, there is a chance that
145 // new attributes do apply - meaning text-attributes.
146 // So the currently applying attributes would have to be determined.
147 // That can be done in one go by the handler.
150 else if( !bHasSelection
!= !(*pCurCrsr
->GetPoint() != *pCurCrsr
->GetMark()) )
152 // always call change link when selection changes
155 else if( rShell
.aChgLnk
.IsSet() && ND_TEXTNODE
== nNdWhich
&&
156 nCntnt
!= nAktCntnt
)
158 // If travelling with left/right only and the frame is
159 // unchanged (columns!) then check text hints.
160 if( nLeftFrmPos
== SwCallLink::getLayoutFrm( rShell
.GetLayout(), (SwTxtNode
&)*pCNd
, nAktCntnt
,
161 !rShell
.ActionPend() ) &&
162 (( nCmp
= nCntnt
) + 1 == nAktCntnt
|| // Right
163 nCntnt
-1 == ( nCmp
= nAktCntnt
)) ) // Left
165 if( nCmp
== nAktCntnt
&& pCurCrsr
->HasMark() ) // left & select
167 if ( ((SwTxtNode
*)pCNd
)->HasHints() )
170 const SwpHints
&rHts
= ((SwTxtNode
*)pCNd
)->GetSwpHints();
173 const xub_StrLen
*pEnd
;
175 for( n
= 0; n
< rHts
.Count(); n
++ )
177 const SwTxtAttr
* pHt
= rHts
[ n
];
178 pEnd
= pHt
->GetEnd();
179 nStart
= *pHt
->GetStart();
181 // If "only start" or "start and end equal" then call on
182 // every overflow of start.
183 if( ( !pEnd
|| ( nStart
== *pEnd
) ) &&
184 ( nStart
== nCntnt
|| nStart
== nAktCntnt
) )
190 // If the attribute has an area and that area is not empty ...
191 else if( pEnd
&& nStart
< *pEnd
&&
192 // ... then test if travelling occurred via start/end.
194 ( pHt
->DontExpand() ? nCmp
== *pEnd
-1
204 if( pBreakIt
->GetBreakIter().is() )
206 const String
& rTxt
= ((SwTxtNode
*)pCNd
)->GetTxt();
208 pBreakIt
->GetBreakIter()->getScriptType( rTxt
, nCmp
)
209 != pBreakIt
->GetBreakIter()->getScriptType( rTxt
, nCmp
- 1 ))
217 // If travelling more than one character with home/end/.. then
218 // always call ChgLnk, because it can not be determined here what
219 // has changed. Something may have changed.
224 const SwFlyFrm
*pFlyFrm
;
225 if( !rShell
.ActionPend() && 0 != ( pFrm
= pCNd
->getLayoutFrm(rShell
.GetLayout(),0,0,sal_False
) ) &&
226 0 != ( pFlyFrm
= pFrm
->FindFlyFrm() ) && !rShell
.IsTableMode() )
228 const SwNodeIndex
* pIndex
= pFlyFrm
->GetFmt()->GetCntnt().GetCntntIdx();
229 OSL_ENSURE( pIndex
, "Fly without Cntnt" );
234 const SwNode
& rStNd
= pIndex
->GetNode();
236 if( rStNd
.EndOfSectionNode()->StartOfSectionIndex() > nNode
||
237 nNode
> rStNd
.EndOfSectionIndex() )
238 rShell
.GetFlyMacroLnk().Call( (void*)pFlyFrm
->GetFmt() );
242 long SwCallLink::getLayoutFrm( const SwRootFrm
* pRoot
, SwTxtNode
& rNd
, xub_StrLen nCntPos
, sal_Bool bCalcFrm
)
244 SwTxtFrm
* pFrm
= (SwTxtFrm
*)rNd
.getLayoutFrm(pRoot
,0,0,bCalcFrm
), *pNext
= pFrm
;
245 if ( pFrm
&& !pFrm
->IsHiddenNow() )
247 if( pFrm
->HasFollow() )
248 while( 0 != ( pNext
= (SwTxtFrm
*)pFrm
->GetFollow() ) &&
249 nCntPos
>= pNext
->GetOfst() )
252 return pFrm
->Frm().Left();
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */