LibreOffice Module sw (master)  1
dbg_lay.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifdef DBG_UTIL
21 
22 /*
23  * And here's the description:
24  *
25  * The PROTOCOL macros allow you to log events in frame methods. In places where
26  * logging is useful either one of the PROTOCOL(...) or PROTOCOL_ENTER(...) can
27  * be used. PROTOCOL_ENTER(...) additionally logs the leaving of a method.
28  *
29  * The PROTOCOL macros accept the following parameters:
30  * 1. A pointer to an SwFrame (usually "this" or "rThis")
31  * 2. The function group i.e. PROT::MakeAll. This is used to decide (inline)
32  * whether this event shall be logged at the current time.
33  * 3. The action, usually 0. For example DbgAction::Start indents output in the log
34  * file and DbgAction::End stops the indentation. This allows for example
35  * PROTOCOL_ENTER to indent at the beginning of a method and stop indenting
36  * when leaving the method.
37  * 4. The fourth parameter is a void pointer which allows to pass anything
38  * which can be used in the log. A good example is PROT::Grow: this requires
39  * a pointer to the value which defines how much to grow.
40  *
41  * The log file is called "dbg_lay.out", which is saved in the current (BIN-)
42  * directory. The file contains lines with FrameId, function group and additional
43  * information.
44  *
45  * What exactly is going to be logged, can be defined as follows:
46  * 1. The static variable SwProtocol::nRecord contains the function groups
47  * which shall be logged.
48  * A value of i.e. PROT::Grow causes calls to SwFrame::Grow to be
49  * logged; PROT::MakeAll logs the calls to xxx::MakeAll.
50  * The PROT_XY values can be combined using binary OR, the default value
51  * is null - no method calls are logged.
52  * 2. The SwImplProtocol class contains a filter for frame types, only method
53  * call of frame types which are defined there are logged.
54  * The member nTypes can be set to values like SwFrameType::Page or SwFrameType::Section and
55  * may be combined using binary OR. The default values is 0xFFFF - meaning
56  * all frame types.
57  * 3. The SwImplProtocol class contains an ArrayPointer to FrameIds which need to be
58  * tracked. If the pointer is null, all frames will be logged; otherwise
59  * only frames of linked from the array will be logged.
60  *
61  * Code changes are needed to start logging; either change the default of nRecord
62  * in SwProtocol::Init() or change the debugger. There are several possible
63  * places in the debugger:
64  * 1. Set a breakpoint in SwProtocol::Init() and manipulate nRecord there, set
65  * FrameIds accordingly then start logging during program start.
66  * 2. Set a breakpoint before any PROTOCOL or PROTOCOL_ENTER macro during
67  * program execution, then set the lowest bit (PROT::Init) of
68  * SwProtocol::nRecord. This activates the function group of the following
69  * macro and causes it to be logged in the future.
70  * 3. There's a special case for 2: If one uses 2. in SwRootFrame::PaintSwFrame(..),
71  * the log settings are taken from the file "dbg_lay.ini"!
72  * In this INI-file you can have comment lines starting with a '#'.
73  * The sections "[frmid]", "[frmtype]" and "[record]" are relevant.
74  * In the [frmid] section, you can put FrameIds of the Frames to be logged.
75  * If there are no entries in this section, all Frames will be logged.
76  * In the [frmtype] section, the frame types which should be logged are
77  * listed; default is USHRT_MAX which means that all types are logged.
78  * It's possible to remove types from the list using '!' in front of a
79  * value. The value !0xC000 would for example exclude SwContentFrames from
80  * logging.
81  * In the [record] section the functions group which should be logged are
82  * listed; default is 0 which means that none are logged. It's also
83  * possible to remove functions using '!'.
84  * An example INI file:
85  * #Functions: all(0x0007ffff), except PrintArea (0x200)
86  * [record] 524287 !512
87  * [frmid]
88  * #the following FrameIds:
89  * 1 2 12 13 14 15
90  * #no layout frames, except ColumnFrames
91  * [frmtype] !0x3FFF 0x4
92  *
93  * As soon as the logging is in process, one can manipulate many things in
94  * SwImplProtocol::Record_(...) using a debugger, especially concerning
95  * frame types and FrameIds.
96  */
97 
98 #include <dbg_lay.hxx>
99 
100 #include <flyfrm.hxx>
101 #include <txtfrm.hxx>
102 #include <fntcache.hxx>
103 #include <tabfrm.hxx>
104 #include <swtblfmt.hxx>
105 #include <rowfrm.hxx>
106 #include <cellfrm.hxx>
107 #include <layfrm.hxx>
108 #include <frame.hxx>
109 #include <swtable.hxx>
110 #include <ndtxt.hxx>
111 #include <sal/log.hxx>
112 #include <tools/stream.hxx>
113 
116 
117 static sal_uLong lcl_GetFrameId( const SwFrame* pFrame )
118 {
119 #if OSL_DEBUG_LEVEL > 1
120  static bool bFrameId = false;
121  if( bFrameId )
122  return pFrame->GetFrameId();
123 #endif
124  if( pFrame )
125  return pFrame->GetFrameId();
126  return 0;
127 }
128 
130 {
131  std::unique_ptr<SvFileStream> pStream; // output stream
132  std::unique_ptr<std::set<sal_uInt16>> pFrameIds; // which FrameIds shall be logged ( NULL == all)
133  std::vector<long> aVars; // variables
134  OStringBuffer aLayer; // indentation of output (" " per start/end)
135  SwFrameType nTypes; // which types shall be logged
136  sal_uInt16 nLineCount; // printed lines
137  sal_uInt16 nMaxLines; // max lines to be printed
138  sal_uInt8 nInitFile; // range (FrameId,FrameType,Record) during reading of the INI file
139  sal_uInt8 nTestMode; // special for test formatting, logging may only be done in test formatting.
140  void Record_( const SwFrame* pFrame, PROT nFunction, DbgAction nAct, void* pParam );
141  bool NewStream();
142  void CheckLine( OString& rLine );
143  static void SectFunc( OStringBuffer& rOut, DbgAction nAct, void const * pParam );
144 public:
145  SwImplProtocol();
146  ~SwImplProtocol();
147  // logging
148  void Record( const SwFrame* pFrame, PROT nFunction, DbgAction nAct, void* pParam )
149  { if( pStream ) Record_( pFrame, nFunction, nAct, pParam ); }
150  void InsertFrame( sal_uInt16 nFrameId ); // take FrameId for logging
151  void DeleteFrame( sal_uInt16 nFrameId ); // remove FrameId; don't log him anymore
152  void FileInit(); // read the INI file
153  void ChkStream() { if( !pStream ) NewStream(); }
154 };
155 
156 /* Through the PROTOCOL_ENTER macro a SwEnterLeave object gets created. If the
157  * current function should be logged a SwImplEnterLeace object gets created.
158  * The funny thing here is, that the Ctor of the Impl object is automatically
159  * called at the beginning of the function and the Dtor is automatically called
160  * when leaving the function. In the base implementation the Ctor calls only
161  * PROTOCOL(..) with DbgAction::Start and in the Dtor a PROTOCOL(..) with DbgAction::End.
162  * It's possible to derive from this class, for example to be able to document
163  * frame resize while leaving a function. To do this, one only needs to add the
164  * desired SwImplEnterLeave class in SwEnterLeave::Ctor().
165  */
166 
168 {
169 protected:
170  const SwFrame* pFrame; // the frame
171  PROT const nFunction; // the function
172  DbgAction const nAction; // the action if needed
173  void* const pParam; // further parameter
174 public:
175  SwImplEnterLeave( const SwFrame* pF, PROT nFunct, DbgAction nAct, void* pPar )
176  : pFrame( pF ), nFunction( nFunct ), nAction( nAct ), pParam( pPar ) {}
177  virtual ~SwImplEnterLeave() {}
178  virtual void Enter(); // message when entering
179  virtual void Leave(); // message when leaving
180 };
181 
183 {
185 public:
186  SwSizeEnterLeave( const SwFrame* pF, PROT nFunct, DbgAction nAct, void* pPar )
187  : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrameHeight( pF->getFrameArea().Height() ) {}
188 
189  virtual void Leave() override; // resize message
190 };
191 
193 {
194  sal_uInt16 nFrameId;
195 public:
196  SwUpperEnterLeave( const SwFrame* pF, PROT nFunct, DbgAction nAct, void* pPar )
197  : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrameId( 0 ) {}
198 
199  virtual void Enter() override; // message
200  virtual void Leave() override; // message of FrameId from upper
201 };
202 
204 {
206 public:
207  SwFrameChangesLeave( const SwFrame* pF, PROT nFunct, DbgAction nAct, void* pPar )
208  : SwImplEnterLeave( pF, nFunct, nAct, pPar ), aFrame( pF->getFrameArea() ) {}
209 
210  virtual void Enter() override; // no message
211  virtual void Leave() override; // message when resizing the Frame area
212 };
213 
214 void SwProtocol::Record( const SwFrame* pFrame, PROT nFunction, DbgAction nAct, void* pParam )
215 {
216  if( Start() )
217  { // We reach this point if SwProtocol::nRecord is binary OR'd with PROT::Init(0x1) using the debugger
218  bool bFinit = false; // This gives the possibility to stop logging of this action in the debugger
219  if( bFinit )
220  {
221  nRecord &= ~nFunction; // Don't log this function any longer
222  nRecord &= ~PROT::Init; // Always reset PROT::Init
223  return;
224  }
225  nRecord |= nFunction; // Activate logging of this function
226  nRecord &= ~PROT::Init; // Always reset PROT::Init
227  if( pImpl )
228  pImpl->ChkStream();
229  }
230  if( !pImpl ) // Create Impl object if needed
231  pImpl = new SwImplProtocol();
232  pImpl->Record( pFrame, nFunction, nAct, pParam ); // ...and start logging
233 }
234 
235 // The following function gets called when pulling in the writer DLL through
236 // TextInit(..) and gives the possibility to release functions
237 // and/or FrameIds to the debugger
238 
240 {
242  OUString aName("dbg_lay.go");
243  SvFileStream aStream( aName, StreamMode::READ );
244  if( aStream.IsOpen() )
245  {
246  pImpl = new SwImplProtocol();
247  pImpl->FileInit();
248  }
249  aStream.Close();
250 }
251 
252 // End of logging
253 
255 {
256  if( pImpl )
257  {
258  delete pImpl;
259  pImpl = nullptr;
260  if( pFntCache )
261  pFntCache->Flush();
262  }
264 }
265 
267  : nTypes( FRM_ALL ),
268  nLineCount( 0 ), nMaxLines( USHRT_MAX ), nTestMode( 0 )
269 {
270  NewStream();
271 }
272 
274 {
275  OUString aName("dbg_lay.out");
276  nLineCount = 0;
277  pStream.reset( new SvFileStream( aName, StreamMode::WRITE | StreamMode::TRUNC ) );
278  if( pStream->GetError() )
279  {
280  pStream.reset();
281  }
282  return nullptr != pStream;
283 }
284 
286 {
287  if( pStream )
288  {
289  pStream->Close();
290  pStream.reset();
291  }
292  pFrameIds.reset();
293  aVars.clear();
294 }
295 
297 void SwImplProtocol::CheckLine( OString& rLine )
298 {
299  rLine = rLine.toAsciiLowerCase(); // upper/lower case is the same
300  rLine = rLine.replace( '\t', ' ' );
301  if( '#' == rLine[0] ) // comments start with '#'
302  return;
303  if( '[' == rLine[0] ) // section: FrameIds, type or function
304  {
305  OString aTmp = rLine.getToken(0, ']');
306  if (aTmp == "[frmid") // section FrameIds
307  {
308  nInitFile = 1;
309  pFrameIds.reset(); // default: log all frames
310  }
311  else if (aTmp == "[frmtype")// section types
312  {
313  nInitFile = 2;
314  nTypes = FRM_ALL; // default: log all frame types
315  }
316  else if (aTmp == "[record")// section functions
317  {
318  nInitFile = 3;
319  SwProtocol::SetRecord( PROT::FileInit );// default: don't log any function
320  }
321  else if (aTmp == "[test")// section functions
322  {
323  nInitFile = 4; // default:
324  nTestMode = 0; // log outside of test formatting
325  }
326  else if (aTmp == "[max")// Max number of lines
327  {
328  nInitFile = 5; // default:
330  }
331  else if (aTmp == "[var")// variables
332  {
333  nInitFile = 6;
334  }
335  else
336  nInitFile = 0; // oops: unknown section?
337  rLine = rLine.copy(aTmp.getLength() + 1);
338  }
339 
340  // spaces (or tabs) are the delimiter
341  sal_Int32 nIndex = 0;
342  do
343  {
344  OString aTok = rLine.getToken( 0, ' ', nIndex );
345  bool bNo = false;
346  if( !aTok.isEmpty() && '!' == aTok[0] )
347  {
348  bNo = true; // remove this function/type
349  aTok = aTok.copy(1);
350  }
351  if( !aTok.isEmpty() )
352  {
353  sal_Int64 nVal = aTok.toInt64();
354  switch ( nInitFile )
355  {
356  case 1: InsertFrame( sal_uInt16( nVal ) ); // add FrameId
357  break;
358  case 2: {
359  SwFrameType nNew = static_cast<SwFrameType>(nVal);
360  if( bNo )
361  nTypes &= ~nNew; // remove type
362  else
363  nTypes |= nNew; // add type
364  }
365  break;
366  case 3: {
367  PROT nOld = SwProtocol::Record();
368  if( bNo )
369  nOld &= ~PROT(nVal); // remove function
370  else
371  nOld |= PROT(nVal); // remove function
372  SwProtocol::SetRecord( nOld );
373  }
374  break;
375  case 4: {
376  sal_uInt8 nNew = static_cast<sal_uInt8>(nVal);
377  if( bNo )
378  nTestMode &= ~nNew; // reset test mode
379  else
380  nTestMode |= nNew; // set test mode
381  }
382  break;
383  case 5: nMaxLines = static_cast<sal_uInt16>(nVal);
384  break;
385  case 6: aVars.push_back( nVal );
386  break;
387  }
388  }
389  }
390  while ( nIndex >= 0 );
391 }
392 
395 {
396  OUString aName("dbg_lay.ini");
397  SvFileStream aStream( aName, StreamMode::READ );
398  if( aStream.IsOpen() )
399  {
400  OString aLine;
401  nInitFile = 0;
402  while( aStream.good() )
403  {
404  sal_Char c;
405  aStream.ReadChar( c );
406  if( '\n' == c || '\r' == c ) // line ending
407  {
408  aLine = aLine.trim();
409  if( !aLine.isEmpty() )
410  CheckLine( aLine ); // evaluate line
411  aLine.clear();
412  }
413  else
414  aLine += OString(c);
415  }
416  if( !aLine.isEmpty() )
417  CheckLine( aLine ); // evaluate last line
418  }
419  aStream.Close();
420 }
421 
423 static void lcl_Start(OStringBuffer& rOut, OStringBuffer& rLay, DbgAction nAction)
424 {
425  if( nAction == DbgAction::Start )
426  {
427  rLay.append(" ");
428  rOut.append(" On");
429  }
430  else if( nAction == DbgAction::End )
431  {
432  if( rLay.getLength() > 1 )
433  {
434  rLay.remove(rLay.getLength() - 2, rLay.getLength());
435  rOut.remove(0, 2);
436  }
437  rOut.append(" Off");
438  }
439 }
440 
443 static void lcl_Flags(OStringBuffer& rOut, const SwFrame* pFrame)
444 {
445  rOut.append(" ValidSize");
446  rOut.append(pFrame->isFrameAreaSizeValid() ? '+' : '-');
447  rOut.append(" ValidPos");
448  rOut.append(pFrame->isFrameAreaPositionValid() ? '+' : '-');
449  rOut.append(" ValidPrtArea");
450  rOut.append(pFrame->isFramePrintAreaValid() ? '+' : '-');
451 }
452 
453 static void lcl_Padded(OStringBuffer& rOut, const OString& s, size_t length)
454 {
455  rOut.append(s);
456  for (size_t i = 0; i < length - s.getLength(); i++)
457  {
458  rOut.append(" ");
459  }
460 }
461 
462 static void lcl_Padded(OStringBuffer& rOut, const long n, size_t length = 5)
463 {
464  sal_Char sz[RTL_STR_MAX_VALUEOFINT64];
465  rtl_str_valueOfInt64(sz, n, 10);
466  OString s(sz);
467  lcl_Padded(rOut, s, length);
468 }
469 
471 static void lcl_FrameRect(OStringBuffer& rOut, const char* hint, const SwRect& rect)
472 {
473  rOut.append("[");
474  rOut.append(hint);
475  rOut.append(":X:");
476  lcl_Padded(rOut, rect.Pos().X());
477  rOut.append(", Y:");
478  lcl_Padded(rOut, rect.Pos().Y());
479  rOut.append(", Width:");
480  lcl_Padded(rOut, rect.SSize().Width());
481  rOut.append(", Height:");
482  lcl_Padded(rOut, rect.SSize().Height());
483  rOut.append("] ");
484 }
485 
486 static OString lcl_TableInfo(const SwTabFrame* pTabFrame)
487 {
488  const SwTable* pTable = pTabFrame->GetTable();
489  const SwModify* pModify = pTable->GetRegisteredIn();
490  const SwFormat* pFormat = static_cast<const SwFormat*>(pModify);
491  const OUString& text = pFormat->GetName();
492  return OUStringToOString(text, RTL_TEXTENCODING_ASCII_US);
493 }
494 
495 static OString lcl_RowInfo(const SwRowFrame* pFrame)
496 {
497  // dummy, needs actual functionality...
498  if (pFrame == nullptr)
499  return "";
500  const SwTableLine* pTabLine = pFrame->GetTabLine();
501  if (pTabLine == nullptr)
502  return "";
503 
504  return "RowInfo";
505 }
506 
507 static OUString lcl_CellText(const SwCellFrame* pFrame)
508 {
509  OUString result;
510  int n = 0;
511  sal_Char sz[RTL_STR_MAX_VALUEOFINT64];
512 
513  const SwStartNode* pStartNode = pFrame->GetTabBox()->GetSttNd();
514  const SwEndNode* pEndNode = pStartNode->EndOfSectionNode();
515  const SwNodes& nodes = pStartNode->GetNodes();
516 
517  for (sal_uLong i = pStartNode->GetIndex(); i < nodes.Count(); i++)
518  {
519  SwNode* pNode = nodes[i];
520 
521  if (pNode->IsEndNode())
522  {
523  if (pNode->EndOfSectionNode() == pEndNode)
524  break;
525  }
526  else if (pNode->IsTextNode())
527  {
528  n++;
529  result += "Para:";
530  rtl_str_valueOfInt64(sz, n, 10);
531  OUString s = OUString::createFromAscii(sz);
532  result += s;
533  result += " ";
534  result += pNode->GetTextNode()->GetText();
535  }
536  }
537 
538  rtl_str_valueOfInt64(sz, n, 10);
539  OUString s = OUString::createFromAscii(sz);
540  s += " para(s):";
541  s += result;
542 
543  return s;
544 }
545 
546 static OString lcl_CellInfo(const SwCellFrame* pFrame)
547 {
548  const OUString text = "CellInfo: " + pFrame->GetTabBox()->GetName() + " Text: " + lcl_CellText(pFrame);
549  return OUStringToOString(text, RTL_TEXTENCODING_ASCII_US);
550 }
551 
553 static void lcl_FrameType( OStringBuffer& rOut, const SwFrame* pFrame )
554 {
555  if( pFrame->IsTextFrame() )
556  rOut.append("SwTextFrame ");
557  else if( pFrame->IsLayoutFrame() )
558  {
559  if( pFrame->IsPageFrame() )
560  rOut.append("SwPageFrame ");
561  else if( pFrame->IsColumnFrame() )
562  rOut.append("SwColumnFrame ");
563  else if( pFrame->IsBodyFrame() )
564  {
565  if( pFrame->GetUpper() && pFrame->IsColBodyFrame() )
566  rOut.append("(Col)");
567  rOut.append("SwBodyFrame ");
568  }
569  else if( pFrame->IsRootFrame() )
570  rOut.append("SwRootFrame ");
571  else if( pFrame->IsCellFrame() )
572  rOut.append("SwCellFrame ");
573  else if( pFrame->IsTabFrame() )
574  rOut.append("SwTabFrame ");
575  else if( pFrame->IsRowFrame() )
576  rOut.append("SwRowFrame ");
577  else if( pFrame->IsSctFrame() )
578  rOut.append("SwSectionFrame ");
579  else if( pFrame->IsHeaderFrame() )
580  rOut.append("SwHeaderFrame ");
581  else if( pFrame->IsFooterFrame() )
582  rOut.append("SwFooterFrame ");
583  else if( pFrame->IsFootnoteFrame() )
584  rOut.append("SwFootnoteFrame ");
585  else if( pFrame->IsFootnoteContFrame() )
586  rOut.append("SwFootnoteContFrame ");
587  else if( pFrame->IsFlyFrame() )
588  rOut.append("SwFlyFrame ");
589  else
590  rOut.append("SwLayoutFrame ");
591  }
592  else if( pFrame->IsNoTextFrame() )
593  rOut.append("SwNoTextFrame");
594  else
595  rOut.append("Not impl. ");
596 }
597 
604 void SwImplProtocol::Record_( const SwFrame* pFrame, PROT nFunction, DbgAction nAct, void* pParam )
605 {
606  sal_uInt16 nSpecial = 0;
607  if( nSpecial ) // the possible debugger manipulations
608  {
609  sal_uInt16 nId = sal_uInt16(lcl_GetFrameId( pFrame ));
610  switch ( nSpecial )
611  {
612  case 1: InsertFrame( nId ); break;
613  case 2: DeleteFrame( nId ); break;
614  case 3: pFrameIds.reset(); break;
615  case 4: pStream.reset(); break;
616  }
617  return;
618  }
619  if( !pStream && !NewStream() )
620  return; // still no stream
621 
622  if( pFrameIds && !pFrameIds->count( sal_uInt16(lcl_GetFrameId( pFrame )) ) )
623  return; // doesn't belong to the wished FrameIds
624 
625  if( !(pFrame->GetType() & nTypes) )
626  return; // the type is unwanted
627 
628  if( 1 == nTestMode && nFunction != PROT::TestFormat )
629  return; // we may only log inside a test formatting
630  bool bTmp = false;
631  OStringBuffer aOut(aLayer);
632  aOut.append(static_cast<sal_Int64>(lcl_GetFrameId(pFrame)));
633  aOut.append(' ');
634  lcl_FrameType( aOut, pFrame ); // then the frame type
635  switch ( nFunction ) // and the function
636  {
637  case PROT::MakeAll: aOut.append("SwFrame::MakeAll");
638  lcl_Start( aOut, aLayer, nAct );
639  if( nAct == DbgAction::Start )
640  lcl_Flags( aOut, pFrame );
641  break;
642  case PROT::MoveFwd: bTmp = true;
643  [[fallthrough]];
644  case PROT::MoveBack:
645  if (nFunction == (bTmp ? PROT::Init : PROT::FileInit))
646  aOut.append("SwFlowFrame::MoveFwd");
647  else
648  aOut.append("SwFlowFrame::MoveBwd");
649  lcl_Start( aOut, aLayer, nAct );
650  if( pParam )
651  {
652  aOut.append(' ');
653  aOut.append(static_cast<sal_Int32>(*static_cast<sal_uInt16*>(pParam)));
654  }
655  break;
656  case PROT::GrowTest:
657  aOut.append("SwFrame::Grow (test)");
658  lcl_Start( aOut, aLayer, nAct );
659  break;
660  case PROT::ShrinkTest:
661  aOut.append("SwFrame::Shrink (test)");
662  lcl_Start( aOut, aLayer, nAct );
663  break;
664  case PROT::AdjustN :
665  case PROT::Shrink: bTmp = true;
666  [[fallthrough]];
667  case PROT::Grow:
668  if (!bTmp)
669  aOut.append("SwFrame::Grow");
670  else
671  {
672  if (nFunction == PROT::Shrink)
673  aOut.append("SwFrame::Shrink");
674  else
675  aOut.append("SwFrame::AdjustNeighbourhood");
676  }
677  lcl_Start( aOut, aLayer, nAct );
678  if( pParam )
679  {
680  aOut.append(' ');
681  aOut.append(static_cast<sal_Int64>(*static_cast<long*>(pParam)));
682  }
683  break;
684  case PROT::PrintArea: aOut.append("PROT::PrintArea");
685  lcl_Start( aOut, aLayer, nAct );
686  break;
687  case PROT::Size: aOut.append("PROT::Size");
688  lcl_Start( aOut, aLayer, nAct );
689  aOut.append(' ');
690  aOut.append(static_cast<sal_Int64>(pFrame->getFrameArea().Height()));
691  break;
692  case PROT::Leaf: aOut.append("SwFrame::GetPrev/NextSctLeaf");
693  lcl_Start( aOut, aLayer, nAct );
694  aOut.append(' ');
695  if( pParam )
696  {
697  aOut.append(' ');
698  aOut.append(static_cast<sal_Int64>(lcl_GetFrameId(static_cast<SwFrame*>(pParam))));
699  }
700  break;
701  case PROT::FileInit: FileInit();
702  aOut.append("Initialize");
703  break;
704  case PROT::Section: SectFunc(aOut, nAct, pParam);
705  break;
706  case PROT::Cut: bTmp = true;
707  [[fallthrough]];
708  case PROT::Paste:
709  if (bTmp)
710  aOut.append("PROT::Cut from ");
711  else
712  aOut.append("PROT::Paste to ");
713  aOut.append(static_cast<sal_Int64>(lcl_GetFrameId(static_cast<SwFrame*>(pParam))));
714  break;
715  case PROT::TestFormat:
716  aOut.append("SwTextFrame::TestFormat");
717  lcl_Start( aOut, aLayer, nAct );
718  if( DbgAction::Start == nAct )
719  nTestMode |= 2;
720  else
721  nTestMode &= ~2;
722  break;
723  case PROT::FrmChanges:
724  {
725  SwRect& rFrame = *static_cast<SwRect*>(pParam);
726  if( pFrame->getFrameArea().Pos() != rFrame.Pos() )
727  {
728  aOut.append("PosChg: (");
729  aOut.append(static_cast<sal_Int64>(rFrame.Left()));
730  aOut.append(", ");
731  aOut.append(static_cast<sal_Int64>(rFrame.Top()));
732  aOut.append(") -> (");
733  aOut.append(static_cast<sal_Int64>(pFrame->getFrameArea().Left()));
734  aOut.append(", ");
735  aOut.append(static_cast<sal_Int64>(pFrame->getFrameArea().Top()));
736  aOut.append(") ");
737  }
738  if( pFrame->getFrameArea().Height() != rFrame.Height() )
739  {
740  aOut.append("Height: ");
741  aOut.append(static_cast<sal_Int64>(rFrame.Height()));
742  aOut.append(" -> ");
743  aOut.append(static_cast<sal_Int64>(pFrame->getFrameArea().Height()));
744  aOut.append(" ");
745  }
746  if( pFrame->getFrameArea().Width() != rFrame.Width() )
747  {
748  aOut.append("Width: ");
749  aOut.append(static_cast<sal_Int64>(rFrame.Width()));
750  aOut.append(" -> ");
751  aOut.append(static_cast<sal_Int64>(pFrame->getFrameArea().Width()));
752  aOut.append(' ');
753  }
754  break;
755  }
756  default: break;
757  }
758 
759  aOut.append(" ");
760  while (aOut.getLength() < 40) aOut.append(" ");
761  lcl_FrameRect(aOut, "SwFrame", pFrame->getFrameArea());
762 
763  aOut.append(" ");
764  while (aOut.getLength() < 90) aOut.append(" ");
765  lcl_FrameRect(aOut, "SwPrint", pFrame->getFramePrintArea());
766 
767  if (pFrame->IsTextFrame())
768  {
769  aOut.append(" ");
770  while (aOut.getLength() < 140) aOut.append(" ");
771  const OUString& text = static_cast<const SwTextFrame*>(pFrame)->GetText();
772  OString o = OUStringToOString(text, RTL_TEXTENCODING_ASCII_US);
773  aOut.append(o);
774  }
775  else if (pFrame->IsTabFrame())
776  {
777  const SwTabFrame* pTabFrame = static_cast<const SwTabFrame*>(pFrame);
778  aOut.append(lcl_TableInfo(pTabFrame));
779  }
780  else if (pFrame->IsRowFrame())
781  {
782  const SwRowFrame* pRowFrame = static_cast<const SwRowFrame*>(pFrame);
783  aOut.append(lcl_RowInfo(pRowFrame));
784 
785  }
786  else if (pFrame->IsCellFrame())
787  {
788  const SwCellFrame* pCellFrame = static_cast<const SwCellFrame*>(pFrame);
789  aOut.append(lcl_CellInfo(pCellFrame));
790  }
791 
792  pStream->WriteCharPtr( aOut.getStr() );
793  (*pStream) << endl; // output
794  pStream->Flush(); // to the disk, so we can read it immediately
795  SAL_INFO("sw.layout.debug", aOut.getStr());
796  if( ++nLineCount >= nMaxLines ) // max number of lines reached?
797  {
798  SAL_WARN("sw.layout.debug", "max number of lines reached");
799  SwProtocol::SetRecord( PROT::FileInit ); // => end f logging
800  }
801 }
802 
804 void SwImplProtocol::SectFunc(OStringBuffer &rOut, DbgAction nAct, void const * pParam)
805 {
806  bool bTmp = false;
807  switch( nAct )
808  {
809  case DbgAction::Merge: rOut.append("Merge Section ");
810  rOut.append(static_cast<sal_Int64>(lcl_GetFrameId(static_cast<SwFrame const *>(pParam))));
811  break;
812  case DbgAction::CreateMaster: bTmp = true;
813  [[fallthrough]];
814  case DbgAction::CreateFollow: rOut.append("Create Section ");
815  if (bTmp)
816  rOut.append("Master to ");
817  else
818  rOut.append("Follow from ");
819  rOut.append(static_cast<sal_Int64>(lcl_GetFrameId(static_cast<SwFrame const *>(pParam))));
820  break;
821  case DbgAction::DelMaster: bTmp = true;
822  [[fallthrough]];
823  case DbgAction::DelFollow: rOut.append("Delete Section ");
824  if (bTmp)
825  rOut.append("Master to ");
826  else
827  rOut.append("Follow from ");
828  rOut.append(static_cast<sal_Int64>(lcl_GetFrameId(static_cast<SwFrame const *>(pParam))));
829  break;
830  default: break;
831  }
832 }
833 
841 void SwImplProtocol::InsertFrame( sal_uInt16 nId )
842 {
843  if( !pFrameIds )
844  pFrameIds.reset( new std::set<sal_uInt16> );
845  if( pFrameIds->count( nId ) )
846  return;
847  pFrameIds->insert( nId );
848 }
849 
851 void SwImplProtocol::DeleteFrame( sal_uInt16 nId )
852 {
853  if( !pFrameIds )
854  return;
855  pFrameIds->erase(nId);
856 }
857 
858 /*
859  * The task here is to find the right SwImplEnterLeave object based on the
860  * function; everything else is then done in his Ctor/Dtor.
861  */
862 SwEnterLeave::SwEnterLeave( const SwFrame* pFrame, PROT nFunc, DbgAction nAct, void* pPar )
863 {
864  if( !SwProtocol::Record( nFunc ) )
865  return;
866  switch( nFunc )
867  {
868  case PROT::AdjustN :
869  case PROT::Grow:
870  case PROT::Shrink : pImpl.reset( new SwSizeEnterLeave( pFrame, nFunc, nAct, pPar ) ); break;
871  case PROT::MoveFwd:
872  case PROT::MoveBack : pImpl.reset( new SwUpperEnterLeave( pFrame, nFunc, nAct, pPar ) ); break;
873  case PROT::FrmChanges : pImpl.reset( new SwFrameChangesLeave( pFrame, nFunc, nAct, pPar ) ); break;
874  default: pImpl.reset( new SwImplEnterLeave( pFrame, nFunc, nAct, pPar ) ); break;
875  }
876  pImpl->Enter();
877 }
878 
879 /* This is not inline because we don't want the SwImplEnterLeave definition inside
880  * dbg_lay.hxx.
881  */
883 {
884  if (pImpl)
885  pImpl->Leave();
886 }
887 
889 {
891 }
892 
894 {
896 }
897 
899 {
902 }
903 
905 {
906  nFrameId = pFrame->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrame->GetUpper() )) : 0;
908 }
909 
911 {
912  nFrameId = pFrame->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrame->GetUpper() )) : 0;
914 }
915 
917 {
918 }
919 
921 {
922  if( pFrame->getFrameArea() != aFrame )
924 }
925 
926 #endif // DBG_UTIL
927 
928 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
Starts a section of nodes in the document model.
Definition: node.hxx:303
void Record(const SwFrame *pFrame, PROT nFunction, DbgAction nAct, void *pParam)
Definition: dbg_lay.cxx:148
SwUpperEnterLeave(const SwFrame *pF, PROT nFunct, DbgAction nAct, void *pPar)
Definition: dbg_lay.cxx:196
Base class of the Writer layout elements.
Definition: frame.hxx:295
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
sal_uLong GetIndex() const
Definition: node.hxx:282
sal_uLong Count() const
Definition: ndarr.hxx:143
OStringBuffer aLayer
Definition: dbg_lay.cxx:134
virtual void Enter() override
Definition: dbg_lay.cxx:916
std::unique_ptr< std::set< sal_uInt16 > > pFrameIds
Definition: dbg_lay.cxx:132
bool IsRootFrame() const
Definition: frame.hxx:1150
virtual ~SwImplEnterLeave()
Definition: dbg_lay.cxx:177
std::unique_ptr< SvFileStream > pStream
Definition: dbg_lay.cxx:131
std::vector< long > aVars
Definition: dbg_lay.cxx:133
const OUString & GetText() const
Definition: ndtxt.hxx:211
void *const pParam
Definition: dbg_lay.cxx:173
const SwTable * GetTable() const
Definition: tabfrm.hxx:142
virtual void Enter() override
Definition: dbg_lay.cxx:904
SwFrameType GetType() const
Definition: frame.hxx:498
SwFrameChangesLeave(const SwFrame *pF, PROT nFunct, DbgAction nAct, void *pPar)
Definition: dbg_lay.cxx:207
sal_uIntPtr sal_uLong
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
void Height(long nNew)
Definition: swrect.hxx:189
sal_Int16 nId
PROT
Definition: dbg_lay.hxx:26
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
virtual void Leave() override
Definition: dbg_lay.cxx:910
SwSizeEnterLeave(const SwFrame *pF, PROT nFunct, DbgAction nAct, void *pPar)
Definition: dbg_lay.cxx:186
sal_uInt8 nTestMode
Definition: dbg_lay.cxx:139
void Pos(const Point &rNew)
Definition: swrect.hxx:167
static PROT Record()
Definition: dbg_lay.hxx:72
bool IsCellFrame() const
Definition: frame.hxx:1202
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
void CheckLine(OString &rLine)
analyze a line in the INI file
Definition: dbg_lay.cxx:297
static bool Start()
Definition: dbg_lay.hxx:69
static OString lcl_TableInfo(const SwTabFrame *pTabFrame)
Definition: dbg_lay.cxx:486
bool IsFootnoteFrame() const
Definition: frame.hxx:1178
SwEnterLeave(const SwFrame *pFrame, PROT nFunc, DbgAction nAct, void *pPar)
Definition: dbg_lay.cxx:862
void InsertFrame(sal_uInt16 nFrameId)
if pFrameIds==NULL all Frames will be logged.
Definition: dbg_lay.cxx:841
bool IsFlyFrame() const
Definition: frame.hxx:1186
void Top(const long nTop)
Definition: swrect.hxx:202
const SwTableBox * GetTabBox() const
Definition: cellfrm.hxx:52
const SwRect & getFrameArea() const
Definition: frame.hxx:175
char sal_Char
SwImplEnterLeave(const SwFrame *pF, PROT nFunct, DbgAction nAct, void *pPar)
Definition: dbg_lay.cxx:175
length
const OUString & GetName() const
Definition: format.hxx:111
bool IsTextFrame() const
Definition: frame.hxx:1210
void Flush()
Definition: fntcache.cxx:165
static void lcl_Flags(OStringBuffer &rOut, const SwFrame *pFrame)
output the ValidSize-, ValidPos- and ValidPrtArea-Flag ("Sz","Ps","PA") of the frame; "+" stands for ...
Definition: dbg_lay.cxx:443
#define FRM_ALL
Definition: frame.hxx:100
static void SectFunc(OStringBuffer &rOut, DbgAction nAct, void const *pParam)
Handle the output of the SectionFrames.
Definition: dbg_lay.cxx:804
bool IsSctFrame() const
Definition: frame.hxx:1190
void DeleteFrame(sal_uInt16 nFrameId)
Removes a FrameId from the pFrameIds array, so that it won't be logged anymore.
Definition: dbg_lay.cxx:851
static void SetRecord(PROT nNew)
Definition: dbg_lay.hxx:73
SwFrameType nTypes
Definition: dbg_lay.cxx:135
DbgAction
Definition: dbg_lay.hxx:50
sal_uInt8 nInitFile
Definition: dbg_lay.cxx:138
Base class for various Writer styles.
Definition: format.hxx:43
bool IsColumnFrame() const
Definition: frame.hxx:1158
OUString GetName() const
Definition: swtable.cxx:1828
static sal_uLong lcl_GetFrameId(const SwFrame *pFrame)
Definition: dbg_lay.cxx:117
static SwImplProtocol * pImpl
Definition: dbg_lay.hxx:68
static void Init()
Definition: dbg_lay.cxx:239
SwFrameType
Definition: frame.hxx:72
static void lcl_FrameRect(OStringBuffer &rOut, const char *hint, const SwRect &rect)
output the frame as plain text.
Definition: dbg_lay.cxx:471
PROT const nFunction
Definition: dbg_lay.cxx:171
MetadataImporterPluginType * result
int i
virtual void Leave() override
Definition: dbg_lay.cxx:920
SwLayoutFrame * GetUpper()
Definition: frame.hxx:656
bool isFramePrintAreaValid() const
Definition: frame.hxx:164
bool IsRowFrame() const
Definition: frame.hxx:1198
static PROT nRecord
Definition: dbg_lay.hxx:67
sal_uInt16 nLineCount
Definition: dbg_lay.cxx:136
virtual void Enter()
Definition: dbg_lay.cxx:888
bool IsEndNode() const
Definition: node.hxx:632
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:693
bool isFrameAreaPositionValid() const
Definition: frame.hxx:162
void SSize(const Size &rNew)
Definition: swrect.hxx:176
bool isFrameAreaSizeValid() const
Definition: frame.hxx:163
SwFntCache * pFntCache
Definition: fntcache.cxx:66
static void lcl_Padded(OStringBuffer &rOut, const OString &s, size_t length)
Definition: dbg_lay.cxx:453
static OUString lcl_CellText(const SwCellFrame *pFrame)
Definition: dbg_lay.cxx:507
static void lcl_Start(OStringBuffer &rOut, OStringBuffer &rLay, DbgAction nAction)
enable indentation by two spaces during DbgAction::Start and disable it again at DbgAction::End.
Definition: dbg_lay.cxx:423
static OString lcl_CellInfo(const SwCellFrame *pFrame)
Definition: dbg_lay.cxx:546
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:110
static void lcl_FrameType(OStringBuffer &rOut, const SwFrame *pFrame)
output the type of the frame as plain text.
Definition: dbg_lay.cxx:553
DbgAction const nAction
Definition: dbg_lay.cxx:172
OString OUStringToOString(const OUString &str, ConnectionSettings const *settings)
sal_uInt16 nFrameId
Definition: dbg_lay.cxx:194
bool IsLayoutFrame() const
Definition: frame.hxx:1146
void Left(const long nLeft)
Definition: swrect.hxx:193
virtual void Leave()
Definition: dbg_lay.cxx:893
SvStream & ReadChar(char &rChar)
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:439
static void Stop()
Definition: dbg_lay.cxx:254
bool IsTabFrame() const
Definition: frame.hxx:1194
void ChkStream()
Definition: dbg_lay.cxx:153
unsigned char sal_uInt8
void Width(long nNew)
Definition: swrect.hxx:185
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:259
SvStream & endl(SvStream &rStr)
#define SAL_INFO(area, stream)
bool IsNoTextFrame() const
Definition: frame.hxx:1214
const SwModify * GetRegisteredIn() const
Definition: calbck.hxx:157
bool IsColBodyFrame() const
These SwFrame inlines are here, so that frame.hxx does not need to include layfrm.hxx.
Definition: layfrm.hxx:208
void Record_(const SwFrame *pFrame, PROT nFunction, DbgAction nAct, void *pParam)
Is only called if the PROTOCOL macro finds out, that this function should be recorded (...
Definition: dbg_lay.cxx:604
bool NewStream()
Definition: dbg_lay.cxx:273
bool IsPageFrame() const
Definition: frame.hxx:1154
static OString lcl_RowInfo(const SwRowFrame *pFrame)
Definition: dbg_lay.cxx:495
bool good() const
def text(shape, st)
OString const aName
sal_uInt16 nMaxLines
Definition: dbg_lay.cxx:137
void FileInit()
read the file "dbg_lay.ini" in the current directory and evaluate it.
Definition: dbg_lay.cxx:394
#define SAL_WARN(area, stream)
Ends a section of nodes in the document model.
Definition: node.hxx:333
const SwTableLine * GetTabLine() const
Definition: rowfrm.hxx:68
bool IsFootnoteContFrame() const
Definition: frame.hxx:1174
bool IsBodyFrame() const
Definition: frame.hxx:1182
const int nLineCount
bool IsTextNode() const
Definition: node.hxx:636
bool IsFooterFrame() const
Definition: frame.hxx:1170
const SwFrame * pFrame
Definition: dbg_lay.cxx:170
std::unique_ptr< SwImplEnterLeave > pImpl
Definition: dbg_lay.hxx:82
sal_uInt32 GetFrameId() const
Definition: frame.hxx:170
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
bool IsOpen() const
bool IsHeaderFrame() const
Definition: frame.hxx:1166
virtual void Leave() override
Definition: dbg_lay.cxx:898
Base class of the Writer document model elements.
Definition: node.hxx:79