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 
10 #include <frame.hxx>
11 #include <frmfmt.hxx>
12 #include <ftnfrm.hxx>
13 #include <sectfrm.hxx>
14 #include <tabfrm.hxx>
15 #include <pagefrm.hxx>
16 #include <txtfrm.hxx>
17 #include <cellfrm.hxx>
18 #include <hffrm.hxx>
19 #include <rootfrm.hxx>
20 #include <editsh.hxx>
21 #include <ndtxt.hxx>
22 #include "porlin.hxx"
23 #include "porlay.hxx"
24 #include "portxt.hxx"
25 #include <sortedobjs.hxx>
26 #include <swfont.hxx>
27 #include <anchoredobject.hxx>
28 #include <libxml/xmlwriter.h>
29 #include <SwPortionHandler.hxx>
30 #include <view.hxx>
31 #include <svx/svdobj.hxx>
32 
33 class XmlPortionDumper:public SwPortionHandler
34 {
35   private:
36     xmlTextWriterPtr const writer;
37     TextFrameIndex ofs;
38     const OUString& m_rText;
39     OUString m_aLine;
40 
getTypeName(PortionType nType)41     static const char* getTypeName( PortionType nType )
42     {
43         switch ( nType )
44         {
45             case PortionType::NONE: return "PortionType::NONE";
46             case PortionType::FlyCnt: return "PortionType::FlyCnt";
47 
48             case PortionType::Hole: return "PortionType::Hole";
49             case PortionType::TempEnd: return "PortionType::TempEnd";
50             case PortionType::Break: return "PortionType::Break";
51             case PortionType::Kern: return "PortionType::Kern";
52             case PortionType::Arrow: return "PortionType::Arrow";
53             case PortionType::Multi: return "PortionType::Multi";
54             case PortionType::HiddenText: return "PortionType::HiddenText";
55             case PortionType::ControlChar: return "PortionType::ControlChar";
56 
57             case PortionType::Text: return "PortionType::Text";
58             case PortionType::Lay: return "PortionType::Lay";
59             case PortionType::Para: return "PortionType::Para";
60             case PortionType::Hanging: return "PortionType::Hanging";
61 
62             case PortionType::Drop: return "PortionType::Drop";
63             case PortionType::Tox: return "PortionType::Tox";
64             case PortionType::IsoTox: return "PortionType::IsoTox";
65             case PortionType::Ref: return "PortionType::Ref";
66             case PortionType::IsoRef: return "PortionType::IsoRef";
67             case PortionType::Meta: return "PortionType::Meta";
68             case PortionType::FieldMark: return "PortionType::FieldMark";
69             case PortionType::FieldFormCheckbox: return "PortionType::FieldFormCheckbox";
70 
71             case PortionType::Expand: return "PortionType::Expand";
72             case PortionType::Blank: return "PortionType::Blank";
73             case PortionType::PostIts: return "PortionType::PostIts";
74 
75             case PortionType::Hyphen: return "PortionType::Hyphen";
76             case PortionType::HyphenStr: return "PortionType::HyphenStr";
77             case PortionType::SoftHyphen: return "PortionType::SoftHyphen";
78             case PortionType::SoftHyphenStr: return "PortionType::SoftHyphenStr";
79             case PortionType::SoftHyphenComp: return "PortionType::SoftHyphenComp";
80 
81             case PortionType::Field: return "PortionType::Field";
82             case PortionType::Hidden: return "PortionType::Hidden";
83             case PortionType::QuoVadis: return "PortionType::QuoVadis";
84             case PortionType::ErgoSum: return "PortionType::ErgoSum";
85             case PortionType::Combined: return "PortionType::Combined";
86             case PortionType::Footnote: return "PortionType::Footnote";
87 
88             case PortionType::FootnoteNum: return "PortionType::FootnoteNum";
89             case PortionType::Number: return "PortionType::Number";
90             case PortionType::Bullet: return "PortionType::Bullet";
91             case PortionType::GrfNum: return "PortionType::GrfNum";
92 
93             case PortionType::Glue: return "PortionType::Glue";
94 
95             case PortionType::Margin: return "PortionType::Margin";
96 
97             case PortionType::Fix: return "PortionType::Fix";
98             case PortionType::Fly: return "PortionType::Fly";
99 
100             case PortionType::Table: return "PortionType::Table";
101 
102             case PortionType::TabRight: return "PortionType::TabRight";
103             case PortionType::TabCenter: return "PortionType::TabCenter";
104             case PortionType::TabDecimal: return "PortionType::TabDecimal";
105 
106             case PortionType::TabLeft: return "PortionType::TabLeft";
107             default:
108                 return "Unknown";
109         }
110     }
111 
112   public:
113 
XmlPortionDumper(xmlTextWriterPtr some_writer,const OUString & rText)114     explicit XmlPortionDumper( xmlTextWriterPtr some_writer, const OUString& rText ):writer( some_writer ), ofs( 0 ), m_rText(rText)
115     {
116     }
117 
118     /**
119         @param nLength
120                 length of this portion in the model string
121         @param rText
122                 text which is painted on-screen
123       */
Text(TextFrameIndex nLength,PortionType nType,sal_Int32 nHeight,sal_Int32 nWidth)124     virtual void Text( TextFrameIndex nLength,
125                        PortionType nType,
126                        sal_Int32 nHeight,
127                        sal_Int32 nWidth) override
128     {
129         xmlTextWriterStartElement( writer, BAD_CAST( "Text" ) );
130         xmlTextWriterWriteFormatAttribute( writer,
131                                            BAD_CAST( "nLength" ),
132                                            "%i", static_cast<int>(static_cast<sal_Int32>(nLength)) );
133         xmlTextWriterWriteFormatAttribute( writer,
134                                            BAD_CAST( "nType" ),
135                                            "%s", getTypeName( nType ) );
136         if (nHeight > 0)
137             xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nHeight"), "%i", static_cast<int>(nHeight));
138         if (nWidth > 0)
139             xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nWidth"), "%i", static_cast<int>(nWidth));
140         if (nLength > TextFrameIndex(0))
141             xmlTextWriterWriteAttribute(writer, BAD_CAST("Portion"),
142                 BAD_CAST(m_rText.copy(sal_Int32(ofs), sal_Int32(nLength)).toUtf8().getStr()));
143 
144         xmlTextWriterEndElement( writer );
145         m_aLine += m_rText.copy(sal_Int32(ofs), sal_Int32(nLength));
146         ofs += nLength;
147     }
148 
149     /**
150         @param nLength
151                 length of this portion in the model string
152         @param rText
153                 text which is painted on-screen
154         @param nType
155                 type of this portion
156         @param nHeight
157                 font size of the painted text
158       */
Special(TextFrameIndex nLength,const OUString & rText,PortionType nType,sal_Int32 nHeight,sal_Int32 nWidth,const SwFont * pFont)159     virtual void Special( TextFrameIndex nLength,
160                           const OUString & rText,
161                           PortionType nType,
162                           sal_Int32 nHeight,
163                           sal_Int32 nWidth,
164                           const SwFont* pFont ) override
165     {
166         xmlTextWriterStartElement( writer, BAD_CAST( "Special" ) );
167         xmlTextWriterWriteFormatAttribute( writer,
168                                            BAD_CAST( "nLength" ),
169                                            "%i", static_cast<int>(static_cast<sal_Int32>(nLength)) );
170         xmlTextWriterWriteFormatAttribute( writer,
171                                            BAD_CAST( "nType" ),
172                                            "%s", getTypeName( nType ) );
173         OString sText8 = OUStringToOString( rText, RTL_TEXTENCODING_UTF8 );
174         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "rText" ),
175                                            "%s", sText8.getStr(  ) );
176 
177         if (nHeight > 0)
178             xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nHeight"), "%i", static_cast<int>(nHeight));
179 
180         if (nWidth > 0)
181             xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nWidth"), "%i", static_cast<int>(nWidth));
182 
183         if (pFont)
184             pFont->dumpAsXml(writer);
185 
186         xmlTextWriterEndElement( writer );
187         m_aLine += rText;
188         ofs += nLength;
189     }
190 
LineBreak(sal_Int32 nWidth)191     virtual void LineBreak( sal_Int32 nWidth ) override
192     {
193         xmlTextWriterStartElement( writer, BAD_CAST( "LineBreak" ) );
194         if (nWidth > 0)
195             xmlTextWriterWriteFormatAttribute( writer,
196                                                BAD_CAST( "nWidth" ),
197                                                "%i", static_cast<int>(nWidth) );
198         if (!m_aLine.isEmpty())
199         {
200             xmlTextWriterWriteAttribute(writer, BAD_CAST("Line"),
201                                         BAD_CAST(m_aLine.toUtf8().getStr()));
202             m_aLine.clear();
203         }
204         xmlTextWriterEndElement( writer );
205     }
206 
207     /**
208       * @param nLength
209       *         number of 'model string' characters to be skipped
210       */
Skip(TextFrameIndex nLength)211     virtual void Skip( TextFrameIndex nLength ) override
212     {
213         xmlTextWriterStartElement( writer, BAD_CAST( "Skip" ) );
214         xmlTextWriterWriteFormatAttribute( writer,
215                                            BAD_CAST( "nLength" ),
216                                            "%i", static_cast<int>(static_cast<sal_Int32>(nLength)) );
217         xmlTextWriterEndElement( writer );
218         ofs += nLength;
219     }
220 
Finish()221     virtual void Finish(  ) override
222     {
223         xmlTextWriterStartElement( writer, BAD_CAST( "Finish" ) );
224         xmlTextWriterEndElement( writer );
225     }
226 
227 };
228 
229 namespace
230 {
lcl_createDefaultWriter()231     xmlTextWriterPtr lcl_createDefaultWriter()
232     {
233         xmlTextWriterPtr writer = xmlNewTextWriterFilename( "layout.xml", 0 );
234         xmlTextWriterSetIndent(writer,1);
235         xmlTextWriterSetIndentString(writer, BAD_CAST("  "));
236         xmlTextWriterStartDocument( writer, nullptr, nullptr, nullptr );
237         return writer;
238     }
239 
lcl_freeWriter(xmlTextWriterPtr writer)240     void lcl_freeWriter( xmlTextWriterPtr writer )
241     {
242         xmlTextWriterEndDocument( writer );
243         xmlFreeTextWriter( writer );
244     }
245 }
246 
dumpTopMostAsXml(xmlTextWriterPtr writer) const247 void SwFrame::dumpTopMostAsXml(xmlTextWriterPtr writer) const
248 {
249     const SwFrame* pFrame = this;
250     while (pFrame->GetUpper())
251     {
252         pFrame = pFrame->GetUpper();
253     }
254 
255     pFrame->dumpAsXml(writer);
256 }
257 
dumpAsXml(xmlTextWriterPtr writer) const258 void SwFrame::dumpAsXml( xmlTextWriterPtr writer ) const
259 {
260     bool bCreateWriter = ( nullptr == writer );
261     if ( bCreateWriter )
262         writer = lcl_createDefaultWriter();
263 
264     const char *name = nullptr;
265 
266     switch ( GetType(  ) )
267     {
268     case SwFrameType::Root:
269         name = "root";
270         break;
271     case SwFrameType::Page:
272         name = "page";
273         break;
274     case SwFrameType::Column:
275         name = "column";
276         break;
277     case SwFrameType::Header:
278         name = "header";
279         break;
280     case SwFrameType::Footer:
281         name = "footer";
282         break;
283     case SwFrameType::FtnCont:
284         name = "ftncont";
285         break;
286     case SwFrameType::Ftn:
287         name = "ftn";
288         break;
289     case SwFrameType::Body:
290         name = "body";
291         break;
292     case SwFrameType::Fly:
293         name = "fly";
294         break;
295     case SwFrameType::Section:
296         name = "section";
297         break;
298     case SwFrameType::Tab:
299         name = "tab";
300         break;
301     case SwFrameType::Row:
302         name = "row";
303         break;
304     case SwFrameType::Cell:
305         name = "cell";
306         break;
307     case SwFrameType::Txt:
308         name = "txt";
309         break;
310     case SwFrameType::NoTxt:
311         name = "notxt";
312         break;
313     default: break;
314     };
315 
316     if ( name != nullptr )
317     {
318         xmlTextWriterStartElement( writer, reinterpret_cast<const xmlChar *>(name) );
319 
320         dumpAsXmlAttributes( writer );
321 
322         if (IsRootFrame())
323         {
324             const SwRootFrame* pRootFrame = static_cast<const SwRootFrame*>(this);
325             xmlTextWriterStartElement(writer, BAD_CAST("sfxViewShells"));
326             SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>));
327             while (pView)
328             {
329                 if (pView->GetObjectShell() == pRootFrame->GetCurrShell()->GetSfxViewShell()->GetObjectShell())
330                     pView->dumpAsXml(writer);
331                 pView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>));
332             }
333             xmlTextWriterEndElement(writer);
334         }
335 
336         if (IsPageFrame())
337         {
338             const SwPageFrame* pPageFrame = static_cast<const SwPageFrame*>(this);
339             xmlTextWriterStartElement(writer, BAD_CAST("page_status"));
340             xmlTextWriterWriteAttribute(writer, BAD_CAST("ValidFlyLayout"), BAD_CAST(OString::boolean(!pPageFrame->IsInvalidFlyLayout()).getStr()));
341             xmlTextWriterWriteAttribute(writer, BAD_CAST("ValidFlyContent"), BAD_CAST(OString::boolean(!pPageFrame->IsInvalidFlyContent()).getStr()));
342             xmlTextWriterWriteAttribute(writer, BAD_CAST("ValidFlyInCnt"), BAD_CAST(OString::boolean(!pPageFrame->IsInvalidFlyInCnt()).getStr()));
343             xmlTextWriterWriteAttribute(writer, BAD_CAST("ValidLayout"), BAD_CAST(OString::boolean(!pPageFrame->IsInvalidLayout()).getStr()));
344             xmlTextWriterWriteAttribute(writer, BAD_CAST("ValidContent"), BAD_CAST(OString::boolean(!pPageFrame->IsInvalidContent()).getStr()));
345             xmlTextWriterEndElement(writer);
346         }
347 
348         if (IsTextFrame())
349         {
350             const SwTextFrame *pTextFrame = static_cast<const SwTextFrame *>(this);
351             sw::MergedPara const*const pMerged(pTextFrame->GetMergedPara());
352             if (pMerged)
353             {
354                 xmlTextWriterStartElement( writer, BAD_CAST( "merged" ) );
355                 xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "paraPropsNodeIndex" ), "%" SAL_PRIuUINTPTR, pMerged->pParaPropsNode->GetIndex() );
356                 for (auto const& e : pMerged->extents)
357                 {
358                     xmlTextWriterStartElement( writer, BAD_CAST( "extent" ) );
359                     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "txtNodeIndex" ), "%" SAL_PRIuUINTPTR, e.pNode->GetIndex() );
360                     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "start" ), "%" SAL_PRIdINT32, e.nStart );
361                     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "end" ), "%" SAL_PRIdINT32, e.nEnd );
362                     xmlTextWriterEndElement( writer );
363                 }
364                 xmlTextWriterEndElement( writer );
365             }
366         }
367 
368         if (IsCellFrame())
369         {
370             SwCellFrame const* pCellFrame(static_cast<SwCellFrame const*>(this));
371             xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "rowspan" ), "%ld", pCellFrame->GetLayoutRowSpan() );
372         }
373 
374         xmlTextWriterStartElement( writer, BAD_CAST( "infos" ) );
375         dumpInfosAsXml( writer );
376         xmlTextWriterEndElement( writer );
377 
378         // Dump Anchored objects if any
379         const SwSortedObjs* pAnchored = GetDrawObjs();
380         if ( pAnchored && pAnchored->size() > 0 )
381         {
382             xmlTextWriterStartElement( writer, BAD_CAST( "anchored" ) );
383 
384             for (SwAnchoredObject* pObject : *pAnchored)
385             {
386                 pObject->dumpAsXml( writer );
387             }
388 
389             xmlTextWriterEndElement( writer );
390         }
391 
392         // Dump the children
393         if ( IsTextFrame(  ) )
394         {
395             const SwTextFrame *pTextFrame = static_cast<const SwTextFrame *>(this);
396             OUString aText = pTextFrame->GetText(  );
397             for ( int i = 0; i < 32; i++ )
398             {
399                 aText = aText.replace( i, '*' );
400             }
401             OString aText8 =OUStringToOString( aText,
402                                                           RTL_TEXTENCODING_UTF8 );
403             xmlTextWriterWriteString( writer,
404                                       reinterpret_cast<const xmlChar *>(aText8.getStr(  )) );
405             XmlPortionDumper pdumper( writer, aText );
406             pTextFrame->VisitPortions( pdumper );
407 
408         }
409         else
410         {
411             dumpChildrenAsXml( writer );
412         }
413         xmlTextWriterEndElement( writer );
414     }
415 
416     if ( bCreateWriter )
417         lcl_freeWriter( writer );
418 }
419 
dumpInfosAsXml(xmlTextWriterPtr writer) const420 void SwFrame::dumpInfosAsXml( xmlTextWriterPtr writer ) const
421 {
422     // output the Frame
423     xmlTextWriterStartElement( writer, BAD_CAST( "bounds" ) );
424     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "left" ), "%ld", getFrameArea().Left() );
425     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "top" ), "%ld", getFrameArea().Top() );
426     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "width" ), "%ld", getFrameArea().Width() );
427     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "height" ), "%ld", getFrameArea().Height() );
428     xmlTextWriterWriteAttribute(writer, BAD_CAST("mbFixSize"), BAD_CAST(OString::boolean(HasFixSize()).getStr()));
429     xmlTextWriterWriteAttribute(writer, BAD_CAST("mbValidPos"), BAD_CAST(OString::boolean(isFrameAreaPositionValid()).getStr()));
430     xmlTextWriterWriteAttribute(writer, BAD_CAST("mbValidSize"), BAD_CAST(OString::boolean(isFrameAreaSizeValid()).getStr()));
431     xmlTextWriterWriteAttribute(writer, BAD_CAST("mbValidPrtArea"), BAD_CAST(OString::boolean(isFramePrintAreaValid()).getStr()));
432     xmlTextWriterEndElement( writer );
433 
434     // output the Prt
435     xmlTextWriterStartElement( writer, BAD_CAST( "prtBounds" ) );
436     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "left" ), "%ld", getFramePrintArea().Left() );
437     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "top" ), "%ld", getFramePrintArea().Top() );
438     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "width" ), "%ld", getFramePrintArea().Width() );
439     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "height" ), "%ld", getFramePrintArea().Height() );
440     xmlTextWriterEndElement( writer );
441 }
442 
443 // Hack: somehow conversion from "..." to va_list does
444 // bomb on two string literals in the format.
445 static const char* const TMP_FORMAT = "%" SAL_PRIuUINTPTR;
446 
dumpAsXmlAttributes(xmlTextWriterPtr writer) const447 void SwFrame::dumpAsXmlAttributes( xmlTextWriterPtr writer ) const
448 {
449     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "ptr" ), "%p", this );
450     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "id" ), "%" SAL_PRIuUINT32, GetFrameId() );
451     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "symbol" ), "%s", BAD_CAST( typeid( *this ).name( ) ) );
452     if ( GetNext( ) )
453         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "next" ), "%" SAL_PRIuUINT32, GetNext()->GetFrameId() );
454     if ( GetPrev( ) )
455         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "prev" ), "%" SAL_PRIuUINT32, GetPrev()->GetFrameId() );
456     if ( GetUpper( ) )
457         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "upper" ), "%" SAL_PRIuUINT32, GetUpper()->GetFrameId() );
458     if ( GetLower( ) )
459         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "lower" ), "%" SAL_PRIuUINT32, GetLower()->GetFrameId() );
460     if (IsFootnoteFrame())
461     {
462         SwFootnoteFrame const*const pFF(static_cast<SwFootnoteFrame const*>(this));
463         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST("ref"), "%" SAL_PRIuUINT32, pFF->GetRef()->GetFrameId() );
464         if (pFF->GetMaster())
465             xmlTextWriterWriteFormatAttribute( writer, BAD_CAST("master"), "%" SAL_PRIuUINT32, pFF->GetMaster()->GetFrameId() );
466         if (pFF->GetFollow())
467             xmlTextWriterWriteFormatAttribute( writer, BAD_CAST("follow"), "%" SAL_PRIuUINT32, pFF->GetFollow()->GetFrameId() );
468     }
469     if ( IsTextFrame(  ) )
470     {
471         const SwTextFrame *pTextFrame = static_cast<const SwTextFrame *>(this);
472         const SwTextNode *pTextNode = pTextFrame->GetTextNodeFirst();
473         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "txtNodeIndex" ), TMP_FORMAT, pTextNode->GetIndex() );
474 
475         OString aMode = "Horizontal";
476         if (IsVertLRBT())
477         {
478             aMode = "VertBTLR";
479         }
480         else if (IsVertLR())
481         {
482             aMode = "VertLR";
483         }
484         else if (IsVertical())
485         {
486             aMode = "Vertical";
487         }
488         xmlTextWriterWriteAttribute(writer, BAD_CAST("WritingMode"), BAD_CAST(aMode.getStr()));
489     }
490     if (IsHeaderFrame() || IsFooterFrame())
491     {
492         const SwHeadFootFrame *pHeadFootFrame = static_cast<const SwHeadFootFrame*>(this);
493         OUString aFormatName = pHeadFootFrame->GetFormat()->GetName();
494         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "fmtName" ), "%s", BAD_CAST(OUStringToOString(aFormatName, RTL_TEXTENCODING_UTF8).getStr()));
495         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "fmtPtr" ), "%p", pHeadFootFrame->GetFormat());
496     }
497 }
498 
dumpChildrenAsXml(xmlTextWriterPtr writer) const499 void SwFrame::dumpChildrenAsXml( xmlTextWriterPtr writer ) const
500 {
501     const SwFrame *pFrame = GetLower(  );
502     for ( ; pFrame != nullptr; pFrame = pFrame->GetNext(  ) )
503     {
504         pFrame->dumpAsXml( writer );
505     }
506 }
507 
dumpAsXml(xmlTextWriterPtr writer) const508 void SwAnchoredObject::dumpAsXml( xmlTextWriterPtr writer ) const
509 {
510     bool bCreateWriter = ( nullptr == writer );
511     if ( bCreateWriter )
512         writer = lcl_createDefaultWriter();
513 
514     xmlTextWriterStartElement( writer, BAD_CAST( getElementName() ) );
515     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "ptr" ), "%p", this );
516 
517     xmlTextWriterStartElement( writer, BAD_CAST( "bounds" ) );
518     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "left" ), "%ld", GetObjBoundRect().Left() );
519     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "top" ), "%ld", GetObjBoundRect().Top() );
520     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "width" ), "%ld", GetObjBoundRect().Width() );
521     xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "height" ), "%ld", GetObjBoundRect().Height() );
522     xmlTextWriterEndElement( writer );
523 
524     if (const SdrObject* pObject = GetDrawObj())
525         pObject->dumpAsXml(writer);
526 
527     xmlTextWriterEndElement( writer );
528 
529     if ( bCreateWriter )
530         lcl_freeWriter( writer );
531 }
532 
dumpAsXml(xmlTextWriterPtr writer) const533 void SwFont::dumpAsXml(xmlTextWriterPtr writer) const
534 {
535     xmlTextWriterStartElement(writer, BAD_CAST("SwFont"));
536     xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("ptr"), "%p", this);
537     // do not use Color::AsRGBHexString() as that omits the transparency
538     xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("color"), "%08" SAL_PRIxUINT32, sal_uInt32(GetColor()));
539     xmlTextWriterEndElement(writer);
540 }
541 
dumpAsXmlAttributes(xmlTextWriterPtr writer) const542 void SwTextFrame::dumpAsXmlAttributes( xmlTextWriterPtr writer ) const
543 {
544     SwFrame::dumpAsXmlAttributes( writer );
545     if ( HasFollow() )
546         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%" SAL_PRIuUINT32, GetFollow()->GetFrameId() );
547 
548     if (m_pPrecede != nullptr)
549         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "precede" ), "%" SAL_PRIuUINT32, static_cast<SwTextFrame*>(m_pPrecede)->GetFrameId() );
550 }
551 
dumpAsXmlAttributes(xmlTextWriterPtr writer) const552 void SwSectionFrame::dumpAsXmlAttributes( xmlTextWriterPtr writer ) const
553 {
554     SwFrame::dumpAsXmlAttributes( writer );
555     if ( HasFollow() )
556         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%" SAL_PRIuUINT32, GetFollow()->GetFrameId() );
557 
558     if (m_pPrecede != nullptr)
559         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "precede" ), "%" SAL_PRIuUINT32, static_cast<SwSectionFrame*>( m_pPrecede )->GetFrameId() );
560 }
561 
dumpAsXmlAttributes(xmlTextWriterPtr writer) const562 void SwTabFrame::dumpAsXmlAttributes( xmlTextWriterPtr writer ) const
563 {
564     SwFrame::dumpAsXmlAttributes( writer );
565     if ( HasFollow() )
566         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%" SAL_PRIuUINT32, GetFollow()->GetFrameId() );
567 
568     if (m_pPrecede != nullptr)
569         xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "precede" ), "%" SAL_PRIuUINT32, static_cast<SwTabFrame*>( m_pPrecede )->GetFrameId() );
570 }
571 
572 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
573