1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #ifdef DBG_UTIL 28 29 /* -----------------08.01.99 14:55------------------- 30 * Und hier die Beschreibung: 31 * 32 * Durch die PROTOCOL-Makros wird es ermoeglicht, Ereignisse im Frame-Methoden zu protokollieren. 33 * In protokollwuerdigen Stellen in Frame-Methoden muss entweder ein PROTOCOL(...) oder bei Methoden, 34 * bei denen auch das Verlassen der Methode mitprotokolliert werden soll, ein PROTOCOL_ENTER(...)-Makro 35 * stehen. 36 * Die Parameter der PROTOCOL-Makros sind 37 * 1. Ein Pointer auf einen SwFrm, also meist "this" oder "rThis" 38 * 2. Die Funktionsgruppe z.B. PROT_MAKEALL, hierueber wird (inline) entschieden, ob dies 39 * zur Zeit protokolliert werden soll oder nicht. 40 * 3. Die Aktion, im Normalfall 0, aber z.B. ein ACT_START bewirkt eine Einrueckung in der 41 * Ausgabedatei, ein ACT_END nimmt dies wieder zurueck. Auf diese Art wird z.B. durch 42 * PROTOCOL_ENTER am Anfang einer Methode eingerueckt und beim Verlassen wieder zurueck. 43 * 4. Der vierte Parameter ist ein void-Pointer, damit man irgendetwas uebergeben kann, 44 * was in das Protokoll einfliessen kann, typesches Beispiel bei PROT_GROW muss man 45 * einen Pointer auf den Wert, um den gegrowt werden soll, uebergeben. 46 * 47 * 48 * Das Protokoll ist die Datei "dbg_lay.out" im aktuellen (BIN-)Verzeichnis. 49 * Es enthaelt Zeilen mit FrmId, Funktionsgruppe sowie weiteren Infos. 50 * 51 * Was genau protokolliert wird, kann auf folgende Arten eingestellt werden: 52 * 1. Die statische Variable SwProtokoll::nRecord enthaelt die Funktionsgruppen, 53 * die aufgezeichnet werden sollen. 54 * Ein Wert von z.B. PROT_GROW bewirkt, das Aufrufe von SwFrm::Grow dokumentiert werden, 55 * PROT_MAKEALL protokolliert Aufrufe von xxx::MakeAll. 56 * Die PROT_XY-Werte koennen oderiert werden. 57 * Default ist Null, es wird keine Methode aufgezeichnet. 58 * 2. In der SwImplProtocol-Klasse gibt es einen Filter fuer Frame-Typen, 59 * nur die Methodenaufrufe von Frame-Typen, die dort gesetzt sind, werden protokolliert. 60 * Der Member nTypes kann auf Werte wie FRM_PAGE, FRM_SECTION gesetzt und oderiert werden. 61 * Default ist 0xFFFF, d.h. alle Frame-Typen. 62 * 3. In der SwImplProtocol-Klasse gibt es einen ArrayPointer auf FrmIds, die zu ueberwachen sind. 63 * Ist der Pointer Null, so werden alle Frames protokolliert, ansonsten nur Frames, 64 * die in dem Array vermerkt sind. 65 * 66 * Eine Aufzeichnung in Gang zu setzen, erfordert entweder Codemanipulation, z.B. in 67 * SwProtocol::Init() einen anderen Default fuer nRecord setzen oder Debuggermanipulation. 68 * Im Debugger gibt verschiedene, sich anbietende Stellen: 69 * 1. In SwProtocol::Init() einen Breakpoint setzen und dort nRecord manipulieren, ggf. 70 * FrmIds eintragen, dann beginnt die Aufzeichnung bereits beim Programmstart. 71 * 2. Waehrend des Programmlaufs einen Breakpoint vor irgendein PROTOCOL oder PROTOCOL_ENTER- 72 * Makro setzen, dann am SwProtocol::nRecord das unterste Bit setzen (PROT_INIT). Dies 73 * bewirkt, dass die Funktionsgruppe des folgenden Makros aktiviert und in Zukunft 74 * protokolliert wird. 75 * 3. Spezialfall von 2.: Wenn man 2. in der Methode SwRootFrm::Paint(..) anwendet, werden 76 * die Aufzeichnungseinstellung aus der Datei "dbg_lay.ini" ausgelesen! 77 * In dieser INI-Datei kann es Kommentarzeilen geben, diese beginnen mit '#', dann 78 * sind die Sektionen "[frmid]", "[frmtype]" und "[record]" relevant. 79 * Nach [frmid] koennen die FrameIds der zu protokollierenden Frames folgen. Gibt es 80 * dort keine Eintraege, werden alle Frames aufgezeichnet. 81 * Nach [frmtype] koennen FrameTypen folgen, die aufgezeichnet werden sollen, da der 82 * Default hier allerdings USHRT_MAX ist, werden sowieso alle aufgezeichnet. Man kann 83 * allerdings auch Typen entfernen, in dem man ein '!' vor den Wert setzt, z.B. 84 * !0xC000 nimmt die SwCntntFrms aus der Aufzeichnung heraus. 85 * Nach [record] folgen die Funktionsgruppen, die aufgezeichnet werden sollen, Default 86 * ist hier 0, also keine. Auch hier kann man mit einem vorgestellten '!' Funktionen 87 * wieder entfernen. 88 * Hier mal ein Beispiel fuer eine INI-Datei: 89 * ------------------------------------------ 90 * #Funktionen: Alle, ausser PRTAREA 91 * [record] 0xFFFFFFE !0x200 92 * [frmid] 93 * #folgende FrmIds: 94 * 1 2 12 13 14 15 95 * #keine Layoutframes ausser ColumnFrms 96 * [frmtype] !0x3FFF 0x4 97 * ------------------------------------------ 98 * 99 * Wenn die Aufzeichnung erstmal laeuft, kann man in SwImplProtocol::_Record(...) mittels 100 * Debugger vielfaeltige Manipulationen vornehmen, z.B. bezueglich FrameTypen oder FrmIds. 101 * 102 * --------------------------------------------------*/ 103 104 #ifndef DBG_UTIL 105 #error Wer fummelt denn an den makefiles rum? 106 #endif 107 108 109 110 #include "dbg_lay.hxx" 111 #include <tools/stream.hxx> 112 113 #ifndef _SVSTDARR_HXX 114 #define _SVSTDARR_USHORTS 115 #define _SVSTDARR_USHORTSSORT 116 #define _SVSTDARR_LONGS 117 #include <svl/svstdarr.hxx> 118 #endif 119 120 #include <stdio.h> 121 122 #include "frame.hxx" 123 #include "layfrm.hxx" 124 #include "flyfrm.hxx" 125 #include "txtfrm.hxx" 126 #include "ndtxt.hxx" 127 #include "dflyobj.hxx" 128 #include <fntcache.hxx> 129 // OD 2004-05-24 #i28701# 130 #include <sortedobjs.hxx> 131 132 sal_uLong SwProtocol::nRecord = 0; 133 SwImplProtocol* SwProtocol::pImpl = NULL; 134 135 sal_uLong lcl_GetFrameId( const SwFrm* pFrm ) 136 { 137 #ifdef DBG_UTIL 138 static sal_Bool bFrameId = sal_False; 139 if( bFrameId ) 140 return pFrm->GetFrmId(); 141 #endif 142 if( pFrm && pFrm->IsTxtFrm() ) 143 return ((SwTxtFrm*)pFrm)->GetTxtNode()->GetIndex(); 144 return 0; 145 } 146 147 class SwImplProtocol 148 { 149 SvFileStream *pStream; // Ausgabestream 150 SvUShortsSort *pFrmIds; // welche FrmIds sollen aufgezeichnet werden ( NULL == alle ) 151 SvLongs *pVar; // Variables 152 ByteString aLayer; // Einrueckung der Ausgabe (" " pro Start/End) 153 sal_uInt16 nTypes; // welche Typen sollen aufgezeichnet werden 154 sal_uInt16 nLineCount; // Ausgegebene Zeilen 155 sal_uInt16 nMaxLines; // Maximal auszugebende Zeilen 156 sal_uInt8 nInitFile; // Bereich (FrmId,FrmType,Record) beim Einlesen der INI-Datei 157 sal_uInt8 nTestMode; // Special fuer Testformatierung, es wird ggf. nur 158 // innerhalb einer Testformatierung aufgezeichnet. 159 void _Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ); 160 sal_Bool NewStream(); 161 void CheckLine( ByteString& rLine ); 162 void SectFunc( ByteString &rOut, const SwFrm* pFrm, sal_uLong nAct, void* pParam ); 163 public: 164 SwImplProtocol(); 165 ~SwImplProtocol(); 166 // Aufzeichnen 167 void Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ) 168 { if( pStream ) _Record( pFrm, nFunction, nAct, pParam ); } 169 sal_Bool InsertFrm( sal_uInt16 nFrmId ); // FrmId aufnehmen zum Aufzeichnen 170 sal_Bool DeleteFrm( sal_uInt16 nFrmId ); // FrmId entfernen, diesen nicht mehr Aufzeichnen 171 void FileInit(); // Auslesen der INI-Datei 172 void ChkStream() { if( !pStream ) NewStream(); } 173 void SnapShot( const SwFrm* pFrm, sal_uLong nFlags ); 174 void GetVar( const sal_uInt16 nNo, long& rVar ) 175 { if( pVar && nNo < pVar->Count() ) rVar = (*pVar)[ nNo ]; } 176 }; 177 178 /* -----------------11.01.99 10:43------------------- 179 * Durch das PROTOCOL_ENTER-Makro wird ein SwEnterLeave-Objekt erzeugt, 180 * wenn die aktuelle Funktion aufgezeichnet werden soll, wird ein 181 * SwImplEnterLeave-Objekt angelegt. Der Witz dabei ist, das der Ctor 182 * des Impl-Objekt am Anfang der Funktion und automatisch der Dtor beim 183 * Verlassen der Funktion gerufen wird. In der Basis-Implementierung ruft 184 * der Ctor lediglich ein PROTOCOL(..) mit ACT_START und im Dtor ein 185 * PROTOCOL(..) mit ACT_END. 186 * Es lassen sich Ableitungen der Klasse bilden, um z.B. beim Verlassen 187 * einer Funktion Groessenaenderungen des Frames zu dokumentieren u.v.a.m. 188 * Dazu braucht dann nur noch in SwEnterLeave::Ctor(...) die gewuenschte 189 * SwImplEnterLeave-Klasse angelegt zu werden. 190 * 191 * --------------------------------------------------*/ 192 193 class SwImplEnterLeave 194 { 195 protected: 196 const SwFrm* pFrm; // Der Frame, 197 sal_uLong nFunction, nAction; // die Funktion, ggf. die Aktion 198 void* pParam; // und weitere Parameter 199 public: 200 SwImplEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) 201 : pFrm( pF ), nFunction( nFunct ), nAction( nAct ), pParam( pPar ) {} 202 virtual void Enter(); // Ausgabe beim Eintritt 203 virtual void Leave(); // Ausgabe beim Verlassen 204 }; 205 206 class SwSizeEnterLeave : public SwImplEnterLeave 207 { 208 long nFrmHeight; 209 public: 210 SwSizeEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) 211 : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmHeight( pF->Frm().Height() ) {} 212 virtual void Leave(); // Ausgabe der Groessenaenderung 213 }; 214 215 class SwUpperEnterLeave : public SwImplEnterLeave 216 { 217 sal_uInt16 nFrmId; 218 public: 219 SwUpperEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) 220 : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmId( 0 ) {} 221 virtual void Enter(); // Ausgabe 222 virtual void Leave(); // Ausgabe der FrmId des Uppers 223 }; 224 225 class SwFrmChangesLeave : public SwImplEnterLeave 226 { 227 SwRect aFrm; 228 public: 229 SwFrmChangesLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar ) 230 : SwImplEnterLeave( pF, nFunct, nAct, pPar ), aFrm( pF->Frm() ) {} 231 virtual void Enter(); // keine Ausgabe 232 virtual void Leave(); // Ausgabe bei Aenderung der Frm-Area 233 }; 234 235 void SwProtocol::Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ) 236 { 237 if( Start() ) 238 { // Hier landen wir, wenn im Debugger SwProtocol::nRecord mit PROT_INIT(0x1) oderiert wurde 239 sal_Bool bFinit = sal_False; // Dies bietet im Debugger die Moeglichkeit, 240 if( bFinit ) // die Aufzeichnung dieser Action zu beenden 241 { 242 nRecord &= ~nFunction; // Diese Funktion nicht mehr aufzeichnen 243 nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen 244 return; 245 } 246 nRecord |= nFunction; // Aufzeichnung dieser Funktion freischalten 247 nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen 248 if( pImpl ) 249 pImpl->ChkStream(); 250 } 251 if( !pImpl ) // Impl-Object anlegen, wenn noetig 252 pImpl = new SwImplProtocol(); 253 pImpl->Record( pFrm, nFunction, nAct, pParam ); // ...und Aufzeichnen 254 } 255 256 // Die folgende Funktion wird beim Anziehen der Writer-DLL durch TxtInit(..) aufgerufen 257 // und ermoeglicht dem Debuggenden Funktionen und/oder FrmIds freizuschalten 258 259 void SwProtocol::Init() 260 { 261 nRecord = 0; 262 XubString aName( "dbg_lay.go", RTL_TEXTENCODING_MS_1252 ); 263 SvFileStream aStream( aName, STREAM_READ ); 264 if( aStream.IsOpen() ) 265 { 266 pImpl = new SwImplProtocol(); 267 pImpl->FileInit(); 268 } 269 aStream.Close(); 270 } 271 272 // Ende der Aufzeichnung 273 274 void SwProtocol::Stop() 275 { 276 if( pImpl ) 277 { 278 delete pImpl; 279 pImpl = NULL; 280 if( pFntCache ) 281 pFntCache->Flush(); 282 } 283 nRecord = 0; 284 } 285 286 // Creates a more or less detailed snapshot of the layout structur 287 288 void SwProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags ) 289 { 290 if( pImpl ) 291 pImpl->SnapShot( pFrm, nFlags ); 292 } 293 294 void SwProtocol::GetVar( const sal_uInt16 nNo, long& rVar ) 295 { 296 if( pImpl ) 297 pImpl->GetVar( nNo, rVar ); 298 } 299 300 SwImplProtocol::SwImplProtocol() 301 : pStream( NULL ), pFrmIds( NULL ), pVar( NULL ), nTypes( 0xffff ), 302 nLineCount( 0 ), nMaxLines( USHRT_MAX ), nTestMode( 0 ) 303 { 304 NewStream(); 305 } 306 307 sal_Bool SwImplProtocol::NewStream() 308 { 309 XubString aName( "dbg_lay.out", RTL_TEXTENCODING_MS_1252 ); 310 nLineCount = 0; 311 pStream = new SvFileStream( aName, STREAM_WRITE | STREAM_TRUNC ); 312 if( pStream->GetError() ) 313 { 314 delete pStream; 315 pStream = NULL; 316 } 317 return 0 != pStream; 318 } 319 320 SwImplProtocol::~SwImplProtocol() 321 { 322 if( pStream ) 323 { 324 pStream->Close(); 325 delete pStream; 326 } 327 delete pFrmIds; 328 delete pVar; 329 } 330 331 /* -----------------11.01.99 11:03------------------- 332 * SwImplProtocol::CheckLine analysiert eine Zeile der INI-Datei 333 * --------------------------------------------------*/ 334 335 void SwImplProtocol::CheckLine( ByteString& rLine ) 336 { 337 rLine = rLine.ToLowerAscii(); // Gross/Kleinschreibung ist einerlei 338 while( STRING_LEN > rLine.SearchAndReplace( '\t', ' ' ) ) 339 ; //nothing // Tabs werden durch Blanks ersetzt 340 if( '#' == rLine.GetChar(0) ) // Kommentarzeilen beginnen mit '#' 341 return; 342 if( '[' == rLine.GetChar(0) ) // Bereiche: FrmIds, Typen oder Funktionen 343 { 344 ByteString aTmp = rLine.GetToken( 0, ']' ); 345 if( "[frmid" == aTmp ) // Bereich FrmIds 346 { 347 nInitFile = 1; 348 delete pFrmIds; 349 pFrmIds = NULL; // Default: Alle Frames aufzeichnen 350 } 351 else if( "[frmtype" == aTmp )// Bereich Typen 352 { 353 nInitFile = 2; 354 nTypes = USHRT_MAX; // Default: Alle FrmaeTypen aufzeichnen 355 } 356 else if( "[record" == aTmp )// Bereich Funktionen 357 { 358 nInitFile = 3; 359 SwProtocol::SetRecord( 0 );// Default: Keine Funktion wird aufgezeichnet 360 } 361 else if( "[test" == aTmp )// Bereich Funktionen 362 { 363 nInitFile = 4; // Default: 364 nTestMode = 0; // Ausserhalb der Testformatierung wird aufgezeichnet 365 } 366 else if( "[max" == aTmp )// maximale Zeilenzahl 367 { 368 nInitFile = 5; // Default: 369 nMaxLines = USHRT_MAX; 370 } 371 else if( "[var" == aTmp )// variables 372 { 373 nInitFile = 6; 374 if( !pVar ) 375 pVar = new SvLongs( 5, 5 ); 376 } 377 else 378 nInitFile = 0; // Nanu: Unbekannter Bereich? 379 rLine.Erase( 0, aTmp.Len() + 1 ); 380 } 381 sal_uInt16 nToks = rLine.GetTokenCount( ' ' ); // Blanks (oder Tabs) sind die Trenner 382 for( sal_uInt16 i=0; i < nToks; ++i ) 383 { 384 ByteString aTok = rLine.GetToken( i, ' ' ); 385 sal_Bool bNo = sal_False; 386 if( '!' == aTok.GetChar(0) ) 387 { 388 bNo = sal_True; // Diese(n) Funktion/Typ entfernen 389 aTok.Erase( 0, 1 ); 390 } 391 if( aTok.Len() ) 392 { 393 sal_uLong nVal; 394 sscanf( aTok.GetBuffer(), "%li", &nVal ); 395 switch ( nInitFile ) 396 { 397 case 1: InsertFrm( sal_uInt16( nVal ) ); // FrmId aufnehmen 398 break; 399 case 2: { 400 sal_uInt16 nNew = (sal_uInt16)nVal; 401 if( bNo ) 402 nTypes &= ~nNew; // Typ entfernen 403 else 404 nTypes |= nNew; // Typ aufnehmen 405 } 406 break; 407 case 3: { 408 sal_uLong nOld = SwProtocol::Record(); 409 if( bNo ) 410 nOld &= ~nVal; // Funktion entfernen 411 else 412 nOld |= nVal; // Funktion aufnehmen 413 SwProtocol::SetRecord( nOld ); 414 } 415 break; 416 case 4: { 417 sal_uInt8 nNew = (sal_uInt8)nVal; 418 if( bNo ) 419 nTestMode &= ~nNew; // TestMode zuruecksetzen 420 else 421 nTestMode |= nNew; // TestMode setzen 422 } 423 break; 424 case 5: nMaxLines = (sal_uInt16)nVal; 425 break; 426 case 6: pVar->Insert( (long)nVal, pVar->Count() ); 427 break; 428 } 429 } 430 } 431 } 432 433 /* -----------------11.01.99 11:17------------------- 434 * SwImplProtocol::FileInit() liest die Datei "dbg_lay.ini" 435 * im aktuellen Verzeichnis und wertet sie aus. 436 * --------------------------------------------------*/ 437 void SwImplProtocol::FileInit() 438 { 439 XubString aName( "dbg_lay.ini", RTL_TEXTENCODING_MS_1252 ); 440 SvFileStream aStream( aName, STREAM_READ ); 441 if( aStream.IsOpen() ) 442 { 443 ByteString aLine; 444 nInitFile = 0; 445 while( !aStream.IsEof() ) 446 { 447 sal_Char c; 448 aStream >> c; 449 if( '\n' == c || '\r' == c ) // Zeilenende 450 { 451 aLine.EraseLeadingChars(); 452 aLine.EraseTrailingChars(); 453 if( aLine.Len() ) 454 CheckLine( aLine ); // Zeile auswerten 455 aLine.Erase(); 456 } 457 else 458 aLine += c; 459 } 460 if( aLine.Len() ) 461 CheckLine( aLine ); // letzte Zeile auswerten 462 } 463 aStream.Close(); 464 } 465 466 /* -----------------11.01.99 11:20------------------- 467 * lcl_Start sorgt fuer Einrueckung um zwei Blanks bei ACT_START 468 * und nimmt diese bei ACT_END wieder zurueck. 469 * --------------------------------------------------*/ 470 void lcl_Start( ByteString& rOut, ByteString& rLay, sal_uLong nAction ) 471 { 472 if( nAction == ACT_START ) 473 { 474 rLay += " "; 475 rOut += " On"; 476 } 477 else if( nAction == ACT_END ) 478 { 479 if( rLay.Len() > 1 ) 480 { 481 rLay.Erase( rLay.Len() - 2 ); 482 rOut.Erase( 0, 2 ); 483 } 484 rOut += " Off"; 485 } 486 } 487 488 /* -----------------11.01.99 11:21------------------- 489 * lcl_Flags gibt das ValidSize-, ValidPos- und ValidPrtArea-Flag ("Sz","Ps","PA") 490 * des Frames aus, "+" fuer valid, "-" fuer invalid. 491 * --------------------------------------------------*/ 492 493 void lcl_Flags( ByteString& rOut, const SwFrm* pFrm ) 494 { 495 rOut += " Sz"; 496 rOut += pFrm->GetValidSizeFlag() ? '+' : '-'; 497 rOut += " Ps"; 498 rOut += pFrm->GetValidPosFlag() ? '+' : '-'; 499 rOut += " PA"; 500 rOut += pFrm->GetValidPrtAreaFlag() ? '+' : '-'; 501 } 502 503 /* -----------------11.01.99 11:23------------------- 504 * lcl_FrameType gibt den Typ des Frames in Klartext aus. 505 * --------------------------------------------------*/ 506 507 void lcl_FrameType( ByteString& rOut, const SwFrm* pFrm ) 508 { 509 if( pFrm->IsTxtFrm() ) 510 rOut += "Txt "; 511 else if( pFrm->IsLayoutFrm() ) 512 { 513 if( pFrm->IsPageFrm() ) 514 rOut += "Page "; 515 else if( pFrm->IsColumnFrm() ) 516 rOut += "Col "; 517 else if( pFrm->IsBodyFrm() ) 518 { 519 if( pFrm->GetUpper() && pFrm->IsColBodyFrm() ) 520 rOut += "(Col)"; 521 rOut += "Body "; 522 } 523 else if( pFrm->IsRootFrm() ) 524 rOut += "Root "; 525 else if( pFrm->IsCellFrm() ) 526 rOut += "Cell "; 527 else if( pFrm->IsTabFrm() ) 528 rOut += "Tab "; 529 else if( pFrm->IsRowFrm() ) 530 rOut += "Row "; 531 else if( pFrm->IsSctFrm() ) 532 rOut += "Sect "; 533 else if( pFrm->IsHeaderFrm() ) 534 rOut += "Header "; 535 else if( pFrm->IsFooterFrm() ) 536 rOut += "Footer "; 537 else if( pFrm->IsFtnFrm() ) 538 rOut += "Ftn "; 539 else if( pFrm->IsFtnContFrm() ) 540 rOut += "FtnCont "; 541 else if( pFrm->IsFlyFrm() ) 542 rOut += "Fly "; 543 else 544 rOut += "Layout "; 545 } 546 else if( pFrm->IsNoTxtFrm() ) 547 rOut += "NoTxt "; 548 else 549 rOut += "Not impl. "; 550 } 551 552 /* -----------------11.01.99 11:25------------------- 553 * SwImplProtocol::Record(..) wird nur gerufen, wenn das PROTOCOL-Makro 554 * feststellt, dass die Funktion aufgezeichnet werden soll ( SwProtocol::nRecord ). 555 * In dieser Methode werden noch die beiden weiteren Einschraenkungen ueberprueft, 556 * ob die FrmId und der FrameType zu den aufzuzeichnenden gehoeren. 557 * --------------------------------------------------*/ 558 559 void SwImplProtocol::_Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam ) 560 { 561 sal_uInt16 nSpecial = 0; 562 if( nSpecial ) // Debugger-Manipulationsmoeglichkeit 563 { 564 sal_uInt16 nId = sal_uInt16(lcl_GetFrameId( pFrm )); 565 switch ( nSpecial ) 566 { 567 case 1: InsertFrm( nId ); break; 568 case 2: DeleteFrm( nId ); break; 569 case 3: delete pFrmIds; pFrmIds = NULL; break; 570 case 4: delete pStream; pStream = NULL; break; 571 } 572 return; 573 } 574 if( !pStream && !NewStream() ) 575 return; // Immer noch kein Stream 576 577 if( pFrmIds && !pFrmIds->Seek_Entry( sal_uInt16(lcl_GetFrameId( pFrm )) ) ) 578 return; // gehoert nicht zu den gewuenschten FrmIds 579 580 if( !(pFrm->GetType() & nTypes) ) 581 return; // Der Typ ist unerwuenscht 582 583 if( 1 == nTestMode && nFunction != PROT_TESTFORMAT ) 584 return; // Wir sollen nur innerhalb einer Testformatierung aufzeichnen 585 sal_Bool bTmp = sal_False; 586 ByteString aOut = aLayer; 587 aOut += ByteString::CreateFromInt64( lcl_GetFrameId( pFrm ) ); 588 aOut += ' '; 589 lcl_FrameType( aOut, pFrm ); // dann den FrameType 590 switch ( nFunction ) // und die Funktion 591 { 592 case PROT_SNAPSHOT: lcl_Flags( aOut, pFrm ); 593 break; 594 case PROT_MAKEALL: aOut += "MakeAll"; 595 lcl_Start( aOut, aLayer, nAct ); 596 if( nAct == ACT_START ) 597 lcl_Flags( aOut, pFrm ); 598 break; 599 case PROT_MOVE_FWD: bTmp = sal_True; // NoBreak 600 case PROT_MOVE_BWD: aOut += ( nFunction == bTmp ) ? "Fwd" : "Bwd"; 601 lcl_Start( aOut, aLayer, nAct ); 602 if( pParam ) 603 { 604 aOut += ' '; 605 aOut += ByteString::CreateFromInt32( *((sal_uInt16*)pParam) ); 606 } 607 break; 608 case PROT_GROW_TST: if( ACT_START != nAct ) 609 return; 610 aOut += "TestGrow"; 611 break; 612 case PROT_SHRINK_TST: if( ACT_START != nAct ) 613 return; 614 aOut += "TestShrink"; 615 break; 616 case PROT_ADJUSTN : 617 case PROT_SHRINK: bTmp = sal_True; // NoBreak 618 case PROT_GROW: aOut += !bTmp ? "Grow" : 619 ( nFunction == PROT_SHRINK ? "Shrink" : "AdjustNgbhd" ); 620 lcl_Start( aOut, aLayer, nAct ); 621 if( pParam ) 622 { 623 aOut += ' '; 624 aOut += ByteString::CreateFromInt64( *((long*)pParam) ); 625 } 626 break; 627 case PROT_POS: break; 628 case PROT_PRTAREA: aOut += "PrtArea"; 629 lcl_Start( aOut, aLayer, nAct ); 630 break; 631 case PROT_SIZE: aOut += "Size"; 632 lcl_Start( aOut, aLayer, nAct ); 633 aOut += ' '; 634 aOut += ByteString::CreateFromInt64( pFrm->Frm().Height() ); 635 break; 636 case PROT_LEAF: aOut += "Prev/NextLeaf"; 637 lcl_Start( aOut, aLayer, nAct ); 638 aOut += ' '; 639 if( pParam ) 640 { 641 aOut += ' '; 642 aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); 643 } 644 break; 645 case PROT_FILE_INIT: FileInit(); 646 aOut = "Initialize"; 647 break; 648 case PROT_SECTION: SectFunc( aOut, pFrm, nAct, pParam ); 649 break; 650 case PROT_CUT: bTmp = sal_True; // NoBreak 651 case PROT_PASTE: aOut += bTmp ? "Cut from " : "Paste to "; 652 aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); 653 break; 654 case PROT_TESTFORMAT: aOut += "Test"; 655 lcl_Start( aOut, aLayer, nAct ); 656 if( ACT_START == nAct ) 657 nTestMode |= 2; 658 else 659 nTestMode &= ~2; 660 break; 661 case PROT_FRMCHANGES: 662 { 663 SwRect& rFrm = *((SwRect*)pParam); 664 if( pFrm->Frm().Pos() != rFrm.Pos() ) 665 { 666 aOut += "PosChg: ("; 667 aOut += ByteString::CreateFromInt64(rFrm.Left()); 668 aOut += ", "; 669 aOut += ByteString::CreateFromInt64(rFrm.Top()); 670 aOut += ") ("; 671 aOut += ByteString::CreateFromInt64(pFrm->Frm().Left()); 672 aOut += ", "; 673 aOut += ByteString::CreateFromInt64(pFrm->Frm().Top()); 674 aOut += ") "; 675 } 676 if( pFrm->Frm().Height() != rFrm.Height() ) 677 { 678 aOut += "Height: "; 679 aOut += ByteString::CreateFromInt64(rFrm.Height()); 680 aOut += " -> "; 681 aOut += ByteString::CreateFromInt64(pFrm->Frm().Height()); 682 aOut += " "; 683 } 684 if( pFrm->Frm().Width() != rFrm.Width() ) 685 { 686 aOut += "Width: "; 687 aOut += ByteString::CreateFromInt64(rFrm.Width()); 688 aOut += " -> "; 689 aOut += ByteString::CreateFromInt64(pFrm->Frm().Width()); 690 aOut += " "; 691 } 692 break; 693 } 694 } 695 *pStream << aOut.GetBuffer() << endl; // Ausgabe 696 pStream->Flush(); // Gleich auf die Platte, damit man mitlesen kann 697 if( ++nLineCount >= nMaxLines ) // Maximale Ausgabe erreicht? 698 SwProtocol::SetRecord( 0 ); // => Ende der Aufzeichnung 699 } 700 701 /* -----------------13.01.99 11:39------------------- 702 * SwImplProtocol::SectFunc(...) wird von SwImplProtocol::_Record(..) gerufen, 703 * hier werden die Ausgaben rund um SectionFrms abgehandelt. 704 * --------------------------------------------------*/ 705 706 void SwImplProtocol::SectFunc( ByteString &rOut, const SwFrm* , sal_uLong nAct, void* pParam ) 707 { 708 sal_Bool bTmp = sal_False; 709 switch( nAct ) 710 { 711 case ACT_MERGE: rOut += "Merge Section "; 712 rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); 713 break; 714 case ACT_CREATE_MASTER: bTmp = sal_True; // NoBreak 715 case ACT_CREATE_FOLLOW: rOut += "Create Section "; 716 rOut += bTmp ? "Master to " : "Follow from "; 717 rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); 718 break; 719 case ACT_DEL_MASTER: bTmp = sal_True; // NoBreak 720 case ACT_DEL_FOLLOW: rOut += "Delete Section "; 721 rOut += bTmp ? "Master to " : "Follow from "; 722 rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) ); 723 break; 724 } 725 } 726 727 /* -----------------11.01.99 11:31------------------- 728 * SwImplProtocol::InsertFrm(..) nimmt eine neue FrmId zum Aufzeichnen auf, 729 * wenn pFrmIds==NULL, werden alle aufgezeichnet, sobald durch InsertFrm(..) 730 * pFrmIds angelegt wird, werden nur noch die enthaltenen FrmIds aufgezeichnet. 731 * --------------------------------------------------*/ 732 733 sal_Bool SwImplProtocol::InsertFrm( sal_uInt16 nId ) 734 { 735 if( !pFrmIds ) 736 pFrmIds = new SvUShortsSort(5,5); 737 if( pFrmIds->Seek_Entry( nId ) ) 738 return sal_False; 739 pFrmIds->Insert( nId ); 740 return sal_True; 741 } 742 743 /* -----------------11.01.99 11:52------------------- 744 * SwImplProtocol::DeleteFrm(..) entfernt eine FrmId aus dem pFrmIds-Array, 745 * so dass diese Frame nicht mehr aufgezeichnet wird. 746 * --------------------------------------------------*/ 747 sal_Bool SwImplProtocol::DeleteFrm( sal_uInt16 nId ) 748 { 749 sal_uInt16 nPos; 750 if( !pFrmIds || !pFrmIds->Seek_Entry( nId, &nPos ) ) 751 return sal_False; 752 pFrmIds->Remove( nPos ); 753 return sal_True; 754 } 755 756 /*-----------------20.9.2001 10:29------------------ 757 * SwProtocol::SnapShot(..) 758 * creates a snapshot of the given frame and its content. 759 * --------------------------------------------------*/ 760 void SwImplProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags ) 761 { 762 while( pFrm ) 763 { 764 _Record( pFrm, PROT_SNAPSHOT, 0, 0); 765 if( pFrm->GetDrawObjs() && nFlags & SNAP_FLYFRAMES ) 766 { 767 aLayer += "[ "; 768 const SwSortedObjs &rObjs = *pFrm->GetDrawObjs(); 769 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i ) 770 { 771 SwAnchoredObject* pObj = rObjs[i]; 772 if ( pObj->ISA(SwFlyFrm) ) 773 SnapShot( static_cast<SwFlyFrm*>(pObj), nFlags ); 774 } 775 if( aLayer.Len() > 1 ) 776 aLayer.Erase( aLayer.Len() - 2 ); 777 } 778 if( pFrm->IsLayoutFrm() && nFlags & SNAP_LOWER && 779 ( !pFrm->IsTabFrm() || nFlags & SNAP_TABLECONT ) ) 780 { 781 aLayer += " "; 782 SnapShot( ((SwLayoutFrm*)pFrm)->Lower(), nFlags ); 783 if( aLayer.Len() > 1 ) 784 aLayer.Erase( aLayer.Len() - 2 ); 785 } 786 pFrm = pFrm->GetNext(); 787 } 788 } 789 790 /* -----------------11.01.99 11:53------------------- 791 * SwEnterLeave::Ctor(..) wird vom eigentlichen (inline-)Kontruktor gerufen, 792 * wenn die Funktion aufgezeichnet werden soll. 793 * Die Aufgabe ist es abhaengig von der Funktion das richtige SwImplEnterLeave-Objekt 794 * zu erzeugen, alles weitere geschieht dann in dessen Ctor/Dtor. 795 * --------------------------------------------------*/ 796 void SwEnterLeave::Ctor( const SwFrm* pFrm, sal_uLong nFunc, sal_uLong nAct, void* pPar ) 797 { 798 switch( nFunc ) 799 { 800 case PROT_ADJUSTN : 801 case PROT_GROW: 802 case PROT_SHRINK : pImpl = new SwSizeEnterLeave( pFrm, nFunc, nAct, pPar ); break; 803 case PROT_MOVE_FWD: 804 case PROT_MOVE_BWD : pImpl = new SwUpperEnterLeave( pFrm, nFunc, nAct, pPar ); break; 805 case PROT_FRMCHANGES : pImpl = new SwFrmChangesLeave( pFrm, nFunc, nAct, pPar ); break; 806 default: pImpl = new SwImplEnterLeave( pFrm, nFunc, nAct, pPar ); break; 807 } 808 pImpl->Enter(); 809 } 810 811 /* -----------------11.01.99 11:56------------------- 812 * SwEnterLeave::Dtor() ruft lediglich den Destruktor des SwImplEnterLeave-Objekts, 813 * ist nur deshalb nicht inline, damit die SwImplEnterLeave-Definition nicht 814 * im dbg_lay.hxx zu stehen braucht. 815 * --------------------------------------------------*/ 816 817 void SwEnterLeave::Dtor() 818 { 819 if( pImpl ) 820 { 821 pImpl->Leave(); 822 delete pImpl; 823 } 824 } 825 826 void SwImplEnterLeave::Enter() 827 { 828 SwProtocol::Record( pFrm, nFunction, ACT_START, pParam ); 829 } 830 831 void SwImplEnterLeave::Leave() 832 { 833 SwProtocol::Record( pFrm, nFunction, ACT_END, pParam ); 834 } 835 836 void SwSizeEnterLeave::Leave() 837 { 838 nFrmHeight = pFrm->Frm().Height() - nFrmHeight; 839 SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmHeight ); 840 } 841 842 void SwUpperEnterLeave::Enter() 843 { 844 nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0; 845 SwProtocol::Record( pFrm, nFunction, ACT_START, &nFrmId ); 846 } 847 848 void SwUpperEnterLeave::Leave() 849 { 850 nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0; 851 SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmId ); 852 } 853 854 void SwFrmChangesLeave::Enter() 855 { 856 } 857 858 void SwFrmChangesLeave::Leave() 859 { 860 if( pFrm->Frm() != aFrm ) 861 SwProtocol::Record( pFrm, PROT_FRMCHANGES, 0, &aFrm ); 862 } 863 864 #endif // DBG_UTIL 865 866