merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / crsr / callnk.cxx
blob603e4f885cb4353f8e7e60a57ca1ac8c1c51d3fc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: callnk.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
37 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
38 #include <com/sun/star/i18n/ScriptType.hdl>
39 #endif
40 #include <fmtcntnt.hxx>
41 #include <txatbase.hxx>
42 #include <frmatr.hxx>
43 #include <viscrs.hxx>
44 #include <callnk.hxx>
45 #include <crsrsh.hxx>
46 #include <doc.hxx>
47 #include <frmfmt.hxx>
48 #include <txtfrm.hxx>
49 #include <tabfrm.hxx>
50 #include <rowfrm.hxx>
51 #include <fmtfsize.hxx>
52 #include <ndtxt.hxx>
53 #include <flyfrm.hxx>
54 #include <breakit.hxx>
56 #include<vcl/window.hxx>
59 SwCallLink::SwCallLink( SwCrsrShell & rSh, ULONG nAktNode, xub_StrLen nAktCntnt,
60 BYTE nAktNdTyp, long nLRPos, bool bAktSelection )
61 : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
62 nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
63 bHasSelection( bAktSelection )
68 SwCallLink::SwCallLink( SwCrsrShell & rSh )
69 : rShell( rSh )
71 // SPoint-Werte vom aktuellen Cursor merken
72 SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
73 SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
74 nNode = rNd.GetIndex();
75 nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
76 nNdTyp = rNd.GetNodeType();
77 bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
79 if( ND_TEXTNODE & nNdTyp )
80 nLeftFrmPos = SwCallLink::GetFrm( (SwTxtNode&)rNd, nCntnt,
81 !rShell.ActionPend() );
82 else
84 nLeftFrmPos = 0;
86 // eine Sonderbehandlung fuer die SwFeShell: diese setzt beim Loeschen
87 // der Kopf-/Fusszeile, Fussnoten den Cursor auf NULL (Node + Content)
88 // steht der Cursor auf keinem CntntNode, wird sich das im NdType
89 // gespeichert.
90 if( ND_CONTENTNODE & nNdTyp )
91 nNdTyp = 0;
96 SwCallLink::~SwCallLink()
98 if( !nNdTyp || !rShell.bCallChgLnk ) // siehe ctor
99 return ;
101 // wird ueber Nodes getravellt, Formate ueberpruefen und im neuen
102 // Node wieder anmelden
103 SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
104 SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
105 if( !pCNd )
106 return;
108 bool bUpdatedTable = false;
109 SwFrm *myFrm=pCNd->GetFrm();
110 if (myFrm!=NULL)
112 // We need to emulated a change of the row height in order
113 // to have the complete row redrawn
114 SwRowFrm* pRow = myFrm->FindRowFrm( );
115 if ( pRow )
117 const SwTableLine* pLine = pRow->GetTabLine( );
118 SwFmtFrmSize pSize = pLine->GetFrmFmt( )->GetFrmSize( );
119 pRow->Modify( NULL, &pSize );
121 bUpdatedTable = true;
125 const SwDoc *pDoc=rShell.GetDoc();
126 const SwCntntNode *pNode=(pDoc!=NULL?pDoc->GetNodes()[nNode]->GetCntntNode():NULL);
127 if ( pNode != NULL )
129 SwFrm *myFrm2=pNode->GetFrm();
130 if (myFrm2!=NULL)
132 // We need to emulated a change of the row height in order
133 // to have the complete row redrawn
134 SwRowFrm* pRow = myFrm2->FindRowFrm();
135 if ( pRow )
137 const SwTableLine* pLine = pRow->GetTabLine( );
138 SwFmtFrmSize pSize = pLine->GetFrmFmt( )->GetFrmSize( );
139 pRow->Modify( NULL, &pSize );
141 bUpdatedTable = true;
146 if ( bUpdatedTable )
147 rShell.GetWin( )->Invalidate( 0 );
149 xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
150 USHORT nNdWhich = pCNd->GetNodeType();
151 ULONG nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
153 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen
154 // alle Attribut-Aenderungen ueber den Link weiter gemeldet werden.
155 pCNd->Add( &rShell );
157 if( nNdTyp != nNdWhich || nNode != nAktNode )
159 /* immer, wenn zwischen Nodes gesprungen wird, kann es
160 * vorkommen, das neue Attribute gelten; die Text-Attribute.
161 * Es muesste also festgestellt werden, welche Attribute
162 * jetzt gelten; das kann auch gleich der Handler machen
164 rShell.CallChgLnk();
166 else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
168 // always call change link when selection changes
169 rShell.CallChgLnk();
171 else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
172 nCntnt != nAktCntnt )
174 // nur wenn mit Left/right getravellt, dann Text-Hints pruefen
175 // und sich nicht der Frame geaendert hat (Spalten!)
176 if( nLeftFrmPos == SwCallLink::GetFrm( (SwTxtNode&)*pCNd, nAktCntnt,
177 !rShell.ActionPend() ) &&
178 (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
179 nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
181 if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & Sele
182 ++nCmp;
183 if ( ((SwTxtNode*)pCNd)->HasHints() )
186 const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
187 USHORT n;
188 xub_StrLen nStart;
189 const xub_StrLen *pEnd;
191 for( n = 0; n < rHts.Count(); n++ )
193 const SwTxtAttr* pHt = rHts[ n ];
194 pEnd = pHt->GetEnd();
195 nStart = *pHt->GetStart();
197 // nur Start oder Start und Ende gleich, dann immer
198 // beim Ueberlaufen von Start callen
199 if( ( !pEnd || ( nStart == *pEnd ) ) &&
200 ( nStart == nCntnt || nStart == nAktCntnt) )
202 rShell.CallChgLnk();
203 return;
206 // hat das Attribut einen Bereich und dieser nicht leer
207 else if( pEnd && nStart < *pEnd &&
208 // dann teste, ob ueber Start/Ende getravellt wurde
209 ( nStart == nCmp ||
210 ( pHt->DontExpand() ? nCmp == *pEnd-1
211 : nCmp == *pEnd ) ))
213 rShell.CallChgLnk();
214 return;
216 nStart = 0;
220 if( pBreakIt->GetBreakIter().is() )
222 const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
223 if( !nCmp ||
224 pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
225 != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
227 rShell.CallChgLnk();
228 return;
232 else
233 /* wenn mit Home/End/.. mehr als 1 Zeichen getravellt, dann
234 * immer den ChgLnk rufen, denn es kann hier nicht
235 * festgestellt werden, was sich geaendert; etwas kann
236 * veraendert sein.
238 rShell.CallChgLnk();
241 const SwFrm* pFrm;
242 const SwFlyFrm *pFlyFrm;
243 if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->GetFrm(0,0,FALSE) ) &&
244 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
246 const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
247 ASSERT( pIndex, "Fly ohne Cntnt" );
248 const SwNode& rStNd = pIndex->GetNode();
250 if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
251 nNode > rStNd.EndOfSectionIndex() )
252 rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
256 long SwCallLink::GetFrm( SwTxtNode& rNd, xub_StrLen nCntPos, BOOL bCalcFrm )
258 SwTxtFrm* pFrm = (SwTxtFrm*)rNd.GetFrm(0,0,bCalcFrm), *pNext = pFrm;
259 if ( pFrm && !pFrm->IsHiddenNow() )
261 if( pFrm->HasFollow() )
262 while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
263 nCntPos >= pNext->GetOfst() )
264 pFrm = pNext;
266 return pFrm->Frm().Left();
268 return 0;