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 .
21 #include "formatclipboard.hxx"
24 #include <hintids.hxx>
25 #include <svx/svxids.hrc>
28 #include <charfmt.hxx>
31 #include <docstyle.hxx>
32 #include <fchrfmt.hxx>
34 // header for class SdrView
35 #include <svx/svdview.hxx>
37 #include <editeng/brushitem.hxx>
38 #include <editeng/shaditem.hxx>
40 // header for class SvxBoxInfoItem
41 #include <editeng/boxitem.hxx>
42 // header for class SvxFmtBreakItem
43 #include <editeng/formatbreakitem.hxx>
44 // header for class SwFmtLayoutSplit
45 #include <fmtlsplt.hxx>
46 // header for class SvxFmtKeepItem
47 #include <editeng/keepitem.hxx>
48 // header for class SvxFrameDirectionItem
49 #include <editeng/frmdiritem.hxx>
51 #include <fmtpdsc.hxx>
52 #include <fmtrowsplt.hxx>
53 #include <swundo.hxx> // fuer die UndoIds
54 #include <boost/shared_ptr.hpp>
60 #define FORMAT_PAINTBRUSH_FRAME_IDS \
61 RES_FRMATR_BEGIN, RES_FILL_ORDER, \
62 /* no RES_FRM_SIZE */ \
63 RES_PAPER_BIN, RES_SURROUND, \
64 /* no RES_VERT_ORIENT */ \
65 /* no RES_HORI_ORIENT */ \
67 RES_BACKGROUND, RES_SHADOW, \
68 /* no RES_FRMMACRO */ \
71 RES_EDIT_IN_READONLY, RES_LAYOUT_SPLIT, \
73 RES_TEXTGRID, RES_FRMATR_END-1,
75 #define FORMAT_PAINTBRUSH_PARAGRAPH_IDS \
76 RES_PARATR_BEGIN, RES_PARATR_END -1, \
77 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END -1, \
78 FORMAT_PAINTBRUSH_FRAME_IDS
80 SfxItemSet
* lcl_CreateEmptyItemSet( int nSelectionType
, SfxItemPool
& rPool
, bool bNoParagraphFormats
= false )
82 SfxItemSet
* pItemSet
= 0;
83 if( nSelectionType
& (nsSelectionType::SEL_FRM
| nsSelectionType::SEL_OLE
| nsSelectionType::SEL_GRF
) )
85 pItemSet
= new SfxItemSet(rPool
,
86 FORMAT_PAINTBRUSH_FRAME_IDS
89 else if( nSelectionType
& nsSelectionType::SEL_DRW
)
91 //is handled different
93 else if( nSelectionType
& nsSelectionType::SEL_TXT
)
95 if( bNoParagraphFormats
)
96 pItemSet
= new SfxItemSet(rPool
,
97 RES_CHRATR_BEGIN
, RES_CHRATR_END
- 1,
100 pItemSet
= new SfxItemSet(rPool
,
101 RES_CHRATR_BEGIN
, RES_CHRATR_END
- 1,
102 FORMAT_PAINTBRUSH_PARAGRAPH_IDS
108 void lcl_getTableAttributes( SfxItemSet
& rSet
, SwWrtShell
&rSh
)
110 SvxBrushItem
aBrush( RES_BACKGROUND
);
111 rSh
.GetBoxBackground(aBrush
);
113 if(rSh
.GetRowBackground(aBrush
))
114 rSet
.Put( aBrush
, SID_ATTR_BRUSH_ROW
);
116 rSet
.InvalidateItem(SID_ATTR_BRUSH_ROW
);
117 rSh
.GetTabBackground(aBrush
);
118 rSet
.Put( aBrush
, SID_ATTR_BRUSH_TABLE
);
120 SvxBoxInfoItem
aBoxInfo( SID_ATTR_BORDER_INNER
);
122 rSh
.GetTabBorders( rSet
);
124 SvxFrameDirectionItem
aBoxDirection( FRMDIR_ENVIRONMENT
, RES_FRAMEDIR
);
125 if(rSh
.GetBoxDirection( aBoxDirection
))
126 rSet
.Put(aBoxDirection
, FN_TABLE_BOX_TEXTORIENTATION
);
128 rSet
.Put(SfxUInt16Item(FN_TABLE_SET_VERT_ALIGN
, rSh
.GetBoxAlign()));
130 rSet
.Put( SfxUInt16Item( FN_PARAM_TABLE_HEADLINE
, rSh
.GetRowsToRepeat() ) );
132 SwFrmFmt
*pFrmFmt
= rSh
.GetTableFmt();
135 rSet
.Put( pFrmFmt
->GetShadow() );
136 rSet
.Put( pFrmFmt
->GetBreak() );
137 rSet
.Put( pFrmFmt
->GetPageDesc() );
138 rSet
.Put( pFrmFmt
->GetLayoutSplit() );
139 rSet
.Put( pFrmFmt
->GetKeep() );
140 rSet
.Put( pFrmFmt
->GetFrmDir() );
143 SwFmtRowSplit
* pSplit
= 0;
144 rSh
.GetRowSplit(pSplit
);
149 void lcl_setTableAttributes( const SfxItemSet
& rSet
, SwWrtShell
&rSh
)
151 const SfxPoolItem
* pItem
= 0;
152 bool bBorder
= ( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOX
) ||
153 SFX_ITEM_SET
== rSet
.GetItemState( SID_ATTR_BORDER_INNER
) );
154 sal_Bool bBackground
= SFX_ITEM_SET
== rSet
.GetItemState( RES_BACKGROUND
, sal_False
, &pItem
);
155 const SfxPoolItem
* pRowItem
= 0, *pTableItem
= 0;
156 bBackground
|= SFX_ITEM_SET
== rSet
.GetItemState( SID_ATTR_BRUSH_ROW
, sal_False
, &pRowItem
);
157 bBackground
|= SFX_ITEM_SET
== rSet
.GetItemState( SID_ATTR_BRUSH_TABLE
, sal_False
, &pTableItem
);
162 rSh
.SetBoxBackground( *(const SvxBrushItem
*)pItem
);
165 SvxBrushItem
aBrush(*(const SvxBrushItem
*)pRowItem
);
166 aBrush
.SetWhich(RES_BACKGROUND
);
167 rSh
.SetRowBackground(aBrush
);
171 SvxBrushItem
aBrush(*(const SvxBrushItem
*)pTableItem
);
172 aBrush
.SetWhich(RES_BACKGROUND
);
173 rSh
.SetTabBackground( aBrush
);
177 rSh
.SetTabBorders( rSet
);
179 if( SFX_ITEM_SET
== rSet
.GetItemState( FN_PARAM_TABLE_HEADLINE
, sal_False
, &pItem
) )
180 rSh
.SetRowsToRepeat( ((SfxUInt16Item
*)pItem
)->GetValue() );
182 SwFrmFmt
* pFrmFmt
= rSh
.GetTableFmt();
187 rSet
.GetItemState(rSet
.GetPool()->GetWhich(RES_SHADOW
), sal_False
, &pItem
);
189 pFrmFmt
->SetFmtAttr( *pItem
);
193 rSet
.GetItemState(rSet
.GetPool()->GetWhich(RES_BREAK
), sal_False
, &pItem
);
195 pFrmFmt
->SetFmtAttr( *pItem
);
199 rSet
.GetItemState(rSet
.GetPool()->GetWhich(RES_PAGEDESC
), sal_False
, &pItem
);
201 pFrmFmt
->SetFmtAttr( *pItem
);
205 rSet
.GetItemState(rSet
.GetPool()->GetWhich(RES_LAYOUT_SPLIT
), sal_False
, &pItem
);
207 pFrmFmt
->SetFmtAttr( *pItem
);
211 rSet
.GetItemState(rSet
.GetPool()->GetWhich(RES_KEEP
), sal_False
, &pItem
);
213 pFrmFmt
->SetFmtAttr( *pItem
);
217 rSet
.GetItemState(rSet
.GetPool()->GetWhich(RES_FRAMEDIR
), sal_False
, &pItem
);
219 pFrmFmt
->SetFmtAttr( *pItem
);
222 if( SFX_ITEM_SET
== rSet
.GetItemState( FN_TABLE_BOX_TEXTORIENTATION
, sal_False
, &pItem
) )
224 SvxFrameDirectionItem
aDirection( FRMDIR_ENVIRONMENT
, RES_FRAMEDIR
);
225 aDirection
.SetValue(static_cast< const SvxFrameDirectionItem
* >(pItem
)->GetValue());
226 rSh
.SetBoxDirection(aDirection
);
229 if( SFX_ITEM_SET
== rSet
.GetItemState( FN_TABLE_SET_VERT_ALIGN
, sal_False
, &pItem
))
230 rSh
.SetBoxAlign(((SfxUInt16Item
*)(pItem
))->GetValue());
232 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_ROW_SPLIT
, sal_False
, &pItem
) )
233 rSh
.SetRowSplit(*static_cast<const SwFmtRowSplit
*>(pItem
));
235 }//end anonymous namespace
237 SwFormatClipboard::SwFormatClipboard()
238 : m_nSelectionType(0)
239 , m_pItemSet_TxtAttr(0)
240 , m_pItemSet_ParAttr(0)
242 , m_bPersistentCopy(false)
245 SwFormatClipboard::~SwFormatClipboard()
247 delete m_pItemSet_TxtAttr
;
248 delete m_pItemSet_ParAttr
;
249 delete m_pTableItemSet
;
252 bool SwFormatClipboard::HasContent() const
254 return m_pItemSet_TxtAttr
!=0
255 || m_pItemSet_ParAttr
!=0
256 || m_pTableItemSet
!= 0
257 || m_aCharStyle
.Len()
258 || m_aParaStyle
.Len()
261 bool SwFormatClipboard::HasContentForThisType( int nSelectionType
) const
266 if( m_nSelectionType
== nSelectionType
)
269 if( ( nSelectionType
& (nsSelectionType::SEL_FRM
| nsSelectionType::SEL_OLE
| nsSelectionType::SEL_GRF
) )
271 ( m_nSelectionType
& (nsSelectionType::SEL_FRM
| nsSelectionType::SEL_OLE
| nsSelectionType::SEL_GRF
) )
275 if( nSelectionType
& nsSelectionType::SEL_TXT
&& m_nSelectionType
& nsSelectionType::SEL_TXT
)
281 bool SwFormatClipboard::CanCopyThisType( int nSelectionType
) const
283 if( nSelectionType
& (nsSelectionType::SEL_FRM
| nsSelectionType::SEL_OLE
| nsSelectionType::SEL_GRF
284 | nsSelectionType::SEL_TXT
| nsSelectionType::SEL_DRW
| nsSelectionType::SEL_TBL
| nsSelectionType::SEL_TBL_CELLS
) )
289 void SwFormatClipboard::Copy( SwWrtShell
& rWrtShell
, SfxItemPool
& rPool
, bool bPersistentCopy
)
291 // first clear the previously stored attributes
293 m_bPersistentCopy
= bPersistentCopy
;
295 int nSelectionType
= rWrtShell
.GetSelectionType();
296 SfxItemSet
* pItemSet_TxtAttr
= lcl_CreateEmptyItemSet( nSelectionType
, rPool
, true );
297 SfxItemSet
* pItemSet_ParAttr
= lcl_CreateEmptyItemSet( nSelectionType
, rPool
, false );
299 rWrtShell
.StartAction();
302 // modify the "Point and Mark" of the cursor
303 // in order to select only the last character of the
304 // selection(s) and then to get the attributes of this single character
305 if( nSelectionType
== nsSelectionType::SEL_TXT
)
307 // get the current PaM, the cursor
308 // if there several selection it curently point
309 // on the last (sort by there creation time) selection
310 SwPaM
* pCrsr
= rWrtShell
.GetCrsr();
312 sal_Bool bHasSelection
= pCrsr
->HasMark();
313 bool bForwardSelection
= false;
315 if(!bHasSelection
&& pCrsr
->GetPrev() != pCrsr
&& pCrsr
->GetPrev() != 0)
317 // if cursor has multiple selections
319 // clear all the selections except the last
320 rWrtShell
.KillPams();
322 // reset the cursor to the remaining selection
323 pCrsr
= rWrtShell
.GetCrsr();
324 bHasSelection
= true;
327 bool dontMove
= false;
330 bForwardSelection
= (*pCrsr
->GetPoint()) > (*pCrsr
->GetMark());
332 // clear the selection leaving just the cursor
338 bool rightToLeft
= rWrtShell
.IsInRightToLeftText();
339 // if there were no selection (only a cursor) and the cursor was at
340 // the end of the paragraph then don't move
341 if ( rWrtShell
.IsEndPara() && !rightToLeft
)
344 // revert left and right
347 if (pCrsr
->GetPoint()->nContent
== 0)
350 bForwardSelection
= !bForwardSelection
;
354 // move the cursor in order to select one character
356 pCrsr
->Move( bForwardSelection
? fnMoveBackward
: fnMoveForward
);
361 if( nSelectionType
& (nsSelectionType::SEL_FRM
| nsSelectionType::SEL_OLE
| nsSelectionType::SEL_GRF
) )
362 rWrtShell
.GetFlyFrmAttr(*pItemSet_TxtAttr
);
365 // get the text attributes from named and automatic formatting
366 rWrtShell
.GetCurAttr(*pItemSet_TxtAttr
);
368 if( nSelectionType
& nsSelectionType::SEL_TXT
)
370 // get the paragraph attributes (could be character properties)
371 // from named and automatic formatting
372 rWrtShell
.GetCurParAttr(*pItemSet_ParAttr
);
376 else if ( nSelectionType
& nsSelectionType::SEL_DRW
)
378 SdrView
* pDrawView
= rWrtShell
.GetDrawView();
381 sal_Bool bOnlyHardAttr
= sal_True
;
382 if( pDrawView
->AreObjectsMarked() )
384 pItemSet_TxtAttr
= new SfxItemSet( pDrawView
->GetAttrFromMarked(bOnlyHardAttr
) );
385 //remove attributes defining the type/data of custom shapes
386 pItemSet_TxtAttr
->ClearItem(SDRATTR_CUSTOMSHAPE_ENGINE
);
387 pItemSet_TxtAttr
->ClearItem(SDRATTR_CUSTOMSHAPE_DATA
);
388 pItemSet_TxtAttr
->ClearItem(SDRATTR_CUSTOMSHAPE_GEOMETRY
);
389 pItemSet_TxtAttr
->ClearItem(SDRATTR_CUSTOMSHAPE_REPLACEMENT_URL
);
394 if( nSelectionType
& nsSelectionType::SEL_TBL_CELLS
)//only copy table attributes if really cells are selected (not only text in tables)
396 m_pTableItemSet
= new SfxItemSet(rPool
,
397 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_SHADOW
, //SID_ATTR_BORDER_OUTER is inbetween
398 RES_BACKGROUND
, RES_SHADOW
, //RES_BOX is inbetween
399 SID_ATTR_BRUSH_ROW
, SID_ATTR_BRUSH_TABLE
,
400 RES_BREAK
, RES_BREAK
,
401 RES_PAGEDESC
, RES_PAGEDESC
,
402 RES_LAYOUT_SPLIT
, RES_LAYOUT_SPLIT
,
403 RES_ROW_SPLIT
, RES_ROW_SPLIT
,
405 RES_FRAMEDIR
, RES_FRAMEDIR
,
406 FN_PARAM_TABLE_HEADLINE
, FN_PARAM_TABLE_HEADLINE
,
407 FN_TABLE_BOX_TEXTORIENTATION
, FN_TABLE_BOX_TEXTORIENTATION
,
408 FN_TABLE_SET_VERT_ALIGN
, FN_TABLE_SET_VERT_ALIGN
,
410 lcl_getTableAttributes( *m_pTableItemSet
, rWrtShell
);
413 m_nSelectionType
= nSelectionType
;
414 m_pItemSet_TxtAttr
= pItemSet_TxtAttr
;
415 m_pItemSet_ParAttr
= pItemSet_ParAttr
;
417 if( nSelectionType
& nsSelectionType::SEL_TXT
)
419 // if text is selected save the named character format
420 SwFmt
* pFmt
= rWrtShell
.GetCurCharFmt();
422 m_aCharStyle
= pFmt
->GetName();
424 // and the named paragraph format
425 pFmt
= rWrtShell
.GetCurTxtFmtColl();
427 m_aParaStyle
= pFmt
->GetName();
430 rWrtShell
.Pop(sal_False
);
431 rWrtShell
.EndAction();
434 typedef boost::shared_ptr
< SfxPoolItem
> SfxPoolItemSharedPtr
;
435 typedef std::vector
< SfxPoolItemSharedPtr
> ItemVector
;
436 // collect all PoolItems from the applied styles
437 static void lcl_AppendSetItems( ItemVector
& rItemVector
, const SfxItemSet
& rStyleAttrSet
)
439 const sal_uInt16
* pRanges
= rStyleAttrSet
.GetRanges();
442 for ( sal_uInt16 nWhich
= *pRanges
; nWhich
<= *(pRanges
+1); ++nWhich
)
444 const SfxPoolItem
* pItem
;
445 if( SFX_ITEM_SET
== rStyleAttrSet
.GetItemState( nWhich
, sal_False
, &pItem
) )
447 rItemVector
.push_back( SfxPoolItemSharedPtr( pItem
->Clone() ) );
453 // remove all items that are inherited from the styles
454 static void lcl_RemoveEqualItems( SfxItemSet
& rTemplateItemSet
, const ItemVector
& rItemVector
)
456 ItemVector::const_iterator aEnd
= rItemVector
.end();
457 ItemVector::const_iterator aIter
= rItemVector
.begin();
458 while( aIter
!= aEnd
)
460 const SfxPoolItem
* pItem
;
461 if( SFX_ITEM_SET
== rTemplateItemSet
.GetItemState( (*aIter
)->Which(), sal_True
, &pItem
) &&
462 *pItem
== *(*aIter
) )
464 rTemplateItemSet
.ClearItem( (*aIter
)->Which() );
470 void SwFormatClipboard::Paste( SwWrtShell
& rWrtShell
, SfxStyleSheetBasePool
* pPool
471 , bool bNoCharacterFormats
, bool bNoParagraphFormats
)
473 int nSelectionType
= rWrtShell
.GetSelectionType();
474 if( !this->HasContentForThisType(nSelectionType
) )
476 if(!m_bPersistentCopy
)
481 rWrtShell
.StartAction();
482 rWrtShell
.StartUndo(UNDO_INSATTR
);
484 ItemVector aItemVector
;
486 if( nSelectionType
& nsSelectionType::SEL_TXT
)
488 // apply the named text and paragraph formatting
491 // if there is a named text format recorded and the user wants to apply it
492 if(m_aCharStyle
.Len() && !bNoCharacterFormats
)
494 // look for the named text format in the pool
495 SwDocStyleSheet
* pStyle
= static_cast<SwDocStyleSheet
*>(pPool
->Find(m_aCharStyle
, SFX_STYLE_FAMILY_CHAR
));
497 // if the style is found
500 SwFmtCharFmt
aFmt(pStyle
->GetCharFmt());
501 // store the attributes from this style in aItemVector in order
502 // not to apply them as automatic formatting attributes later in the code
503 lcl_AppendSetItems( aItemVector
, aFmt
.GetCharFmt()->GetAttrSet());
505 // apply the named format
506 rWrtShell
.SetAttr( aFmt
);
510 // if there is a named paragraph format recorded and the user wants to apply it
511 if(m_aParaStyle
.Len() && !bNoParagraphFormats
)
513 // look for the named pragraph format in the pool
514 SwDocStyleSheet
* pStyle
= static_cast<SwDocStyleSheet
*>(pPool
->Find(m_aParaStyle
, SFX_STYLE_FAMILY_PARA
));
517 // store the attributes from this style in aItemVector in order
518 // not to apply them as automatic formatting attributes later in the code
519 lcl_AppendSetItems( aItemVector
, pStyle
->GetCollection()->GetAttrSet());
521 // apply the named format
522 rWrtShell
.SetTxtFmtColl( pStyle
->GetCollection() );
527 // apply the paragraph automatic attributes
528 if ( m_pItemSet_ParAttr
&& m_pItemSet_ParAttr
->Count() != 0 && !bNoParagraphFormats
)
530 // temporary SfxItemSet
531 SfxItemSet
* pTemplateItemSet
= lcl_CreateEmptyItemSet(
532 nSelectionType
, *m_pItemSet_ParAttr
->GetPool(), false);
533 // no need to verify the existance of pTemplateItemSet as we
534 // know that here the selection type is SEL_TXT
536 pTemplateItemSet
->Put( *m_pItemSet_ParAttr
);
538 // remove attribute that were applied by named text and paragraph formatting
539 lcl_RemoveEqualItems( *pTemplateItemSet
, aItemVector
);
541 // apply the paragraph automatic attributes to all the nodes in the selection
542 rWrtShell
.SetAttr(*pTemplateItemSet
);
544 // store the attributes in aItemVector in order not to apply them as
545 // text automatic formating attributes later in the code
546 lcl_AppendSetItems( aItemVector
, *pTemplateItemSet
);
548 delete pTemplateItemSet
;
552 if(m_pItemSet_TxtAttr
)
554 if( nSelectionType
& nsSelectionType::SEL_DRW
)
556 SdrView
* pDrawView
= rWrtShell
.GetDrawView();
559 sal_Bool bReplaceAll
= sal_True
;
560 pDrawView
->SetAttrToMarked(*m_pItemSet_TxtAttr
, bReplaceAll
);
565 // temporary SfxItemSet
566 SfxItemSet
* pTemplateItemSet
= lcl_CreateEmptyItemSet(
567 nSelectionType
, *m_pItemSet_TxtAttr
->GetPool(), true );
571 // copy the stored automatic text attributes in a temporary SfxItemSet
572 pTemplateItemSet
->Put( *m_pItemSet_TxtAttr
);
574 // only attributes that were not apply by named style attributes and automatic
575 // paragraph attributes should be applied
576 lcl_RemoveEqualItems( *pTemplateItemSet
, aItemVector
);
578 // apply the character automatic attributes
579 if( nSelectionType
& (nsSelectionType::SEL_FRM
| nsSelectionType::SEL_OLE
| nsSelectionType::SEL_GRF
) )
580 rWrtShell
.SetFlyFrmAttr(*pTemplateItemSet
);
581 else if ( !bNoCharacterFormats
)
582 rWrtShell
.SetAttr(*pTemplateItemSet
);
584 delete pTemplateItemSet
;
589 if( m_pTableItemSet
&& nSelectionType
& (nsSelectionType::SEL_TBL
| nsSelectionType::SEL_TBL_CELLS
) )
590 lcl_setTableAttributes( *m_pTableItemSet
, rWrtShell
);
592 rWrtShell
.EndUndo(UNDO_INSATTR
);
593 rWrtShell
.EndAction();
595 if(!m_bPersistentCopy
)
599 void SwFormatClipboard::Erase()
601 m_nSelectionType
= 0;
603 delete m_pItemSet_TxtAttr
;
604 m_pItemSet_TxtAttr
= 0;
606 delete m_pItemSet_ParAttr
;
607 m_pItemSet_ParAttr
= 0;
609 delete m_pTableItemSet
;
612 if( m_aCharStyle
.Len() )
613 m_aCharStyle
.Erase();
614 if( m_aParaStyle
.Len() )
615 m_aParaStyle
.Erase();
617 m_bPersistentCopy
= false;
620 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */