diff options
Diffstat (limited to 'sw/source/core/layout/dbg_lay.cxx')
-rw-r--r-- | sw/source/core/layout/dbg_lay.cxx | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/sw/source/core/layout/dbg_lay.cxx b/sw/source/core/layout/dbg_lay.cxx new file mode 100644 index 000000000000..82bce24fc8ee --- /dev/null +++ b/sw/source/core/layout/dbg_lay.cxx @@ -0,0 +1,869 @@ +/************************************************************************* + * + * 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" + +#ifdef DBG_UTIL + +/* -----------------08.01.99 14:55------------------- + * Und hier die Beschreibung: + * + * Durch die PROTOCOL-Makros wird es ermoeglicht, Ereignisse im Frame-Methoden zu protokollieren. + * In protokollwuerdigen Stellen in Frame-Methoden muss entweder ein PROTOCOL(...) oder bei Methoden, + * bei denen auch das Verlassen der Methode mitprotokolliert werden soll, ein PROTOCOL_ENTER(...)-Makro + * stehen. + * Die Parameter der PROTOCOL-Makros sind + * 1. Ein Pointer auf einen SwFrm, also meist "this" oder "rThis" + * 2. Die Funktionsgruppe z.B. PROT_MAKEALL, hierueber wird (inline) entschieden, ob dies + * zur Zeit protokolliert werden soll oder nicht. + * 3. Die Aktion, im Normalfall 0, aber z.B. ein ACT_START bewirkt eine Einrueckung in der + * Ausgabedatei, ein ACT_END nimmt dies wieder zurueck. Auf diese Art wird z.B. durch + * PROTOCOL_ENTER am Anfang einer Methode eingerueckt und beim Verlassen wieder zurueck. + * 4. Der vierte Parameter ist ein void-Pointer, damit man irgendetwas uebergeben kann, + * was in das Protokoll einfliessen kann, typesches Beispiel bei PROT_GROW muss man + * einen Pointer auf den Wert, um den gegrowt werden soll, uebergeben. + * + * + * Das Protokoll ist die Datei "dbg_lay.out" im aktuellen (BIN-)Verzeichnis. + * Es enthaelt Zeilen mit FrmId, Funktionsgruppe sowie weiteren Infos. + * + * Was genau protokolliert wird, kann auf folgende Arten eingestellt werden: + * 1. Die statische Variable SwProtokoll::nRecord enthaelt die Funktionsgruppen, + * die aufgezeichnet werden sollen. + * Ein Wert von z.B. PROT_GROW bewirkt, das Aufrufe von SwFrm::Grow dokumentiert werden, + * PROT_MAKEALL protokolliert Aufrufe von xxx::MakeAll. + * Die PROT_XY-Werte koennen oderiert werden. + * Default ist Null, es wird keine Methode aufgezeichnet. + * 2. In der SwImplProtocol-Klasse gibt es einen Filter fuer Frame-Typen, + * nur die Methodenaufrufe von Frame-Typen, die dort gesetzt sind, werden protokolliert. + * Der Member nTypes kann auf Werte wie FRM_PAGE, FRM_SECTION gesetzt und oderiert werden. + * Default ist 0xFFFF, d.h. alle Frame-Typen. + * 3. In der SwImplProtocol-Klasse gibt es einen ArrayPointer auf FrmIds, die zu ueberwachen sind. + * Ist der Pointer Null, so werden alle Frames protokolliert, ansonsten nur Frames, + * die in dem Array vermerkt sind. + * + * Eine Aufzeichnung in Gang zu setzen, erfordert entweder Codemanipulation, z.B. in + * SwProtocol::Init() einen anderen Default fuer nRecord setzen oder Debuggermanipulation. + * Im Debugger gibt verschiedene, sich anbietende Stellen: + * 1. In SwProtocol::Init() einen Breakpoint setzen und dort nRecord manipulieren, ggf. + * FrmIds eintragen, dann beginnt die Aufzeichnung bereits beim Programmstart. + * 2. Waehrend des Programmlaufs einen Breakpoint vor irgendein PROTOCOL oder PROTOCOL_ENTER- + * Makro setzen, dann am SwProtocol::nRecord das unterste Bit setzen (PROT_INIT). Dies + * bewirkt, dass die Funktionsgruppe des folgenden Makros aktiviert und in Zukunft + * protokolliert wird. + * 3. Spezialfall von 2.: Wenn man 2. in der Methode SwRootFrm::Paint(..) anwendet, werden + * die Aufzeichnungseinstellung aus der Datei "dbg_lay.ini" ausgelesen! + * In dieser INI-Datei kann es Kommentarzeilen geben, diese beginnen mit '#', dann + * sind die Sektionen "[frmid]", "[frmtype]" und "[record]" relevant. + * Nach [frmid] koennen die FrameIds der zu protokollierenden Frames folgen. Gibt es + * dort keine Eintraege, werden alle Frames aufgezeichnet. + * Nach [frmtype] koennen FrameTypen folgen, die aufgezeichnet werden sollen, da der + * Default hier allerdings USHRT_MAX ist, werden sowieso alle aufgezeichnet. Man kann + * allerdings auch Typen entfernen, in dem man ein '!' vor den Wert setzt, z.B. + * !0xC000 nimmt die SwCntntFrms aus der Aufzeichnung heraus. + * Nach [record] folgen die Funktionsgruppen, die aufgezeichnet werden sollen, Default + * ist hier 0, also keine. Auch hier kann man mit einem vorgestellten '!' Funktionen + * wieder entfernen. + * Hier mal ein Beispiel fuer eine INI-Datei: + * ------------------------------------------ + * #Funktionen: Alle, ausser PRTAREA + * [record] 0xFFFFFFE !0x200 + * [frmid] + * #folgende FrmIds: + * 1 2 12 13 14 15 + * #keine Layoutframes ausser ColumnFrms + * [frmtype] !0x3FFF 0x4 + * ------------------------------------------ + * + * Wenn die Aufzeichnung erstmal laeuft, kann man in SwImplProtocol::_Record(...) mittels + * Debugger vielfaeltige Manipulationen vornehmen, z.B. bezueglich FrameTypen oder FrmIds. + * + * --------------------------------------------------*/ + +#ifndef DBG_UTIL +#error Wer fummelt denn an den makefiles rum? +#endif + + + +#include "dbg_lay.hxx" +#include <tools/stream.hxx> + +#ifndef _SVSTDARR_HXX +#define _SVSTDARR_USHORTS +#define _SVSTDARR_USHORTSSORT +#define _SVSTDARR_LONGS +#include <svl/svstdarr.hxx> +#endif + +#include <stdio.h> + +#include "frame.hxx" +#include "layfrm.hxx" +#include "flyfrm.hxx" +#include "txtfrm.hxx" +#include "ndtxt.hxx" +#include "dflyobj.hxx" +#include <fntcache.hxx> +// OD 2004-05-24 #i28701# +#include <sortedobjs.hxx> + +sal_uLong SwProtocol::nRecord = 0; +SwImplProtocol* SwProtocol::pImpl = NULL; + +sal_uLong lcl_GetFrameId( const SwFrm* pFrm ) +{ +#ifdef DBG_UTIL + static sal_Bool bFrameId = sal_False; + if( bFrameId ) + return pFrm->GetFrmId(); +#endif + if( pFrm && pFrm->IsTxtFrm() ) + return ((SwTxtFrm*)pFrm)->GetTxtNode()->GetIndex(); + return 0; +} + +class SwImplProtocol +{ + SvFileStream *pStream; // Ausgabestream + SvUShortsSort *pFrmIds; // welche FrmIds sollen aufgezeichnet werden ( NULL == alle ) + SvLongs *pVar; // Variables + ByteString aLayer; // Einrueckung der Ausgabe (" " pro Start/End) + sal_uInt16 nTypes; // welche Typen sollen aufgezeichnet werden + sal_uInt16 nLineCount; // Ausgegebene Zeilen + sal_uInt16 nMaxLines; // Maximal auszugebende Zeilen + sal_uInt8 nInitFile; // Bereich (FrmId,FrmType,Record) beim Einlesen der INI-Datei + sal_uInt8 nTestMode; // Special fuer Testformatierung, es wird ggf. nur + // innerhalb einer Testformatierung aufgezeichnet. + void _Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ); + sal_Bool NewStream(); + void CheckLine( ByteString& rLine ); + void SectFunc( ByteString &rOut, const SwFrm* pFrm, sal_uLong nAct, void* pParam ); +public: + SwImplProtocol(); + ~SwImplProtocol(); + // Aufzeichnen + void Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ) + { if( pStream ) _Record( pFrm, nFunction, nAct, pParam ); } + sal_Bool InsertFrm( sal_uInt16 nFrmId ); // FrmId aufnehmen zum Aufzeichnen + sal_Bool DeleteFrm( sal_uInt16 nFrmId ); // FrmId entfernen, diesen nicht mehr Aufzeichnen + void FileInit(); // Auslesen der INI-Datei + void ChkStream() { if( !pStream ) NewStream(); } + void SnapShot( const SwFrm* pFrm, sal_uLong nFlags ); + void GetVar( const sal_uInt16 nNo, long& rVar ) + { if( pVar && nNo < pVar->Count() ) rVar = (*pVar)[ nNo ]; } +}; + +/* -----------------11.01.99 10:43------------------- + * Durch das PROTOCOL_ENTER-Makro wird ein SwEnterLeave-Objekt erzeugt, + * wenn die aktuelle Funktion aufgezeichnet werden soll, wird ein + * SwImplEnterLeave-Objekt angelegt. Der Witz dabei ist, das der Ctor + * des Impl-Objekt am Anfang der Funktion und automatisch der Dtor beim + * Verlassen der Funktion gerufen wird. In der Basis-Implementierung ruft + * der Ctor lediglich ein PROTOCOL(..) mit ACT_START und im Dtor ein + * PROTOCOL(..) mit ACT_END. + * Es lassen sich Ableitungen der Klasse bilden, um z.B. beim Verlassen + * einer Funktion Groessenaenderungen des Frames zu dokumentieren u.v.a.m. + * Dazu braucht dann nur noch in SwEnterLeave::Ctor(...) die gewuenschte + * SwImplEnterLeave-Klasse angelegt zu werden. + * + * --------------------------------------------------*/ + +class SwImplEnterLeave +{ +protected: + const SwFrm* pFrm; // Der Frame, + sal_uLong nFunction, nAction; // die Funktion, ggf. die Aktion + void* pParam; // und weitere Parameter +public: + SwImplEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) + : pFrm( pF ), nFunction( nFunct ), nAction( nAct ), pParam( pPar ) {} + virtual void Enter(); // Ausgabe beim Eintritt + virtual void Leave(); // Ausgabe beim Verlassen +}; + +class SwSizeEnterLeave : public SwImplEnterLeave +{ + long nFrmHeight; +public: + SwSizeEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) + : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmHeight( pF->Frm().Height() ) {} + virtual void Leave(); // Ausgabe der Groessenaenderung +}; + +class SwUpperEnterLeave : public SwImplEnterLeave +{ + sal_uInt16 nFrmId; +public: + SwUpperEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) + : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmId( 0 ) {} + virtual void Enter(); // Ausgabe + virtual void Leave(); // Ausgabe der FrmId des Uppers +}; + +class SwFrmChangesLeave : public SwImplEnterLeave +{ + SwRect aFrm; +public: + SwFrmChangesLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) + : SwImplEnterLeave( pF, nFunct, nAct, pPar ), aFrm( pF->Frm() ) {} + virtual void Enter(); // keine Ausgabe + virtual void Leave(); // Ausgabe bei Aenderung der Frm-Area +}; + +void SwProtocol::Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ) +{ + if( Start() ) + { // Hier landen wir, wenn im Debugger SwProtocol::nRecord mit PROT_INIT(0x1) oderiert wurde + sal_Bool bFinit = sal_False; // Dies bietet im Debugger die Moeglichkeit, + if( bFinit ) // die Aufzeichnung dieser Action zu beenden + { + nRecord &= ~nFunction; // Diese Funktion nicht mehr aufzeichnen + nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen + return; + } + nRecord |= nFunction; // Aufzeichnung dieser Funktion freischalten + nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen + if( pImpl ) + pImpl->ChkStream(); + } + if( !pImpl ) // Impl-Object anlegen, wenn noetig + pImpl = new SwImplProtocol(); + pImpl->Record( pFrm, nFunction, nAct, pParam ); // ...und Aufzeichnen +} + +// Die folgende Funktion wird beim Anziehen der Writer-DLL durch TxtInit(..) aufgerufen +// und ermoeglicht dem Debuggenden Funktionen und/oder FrmIds freizuschalten + +void SwProtocol::Init() +{ + nRecord = 0; + XubString aName( "dbg_lay.go", RTL_TEXTENCODING_MS_1252 ); + SvFileStream aStream( aName, STREAM_READ ); + if( aStream.IsOpen() ) + { + pImpl = new SwImplProtocol(); + pImpl->FileInit(); + } + aStream.Close(); +} + +// Ende der Aufzeichnung + +void SwProtocol::Stop() +{ + if( pImpl ) + { + delete pImpl; + pImpl = NULL; + if( pFntCache ) + pFntCache->Flush(); + } + nRecord = 0; +} + +// Creates a more or less detailed snapshot of the layout structur + +void SwProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags ) +{ + if( pImpl ) + pImpl->SnapShot( pFrm, nFlags ); +} + +void SwProtocol::GetVar( const sal_uInt16 nNo, long& rVar ) +{ + if( pImpl ) + pImpl->GetVar( nNo, rVar ); +} + +SwImplProtocol::SwImplProtocol() + : pStream( NULL ), pFrmIds( NULL ), pVar( NULL ), nTypes( 0xffff ), + nLineCount( 0 ), nMaxLines( USHRT_MAX ), nTestMode( 0 ) +{ + NewStream(); +} + +sal_Bool SwImplProtocol::NewStream() +{ + XubString aName( "dbg_lay.out", RTL_TEXTENCODING_MS_1252 ); + nLineCount = 0; + pStream = new SvFileStream( aName, STREAM_WRITE | STREAM_TRUNC ); + if( pStream->GetError() ) + { + delete pStream; + pStream = NULL; + } + return 0 != pStream; +} + +SwImplProtocol::~SwImplProtocol() +{ + if( pStream ) + { + pStream->Close(); + delete pStream; + } + delete pFrmIds; + delete pVar; +} + +/* -----------------11.01.99 11:03------------------- + * SwImplProtocol::CheckLine analysiert eine Zeile der INI-Datei + * --------------------------------------------------*/ + +void SwImplProtocol::CheckLine( ByteString& rLine ) +{ + rLine = rLine.ToLowerAscii(); // Gross/Kleinschreibung ist einerlei + while( STRING_LEN > rLine.SearchAndReplace( '\t', ' ' ) ) + ; //nothing // Tabs werden durch Blanks ersetzt + if( '#' == rLine.GetChar(0) ) // Kommentarzeilen beginnen mit '#' + return; + if( '[' == rLine.GetChar(0) ) // Bereiche: FrmIds, Typen oder Funktionen + { + ByteString aTmp = rLine.GetToken( 0, ']' ); + if( "[frmid" == aTmp ) // Bereich FrmIds + { + nInitFile = 1; + delete pFrmIds; + pFrmIds = NULL; // Default: Alle Frames aufzeichnen + } + else if( "[frmtype" == aTmp )// Bereich Typen + { + nInitFile = 2; + nTypes = USHRT_MAX; // Default: Alle FrmaeTypen aufzeichnen + } + else if( "[record" == aTmp )// Bereich Funktionen + { + nInitFile = 3; + SwProtocol::SetRecord( 0 );// Default: Keine Funktion wird aufgezeichnet + } + else if( "[test" == aTmp )// Bereich Funktionen + { + nInitFile = 4; // Default: + nTestMode = 0; // Ausserhalb der Testformatierung wird aufgezeichnet + } + else if( "[max" == aTmp )// maximale Zeilenzahl + { + nInitFile = 5; // Default: + nMaxLines = USHRT_MAX; + } + else if( "[var" == aTmp )// variables + { + nInitFile = 6; + if( !pVar ) + pVar = new SvLongs( 5, 5 ); + } + else + nInitFile = 0; // Nanu: Unbekannter Bereich? + rLine.Erase( 0, aTmp.Len() + 1 ); + } + sal_uInt16 nToks = rLine.GetTokenCount( ' ' ); // Blanks (oder Tabs) sind die Trenner + for( sal_uInt16 i=0; i < nToks; ++i ) + { + ByteString aTok = rLine.GetToken( i, ' ' ); + sal_Bool bNo = sal_False; + if( '!' == aTok.GetChar(0) ) + { + bNo = sal_True; // Diese(n) Funktion/Typ entfernen + aTok.Erase( 0, 1 ); + } + if( aTok.Len() ) + { + sal_uLong nVal; + sscanf( aTok.GetBuffer(), "%li", &nVal ); + switch ( nInitFile ) + { + case 1: InsertFrm( sal_uInt16( nVal ) ); // FrmId aufnehmen + break; + case 2: { + sal_uInt16 nNew = (sal_uInt16)nVal; + if( bNo ) + nTypes &= ~nNew; // Typ entfernen + else + nTypes |= nNew; // Typ aufnehmen + } + break; + case 3: { + sal_uLong nOld = SwProtocol::Record(); + if( bNo ) + nOld &= ~nVal; // Funktion entfernen + else + nOld |= nVal; // Funktion aufnehmen + SwProtocol::SetRecord( nOld ); + } + break; + case 4: { + sal_uInt8 nNew = (sal_uInt8)nVal; + if( bNo ) + nTestMode &= ~nNew; // TestMode zuruecksetzen + else + nTestMode |= nNew; // TestMode setzen + } + break; + case 5: nMaxLines = (sal_uInt16)nVal; + break; + case 6: pVar->Insert( (long)nVal, pVar->Count() ); + break; + } + } + } +} + +/* -----------------11.01.99 11:17------------------- + * SwImplProtocol::FileInit() liest die Datei "dbg_lay.ini" + * im aktuellen Verzeichnis und wertet sie aus. + * --------------------------------------------------*/ +void SwImplProtocol::FileInit() +{ + XubString aName( "dbg_lay.ini", RTL_TEXTENCODING_MS_1252 ); + SvFileStream aStream( aName, STREAM_READ ); + if( aStream.IsOpen() ) + { + ByteString aLine; + nInitFile = 0; + while( !aStream.IsEof() ) + { + sal_Char c; + aStream >> c; + if( '\n' == c || '\r' == c ) // Zeilenende + { + aLine.EraseLeadingChars(); + aLine.EraseTrailingChars(); + if( aLine.Len() ) + CheckLine( aLine ); // Zeile auswerten + aLine.Erase(); + } + else + aLine += c; + } + if( aLine.Len() ) + CheckLine( aLine ); // letzte Zeile auswerten + } + aStream.Close(); +} + +/* -----------------11.01.99 11:20------------------- + * lcl_Start sorgt fuer Einrueckung um zwei Blanks bei ACT_START + * und nimmt diese bei ACT_END wieder zurueck. + * --------------------------------------------------*/ +void lcl_Start( ByteString& rOut, ByteString& rLay, sal_uLong nAction ) +{ + if( nAction == ACT_START ) + { + rLay += " "; + rOut += " On"; + } + else if( nAction == ACT_END ) + { + if( rLay.Len() > 1 ) + { + rLay.Erase( rLay.Len() - 2 ); + rOut.Erase( 0, 2 ); + } + rOut += " Off"; + } +} + +/* -----------------11.01.99 11:21------------------- + * lcl_Flags gibt das ValidSize-, ValidPos- und ValidPrtArea-Flag ("Sz","Ps","PA") + * des Frames aus, "+" fuer valid, "-" fuer invalid. + * --------------------------------------------------*/ + +void lcl_Flags( ByteString& rOut, const SwFrm* pFrm ) +{ + rOut += " Sz"; + rOut += pFrm->GetValidSizeFlag() ? '+' : '-'; + rOut += " Ps"; + rOut += pFrm->GetValidPosFlag() ? '+' : '-'; + rOut += " PA"; + rOut += pFrm->GetValidPrtAreaFlag() ? '+' : '-'; +} + +/* -----------------11.01.99 11:23------------------- + * lcl_FrameType gibt den Typ des Frames in Klartext aus. + * --------------------------------------------------*/ + +void lcl_FrameType( ByteString& rOut, const SwFrm* pFrm ) +{ + if( pFrm->IsTxtFrm() ) + rOut += "Txt "; + else if( pFrm->IsLayoutFrm() ) + { + if( pFrm->IsPageFrm() ) + rOut += "Page "; + else if( pFrm->IsColumnFrm() ) + rOut += "Col "; + else if( pFrm->IsBodyFrm() ) + { + if( pFrm->GetUpper() && pFrm->IsColBodyFrm() ) + rOut += "(Col)"; + rOut += "Body "; + } + else if( pFrm->IsRootFrm() ) + rOut += "Root "; + else if( pFrm->IsCellFrm() ) + rOut += "Cell "; + else if( pFrm->IsTabFrm() ) + rOut += "Tab "; + else if( pFrm->IsRowFrm() ) + rOut += "Row "; + else if( pFrm->IsSctFrm() ) + rOut += "Sect "; + else if( pFrm->IsHeaderFrm() ) + rOut += "Header "; + else if( pFrm->IsFooterFrm() ) + rOut += "Footer "; + else if( pFrm->IsFtnFrm() ) + rOut += "Ftn "; + else if( pFrm->IsFtnContFrm() ) + rOut += "FtnCont "; + else if( pFrm->IsFlyFrm() ) + rOut += "Fly "; + else + rOut += "Layout "; + } + else if( pFrm->IsNoTxtFrm() ) + rOut += "NoTxt "; + else + rOut += "Not impl. "; +} + +/* -----------------11.01.99 11:25------------------- + * SwImplProtocol::Record(..) wird nur gerufen, wenn das PROTOCOL-Makro + * feststellt, dass die Funktion aufgezeichnet werden soll ( SwProtocol::nRecord ). + * In dieser Methode werden noch die beiden weiteren Einschraenkungen ueberprueft, + * ob die FrmId und der FrameType zu den aufzuzeichnenden gehoeren. + * --------------------------------------------------*/ + +void SwImplProtocol::_Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ) +{ + sal_uInt16 nSpecial = 0; + if( nSpecial ) // Debugger-Manipulationsmoeglichkeit + { + sal_uInt16 nId = sal_uInt16(lcl_GetFrameId( pFrm )); + switch ( nSpecial ) + { + case 1: InsertFrm( nId ); break; + case 2: DeleteFrm( nId ); break; + case 3: delete pFrmIds; pFrmIds = NULL; break; + case 4: delete pStream; pStream = NULL; break; + } + return; + } + if( !pStream && !NewStream() ) + return; // Immer noch kein Stream + + if( pFrmIds && !pFrmIds->Seek_Entry( sal_uInt16(lcl_GetFrameId( pFrm )) ) ) + return; // gehoert nicht zu den gewuenschten FrmIds + + if( !(pFrm->GetType() & nTypes) ) + return; // Der Typ ist unerwuenscht + + if( 1 == nTestMode && nFunction != PROT_TESTFORMAT ) + return; // Wir sollen nur innerhalb einer Testformatierung aufzeichnen + sal_Bool bTmp = sal_False; + ByteString aOut = aLayer; + aOut += ByteString::CreateFromInt64( lcl_GetFrameId( pFrm ) ); + aOut += ' '; + lcl_FrameType( aOut, pFrm ); // dann den FrameType + switch ( nFunction ) // und die Funktion + { + case PROT_SNAPSHOT: lcl_Flags( aOut, pFrm ); + break; + case PROT_MAKEALL: aOut += "MakeAll"; + lcl_Start( aOut, aLayer, nAct ); + if( nAct == ACT_START ) + lcl_Flags( aOut, pFrm ); + break; + case PROT_MOVE_FWD: bTmp = sal_True; // NoBreak + case PROT_MOVE_BWD: aOut += ( nFunction == bTmp ) ? "Fwd" : "Bwd"; + lcl_Start( aOut, aLayer, nAct ); + if( pParam ) + { + aOut += ' '; + aOut += ByteString::CreateFromInt32( *((sal_uInt16*)pParam) ); + } + break; + case PROT_GROW_TST: if( ACT_START != nAct ) + return; + aOut += "TestGrow"; + break; + case PROT_SHRINK_TST: if( ACT_START != nAct ) + return; + aOut += "TestShrink"; + break; + case PROT_ADJUSTN : + case PROT_SHRINK: bTmp = sal_True; // NoBreak + case PROT_GROW: aOut += !bTmp ? "Grow" : + ( nFunction == PROT_SHRINK ? "Shrink" : "AdjustNgbhd" ); + lcl_Start( aOut, aLayer, nAct ); + if( pParam ) + { + aOut += ' '; + aOut += ByteString::CreateFromInt64( *((long*)pParam) ); + } + break; + case PROT_POS: break; + case PROT_PRTAREA: aOut += "PrtArea"; + lcl_Start( aOut, aLayer, nAct ); + break; + case PROT_SIZE: aOut += "Size"; + lcl_Start( aOut, aLayer, nAct ); + aOut += ' '; + aOut += ByteString::CreateFromInt64( pFrm->Frm().Height() ); + break; + case PROT_LEAF: aOut += "Prev/NextLeaf"; + lcl_Start( aOut, aLayer, nAct ); + aOut += ' '; + if( pParam ) + { + aOut += ' '; + aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); + } + break; + case PROT_FILE_INIT: FileInit(); + aOut = "Initialize"; + break; + case PROT_SECTION: SectFunc( aOut, pFrm, nAct, pParam ); + break; + case PROT_CUT: bTmp = sal_True; // NoBreak + case PROT_PASTE: aOut += bTmp ? "Cut from " : "Paste to "; + aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); + break; + case PROT_TESTFORMAT: aOut += "Test"; + lcl_Start( aOut, aLayer, nAct ); + if( ACT_START == nAct ) + nTestMode |= 2; + else + nTestMode &= ~2; + break; + case PROT_FRMCHANGES: + { + SwRect& rFrm = *((SwRect*)pParam); + if( pFrm->Frm().Pos() != rFrm.Pos() ) + { + aOut += "PosChg: ("; + aOut += ByteString::CreateFromInt64(rFrm.Left()); + aOut += ", "; + aOut += ByteString::CreateFromInt64(rFrm.Top()); + aOut += ") ("; + aOut += ByteString::CreateFromInt64(pFrm->Frm().Left()); + aOut += ", "; + aOut += ByteString::CreateFromInt64(pFrm->Frm().Top()); + aOut += ") "; + } + if( pFrm->Frm().Height() != rFrm.Height() ) + { + aOut += "Height: "; + aOut += ByteString::CreateFromInt64(rFrm.Height()); + aOut += " -> "; + aOut += ByteString::CreateFromInt64(pFrm->Frm().Height()); + aOut += " "; + } + if( pFrm->Frm().Width() != rFrm.Width() ) + { + aOut += "Width: "; + aOut += ByteString::CreateFromInt64(rFrm.Width()); + aOut += " -> "; + aOut += ByteString::CreateFromInt64(pFrm->Frm().Width()); + aOut += " "; + } + break; + } + } + *pStream << aOut.GetBuffer() << endl; // Ausgabe + pStream->Flush(); // Gleich auf die Platte, damit man mitlesen kann + if( ++nLineCount >= nMaxLines ) // Maximale Ausgabe erreicht? + SwProtocol::SetRecord( 0 ); // => Ende der Aufzeichnung +} + +/* -----------------13.01.99 11:39------------------- + * SwImplProtocol::SectFunc(...) wird von SwImplProtocol::_Record(..) gerufen, + * hier werden die Ausgaben rund um SectionFrms abgehandelt. + * --------------------------------------------------*/ + +void SwImplProtocol::SectFunc( ByteString &rOut, const SwFrm* , sal_uLong nAct, void* pParam ) +{ + sal_Bool bTmp = sal_False; + switch( nAct ) + { + case ACT_MERGE: rOut += "Merge Section "; + rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); + break; + case ACT_CREATE_MASTER: bTmp = sal_True; // NoBreak + case ACT_CREATE_FOLLOW: rOut += "Create Section "; + rOut += bTmp ? "Master to " : "Follow from "; + rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); + break; + case ACT_DEL_MASTER: bTmp = sal_True; // NoBreak + case ACT_DEL_FOLLOW: rOut += "Delete Section "; + rOut += bTmp ? "Master to " : "Follow from "; + rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); + break; + } +} + +/* -----------------11.01.99 11:31------------------- + * SwImplProtocol::InsertFrm(..) nimmt eine neue FrmId zum Aufzeichnen auf, + * wenn pFrmIds==NULL, werden alle aufgezeichnet, sobald durch InsertFrm(..) + * pFrmIds angelegt wird, werden nur noch die enthaltenen FrmIds aufgezeichnet. + * --------------------------------------------------*/ + +sal_Bool SwImplProtocol::InsertFrm( sal_uInt16 nId ) +{ + if( !pFrmIds ) + pFrmIds = new SvUShortsSort(5,5); + if( pFrmIds->Seek_Entry( nId ) ) + return sal_False; + pFrmIds->Insert( nId ); + return sal_True; +} + +/* -----------------11.01.99 11:52------------------- + * SwImplProtocol::DeleteFrm(..) entfernt eine FrmId aus dem pFrmIds-Array, + * so dass diese Frame nicht mehr aufgezeichnet wird. + * --------------------------------------------------*/ +sal_Bool SwImplProtocol::DeleteFrm( sal_uInt16 nId ) +{ + sal_uInt16 nPos; + if( !pFrmIds || !pFrmIds->Seek_Entry( nId, &nPos ) ) + return sal_False; + pFrmIds->Remove( nPos ); + return sal_True; +} + +/*-----------------20.9.2001 10:29------------------ + * SwProtocol::SnapShot(..) + * creates a snapshot of the given frame and its content. + * --------------------------------------------------*/ +void SwImplProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags ) +{ + while( pFrm ) + { + _Record( pFrm, PROT_SNAPSHOT, 0, 0); + if( pFrm->GetDrawObjs() && nFlags & SNAP_FLYFRAMES ) + { + aLayer += "[ "; + const SwSortedObjs &rObjs = *pFrm->GetDrawObjs(); + for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i ) + { + SwAnchoredObject* pObj = rObjs[i]; + if ( pObj->ISA(SwFlyFrm) ) + SnapShot( static_cast<SwFlyFrm*>(pObj), nFlags ); + } + if( aLayer.Len() > 1 ) + aLayer.Erase( aLayer.Len() - 2 ); + } + if( pFrm->IsLayoutFrm() && nFlags & SNAP_LOWER && + ( !pFrm->IsTabFrm() || nFlags & SNAP_TABLECONT ) ) + { + aLayer += " "; + SnapShot( ((SwLayoutFrm*)pFrm)->Lower(), nFlags ); + if( aLayer.Len() > 1 ) + aLayer.Erase( aLayer.Len() - 2 ); + } + pFrm = pFrm->GetNext(); + } +} + +/* -----------------11.01.99 11:53------------------- + * SwEnterLeave::Ctor(..) wird vom eigentlichen (inline-)Kontruktor gerufen, + * wenn die Funktion aufgezeichnet werden soll. + * Die Aufgabe ist es abhaengig von der Funktion das richtige SwImplEnterLeave-Objekt + * zu erzeugen, alles weitere geschieht dann in dessen Ctor/Dtor. + * --------------------------------------------------*/ +void SwEnterLeave::Ctor( const SwFrm* pFrm, sal_uLong nFunc, sal_uLong nAct, void* pPar ) +{ + switch( nFunc ) + { + case PROT_ADJUSTN : + case PROT_GROW: + case PROT_SHRINK : pImpl = new SwSizeEnterLeave( pFrm, nFunc, nAct, pPar ); break; + case PROT_MOVE_FWD: + case PROT_MOVE_BWD : pImpl = new SwUpperEnterLeave( pFrm, nFunc, nAct, pPar ); break; + case PROT_FRMCHANGES : pImpl = new SwFrmChangesLeave( pFrm, nFunc, nAct, pPar ); break; + default: pImpl = new SwImplEnterLeave( pFrm, nFunc, nAct, pPar ); break; + } + pImpl->Enter(); +} + +/* -----------------11.01.99 11:56------------------- + * SwEnterLeave::Dtor() ruft lediglich den Destruktor des SwImplEnterLeave-Objekts, + * ist nur deshalb nicht inline, damit die SwImplEnterLeave-Definition nicht + * im dbg_lay.hxx zu stehen braucht. + * --------------------------------------------------*/ + +void SwEnterLeave::Dtor() +{ + if( pImpl ) + { + pImpl->Leave(); + delete pImpl; + } +} + +void SwImplEnterLeave::Enter() +{ + SwProtocol::Record( pFrm, nFunction, ACT_START, pParam ); +} + +void SwImplEnterLeave::Leave() +{ + SwProtocol::Record( pFrm, nFunction, ACT_END, pParam ); +} + +void SwSizeEnterLeave::Leave() +{ + nFrmHeight = pFrm->Frm().Height() - nFrmHeight; + SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmHeight ); +} + +void SwUpperEnterLeave::Enter() +{ + nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0; + SwProtocol::Record( pFrm, nFunction, ACT_START, &nFrmId ); +} + +void SwUpperEnterLeave::Leave() +{ + nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0; + SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmId ); +} + +void SwFrmChangesLeave::Enter() +{ +} + +void SwFrmChangesLeave::Leave() +{ + if( pFrm->Frm() != aFrm ) + SwProtocol::Record( pFrm, PROT_FRMCHANGES, 0, &aFrm ); +} + +#endif // DBG_UTIL + |