1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_SW_SOURCE_FILTER_WW8_WRITERHELPER_HXX
21 #define INCLUDED_SW_SOURCE_FILTER_WW8_WRITERHELPER_HXX
26 #include <com/sun/star/embed/XEmbeddedObject.hpp>
28 #include <sfx2/objsh.hxx>
30 #include <svl/itempool.hxx>
31 #include <svl/itemset.hxx>
35 #include <tools/poly.hxx>
38 class SwTextFormatColl
;
42 class OutlinerParaObject
;
46 class SwFormatCharFormat
;
56 : public std::binary_function
<sal_uInt16
, sal_uInt16
, bool>
59 bool operator()(sal_uInt16 nA
, sal_uInt16 nB
) const;
66 /// STL container of Paragraph Styles (SwTextFormatColl)
67 typedef std::vector
<SwTextFormatColl
*> ParaStyles
;
68 /// STL iterator for ParaStyles
69 typedef ParaStyles::iterator ParaStyleIter
;
70 /// STL container of SfxPoolItems (Attributes)
71 typedef std::map
<sal_uInt16
, const SfxPoolItem
*, sw::util::ItemSort
> PoolItems
;
72 /// STL const iterator for ParaStyles
73 typedef PoolItems::const_iterator cPoolItemIter
;
75 /** Make exporting a Writer Frame easy
77 In word all frames are effectively anchored to character or as
78 character. This is nice and simple, writer is massively complex in this
79 area, so this ww8::Frame simplifies matters by providing a single unified
80 view of the multitude of elements in writer and their differing quirks.
82 A ww8::Frame wraps a writer frame and is guaranteed to have a suitable
83 anchor position available from it. It hides much of the needless
84 complexity of the multitude of floating/inline elements in writer, it...
86 Guarantees an anchor position for a frame.
87 Provides a readable way to see if we are anchored inline. (as character)
88 Provides a simple way to flag what type of entity this frame describes.
89 Provides the size of the element as drawn by writer.
92 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
97 enum WriterSource
{eTextBox
, eGraphic
, eOle
, eDrawing
, eFormControl
,eBulletGrf
};
99 const SwFrameFormat
* mpFlyFrame
;
102 // #i43447# - Size of the frame in the layout.
103 // Especially needed for graphics, whose layout size can differ from its
104 // size, because it is scaled into its environment.
107 WriterSource meWriterType
;
108 const SwNode
*mpStartFrameContent
;
113 Frame(const SwFrameFormat
&rFlyFrame
, const SwPosition
&rPos
);
114 Frame(const Graphic
&, const SwPosition
&);
116 /** Get the writer SwFrameFormat that this object describes
119 The wrapped SwFrameFormat
121 const SwFrameFormat
&GetFrameFormat() const { return *mpFlyFrame
; }
123 /** Get the position this frame is anchored at
126 The anchor position of this frame
128 const SwPosition
&GetPosition() const { return maPos
; }
129 void SetPosition(SwPosition
const& rPos
) { maPos
= rPos
; }
131 /** Get the node this frame is anchored into
134 The SwTextNode this frame is anchored inside
136 const SwContentNode
*GetContentNode() const
137 { return maPos
.nNode
.GetNode().GetContentNode(); }
139 /** Get the type of frame that this wraps
142 a WriterSource which describes the source type of this wrapper
144 WriterSource
GetWriterType() const { return meWriterType
; }
146 /** Is this frame inline (as character)
149 whether this is inline or not
151 bool IsInline() const { return mbIsInline
; }
153 /** Even if the frame isn't an inline frame, force it to behave as one
155 There are a variety of circumstances where word cannot have
156 anything except inline elements, e.g. inside frames. So its easier
157 to force this ww8::Frame into behaving as one, instead of special
158 casing export code all over the place.
161 void ForceTreatAsInline();
163 /** Get the first node of content in the frame
166 the first node of content in the frame, might not be any at all.
168 const SwNode
*GetContent() const { return mpStartFrameContent
; }
169 const Graphic
&GetGraphic() const { return maGrf
; }
170 bool HasGraphic() const { return mbForBullet
; }
172 /** Does this ww8::Frame refer to the same writer content as another
175 if the two ww8::Frames are handling the same writer frame
177 bool RefersToSameFrameAs(const Frame
&rOther
) const
179 if (mbForBullet
&& rOther
.mbForBullet
)
180 return (maGrf
== rOther
.maGrf
);
181 else if ((!mbForBullet
) && (!rOther
.mbForBullet
))
182 return (mpFlyFrame
== rOther
.mpFlyFrame
);
187 /** The Size of the contained element
190 the best size to use to export to word
192 const Size
& GetSize() const { return maSize
; }
194 /** The layout size of the contained element
196 #i43447# - Needed for graphics, which are scaled into its environment
200 const Size
& GetLayoutSize() const
206 /// STL container of Frames
207 typedef std::vector
<Frame
> Frames
;
208 /// STL iterator for Frames
209 typedef std::vector
<Frame
>::iterator FrameIter
;
216 /** Provide a dynamic_cast style cast for SfxPoolItems
218 A SfxPoolItem generally need to be cast back to its original type
219 to be useful, which is both tedious and errorprone. So item_cast is
220 a helper template to aid the process and test if the cast is
224 The SfxPoolItem which is to be casted
227 A SfxPoolItem derived class to cast rItem to
229 @return A rItem upcasted back to a T
231 @exception std::bad_cast Thrown if the rItem was not a T
234 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
236 template<class T
> const T
& item_cast(const SfxPoolItem
&rItem
)
239 if (dynamic_cast<const T
*>(&rItem
) == nullptr)
240 throw std::bad_cast();
241 return static_cast<const T
&>(rItem
);
244 /** Provide a dynamic_cast style cast for SfxPoolItems
246 A SfxPoolItem generally need to be cast back to its original type
247 to be useful, which is both tedious and errorprone. So item_cast is
248 a helper template to aid the process and test if the cast is
252 The SfxPoolItem which is to be casted
255 A SfxPoolItem derived class to cast pItem to
257 @return A pItem upcasted back to a T or 0 if pItem was not a T
260 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
262 template<class T
> const T
* item_cast(const SfxPoolItem
*pItem
)
264 return dynamic_cast<const T
*>(pItem
);
267 /** Extract a SfxPoolItem derived property from a SwContentNode
269 Writer's attributes are retrieved by passing a numeric identifier
270 and receiving a SfxPoolItem reference which must then typically be
271 cast back to its original type which is both tedious and verbose.
273 ItemGet uses item_cast () on the retrieved reference to test that the
274 retrieved property is of the type that the developer thinks it is.
277 The SwContentNode to retrieve the property from
280 The numeric identifier of the property to be retrieved
283 A SfxPoolItem derived class of the retrieved property
285 @exception std::bad_cast Thrown if the property was not a T
287 @return The T requested
290 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
292 template<class T
> const T
& ItemGet(const SwContentNode
&rNode
,
293 sal_uInt16 eType
) throw(std::bad_cast
)
295 return item_cast
<T
>(rNode
.GetAttr(eType
));
298 /** Extract a SfxPoolItem derived property from a SwFormat
300 Writer's attributes are retrieved by passing a numeric identifier
301 and receiving a SfxPoolItem reference which must then typically be
302 cast back to its original type which is both tedious and verbose.
304 ItemGet uses item_cast () on the retrieved reference to test that the
305 retrieved property is of the type that the developer thinks it is.
308 The SwFormat to retrieve the property from
311 The numeric identifier of the property to be retrieved
314 A SfxPoolItem derived class of the retrieved property
316 @exception std::bad_cast Thrown if the property was not a T
319 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
321 template<class T
> const T
& ItemGet(const SwFormat
&rFormat
,
322 sal_uInt16 eType
) throw(std::bad_cast
, css::uno::RuntimeException
)
324 return item_cast
<T
>(rFormat
.GetFormatAttr(eType
));
327 /** Extract a SfxPoolItem derived property from a SfxItemSet
329 Writer's attributes are retrieved by passing a numeric identifier
330 and receiving a SfxPoolItem reference which must then typically be
331 cast back to its original type which is both tedious and verbose.
333 ItemGet uses item_cast () on the retrieved reference to test that the
334 retrieved property is of the type that the developer thinks it is.
337 The SfxItemSet to retrieve the property from
340 The numeric identifier of the property to be retrieved
343 A SfxPoolItem derived class of the retrieved property
345 @exception std::bad_cast Thrown if the property was not a T
347 @return The T requested
350 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
352 template<class T
> const T
& ItemGet(const SfxItemSet
&rSet
,
353 sal_uInt16 eType
) throw(std::bad_cast
)
355 return item_cast
<T
>(rSet
.Get(eType
));
358 /** Extract a default SfxPoolItem derived property from a SfxItemPool
360 Writer's attributes are retrieved by passing a numeric identifier
361 and receiving a SfxPoolItem reference which must then typically be
362 cast back to its original type which is both tedious and verbose.
364 DefaultItemGet returns a reference to the default property of a
365 given SfxItemPool for a given property id, e.g. default fontsize
367 DefaultItemGet uses item_cast () on the retrieved reference to test
368 that the retrieved property is of the type that the developer thinks
372 The SfxItemPool whose default property we want
375 The numeric identifier of the default property to be retrieved
378 A SfxPoolItem derived class of the retrieved property
380 @exception std::bad_cast Thrown if the property was not a T
382 @return The T requested
385 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
387 template<class T
> const T
& DefaultItemGet(const SfxItemPool
&rPool
,
388 sal_uInt16 eType
) throw(std::bad_cast
)
390 return item_cast
<T
>(rPool
.GetDefaultItem(eType
));
393 /** Extract a default SfxPoolItem derived property from a SwDoc
395 Writer's attributes are retrieved by passing a numeric identifier
396 and receiving a SfxPoolItem reference which must then typically be
397 cast back to its original type which is both tedious and verbose.
399 DefaultItemGet returns a reference to the default property of a
400 given SwDoc (Writer Document) for a given property id, e.g default
403 DefaultItemGet uses item_cast () on the retrieved reference to test
404 that the retrieved property is of the type that the developer thinks
408 The SfxItemPool whose default property we want
411 The numeric identifier of the default property to be retrieved
414 A SfxPoolItem derived class of the retrieved property
416 @exception std::bad_cast Thrown if the property was not a T
418 @return The T requested
421 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
423 template<class T
> const T
& DefaultItemGet(const SwDoc
&rDoc
,
424 sal_uInt16 eType
) throw(std::bad_cast
)
426 return DefaultItemGet
<T
>(rDoc
.GetAttrPool(), eType
);
429 /** Get the Paragraph Styles of a SwDoc
431 Writer's styles are in one of those dreaded macro based pre-STL
432 containers. Give me an STL container of the paragraph styles
436 The SwDoc document to get the styles from
438 @return A ParaStyles containing the SwDoc's Paragraph Styles
441 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
443 ww8::ParaStyles
GetParaStyles(const SwDoc
&rDoc
);
445 /** Get a Paragraph Style which fits a given name
447 Its surprisingly tricky to get a style when all you have is a name,
448 but that's what this does
451 The SwDoc document to search in
454 The name of the style to search for
456 @return A Paragraph Style if one exists which matches the name
459 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
461 SwTextFormatColl
* GetParaStyle(SwDoc
&rDoc
, const OUString
& rName
);
463 /** Get a Character Style which fits a given name
465 Its surprisingly tricky to get a style when all you have is a name,
466 but that's what this does
469 The SwDoc document to search in
472 The name of the style to search for
474 @return A Character Style if one exists which matches the name
477 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
479 SwCharFormat
* GetCharStyle(SwDoc
&rDoc
, const OUString
& rName
);
481 /** Sort sequence of Paragraph Styles by assigned outline style list level
483 Sort ParaStyles in ascending order of assigned outline style list level,
484 e.g. given Normal/Heading1/Heading2/.../Heading10 at their default
485 assigned outline style list levels of body level/level 1/level 2/.../level 10
488 adjust the sorting algorithm due to introduced outline level attribute
491 The ParaStyles to sort
494 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
496 void SortByAssignedOutlineStyleListLevel(ww8::ParaStyles
&rStyles
);
498 /** Get the SfxPoolItems of a SfxItemSet
500 Writer's SfxPoolItems (attributes) are in one of those dreaded
501 macro based pre-STL containers. Give me an STL container of the
505 The SfxItemSet to get the items from
508 The sw::PoolItems to put the items into
511 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
513 void GetPoolItems(const SfxItemSet
&rSet
, ww8::PoolItems
&rItems
, bool bExportParentItemSet
);
515 const SfxPoolItem
*SearchPoolItems(const ww8::PoolItems
&rItems
,
518 template<class T
> const T
* HasItem(const ww8::PoolItems
&rItems
,
521 return item_cast
<T
>(SearchPoolItems(rItems
, eType
));
524 /** Remove properties from an SfxItemSet which a SwFormatCharFormat overrides
526 Given an SfxItemSet and a SwFormatCharFormat remove from the rSet all the
527 properties which the SwFormatCharFormat would override. An SfxItemSet
528 contains attributes, and a SwFormatCharFormat is a "Character Style",
529 so if the SfxItemSet contains bold and so does the character style
530 then delete bold from the SfxItemSet
533 rFormat the SwFormatCharFormat which describes the Character Style
536 rSet the SfxItemSet from which we want to remove any properties
537 which the rFormat would override
540 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
542 @see #i24291# for examples
544 void ClearOverridesFromSet(const SwFormatCharFormat
&rFormat
, SfxItemSet
&rSet
);
546 /** Get the Floating elements in a SwDoc
548 Writer's FrameFormats may or may not be anchored to some text content,
549 e.g. Page Anchored elements will not be. For the winword export we
550 need them to have something to be anchored to. So this method
551 returns all the floating elements in a document as a STL container
552 of ww8::Frames which are guaranteed to have an appropriate anchor.
555 The SwDoc document to get the styles from
558 The SwPam to describe the selection in the document to get the
559 elements from. 0 means the entire document.
561 @return A Frames containing the selections Floating elements
564 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
566 ww8::Frames
GetFrames(const SwDoc
&rDoc
, SwPaM
*pPaM
);
568 /** fix up frame positions, must be called after SetRedlineFlags */
569 void UpdateFramePositions(ww8::Frames
& rFrames
);
571 /** Get the Frames anchored to a given node
573 Given a container of frames, find the ones anchored to a given node
576 The container of frames to search in
579 The SwNode to check for anchors to
581 @return the Frames in rFrames anchored to rNode
584 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
586 ww8::Frames
GetFramesInNode(const ww8::Frames
&rFrames
, const SwNode
&rNode
);
588 /** Get the Numbering Format used on a paragraph
590 There are two differing types of numbering formats that may be on a
591 paragraph, normal and outline. The outline is that numbering you
592 see in tools->outline numbering. Theres no difference in the
593 numbering itself, just how you get it from the SwTextNode. Needless
594 to say the filter generally couldn't care less what type of
598 The SwTextNode that is the paragraph
600 @return A SwNumFormat pointer that describes the numbering level
601 on this paragraph, or 0 if there is none.
604 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
606 const SwNumFormat
* GetNumFormatFromTextNode(const SwTextNode
&rTextNode
);
608 /** Get the Numbering Format for a given level from a numbering rule
616 @return A SwNumFormat pointer that describes the numbering level
617 or 0 if the nLevel is out of range
620 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
622 const SwNumFormat
* GetNumFormatFromSwNumRuleLevel(const SwNumRule
&rRule
,
625 const SwNumRule
* GetNumRuleFromTextNode(const SwTextNode
&rTextNd
);
626 const SwNumRule
* GetNormalNumRuleFromTextNode(const SwTextNode
&rTextNd
);
628 /** Get the SwNoTextNode associated with a SwFrameFormat if here is one
630 There are two differing types of numbering formats that may be on a
631 paragraph, normal and outline. The outline is that numbering you
632 see in tools->outline numbering. Theres no difference in the
633 numbering itself, just how you get it from the SwTextNode. Needless
634 to say the filter generally couldn't care less what type of
638 The SwFrameFormat that may describe a graphic
640 @return A SwNoTextNode pointer that describes the graphic of this
641 frame if there is one, or 0 if there is none.
644 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
646 SwNoTextNode
*GetNoTextNodeFromSwFrameFormat(const SwFrameFormat
&rFormat
);
648 /** Does a node have a "page break before" applied
650 Both text nodes and tables in writer can have "page break before"
651 This function gives a unified view to both entities
654 The SwNode to query the page break of
656 @return true if there is a page break, false otherwise
659 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
661 bool HasPageBreak(const SwNode
&rNode
);
663 /** Make a best fit Polygon from a PolyPolygon
665 For custom contours in writer we use a PolyPolygon, while word uses
666 a simple polygon, so we need to try and make the best polygon from
670 The tools::PolyPolygon to try and turn into a Polygon
672 @return best fit Polygon from rPolyPoly
675 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
677 tools::Polygon
PolygonFromPolyPolygon(const tools::PolyPolygon
&rPolyPoly
);
679 /// Undo all scaling / move tricks of the wrap polygon done during import.
680 tools::Polygon
CorrectWordWrapPolygonForExport(const tools::PolyPolygon
& rPolyPoly
, const SwNoTextNode
* pNd
);
682 /** Make setting a drawing object's layer in a Writer document easy
684 Word has the simple concept of a drawing object either in the
685 foreground and in the background. We have an additional complexity
686 that form components live in a separate layer, which seems
687 unnecessarily complicated. So in the winword filter we set the
688 object's layer through this class with either SendObjectToHell for
689 the bottom layer and SendObjectToHeaven for the top and we don't
690 worry about the odd form layer design wrinkle.
693 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
698 sal_uInt8 mnHeavenLayer
, mnHellLayer
, mnFormLayer
;
699 enum Layer
{eHeaven
, eHell
};
700 void SetObjectLayer(SdrObject
&rObject
, Layer eLayer
) const;
701 void Swap(SetLayer
&rOther
) throw();
704 /** Make Object live in the bottom drawing layer
707 The object to be set to the bottom layer
709 void SendObjectToHell(SdrObject
&rObject
) const;
711 /** Make Object lives in the top top layer
714 The object to be set to the bottom layer
716 void SendObjectToHeaven(SdrObject
&rObject
) const;
718 /** Normal constructor
721 The Writer document whose drawing layers we will be inserting
724 explicit SetLayer(const SwDoc
&rDoc
);
726 SetLayer(const SetLayer
&rOther
) throw();
727 SetLayer
& operator=(const SetLayer
&rOther
) throw();
733 /** Map an ID valid in one SfxItemPool to its equivalent in another
735 Given a WhichId (the id that identifies a property e.g. bold) which
736 is correct in a given SfxItemPool, get the equivalent whichId in
739 This arises because the drawing layer uses the same properties as
740 writer e.g. SvxWeight, but for some reason uses different ids
741 for the same properties as writer.
744 The SfxItemPool in whose terms the Id is returned
747 The SfxItemPool in whose terms the Id is passed in
750 The Id to transform from source to dest
752 @return 0 on failure, the correct property Id on success
755 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
757 sal_uInt16
TransformWhichBetweenPools(const SfxItemPool
&rDestPool
,
758 const SfxItemPool
&rSrcPool
, sal_uInt16 nWhich
);
760 /** Map a SwDoc WhichId to the equivalent Id for a given SfxItemSet
762 Given a WhichId (the id that identifies a property e.g. bold) which
763 is correct for a Writer document, get the equivalent whichId which
764 for a given SfxItemSet.
766 This arises because the drawing layer uses the same properties as
767 writer e.g. SvxWeight, but for some reason uses different ids
768 for the same properties as writer.
770 This is effectively the same as TransformWhichBetweenPools except
771 at a slightly different layer.
774 The SfxItemSet in whose terms the Id is returned
777 The SwDoc in whose terms the Id is passed in
780 The Id to transform from writer to the SfxItemSet's domain
782 @return 0 on failure, the correct SfxItemSet Id on success
785 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
787 sal_uInt16
GetSetWhichFromSwDocWhich(const SfxItemSet
&rSet
,
788 const SwDoc
&rDoc
, sal_uInt16 nWhich
);
790 /** Make inserting an OLE object into a Writer document easy
792 The rest of Office uses SdrOle2Obj for their OLE objects, Writer
793 doesn't, which makes things a bit difficult as this is the type of
794 object that the escher import code shared by the MSOffice filters
795 produces when it imports an OLE object.
797 This utility class takes ownership of the OLE object away from a
798 SdrOle2Obj and can massage it into the condition best suited to
799 insertion into Writer.
801 If the object was not transferred into Writer then it is deleted
805 <a href="mailto:cmc@openoffice.org">Caolán McNamara</a>
807 class DrawingOLEAdaptor
810 css::uno::Reference
< css::embed::XEmbeddedObject
> mxIPRef
;
811 SfxObjectShell
& mrPers
;
812 const Graphic
* mpGraphic
;
814 /** Take ownership of a SdrOle2Objs OLE object
817 The SdrOle2Obj whose OLE object we want to take control of
820 The SvPersist of a SwDoc (SwDoc::GetPersist()) into which we
821 may want to move the object, or remove it from if unwanted.
823 DrawingOLEAdaptor(SdrOle2Obj
&rObj
, SfxObjectShell
&rPers
);
825 /// Destructor will destroy the owned OLE object if not transferred
826 ~DrawingOLEAdaptor();
828 /** Transfer ownership of the OLE object to a document's SvPersist
830 TransferToDoc moves the object into the persist under the name
831 passed in. This name is then suitable to be used as an argument
834 The object is no longer owned by the adaptor after this call,
835 subsequent calls are an error and return false.
838 The name to store the object under in the document.
840 @return On success true is returned, otherwise false. On
841 success rName is then suitable for user with SwDoc::InsertOLE
843 bool TransferToDoc(OUString
&rName
);
845 DrawingOLEAdaptor
& operator=(const DrawingOLEAdaptor
&) = delete;
846 DrawingOLEAdaptor(const DrawingOLEAdaptor
&rDoc
) = delete;
853 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */