merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / txtnode / fmtatr2.cxx
blob3d0a043920e528601656391137775007ad892793
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fmtatr2.cxx,v $
10 * $Revision: 1.30 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include "hintids.hxx"
35 #include "unomid.h"
37 #include <basic/sbxvar.hxx>
38 #include <svtools/macitem.hxx>
39 #include <svtools/stritem.hxx>
40 #include <svtools/stylepool.hxx>
41 #include <fmtautofmt.hxx>
42 #include <fchrfmt.hxx>
43 #include <fmtinfmt.hxx>
44 #include <txtatr.hxx>
45 #include <fmtruby.hxx>
46 #include <charfmt.hxx>
47 #include <hints.hxx> // SwUpdateAttr
48 #include <unostyle.hxx>
49 #include <unoevent.hxx> // SwHyperlinkEventDescriptor
50 #include <com/sun/star/text/RubyAdjust.hdl>
52 #include <cmdid.h>
53 #include <com/sun/star/uno/Any.h>
54 #include <SwStyleNameMapper.hxx>
56 #include <fmtmeta.hxx>
57 #include <ndtxt.hxx> // for meta
58 #include <doc.hxx> // for meta
59 #include <unometa.hxx>
60 #include <unoobj.hxx> // SwXTextRange
61 #include <docsh.hxx>
62 #include <svtools/zforlist.hxx> // GetNumberFormat
64 #include <boost/bind.hpp>
65 #include <algorithm>
68 using namespace ::com::sun::star;
69 using ::rtl::OUString;
71 TYPEINIT1_AUTOFACTORY(SwFmtINetFmt, SfxPoolItem);
72 TYPEINIT1_AUTOFACTORY(SwFmtAutoFmt, SfxPoolItem);
74 /*************************************************************************
76 |* class SwFmtCharFmt
77 |* Beschreibung
78 |* Ersterstellung JP 23.11.90
79 |* Letzte Aenderung JP 09.08.94
81 *************************************************************************/
83 SwFmtCharFmt::SwFmtCharFmt( SwCharFmt *pFmt )
84 : SfxPoolItem( RES_TXTATR_CHARFMT ),
85 SwClient(pFmt),
86 pTxtAttr( 0 )
92 SwFmtCharFmt::SwFmtCharFmt( const SwFmtCharFmt& rAttr )
93 : SfxPoolItem( RES_TXTATR_CHARFMT ),
94 SwClient( rAttr.GetCharFmt() ),
95 pTxtAttr( 0 )
101 SwFmtCharFmt::~SwFmtCharFmt() {}
105 int SwFmtCharFmt::operator==( const SfxPoolItem& rAttr ) const
107 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
108 return GetCharFmt() == ((SwFmtCharFmt&)rAttr).GetCharFmt();
113 SfxPoolItem* SwFmtCharFmt::Clone( SfxItemPool* ) const
115 return new SwFmtCharFmt( *this );
120 // weiterleiten an das TextAttribut
121 void SwFmtCharFmt::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
123 if( pTxtAttr )
124 pTxtAttr->Modify( pOld, pNew );
129 // weiterleiten an das TextAttribut
130 BOOL SwFmtCharFmt::GetInfo( SfxPoolItem& rInfo ) const
132 return pTxtAttr ? pTxtAttr->GetInfo( rInfo ) : FALSE;
134 BOOL SwFmtCharFmt::QueryValue( uno::Any& rVal, BYTE ) const
136 String sCharFmtName;
137 if(GetCharFmt())
138 SwStyleNameMapper::FillProgName(GetCharFmt()->GetName(), sCharFmtName, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
139 rVal <<= OUString( sCharFmtName );
140 return TRUE;
142 BOOL SwFmtCharFmt::PutValue( const uno::Any& , BYTE )
144 DBG_ERROR("Zeichenvorlage kann mit PutValue nicht gesetzt werden!");
145 return FALSE;
148 /*************************************************************************
150 |* class SwFmtAutoFmt
151 |* Beschreibung
152 |* Ersterstellung AMA 12.05.06
153 |* Letzte Aenderung AMA 12.05.06
155 *************************************************************************/
157 SwFmtAutoFmt::SwFmtAutoFmt( USHORT nInitWhich )
158 : SfxPoolItem( nInitWhich )
162 SwFmtAutoFmt::SwFmtAutoFmt( const SwFmtAutoFmt& rAttr )
163 : SfxPoolItem( rAttr.Which() ), mpHandle( rAttr.mpHandle )
167 SwFmtAutoFmt::~SwFmtAutoFmt()
171 int SwFmtAutoFmt::operator==( const SfxPoolItem& rAttr ) const
173 ASSERT( SfxPoolItem::operator==( rAttr ), "different attributes" );
174 return mpHandle == ((SwFmtAutoFmt&)rAttr).mpHandle;
177 SfxPoolItem* SwFmtAutoFmt::Clone( SfxItemPool* ) const
179 return new SwFmtAutoFmt( *this );
182 BOOL SwFmtAutoFmt::QueryValue( uno::Any& rVal, BYTE ) const
184 String sCharFmtName = StylePool::nameOf( mpHandle );
185 rVal <<= OUString( sCharFmtName );
186 return TRUE;
189 BOOL SwFmtAutoFmt::PutValue( const uno::Any& , BYTE )
191 //the format is not renameable via API
192 return FALSE;
195 /*************************************************************************
197 |* class SwFmtINetFmt
198 |* Beschreibung
199 |* Ersterstellung AMA 02.08.96
200 |* Letzte Aenderung AMA 02.08.96
202 *************************************************************************/
204 SwFmtINetFmt::SwFmtINetFmt()
205 : SfxPoolItem( RES_TXTATR_INETFMT ),
206 pMacroTbl( 0 ),
207 pTxtAttr( 0 ),
208 nINetId( 0 ),
209 nVisitedId( 0 )
212 SwFmtINetFmt::SwFmtINetFmt( const XubString& rURL, const XubString& rTarget )
213 : SfxPoolItem( RES_TXTATR_INETFMT ),
214 aURL( rURL ),
215 aTargetFrame( rTarget ),
216 pMacroTbl( 0 ),
217 pTxtAttr( 0 ),
218 nINetId( 0 ),
219 nVisitedId( 0 )
223 SwFmtINetFmt::SwFmtINetFmt( const SwFmtINetFmt& rAttr )
224 : SfxPoolItem( RES_TXTATR_INETFMT ),
225 aURL( rAttr.GetValue() ),
226 aTargetFrame( rAttr.aTargetFrame ),
227 aINetFmt( rAttr.aINetFmt ),
228 aVisitedFmt( rAttr.aVisitedFmt ),
229 aName( rAttr.aName ),
230 pMacroTbl( 0 ),
231 pTxtAttr( 0 ),
232 nINetId( rAttr.nINetId ),
233 nVisitedId( rAttr.nVisitedId )
235 if( rAttr.GetMacroTbl() )
236 pMacroTbl = new SvxMacroTableDtor( *rAttr.GetMacroTbl() );
239 SwFmtINetFmt::~SwFmtINetFmt()
241 delete pMacroTbl;
246 int SwFmtINetFmt::operator==( const SfxPoolItem& rAttr ) const
248 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
249 BOOL bRet = SfxPoolItem::operator==( (SfxPoolItem&) rAttr )
250 && aURL == ((SwFmtINetFmt&)rAttr).aURL
251 && aName == ((SwFmtINetFmt&)rAttr).aName
252 && aTargetFrame == ((SwFmtINetFmt&)rAttr).aTargetFrame
253 && aINetFmt == ((SwFmtINetFmt&)rAttr).aINetFmt
254 && aVisitedFmt == ((SwFmtINetFmt&)rAttr).aVisitedFmt
255 && nINetId == ((SwFmtINetFmt&)rAttr).nINetId
256 && nVisitedId == ((SwFmtINetFmt&)rAttr).nVisitedId;
258 if( !bRet )
259 return FALSE;
261 const SvxMacroTableDtor* pOther = ((SwFmtINetFmt&)rAttr).pMacroTbl;
262 if( !pMacroTbl )
263 return ( !pOther || !pOther->Count() );
264 if( !pOther )
265 return 0 == pMacroTbl->Count();
267 const SvxMacroTableDtor& rOwn = *pMacroTbl;
268 const SvxMacroTableDtor& rOther = *pOther;
270 // Anzahl unterschiedlich => auf jeden Fall ungleich
271 if( rOwn.Count() != rOther.Count() )
272 return FALSE;
274 // einzeln vergleichen; wegen Performance ist die Reihenfolge wichtig
275 for( USHORT nNo = 0; nNo < rOwn.Count(); ++nNo )
277 const SvxMacro *pOwnMac = rOwn.GetObject(nNo);
278 const SvxMacro *pOtherMac = rOther.GetObject(nNo);
279 if ( rOwn.GetKey(pOwnMac) != rOther.GetKey(pOtherMac) ||
280 pOwnMac->GetLibName() != pOtherMac->GetLibName() ||
281 pOwnMac->GetMacName() != pOtherMac->GetMacName() )
282 return FALSE;
284 return TRUE;
289 SfxPoolItem* SwFmtINetFmt::Clone( SfxItemPool* ) const
291 return new SwFmtINetFmt( *this );
296 void SwFmtINetFmt::SetMacroTbl( const SvxMacroTableDtor* pNewTbl )
298 if( pNewTbl )
300 if( pMacroTbl )
301 *pMacroTbl = *pNewTbl;
302 else
303 pMacroTbl = new SvxMacroTableDtor( *pNewTbl );
305 else if( pMacroTbl )
306 delete pMacroTbl, pMacroTbl = 0;
311 void SwFmtINetFmt::SetMacro( USHORT nEvent, const SvxMacro& rMacro )
313 if( !pMacroTbl )
314 pMacroTbl = new SvxMacroTableDtor;
316 SvxMacro *pOldMacro;
317 if( 0 != ( pOldMacro = pMacroTbl->Get( nEvent )) )
319 delete pOldMacro;
320 pMacroTbl->Replace( nEvent, new SvxMacro( rMacro ) );
322 else
323 pMacroTbl->Insert( nEvent, new SvxMacro( rMacro ) );
328 const SvxMacro* SwFmtINetFmt::GetMacro( USHORT nEvent ) const
330 const SvxMacro* pRet = 0;
331 if( pMacroTbl && pMacroTbl->IsKeyValid( nEvent ) )
332 pRet = pMacroTbl->Get( nEvent );
333 return pRet;
338 BOOL SwFmtINetFmt::QueryValue( uno::Any& rVal, BYTE nMemberId ) const
340 BOOL bRet = TRUE;
341 XubString sVal;
342 nMemberId &= ~CONVERT_TWIPS;
343 switch(nMemberId)
345 case MID_URL_URL:
346 sVal = aURL;
347 break;
348 case MID_URL_TARGET:
349 sVal = aTargetFrame;
350 break;
351 case MID_URL_HYPERLINKNAME:
352 sVal = aName;
353 break;
354 case MID_URL_VISITED_FMT:
355 sVal = aVisitedFmt;
356 if( !sVal.Len() && nVisitedId != 0 )
357 SwStyleNameMapper::FillUIName( nVisitedId, sVal );
358 if( sVal.Len() )
359 SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
360 break;
361 case MID_URL_UNVISITED_FMT:
362 sVal = aINetFmt;
363 if( !sVal.Len() && nINetId != 0 )
364 SwStyleNameMapper::FillUIName( nINetId, sVal );
365 if( sVal.Len() )
366 SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
367 break;
368 case MID_URL_HYPERLINKEVENTS:
370 // create (and return) event descriptor
371 SwHyperlinkEventDescriptor* pEvents =
372 new SwHyperlinkEventDescriptor();
373 pEvents->copyMacrosFromINetFmt(*this);
374 uno::Reference<container::XNameReplace> xNameReplace(pEvents);
376 // all others return a string; so we just set rVal here and exit
377 rVal <<= xNameReplace;
378 return bRet;
380 default:
381 break;
383 rVal <<= OUString(sVal);
384 return bRet;
386 BOOL SwFmtINetFmt::PutValue( const uno::Any& rVal, BYTE nMemberId )
388 BOOL bRet = TRUE;
389 nMemberId &= ~CONVERT_TWIPS;
391 // all properties except HyperlinkEvents are of type string, hence
392 // we treat HyperlinkEvents specially
393 if (MID_URL_HYPERLINKEVENTS == nMemberId)
395 uno::Reference<container::XNameReplace> xReplace;
396 rVal >>= xReplace;
397 if (xReplace.is())
399 // Create hyperlink event descriptor. Then copy events
400 // from argument into descriptor. Then copy events from
401 // the descriptor into the format.
402 SwHyperlinkEventDescriptor* pEvents = new SwHyperlinkEventDescriptor();
403 uno::Reference< lang::XServiceInfo> xHold = pEvents;
404 pEvents->copyMacrosFromNameReplace(xReplace);
405 pEvents->copyMacrosIntoINetFmt(*this);
407 else
409 // wrong type!
410 bRet = FALSE;
413 else
415 // all string properties:
416 if(rVal.getValueType() != ::getCppuType((rtl::OUString*)0))
417 return FALSE;
418 XubString sVal = *(rtl::OUString*)rVal.getValue();
419 switch(nMemberId)
421 case MID_URL_URL:
422 aURL = sVal;
423 break;
424 case MID_URL_TARGET:
425 aTargetFrame = sVal;
426 break;
427 case MID_URL_HYPERLINKNAME:
428 aName = sVal;
429 break;
430 case MID_URL_VISITED_FMT:
432 String aString;
433 SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
434 aVisitedFmt = OUString ( aString );
435 nVisitedId = SwStyleNameMapper::GetPoolIdFromUIName( aVisitedFmt,
436 nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
438 break;
439 case MID_URL_UNVISITED_FMT:
441 String aString;
442 SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
443 aINetFmt = OUString ( aString );
444 nINetId = SwStyleNameMapper::GetPoolIdFromUIName( aINetFmt, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
446 break;
447 default:
448 bRet = FALSE;
451 return bRet;
455 /*************************************************************************
456 |* class SwFmtRuby
457 *************************************************************************/
459 SwFmtRuby::SwFmtRuby( const String& rRubyTxt )
460 : SfxPoolItem( RES_TXTATR_CJK_RUBY ),
461 sRubyTxt( rRubyTxt ),
462 pTxtAttr( 0 ),
463 nCharFmtId( 0 ),
464 nPosition( 0 ),
465 nAdjustment( 0 )
469 SwFmtRuby::SwFmtRuby( const SwFmtRuby& rAttr )
470 : SfxPoolItem( RES_TXTATR_CJK_RUBY ),
471 sRubyTxt( rAttr.sRubyTxt ),
472 sCharFmtName( rAttr.sCharFmtName ),
473 pTxtAttr( 0 ),
474 nCharFmtId( rAttr.nCharFmtId),
475 nPosition( rAttr.nPosition ),
476 nAdjustment( rAttr.nAdjustment )
480 SwFmtRuby::~SwFmtRuby()
484 SwFmtRuby& SwFmtRuby::operator=( const SwFmtRuby& rAttr )
486 sRubyTxt = rAttr.sRubyTxt;
487 sCharFmtName = rAttr.sCharFmtName;
488 nCharFmtId = rAttr.nCharFmtId;
489 nPosition = rAttr.nPosition;
490 nAdjustment = rAttr.nAdjustment;
491 pTxtAttr = 0;
492 return *this;
495 int SwFmtRuby::operator==( const SfxPoolItem& rAttr ) const
497 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
498 return sRubyTxt == ((SwFmtRuby&)rAttr).sRubyTxt &&
499 sCharFmtName == ((SwFmtRuby&)rAttr).sCharFmtName &&
500 nCharFmtId == ((SwFmtRuby&)rAttr).nCharFmtId &&
501 nPosition == ((SwFmtRuby&)rAttr).nPosition &&
502 nAdjustment == ((SwFmtRuby&)rAttr).nAdjustment;
505 SfxPoolItem* SwFmtRuby::Clone( SfxItemPool* ) const
507 return new SwFmtRuby( *this );
510 BOOL SwFmtRuby::QueryValue( uno::Any& rVal,
511 BYTE nMemberId ) const
513 BOOL bRet = TRUE;
514 nMemberId &= ~CONVERT_TWIPS;
515 switch( nMemberId )
517 case MID_RUBY_TEXT: rVal <<= (OUString)sRubyTxt; break;
518 case MID_RUBY_ADJUST: rVal <<= (sal_Int16)nAdjustment; break;
519 case MID_RUBY_CHARSTYLE:
521 String aString;
522 SwStyleNameMapper::FillProgName(sCharFmtName, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
523 rVal <<= OUString ( aString );
525 break;
526 case MID_RUBY_ABOVE:
528 sal_Bool bAbove = !nPosition;
529 rVal.setValue(&bAbove, ::getBooleanCppuType());
531 break;
532 default:
533 bRet = FALSE;
535 return bRet;
537 BOOL SwFmtRuby::PutValue( const uno::Any& rVal,
538 BYTE nMemberId )
540 BOOL bRet = TRUE;
541 nMemberId &= ~CONVERT_TWIPS;
542 switch( nMemberId )
544 case MID_RUBY_TEXT:
546 OUString sTmp;
547 bRet = rVal >>= sTmp;
548 sRubyTxt = sTmp;
550 break;
551 case MID_RUBY_ADJUST:
553 sal_Int16 nSet = 0;
554 rVal >>= nSet;
555 if(nSet >= 0 && nSet <= text::RubyAdjust_INDENT_BLOCK)
556 nAdjustment = nSet;
557 else
558 bRet = sal_False;
560 break;
561 case MID_RUBY_ABOVE:
563 const uno::Type& rType = ::getBooleanCppuType();
564 if(rVal.hasValue() && rVal.getValueType() == rType)
566 sal_Bool bAbove = *(sal_Bool*)rVal.getValue();
567 nPosition = bAbove ? 0 : 1;
570 break;
571 case MID_RUBY_CHARSTYLE:
573 OUString sTmp;
574 bRet = rVal >>= sTmp;
575 if(bRet)
576 sCharFmtName = SwStyleNameMapper::GetUIName(sTmp, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
578 break;
579 default:
580 bRet = FALSE;
582 return bRet;
586 /*************************************************************************
587 class SwFmtMeta
588 ************************************************************************/
590 SwFmtMeta * SwFmtMeta::CreatePoolDefault(const USHORT i_nWhich)
592 return new SwFmtMeta(i_nWhich);
595 SwFmtMeta::SwFmtMeta(const USHORT i_nWhich)
596 : SfxPoolItem( i_nWhich )
597 , m_pMeta()
598 , m_pTxtAttr( 0 )
600 ASSERT((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
601 "ERROR: SwFmtMeta: invalid which id!");
604 SwFmtMeta::SwFmtMeta( ::boost::shared_ptr< ::sw::Meta > const & i_pMeta,
605 const USHORT i_nWhich )
606 : SfxPoolItem( i_nWhich )
607 , m_pMeta( i_pMeta )
608 , m_pTxtAttr( 0 )
610 ASSERT((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
611 "ERROR: SwFmtMeta: invalid which id!");
612 ASSERT(m_pMeta, "SwFmtMeta: no Meta ?");
613 // DO NOT call m_pMeta->SetFmtMeta(this) here; only from SetTxtAttr!
616 SwFmtMeta::~SwFmtMeta()
618 if (m_pMeta && (m_pMeta->GetFmtMeta() == this))
620 m_pMeta->SetFmtMeta(0);
624 int SwFmtMeta::operator==( const SfxPoolItem & i_rOther ) const
626 ASSERT( SfxPoolItem::operator==( i_rOther ), "i just copied this assert" );
627 return SfxPoolItem::operator==( i_rOther )
628 && (m_pMeta == static_cast<SwFmtMeta const &>( i_rOther ).m_pMeta);
631 SfxPoolItem * SwFmtMeta::Clone( SfxItemPool * /*pPool*/ ) const
633 // if this is indeed a copy, then DoCopy must be called later!
634 return (m_pMeta) // #i105148# pool default may be cloned also!
635 ? new SwFmtMeta( m_pMeta, Which() ) : new SwFmtMeta( Which() );
638 void SwFmtMeta::SetTxtAttr(SwTxtMeta * const i_pTxtAttr)
640 ASSERT(!(m_pTxtAttr && i_pTxtAttr),
641 "SwFmtMeta::SetTxtAttr: already has text attribute?");
642 ASSERT( m_pTxtAttr || i_pTxtAttr ,
643 "SwFmtMeta::SetTxtAttr: no attribute to remove?");
644 m_pTxtAttr = i_pTxtAttr;
645 ASSERT(m_pMeta, "inserted SwFmtMeta has no sw::Meta?");
646 // the sw::Meta must be able to find the current text attribute!
647 if (i_pTxtAttr && m_pMeta)
649 m_pMeta->SetFmtMeta(this);
653 void SwFmtMeta::NotifyRemoval()
655 // N.B.: do not reset m_pTxtAttr here: see call in nodes.cxx,
656 // where the hint is not deleted!
657 ASSERT(m_pMeta, "NotifyRemoval: no meta ?");
658 if (m_pMeta)
660 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
661 &static_cast<SwModify&>(*m_pMeta) ); // cast to proper base class!
662 m_pMeta->Modify(&aMsgHint, &aMsgHint);
666 void SwFmtMeta::DoCopy(SwFmtMeta & rOriginalMeta)
668 ASSERT(m_pMeta, "DoCopy called for SwFmtMeta with no sw::Meta?");
669 if (m_pMeta)
671 const ::boost::shared_ptr< ::sw::Meta> pOriginal( m_pMeta );
672 // UGLY: original sw::Meta now points at _this_ due to being already
673 // inserted via MakeTxtAttr! so fix it up to point at the original item
674 // (maybe would be better to tell MakeTxtAttr that it creates a copy?)
675 pOriginal->SetFmtMeta(&rOriginalMeta);
676 if (RES_TXTATR_META == Which())
678 m_pMeta.reset( new ::sw::Meta(this) );
680 else
682 ::sw::MetaField *const pMetaField(
683 static_cast< ::sw::MetaField* >(pOriginal.get()));
684 SwDoc * const pTargetDoc( GetTxtAttr()->GetTxtNode()->GetDoc() );
685 m_pMeta = pTargetDoc->GetMetaFieldManager().makeMetaField( this,
686 pMetaField->m_nNumberFormat, pMetaField->IsFixedLanguage() );
688 m_pMeta->RegisterAsCopyOf(*pOriginal);
693 namespace sw {
695 /*************************************************************************
696 class sw::Meta
697 ************************************************************************/
699 Meta::Meta(SwFmtMeta * const i_pFmt)
700 : ::sfx2::Metadatable()
701 , SwModify()
702 , m_pFmt( i_pFmt )
706 Meta::~Meta()
710 SwTxtMeta * Meta::GetTxtAttr() const
712 return (m_pFmt) ? m_pFmt->GetTxtAttr() : 0;
715 SwTxtNode * Meta::GetTxtNode() const
717 SwTxtMeta * const pTxtAttr( GetTxtAttr() );
718 return (pTxtAttr) ? pTxtAttr->GetTxtNode() : 0;
721 // SwClient
722 void Meta::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew )
724 SwTxtNode * const pTxtNode( GetTxtNode() );
725 if (pTxtNode && (GetRegisteredIn() != pTxtNode))
727 pTxtNode->Add(this);
729 SwModify::Modify(pOld, pNew);
732 // sw::Metadatable
733 ::sfx2::IXmlIdRegistry& Meta::GetRegistry()
735 SwTxtNode * const pTxtNode( GetTxtNode() );
736 // GetRegistry may only be called on a meta that is actually in the
737 // document, which means it has a pointer to its text node
738 OSL_ENSURE(pTxtNode, "ERROR: GetRegistry: no text node?");
739 if (!pTxtNode)
740 throw uno::RuntimeException();
741 return pTxtNode->GetRegistry();
744 bool Meta::IsInClipboard() const
746 const SwTxtNode * const pTxtNode( GetTxtNode() );
747 // no text node: in UNDO OSL_ENSURE(pTxtNode, "IsInClipboard: no text node?");
748 return (pTxtNode) ? pTxtNode->IsInClipboard() : false;
751 bool Meta::IsInUndo() const
753 const SwTxtNode * const pTxtNode( GetTxtNode() );
754 // no text node: in UNDO OSL_ENSURE(pTxtNode, "IsInUndo: no text node?");
755 return (pTxtNode) ? pTxtNode->IsInUndo() : true;
758 bool Meta::IsInContent() const
760 const SwTxtNode * const pTxtNode( GetTxtNode() );
761 OSL_ENSURE(pTxtNode, "IsInContent: no text node?");
762 return (pTxtNode) ? pTxtNode->IsInContent() : true;
765 ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable >
766 Meta::MakeUnoObject()
768 // re-use existing SwXMeta
769 SwClientIter iter( *this );
770 SwClient * pClient( iter.First( TYPE( SwXMeta ) ) );
771 while (pClient) {
772 SwXMeta *const pMeta( dynamic_cast<SwXMeta*>(pClient) );
773 if (pMeta && pMeta->GetCoreObject() == this) {
774 return pMeta;
776 pClient = iter.Next();
779 // create new SwXMeta
780 SwTxtMeta * const pTxtAttr( GetTxtAttr() );
781 OSL_ENSURE(pTxtAttr, "MakeUnoObject: no text attr?");
782 if (!pTxtAttr) return 0;
783 SwTxtNode * const pTxtNode( pTxtAttr->GetTxtNode() );
784 OSL_ENSURE(pTxtNode, "MakeUnoObject: no text node?");
785 if (!pTxtNode) return 0;
786 const SwPosition aPos(*pTxtNode, *pTxtAttr->GetStart());
787 const uno::Reference<text::XText> xParentText(
788 SwXTextRange::CreateParentXText(pTxtNode->GetDoc(), aPos) );
789 if (!xParentText.is()) return 0;
790 return (RES_TXTATR_META == m_pFmt->Which())
791 ? new SwXMeta (pTxtNode->GetDoc(), xParentText, 0, pTxtAttr)
792 : new SwXMetaField(pTxtNode->GetDoc(), xParentText, 0, pTxtAttr);
795 /*************************************************************************
796 class sw::MetaField
797 ************************************************************************/
799 MetaField::MetaField(SwFmtMeta * const i_pFmt,
800 const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
801 : Meta(i_pFmt)
802 , m_nNumberFormat( nNumberFormat )
803 , m_bIsFixedLanguage( bIsFixedLanguage )
807 void MetaField::GetPrefixAndSuffix(
808 ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix)
812 const uno::Reference<rdf::XMetadatable> xMetaField( MakeUnoObject() );
813 OSL_ENSURE(dynamic_cast<SwXMetaField*>(xMetaField.get()),
814 "GetPrefixAndSuffix: no SwXMetaField?");
815 if (xMetaField.is())
817 SwTxtNode * const pTxtNode( GetTxtNode() );
818 SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
819 const uno::Reference<frame::XModel> xModel(
820 (pShell) ? pShell->GetModel() : 0, uno::UNO_SET_THROW);
821 getPrefixAndSuffix(xModel, xMetaField, o_pPrefix, o_pSuffix);
823 } catch (uno::Exception) {
824 OSL_ENSURE(false, "exception?");
828 sal_uInt32 MetaField::GetNumberFormat(::rtl::OUString const & rContent) const
830 //TODO: this probably lacks treatment for some special cases
831 sal_uInt32 nNumberFormat( m_nNumberFormat );
832 SwTxtNode * const pTxtNode( GetTxtNode() );
833 if (pTxtNode)
835 SvNumberFormatter *const pNumberFormatter(
836 pTxtNode->GetDoc()->GetNumberFormatter() );
837 double number;
838 (void) pNumberFormatter->IsNumberFormat(
839 rContent, nNumberFormat, number );
841 return nNumberFormat;
844 void MetaField::SetNumberFormat(sal_uInt32 nNumberFormat)
846 // effectively, the member is only a default:
847 // GetNumberFormat checks if the text actually conforms
848 m_nNumberFormat = nNumberFormat;
852 /*************************************************************************
853 class sw::MetaFieldManager
854 ************************************************************************/
857 MetaFieldManager::MetaFieldManager()
861 ::boost::shared_ptr<MetaField>
862 MetaFieldManager::makeMetaField(SwFmtMeta * const i_pFmt,
863 const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
865 const ::boost::shared_ptr<MetaField> pMetaField(
866 new MetaField(i_pFmt, nNumberFormat, bIsFixedLanguage) );
867 m_MetaFields.push_back(pMetaField);
868 return pMetaField;
871 struct IsInUndo
873 bool operator()(::boost::weak_ptr<MetaField> const & pMetaField) {
874 return pMetaField.lock()->IsInUndo();
878 struct MakeUnoObject
880 uno::Reference<text::XTextField>
881 operator()(::boost::weak_ptr<MetaField> const & pMetaField) {
882 return uno::Reference<text::XTextField>(
883 pMetaField.lock()->MakeUnoObject(), uno::UNO_QUERY);
887 ::std::vector< uno::Reference<text::XTextField> >
888 MetaFieldManager::getMetaFields()
890 // erase deleted fields
891 const MetaFieldList_t::iterator iter(
892 ::std::remove_if(m_MetaFields.begin(), m_MetaFields.end(),
893 ::boost::bind(&::boost::weak_ptr<MetaField>::expired, _1)));
894 m_MetaFields.erase(iter, m_MetaFields.end());
895 // filter out fields in UNDO
896 MetaFieldList_t filtered(m_MetaFields.size());
897 const MetaFieldList_t::iterator iter2(
898 ::std::remove_copy_if(m_MetaFields.begin(), m_MetaFields.end(),
899 filtered.begin(), IsInUndo()));
900 filtered.erase(iter2, filtered.end());
901 // create uno objects
902 ::std::vector< uno::Reference<text::XTextField> > ret(filtered.size());
903 ::std::transform(filtered.begin(), filtered.end(), ret.begin(),
904 MakeUnoObject());
905 return ret;
908 } // namespace sw