DISCLAIMER: This page contains some random notes about the code. It may not be true and will evolve with the progress of my understanding of the Sw code.
In order to get a human-readable representation of the internals for a document do the following:
- export SW_DEBUG=t
- ./soffice.bin path/to/the/document
- Hit F12 to dump the layout structure in $PWD/layout.xml or Shift-F12 to dump the document model structure in $PWD/nodes.xml
- For layout debugging, try OSL_DEBUG_LAYOUT values 1 and more
Getting the attributes for a SwPaM
SwUnoCursorHelper::GetCrsrAttr() is a nice example for this, here is an (untested) example from it:
SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_CHRATR_END -1, 0 ); // TODO Get an SwTxtNode pNd and a xub_StrLen nStart and nEnd offset from the SwPaM static_cast<SwTxtNode*>(pNd)->GetAttr(aCharAttrsAtPaM, nStart, nEnd, bOnlyTxtAttr, bGetFromChrFmt); // Do something with aCharAttrsAtPaM
In Writer, sfx2 structures for styles aren't really used: sw is only emulating them to show styles in some common dialogs like Styles and Formatting
From paragraph to lines
- SwTxtFrm::_Format and/or SwTxtFrm::FormatQuick will break the paragraph to lines.
- The hard job is done by the SwTxtFormatter class.
- SwTxtFormatter::Insert( ) adds a new line, but the SwTxtFormatter::Next() method needs to be called to current line to process
- A line is split into portions by SwTxtFormatter::BuildPortions( )
- The Y-position of a line is taken from the SwTxtFormatter::Y(). This position is also depending on the presence of fly objects in the line area.
- To keep white space to show an overlapping fly frame on a line, a special portion is added: SwFlyPortion
- Paragraphs are reformatted after positioning a Frame or Draw object to update the line positions.
- See SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara for the draw object case.
- See SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs for the text frame case
- For debugging this, place a breakpoint in SwTxtIter::Init(). To break only for the formatting of a given frame, just add a condition like the following one condition 1 this->pFrm->mnFrmId == 100 where 100 is the id of the frame to debug. Then, use data breakpoints to monitor the changes of the nY value.
I got the following informations from Oliver Rainer-Wittman's talk in Orvieto.
- One draw model + one draw page
- Invisible Layers: to hide objects in hidden parts of the document (eg: hidden sections)
- Virtual Drawing Object: Placeholder for repeated objects (eg, objects in header/footers)
- Convert an SwPosition into a screen position is possible using SwTxtFrm::GetCharRect( )
- The difference between SwFrm::Frm() and SwFrm::Prt() seems to be only when we have borders around the frame (See this comment)
- editeng/inc/editeng/borderline.hxx: definition of the data structure for the borders.
- sw/source/core/layout/paintfrm.cxx: contains the code for drawing the border lines in Writer. SwFrm::PaintBorderLine and lcl_PaintLeftRightLine for more details.
- See DrawHorFrameBorder and DrawVerFrameBorder for the table borders drawing. This is used in calc as well.
Here are some random notes from what I learned when hacking the InfoBars:
- Give the focus to the document: pViewFrame()->GetWindow()->GrabFocusToDocument( )
- Adding a new UI element:
- create a new SfxChildWindow class. This is used to register the Window in the SfxFrame children.
- The new FooChildWindow constructor needs to create the vcl Window to show.
- To get inspiration from other ChildWindows, grok for SwInputChild (the formula bar in Writer).
- Updating the SfxFrame children from the SfxChildWindow:
- Make sure you have stored the SfxBindings* as a member: it'll provide the way back to the SfxViewFrame
- Get the hand on the SfxViewFrame: m_pBindings->GetDispatcher( )->GetFrame( )
- Use ShowChildWindow( nId ) to update the child window. SetPosSizePixel( ) on the Window object of your Child window won't be used unless this is called.