xref: /AOO41X/main/sw/source/core/crsr/callnk.cxx (revision 69a743679e823ad8f875be547552acb607b8ada5)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <hintids.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
31cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptType.hdl>
32cdf0e10cSrcweir #endif
33cdf0e10cSrcweir #include <fmtcntnt.hxx>
34cdf0e10cSrcweir #include <txatbase.hxx>
35cdf0e10cSrcweir #include <frmatr.hxx>
36cdf0e10cSrcweir #include <viscrs.hxx>
37cdf0e10cSrcweir #include <callnk.hxx>
38cdf0e10cSrcweir #include <crsrsh.hxx>
39cdf0e10cSrcweir #include <doc.hxx>
40cdf0e10cSrcweir #include <frmfmt.hxx>
41cdf0e10cSrcweir #include <txtfrm.hxx>
42cdf0e10cSrcweir #include <ndtxt.hxx>
43cdf0e10cSrcweir #include <flyfrm.hxx>
44cdf0e10cSrcweir #include <breakit.hxx>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir 
SwCallLink(SwCrsrShell & rSh,sal_uLong nAktNode,xub_StrLen nAktCntnt,sal_uInt8 nAktNdTyp,long nLRPos,bool bAktSelection)47cdf0e10cSrcweir SwCallLink::SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt,
48cdf0e10cSrcweir 						sal_uInt8 nAktNdTyp, long nLRPos, bool bAktSelection )
49cdf0e10cSrcweir 	: rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
50cdf0e10cSrcweir       nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
51cdf0e10cSrcweir       bHasSelection( bAktSelection )
52cdf0e10cSrcweir {
53cdf0e10cSrcweir }
54cdf0e10cSrcweir 
55cdf0e10cSrcweir 
SwCallLink(SwCrsrShell & rSh)56cdf0e10cSrcweir SwCallLink::SwCallLink( SwCrsrShell & rSh )
57cdf0e10cSrcweir 	: rShell( rSh )
58cdf0e10cSrcweir {
59cdf0e10cSrcweir 	// SPoint-Werte vom aktuellen Cursor merken
60cdf0e10cSrcweir 	SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
61cdf0e10cSrcweir 	SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
62cdf0e10cSrcweir 	nNode = rNd.GetIndex();
63cdf0e10cSrcweir 	nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
64cdf0e10cSrcweir 	nNdTyp = rNd.GetNodeType();
65cdf0e10cSrcweir     bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
66cdf0e10cSrcweir 
67cdf0e10cSrcweir 	if( ND_TEXTNODE & nNdTyp )
68cdf0e10cSrcweir 		nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt,
69cdf0e10cSrcweir 											!rShell.ActionPend() );
70cdf0e10cSrcweir 	else
71cdf0e10cSrcweir 	{
72cdf0e10cSrcweir 		nLeftFrmPos = 0;
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 		// eine Sonderbehandlung fuer die SwFeShell: diese setzt beim Loeschen
75cdf0e10cSrcweir 		// der Kopf-/Fusszeile, Fussnoten den Cursor auf NULL (Node + Content)
76cdf0e10cSrcweir 		// steht der Cursor auf keinem CntntNode, wird sich das im NdType
77cdf0e10cSrcweir 		// gespeichert.
78cdf0e10cSrcweir 		if( ND_CONTENTNODE & nNdTyp )
79cdf0e10cSrcweir 			nNdTyp = 0;
80cdf0e10cSrcweir 	}
81cdf0e10cSrcweir }
82cdf0e10cSrcweir 
83cdf0e10cSrcweir 
~SwCallLink()84cdf0e10cSrcweir SwCallLink::~SwCallLink()
85cdf0e10cSrcweir {
86cdf0e10cSrcweir 	if( !nNdTyp || !rShell.bCallChgLnk )		// siehe ctor
87cdf0e10cSrcweir 		return ;
88cdf0e10cSrcweir 
89cdf0e10cSrcweir 	// wird ueber Nodes getravellt, Formate ueberpruefen und im neuen
90cdf0e10cSrcweir 	// Node wieder anmelden
91cdf0e10cSrcweir 	SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
92cdf0e10cSrcweir 	SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
93cdf0e10cSrcweir 	if( !pCNd )
94cdf0e10cSrcweir 		return;
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 	xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
97cdf0e10cSrcweir 	sal_uInt16 nNdWhich = pCNd->GetNodeType();
98cdf0e10cSrcweir 	sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
99cdf0e10cSrcweir 
100cdf0e10cSrcweir 	// melde die Shell beim akt. Node als abhaengig an, dadurch koennen
101cdf0e10cSrcweir 	// alle Attribut-Aenderungen ueber den Link weiter gemeldet werden.
102cdf0e10cSrcweir 	pCNd->Add( &rShell );
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 	if( nNdTyp != nNdWhich || nNode != nAktNode )
105cdf0e10cSrcweir 	{
106cdf0e10cSrcweir 		/* immer, wenn zwischen Nodes gesprungen wird, kann es
107cdf0e10cSrcweir 		 * vorkommen, das neue Attribute gelten; die Text-Attribute.
108cdf0e10cSrcweir 		 * Es muesste also festgestellt werden, welche Attribute
109cdf0e10cSrcweir 		 * jetzt gelten; das kann auch gleich der Handler machen
110cdf0e10cSrcweir 		 */
111cdf0e10cSrcweir 		rShell.CallChgLnk();
112cdf0e10cSrcweir 	}
113cdf0e10cSrcweir     else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
114cdf0e10cSrcweir     {
115cdf0e10cSrcweir         // always call change link when selection changes
116cdf0e10cSrcweir 		rShell.CallChgLnk();
117cdf0e10cSrcweir     }
118cdf0e10cSrcweir 	else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
119cdf0e10cSrcweir 			 nCntnt != nAktCntnt )
120cdf0e10cSrcweir 	{
121cdf0e10cSrcweir 		// nur wenn mit Left/right getravellt, dann Text-Hints pruefen
122cdf0e10cSrcweir 		// und sich nicht der Frame geaendert hat (Spalten!)
123cdf0e10cSrcweir 		if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt,
124cdf0e10cSrcweir 													!rShell.ActionPend() ) &&
125cdf0e10cSrcweir 			(( nCmp = nCntnt ) + 1 == nAktCntnt ||			// Right
126cdf0e10cSrcweir 			nCntnt -1 == ( nCmp = nAktCntnt )) )			// Left
127cdf0e10cSrcweir 		{
128cdf0e10cSrcweir 			if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & Sele
129cdf0e10cSrcweir 				++nCmp;
130cdf0e10cSrcweir 			if ( ((SwTxtNode*)pCNd)->HasHints() )
131cdf0e10cSrcweir 			{
132cdf0e10cSrcweir 
133cdf0e10cSrcweir 				const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
134cdf0e10cSrcweir 				sal_uInt16 n;
135cdf0e10cSrcweir 				xub_StrLen nStart;
136cdf0e10cSrcweir 				const xub_StrLen *pEnd;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir 				for( n = 0; n < rHts.Count(); n++ )
139cdf0e10cSrcweir 				{
140cdf0e10cSrcweir 					const SwTxtAttr* pHt = rHts[ n ];
141*69a74367SOliver-Rainer Wittmann 					pEnd = pHt->End();
142cdf0e10cSrcweir 					nStart = *pHt->GetStart();
143cdf0e10cSrcweir 
144cdf0e10cSrcweir 					// nur Start oder Start und Ende gleich, dann immer
145cdf0e10cSrcweir 					// beim Ueberlaufen von Start callen
146cdf0e10cSrcweir 					if( ( !pEnd || ( nStart == *pEnd ) ) &&
147cdf0e10cSrcweir 						( nStart == nCntnt || nStart == nAktCntnt) )
148cdf0e10cSrcweir 					{
149cdf0e10cSrcweir 						rShell.CallChgLnk();
150cdf0e10cSrcweir 						return;
151cdf0e10cSrcweir 					}
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 					// hat das Attribut einen Bereich und dieser nicht leer
154cdf0e10cSrcweir 					else if( pEnd && nStart < *pEnd &&
155cdf0e10cSrcweir 						// dann teste, ob ueber Start/Ende getravellt wurde
156cdf0e10cSrcweir 						( nStart == nCmp ||
157cdf0e10cSrcweir 							( pHt->DontExpand() ? nCmp == *pEnd-1
158cdf0e10cSrcweir 												: nCmp == *pEnd ) ))
159cdf0e10cSrcweir 					{
160cdf0e10cSrcweir 						rShell.CallChgLnk();
161cdf0e10cSrcweir 						return;
162cdf0e10cSrcweir 					}
163cdf0e10cSrcweir 					nStart = 0;
164cdf0e10cSrcweir 				}
165cdf0e10cSrcweir 			}
166cdf0e10cSrcweir 
167cdf0e10cSrcweir 			if( pBreakIt->GetBreakIter().is() )
168cdf0e10cSrcweir 			{
169cdf0e10cSrcweir 				const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
170cdf0e10cSrcweir 				if( !nCmp ||
171cdf0e10cSrcweir 					pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
172cdf0e10cSrcweir 					 != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
173cdf0e10cSrcweir 				{
174cdf0e10cSrcweir 					rShell.CallChgLnk();
175cdf0e10cSrcweir 					return;
176cdf0e10cSrcweir 				}
177cdf0e10cSrcweir 			}
178cdf0e10cSrcweir 		}
179cdf0e10cSrcweir 		else
180cdf0e10cSrcweir 			/* wenn mit Home/End/.. mehr als 1 Zeichen getravellt, dann
181cdf0e10cSrcweir 			 * immer den ChgLnk rufen, denn es kann hier nicht
182cdf0e10cSrcweir 			 * festgestellt werden, was sich geaendert; etwas kann
183cdf0e10cSrcweir 			 * veraendert sein.
184cdf0e10cSrcweir 			 */
185cdf0e10cSrcweir 			rShell.CallChgLnk();
186cdf0e10cSrcweir 	}
187cdf0e10cSrcweir 
188cdf0e10cSrcweir 	const SwFrm* pFrm;
189cdf0e10cSrcweir 	const SwFlyFrm *pFlyFrm;
190cdf0e10cSrcweir 	if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) &&
191cdf0e10cSrcweir 		0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
192cdf0e10cSrcweir 	{
193cdf0e10cSrcweir 		const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
194cdf0e10cSrcweir 		ASSERT( pIndex, "Fly ohne Cntnt" );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir 		if (!pIndex)
197cdf0e10cSrcweir 		    return;
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 		const SwNode& rStNd = pIndex->GetNode();
200cdf0e10cSrcweir 
201cdf0e10cSrcweir 		if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
202cdf0e10cSrcweir 			nNode > rStNd.EndOfSectionIndex() )
203cdf0e10cSrcweir 			rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
204cdf0e10cSrcweir 	}
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
getLayoutFrm(const SwRootFrm * pRoot,SwTxtNode & rNd,xub_StrLen nCntPos,sal_Bool bCalcFrm)207cdf0e10cSrcweir long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm )
208cdf0e10cSrcweir {
209cdf0e10cSrcweir 	SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm;
210cdf0e10cSrcweir 	if ( pFrm && !pFrm->IsHiddenNow() )
211cdf0e10cSrcweir 	{
212cdf0e10cSrcweir 		if( pFrm->HasFollow() )
213cdf0e10cSrcweir 			while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
214cdf0e10cSrcweir 					nCntPos >= pNext->GetOfst() )
215cdf0e10cSrcweir 				pFrm = pNext;
216cdf0e10cSrcweir 
217cdf0e10cSrcweir 		return pFrm->Frm().Left();
218cdf0e10cSrcweir 	}
219cdf0e10cSrcweir 	return 0;
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
222