summaryrefslogtreecommitdiff
path: root/sw/source/core/crsr/callnk.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/crsr/callnk.cxx')
-rw-r--r--sw/source/core/crsr/callnk.cxx221
1 files changed, 221 insertions, 0 deletions
diff --git a/sw/source/core/crsr/callnk.cxx b/sw/source/core/crsr/callnk.cxx
new file mode 100644
index 000000000000..bf06a19d83b0
--- /dev/null
+++ b/sw/source/core/crsr/callnk.cxx
@@ -0,0 +1,221 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
+#include <com/sun/star/i18n/ScriptType.hdl>
+#endif
+#include <fmtcntnt.hxx>
+#include <txatbase.hxx>
+#include <frmatr.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <breakit.hxx>
+
+
+SwCallLink::SwCallLink( SwCrsrShell & rSh, ULONG nAktNode, xub_StrLen nAktCntnt,
+ BYTE nAktNdTyp, long nLRPos, bool bAktSelection )
+ : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
+ nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
+ bHasSelection( bAktSelection )
+{
+}
+
+
+SwCallLink::SwCallLink( SwCrsrShell & rSh )
+ : rShell( rSh )
+{
+ // SPoint-Werte vom aktuellen Cursor merken
+ SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
+ SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
+ nNode = rNd.GetIndex();
+ nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
+ nNdTyp = rNd.GetNodeType();
+ bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
+
+ if( ND_TEXTNODE & nNdTyp )
+ nLeftFrmPos = SwCallLink::GetFrm( (SwTxtNode&)rNd, nCntnt,
+ !rShell.ActionPend() );
+ else
+ {
+ nLeftFrmPos = 0;
+
+ // eine Sonderbehandlung fuer die SwFeShell: diese setzt beim Loeschen
+ // der Kopf-/Fusszeile, Fussnoten den Cursor auf NULL (Node + Content)
+ // steht der Cursor auf keinem CntntNode, wird sich das im NdType
+ // gespeichert.
+ if( ND_CONTENTNODE & nNdTyp )
+ nNdTyp = 0;
+ }
+}
+
+
+SwCallLink::~SwCallLink()
+{
+ if( !nNdTyp || !rShell.bCallChgLnk ) // siehe ctor
+ return ;
+
+ // wird ueber Nodes getravellt, Formate ueberpruefen und im neuen
+ // Node wieder anmelden
+ SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
+ SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
+ if( !pCNd )
+ return;
+
+ xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
+ USHORT nNdWhich = pCNd->GetNodeType();
+ ULONG nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
+
+ // melde die Shell beim akt. Node als abhaengig an, dadurch koennen
+ // alle Attribut-Aenderungen ueber den Link weiter gemeldet werden.
+ pCNd->Add( &rShell );
+
+ if( nNdTyp != nNdWhich || nNode != nAktNode )
+ {
+ /* immer, wenn zwischen Nodes gesprungen wird, kann es
+ * vorkommen, das neue Attribute gelten; die Text-Attribute.
+ * Es muesste also festgestellt werden, welche Attribute
+ * jetzt gelten; das kann auch gleich der Handler machen
+ */
+ rShell.CallChgLnk();
+ }
+ else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
+ {
+ // always call change link when selection changes
+ rShell.CallChgLnk();
+ }
+ else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
+ nCntnt != nAktCntnt )
+ {
+ // nur wenn mit Left/right getravellt, dann Text-Hints pruefen
+ // und sich nicht der Frame geaendert hat (Spalten!)
+ if( nLeftFrmPos == SwCallLink::GetFrm( (SwTxtNode&)*pCNd, nAktCntnt,
+ !rShell.ActionPend() ) &&
+ (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
+ nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
+ {
+ if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & Sele
+ ++nCmp;
+ if ( ((SwTxtNode*)pCNd)->HasHints() )
+ {
+
+ const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
+ USHORT n;
+ xub_StrLen nStart;
+ const xub_StrLen *pEnd;
+
+ for( n = 0; n < rHts.Count(); n++ )
+ {
+ const SwTxtAttr* pHt = rHts[ n ];
+ pEnd = pHt->GetEnd();
+ nStart = *pHt->GetStart();
+
+ // nur Start oder Start und Ende gleich, dann immer
+ // beim Ueberlaufen von Start callen
+ if( ( !pEnd || ( nStart == *pEnd ) ) &&
+ ( nStart == nCntnt || nStart == nAktCntnt) )
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+
+ // hat das Attribut einen Bereich und dieser nicht leer
+ else if( pEnd && nStart < *pEnd &&
+ // dann teste, ob ueber Start/Ende getravellt wurde
+ ( nStart == nCmp ||
+ ( pHt->DontExpand() ? nCmp == *pEnd-1
+ : nCmp == *pEnd ) ))
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+ nStart = 0;
+ }
+ }
+
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
+ if( !nCmp ||
+ pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
+ != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+ }
+ }
+ else
+ /* wenn mit Home/End/.. mehr als 1 Zeichen getravellt, dann
+ * immer den ChgLnk rufen, denn es kann hier nicht
+ * festgestellt werden, was sich geaendert; etwas kann
+ * veraendert sein.
+ */
+ rShell.CallChgLnk();
+ }
+
+ const SwFrm* pFrm;
+ const SwFlyFrm *pFlyFrm;
+ if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->GetFrm(0,0,FALSE) ) &&
+ 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
+ {
+ const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
+ ASSERT( pIndex, "Fly ohne Cntnt" );
+ const SwNode& rStNd = pIndex->GetNode();
+
+ if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
+ nNode > rStNd.EndOfSectionIndex() )
+ rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
+ }
+}
+
+long SwCallLink::GetFrm( SwTxtNode& rNd, xub_StrLen nCntPos, BOOL bCalcFrm )
+{
+ SwTxtFrm* pFrm = (SwTxtFrm*)rNd.GetFrm(0,0,bCalcFrm), *pNext = pFrm;
+ if ( pFrm && !pFrm->IsHiddenNow() )
+ {
+ if( pFrm->HasFollow() )
+ while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
+ nCntPos >= pNext->GetOfst() )
+ pFrm = pNext;
+
+ return pFrm->Frm().Left();
+ }
+ return 0;
+}
+