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
lcl_GetFrameId(const SwFrm * pFrm)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
Record(const SwFrm * pFrm,sal_uLong nFunction,sal_uLong nAct,void * pParam)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
ChkStream()172 void ChkStream() { if( !pStream ) NewStream(); }
173 void SnapShot( const SwFrm* pFrm, sal_uLong nFlags );
GetVar(const sal_uInt16 nNo,long & rVar)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:
SwImplEnterLeave(const SwFrm * pF,sal_uLong nFunct,sal_uLong nAct,void * pPar)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:
SwSizeEnterLeave(const SwFrm * pF,sal_uLong nFunct,sal_uLong nAct,void * pPar)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:
SwUpperEnterLeave(const SwFrm * pF,sal_uLong nFunct,sal_uLong nAct,void * pPar)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:
SwFrmChangesLeave(const SwFrm * pF,sal_uLong nFunct,sal_uLong nAct,void * pPar)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
Record(const SwFrm * pFrm,sal_uLong nFunction,sal_uLong nAct,void * pParam)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
Init()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
Stop()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
SnapShot(const SwFrm * pFrm,sal_uLong nFlags)288 void SwProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags )
289 {
290 if( pImpl )
291 pImpl->SnapShot( pFrm, nFlags );
292 }
293
GetVar(const sal_uInt16 nNo,long & rVar)294 void SwProtocol::GetVar( const sal_uInt16 nNo, long& rVar )
295 {
296 if( pImpl )
297 pImpl->GetVar( nNo, rVar );
298 }
299
SwImplProtocol()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
NewStream()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
~SwImplProtocol()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
CheckLine(ByteString & rLine)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 * --------------------------------------------------*/
FileInit()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 * --------------------------------------------------*/
lcl_Start(ByteString & rOut,ByteString & rLay,sal_uLong nAction)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
lcl_Flags(ByteString & rOut,const SwFrm * pFrm)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
lcl_FrameType(ByteString & rOut,const SwFrm * pFrm)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
_Record(const SwFrm * pFrm,sal_uLong nFunction,sal_uLong nAct,void * pParam)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
SectFunc(ByteString & rOut,const SwFrm *,sal_uLong nAct,void * pParam)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
InsertFrm(sal_uInt16 nId)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 * --------------------------------------------------*/
DeleteFrm(sal_uInt16 nId)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 * --------------------------------------------------*/
SnapShot(const SwFrm * pFrm,sal_uLong nFlags)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 * --------------------------------------------------*/
Ctor(const SwFrm * pFrm,sal_uLong nFunc,sal_uLong nAct,void * pPar)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
Dtor()817 void SwEnterLeave::Dtor()
818 {
819 if( pImpl )
820 {
821 pImpl->Leave();
822 delete pImpl;
823 }
824 }
825
Enter()826 void SwImplEnterLeave::Enter()
827 {
828 SwProtocol::Record( pFrm, nFunction, ACT_START, pParam );
829 }
830
Leave()831 void SwImplEnterLeave::Leave()
832 {
833 SwProtocol::Record( pFrm, nFunction, ACT_END, pParam );
834 }
835
Leave()836 void SwSizeEnterLeave::Leave()
837 {
838 nFrmHeight = pFrm->Frm().Height() - nFrmHeight;
839 SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmHeight );
840 }
841
Enter()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
Leave()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
Enter()854 void SwFrmChangesLeave::Enter()
855 {
856 }
857
Leave()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