xref: /aoo41x/main/sw/source/core/txtnode/fmtatr2.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include "hintids.hxx"
32 #include "unomid.h"
33 
34 #include <basic/sbxvar.hxx>
35 #include <svl/macitem.hxx>
36 #include <svl/stritem.hxx>
37 #include <svl/stylepool.hxx>
38 #include <fmtautofmt.hxx>
39 #include <fchrfmt.hxx>
40 #include <fmtinfmt.hxx>
41 #include <txtatr.hxx>
42 #include <fmtruby.hxx>
43 #include <charfmt.hxx>
44 #include <hints.hxx>        // SwUpdateAttr
45 #include <unostyle.hxx>
46 #include <unoevent.hxx>		// SwHyperlinkEventDescriptor
47 #include <com/sun/star/text/RubyAdjust.hdl>
48 
49 #include <cmdid.h>
50 #include <com/sun/star/uno/Any.h>
51 #include <SwStyleNameMapper.hxx>
52 
53 #include <fmtmeta.hxx>
54 #include <ndtxt.hxx> // for meta
55 #include <doc.hxx> // for meta
56 #include <unometa.hxx>
57 #include <docsh.hxx>
58 #include <svl/zforlist.hxx> // GetNumberFormat
59 
60 #include <boost/bind.hpp>
61 #include <algorithm>
62 
63 
64 using namespace ::com::sun::star;
65 using ::rtl::OUString;
66 
67 TYPEINIT1_AUTOFACTORY(SwFmtINetFmt, SfxPoolItem);
68 TYPEINIT1_AUTOFACTORY(SwFmtAutoFmt, SfxPoolItem);
69 
70 /*************************************************************************
71 |*
72 |*    class SwFmtCharFmt
73 |*    Beschreibung
74 |*    Ersterstellung    JP 23.11.90
75 |*    Letzte Aenderung  JP 09.08.94
76 |*
77 *************************************************************************/
78 
79 SwFmtCharFmt::SwFmtCharFmt( SwCharFmt *pFmt )
80 	: SfxPoolItem( RES_TXTATR_CHARFMT ),
81 	SwClient(pFmt),
82     pTxtAttr( 0 )
83 {
84 }
85 
86 
87 
88 SwFmtCharFmt::SwFmtCharFmt( const SwFmtCharFmt& rAttr )
89 	: SfxPoolItem( RES_TXTATR_CHARFMT ),
90 	SwClient( rAttr.GetCharFmt() ),
91     pTxtAttr( 0 )
92 {
93 }
94 
95 
96 
97 SwFmtCharFmt::~SwFmtCharFmt() {}
98 
99 
100 
101 int SwFmtCharFmt::operator==( const SfxPoolItem& rAttr ) const
102 {
103 	ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
104 	return GetCharFmt() == ((SwFmtCharFmt&)rAttr).GetCharFmt();
105 }
106 
107 
108 
109 SfxPoolItem* SwFmtCharFmt::Clone( SfxItemPool* ) const
110 {
111 	return new SwFmtCharFmt( *this );
112 }
113 
114 
115 
116 // weiterleiten an das TextAttribut
117 void SwFmtCharFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
118 {
119 	if( pTxtAttr )
120 		pTxtAttr->ModifyNotification( pOld, pNew );
121 }
122 
123 
124 
125 // weiterleiten an das TextAttribut
126 sal_Bool SwFmtCharFmt::GetInfo( SfxPoolItem& rInfo ) const
127 {
128 	return pTxtAttr ? pTxtAttr->GetInfo( rInfo ) : sal_False;
129 }
130 sal_Bool SwFmtCharFmt::QueryValue( uno::Any& rVal, sal_uInt8 ) const
131 {
132 	String sCharFmtName;
133 	if(GetCharFmt())
134 		SwStyleNameMapper::FillProgName(GetCharFmt()->GetName(), sCharFmtName,  nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
135 	rVal <<= OUString( sCharFmtName );
136 	return sal_True;
137 }
138 sal_Bool SwFmtCharFmt::PutValue( const uno::Any& , sal_uInt8   )
139 {
140 	DBG_ERROR("Zeichenvorlage kann mit PutValue nicht gesetzt werden!");
141 	return sal_False;
142 }
143 
144 /*************************************************************************
145 |*
146 |*    class SwFmtAutoFmt
147 |*    Beschreibung
148 |*    Ersterstellung    AMA 12.05.06
149 |*    Letzte Aenderung  AMA 12.05.06
150 |*
151 *************************************************************************/
152 
153 SwFmtAutoFmt::SwFmtAutoFmt( sal_uInt16 nInitWhich )
154     : SfxPoolItem( nInitWhich )
155 {
156 }
157 
158 SwFmtAutoFmt::SwFmtAutoFmt( const SwFmtAutoFmt& rAttr )
159     : SfxPoolItem( rAttr.Which() ), mpHandle( rAttr.mpHandle )
160 {
161 }
162 
163 SwFmtAutoFmt::~SwFmtAutoFmt()
164 {
165 }
166 
167 int SwFmtAutoFmt::operator==( const SfxPoolItem& rAttr ) const
168 {
169 	ASSERT( SfxPoolItem::operator==( rAttr ), "different attributes" );
170     return mpHandle == ((SwFmtAutoFmt&)rAttr).mpHandle;
171 }
172 
173 SfxPoolItem* SwFmtAutoFmt::Clone( SfxItemPool* ) const
174 {
175 	return new SwFmtAutoFmt( *this );
176 }
177 
178 sal_Bool SwFmtAutoFmt::QueryValue( uno::Any& rVal, sal_uInt8 ) const
179 {
180 	String sCharFmtName = StylePool::nameOf( mpHandle );
181 	rVal <<= OUString( sCharFmtName );
182 	return sal_True;
183 }
184 
185 sal_Bool SwFmtAutoFmt::PutValue( const uno::Any& , sal_uInt8 )
186 {
187     //the format is not renameable via API
188 	return sal_False;
189 }
190 
191 /*************************************************************************
192 |*
193 |*    class SwFmtINetFmt
194 |*    Beschreibung
195 |*    Ersterstellung    AMA 02.08.96
196 |*    Letzte Aenderung  AMA 02.08.96
197 |*
198 *************************************************************************/
199 
200 SwFmtINetFmt::SwFmtINetFmt()
201 	: SfxPoolItem( RES_TXTATR_INETFMT ),
202     pMacroTbl( 0 ),
203     pTxtAttr( 0 ),
204     nINetId( 0 ),
205 	nVisitedId( 0 )
206 {}
207 
208 SwFmtINetFmt::SwFmtINetFmt( const XubString& rURL, const XubString& rTarget )
209 	: SfxPoolItem( RES_TXTATR_INETFMT ),
210 	aURL( rURL ),
211 	aTargetFrame( rTarget ),
212     pMacroTbl( 0 ),
213     pTxtAttr( 0 ),
214     nINetId( 0 ),
215 	nVisitedId( 0 )
216 {
217 }
218 
219 SwFmtINetFmt::SwFmtINetFmt( const SwFmtINetFmt& rAttr )
220 	: SfxPoolItem( RES_TXTATR_INETFMT ),
221 	aURL( rAttr.GetValue() ),
222     aTargetFrame( rAttr.aTargetFrame ),
223     aINetFmt( rAttr.aINetFmt ),
224     aVisitedFmt( rAttr.aVisitedFmt ),
225     aName( rAttr.aName ),
226     pMacroTbl( 0 ),
227     pTxtAttr( 0 ),
228     nINetId( rAttr.nINetId ),
229 	nVisitedId( rAttr.nVisitedId )
230 {
231 	if( rAttr.GetMacroTbl() )
232 		pMacroTbl = new SvxMacroTableDtor( *rAttr.GetMacroTbl() );
233 }
234 
235 SwFmtINetFmt::~SwFmtINetFmt()
236 {
237 	delete pMacroTbl;
238 }
239 
240 
241 
242 int SwFmtINetFmt::operator==( const SfxPoolItem& rAttr ) const
243 {
244 	ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
245 	sal_Bool bRet = SfxPoolItem::operator==( (SfxPoolItem&) rAttr )
246 				&& aURL == ((SwFmtINetFmt&)rAttr).aURL
247 				&& aName == ((SwFmtINetFmt&)rAttr).aName
248 				&& aTargetFrame == ((SwFmtINetFmt&)rAttr).aTargetFrame
249 				&& aINetFmt == ((SwFmtINetFmt&)rAttr).aINetFmt
250 				&& aVisitedFmt == ((SwFmtINetFmt&)rAttr).aVisitedFmt
251 				&& nINetId == ((SwFmtINetFmt&)rAttr).nINetId
252 				&& nVisitedId == ((SwFmtINetFmt&)rAttr).nVisitedId;
253 
254 	if( !bRet )
255 		return sal_False;
256 
257 	const SvxMacroTableDtor* pOther = ((SwFmtINetFmt&)rAttr).pMacroTbl;
258 	if( !pMacroTbl )
259 		return ( !pOther || !pOther->Count() );
260 	if( !pOther )
261 		return 0 == pMacroTbl->Count();
262 
263 	const SvxMacroTableDtor& rOwn = *pMacroTbl;
264 	const SvxMacroTableDtor& rOther = *pOther;
265 
266 	// Anzahl unterschiedlich => auf jeden Fall ungleich
267 	if( rOwn.Count() != rOther.Count() )
268 		return sal_False;
269 
270 	// einzeln vergleichen; wegen Performance ist die Reihenfolge wichtig
271 	for( sal_uInt16 nNo = 0; nNo < rOwn.Count(); ++nNo )
272 	{
273 		const SvxMacro *pOwnMac = rOwn.GetObject(nNo);
274 		const SvxMacro *pOtherMac = rOther.GetObject(nNo);
275 		if ( 	rOwn.GetKey(pOwnMac) != rOther.GetKey(pOtherMac)  ||
276 				pOwnMac->GetLibName() != pOtherMac->GetLibName() ||
277 				pOwnMac->GetMacName() != pOtherMac->GetMacName() )
278 			return sal_False;
279 	}
280 	return sal_True;
281 }
282 
283 
284 
285 SfxPoolItem* SwFmtINetFmt::Clone( SfxItemPool* ) const
286 {
287 	return new SwFmtINetFmt( *this );
288 }
289 
290 
291 
292 void SwFmtINetFmt::SetMacroTbl( const SvxMacroTableDtor* pNewTbl )
293 {
294 	if( pNewTbl )
295 	{
296 		if( pMacroTbl )
297 			*pMacroTbl = *pNewTbl;
298 		else
299 			pMacroTbl = new SvxMacroTableDtor( *pNewTbl );
300 	}
301 	else if( pMacroTbl )
302 		delete pMacroTbl, pMacroTbl = 0;
303 }
304 
305 
306 
307 void SwFmtINetFmt::SetMacro( sal_uInt16 nEvent, const SvxMacro& rMacro )
308 {
309 	if( !pMacroTbl )
310 		pMacroTbl = new SvxMacroTableDtor;
311 
312 	SvxMacro *pOldMacro;
313 	if( 0 != ( pOldMacro = pMacroTbl->Get( nEvent )) )
314 	{
315 		delete pOldMacro;
316 		pMacroTbl->Replace( nEvent, new SvxMacro( rMacro ) );
317 	}
318 	else
319 		pMacroTbl->Insert( nEvent, new SvxMacro( rMacro ) );
320 }
321 
322 
323 
324 const SvxMacro* SwFmtINetFmt::GetMacro( sal_uInt16 nEvent ) const
325 {
326 	const SvxMacro* pRet = 0;
327 	if( pMacroTbl && pMacroTbl->IsKeyValid( nEvent ) )
328 		pRet = pMacroTbl->Get( nEvent );
329 	return pRet;
330 }
331 
332 
333 
334 sal_Bool SwFmtINetFmt::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
335 {
336 	sal_Bool bRet = sal_True;
337 	XubString sVal;
338     nMemberId &= ~CONVERT_TWIPS;
339 	switch(nMemberId)
340 	{
341 		case MID_URL_URL:
342 			sVal = aURL;
343 		break;
344 		case MID_URL_TARGET:
345 			sVal = aTargetFrame;
346 		break;
347 		case MID_URL_HYPERLINKNAME:
348 			sVal = aName;
349 		break;
350 		case MID_URL_VISITED_FMT:
351 			sVal = aVisitedFmt;
352 			if( !sVal.Len() && nVisitedId != 0 )
353 				SwStyleNameMapper::FillUIName( nVisitedId, sVal );
354 			if( sVal.Len() )
355 				SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
356 		break;
357 		case MID_URL_UNVISITED_FMT:
358 			sVal = aINetFmt;
359 			if( !sVal.Len() && nINetId != 0 )
360 				SwStyleNameMapper::FillUIName( nINetId, sVal );
361 			if( sVal.Len() )
362 				SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
363 		break;
364 		case MID_URL_HYPERLINKEVENTS:
365 		{
366 			// create (and return) event descriptor
367 			SwHyperlinkEventDescriptor* pEvents =
368 				new SwHyperlinkEventDescriptor();
369 			pEvents->copyMacrosFromINetFmt(*this);
370 			uno::Reference<container::XNameReplace> xNameReplace(pEvents);
371 
372 			// all others return a string; so we just set rVal here and exit
373 			rVal <<= xNameReplace;
374 			return bRet;
375 		}
376         default:
377         break;
378 	}
379 	rVal <<= OUString(sVal);
380 	return bRet;
381 }
382 sal_Bool SwFmtINetFmt::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId  )
383 {
384 	sal_Bool bRet = sal_True;
385     nMemberId &= ~CONVERT_TWIPS;
386 
387 	// all properties except HyperlinkEvents are of type string, hence
388 	// we treat HyperlinkEvents specially
389 	if (MID_URL_HYPERLINKEVENTS == nMemberId)
390 	{
391 		uno::Reference<container::XNameReplace> xReplace;
392 		rVal >>= xReplace;
393 		if (xReplace.is())
394 		{
395 			// Create hyperlink event descriptor. Then copy events
396 			// from argument into descriptor. Then copy events from
397 			// the descriptor into the format.
398 			SwHyperlinkEventDescriptor* pEvents = new SwHyperlinkEventDescriptor();
399             uno::Reference< lang::XServiceInfo> xHold = pEvents;
400 			pEvents->copyMacrosFromNameReplace(xReplace);
401 			pEvents->copyMacrosIntoINetFmt(*this);
402 		}
403 		else
404 		{
405 			// wrong type!
406 			bRet = sal_False;
407 		}
408 	}
409 	else
410 	{
411 		// all string properties:
412 		if(rVal.getValueType() != ::getCppuType((rtl::OUString*)0))
413 			return sal_False;
414 		XubString sVal = *(rtl::OUString*)rVal.getValue();
415 		switch(nMemberId)
416 		{
417 			case MID_URL_URL:
418 				aURL = sVal;
419 				break;
420 			case MID_URL_TARGET:
421 				aTargetFrame = sVal;
422 				break;
423 			case MID_URL_HYPERLINKNAME:
424 				aName = sVal;
425 				break;
426 			case MID_URL_VISITED_FMT:
427 			{
428 				String aString;
429 				SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
430 				aVisitedFmt = OUString ( aString );
431 				nVisitedId = SwStyleNameMapper::GetPoolIdFromUIName( aVisitedFmt,
432 											   nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
433 			}
434 			break;
435 			case MID_URL_UNVISITED_FMT:
436 			{
437 				String aString;
438 				SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
439 				aINetFmt = OUString ( aString );
440 				nINetId = SwStyleNameMapper::GetPoolIdFromUIName( aINetFmt,	nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
441 			}
442 			break;
443 			default:
444 				bRet = sal_False;
445 		}
446 	}
447 	return bRet;
448 }
449 
450 
451 /*************************************************************************
452 |*    class SwFmtRuby
453 *************************************************************************/
454 
455 SwFmtRuby::SwFmtRuby( const String& rRubyTxt )
456 	: SfxPoolItem( RES_TXTATR_CJK_RUBY ),
457 	sRubyTxt( rRubyTxt ),
458     pTxtAttr( 0 ),
459     nCharFmtId( 0 ),
460     nPosition( 0 ),
461     nAdjustment( 0 )
462 {
463 }
464 
465 SwFmtRuby::SwFmtRuby( const SwFmtRuby& rAttr )
466 	: SfxPoolItem( RES_TXTATR_CJK_RUBY ),
467 	sRubyTxt( rAttr.sRubyTxt ),
468 	sCharFmtName( rAttr.sCharFmtName ),
469     pTxtAttr( 0 ),
470     nCharFmtId( rAttr.nCharFmtId),
471     nPosition( rAttr.nPosition ),
472     nAdjustment( rAttr.nAdjustment )
473 {
474 }
475 
476 SwFmtRuby::~SwFmtRuby()
477 {
478 }
479 
480 SwFmtRuby& SwFmtRuby::operator=( const SwFmtRuby& rAttr )
481 {
482 	sRubyTxt = rAttr.sRubyTxt;
483 	sCharFmtName = rAttr.sCharFmtName;
484 	nCharFmtId = rAttr.nCharFmtId;
485 	nPosition = rAttr.nPosition;
486 	nAdjustment = rAttr.nAdjustment;
487 	pTxtAttr =  0;
488 	return *this;
489 }
490 
491 int SwFmtRuby::operator==( const SfxPoolItem& rAttr ) const
492 {
493 	ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
494 	return sRubyTxt == ((SwFmtRuby&)rAttr).sRubyTxt &&
495 		   sCharFmtName == ((SwFmtRuby&)rAttr).sCharFmtName &&
496 		   nCharFmtId == ((SwFmtRuby&)rAttr).nCharFmtId &&
497 		   nPosition == ((SwFmtRuby&)rAttr).nPosition &&
498 		   nAdjustment == ((SwFmtRuby&)rAttr).nAdjustment;
499 }
500 
501 SfxPoolItem* SwFmtRuby::Clone( SfxItemPool* ) const
502 {
503 	return new SwFmtRuby( *this );
504 }
505 
506 sal_Bool SwFmtRuby::QueryValue( uno::Any& rVal,
507 							sal_uInt8 nMemberId ) const
508 {
509 	sal_Bool bRet = sal_True;
510     nMemberId &= ~CONVERT_TWIPS;
511 	switch( nMemberId )
512 	{
513 		case MID_RUBY_TEXT: rVal <<= (OUString)sRubyTxt; 					break;
514  		case MID_RUBY_ADJUST:	rVal <<= (sal_Int16)nAdjustment;	break;
515 		case MID_RUBY_CHARSTYLE:
516 		{
517 			String aString;
518 			SwStyleNameMapper::FillProgName(sCharFmtName, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
519 			rVal <<= OUString ( aString );
520 		}
521 		break;
522         case MID_RUBY_ABOVE:
523         {
524             sal_Bool bAbove = !nPosition;
525             rVal.setValue(&bAbove, ::getBooleanCppuType());
526         }
527         break;
528         default:
529 			bRet = sal_False;
530 	}
531 	return bRet;
532 }
533 sal_Bool SwFmtRuby::PutValue( const uno::Any& rVal,
534 							sal_uInt8 nMemberId  )
535 {
536 	sal_Bool bRet = sal_True;
537     nMemberId &= ~CONVERT_TWIPS;
538 	switch( nMemberId )
539 	{
540 		case MID_RUBY_TEXT:
541 		{
542 			OUString sTmp;
543 			bRet = rVal >>= sTmp;
544 			sRubyTxt = sTmp;
545 		}
546 		break;
547  		case MID_RUBY_ADJUST:
548 		{
549 			sal_Int16 nSet = 0;
550 			rVal >>= nSet;
551             if(nSet >= 0 && nSet <= text::RubyAdjust_INDENT_BLOCK)
552 				nAdjustment = nSet;
553 			else
554 				bRet = sal_False;
555 		}
556 		break;
557         case MID_RUBY_ABOVE:
558         {
559             const uno::Type& rType = ::getBooleanCppuType();
560             if(rVal.hasValue() && rVal.getValueType() == rType)
561             {
562                 sal_Bool bAbove = *(sal_Bool*)rVal.getValue();
563                 nPosition = bAbove ? 0 : 1;
564             }
565         }
566         break;
567         case MID_RUBY_CHARSTYLE:
568         {
569             OUString sTmp;
570             bRet = rVal >>= sTmp;
571             if(bRet)
572                 sCharFmtName = SwStyleNameMapper::GetUIName(sTmp, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
573         }
574         break;
575 		default:
576 			bRet = sal_False;
577 	}
578 	return bRet;
579 }
580 
581 
582 /*************************************************************************
583  class SwFmtMeta
584  ************************************************************************/
585 
586 SwFmtMeta * SwFmtMeta::CreatePoolDefault(const sal_uInt16 i_nWhich)
587 {
588     return new SwFmtMeta(i_nWhich);
589 }
590 
591 SwFmtMeta::SwFmtMeta(const sal_uInt16 i_nWhich)
592     : SfxPoolItem( i_nWhich )
593     , m_pMeta()
594     , m_pTxtAttr( 0 )
595 {
596     ASSERT((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
597             "ERROR: SwFmtMeta: invalid which id!");
598 }
599 
600 SwFmtMeta::SwFmtMeta( ::boost::shared_ptr< ::sw::Meta > const & i_pMeta,
601                         const sal_uInt16 i_nWhich )
602     : SfxPoolItem( i_nWhich )
603     , m_pMeta( i_pMeta )
604     , m_pTxtAttr( 0 )
605 {
606     ASSERT((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
607             "ERROR: SwFmtMeta: invalid which id!");
608     ASSERT(m_pMeta, "SwFmtMeta: no Meta ?");
609     // DO NOT call m_pMeta->SetFmtMeta(this) here; only from SetTxtAttr!
610 }
611 
612 SwFmtMeta::~SwFmtMeta()
613 {
614     if (m_pMeta && (m_pMeta->GetFmtMeta() == this))
615     {
616         NotifyChangeTxtNode(0);
617         m_pMeta->SetFmtMeta(0);
618     }
619 }
620 
621 int SwFmtMeta::operator==( const SfxPoolItem & i_rOther ) const
622 {
623     ASSERT( SfxPoolItem::operator==( i_rOther ), "i just copied this assert" );
624     return SfxPoolItem::operator==( i_rOther )
625         && (m_pMeta == static_cast<SwFmtMeta const &>( i_rOther ).m_pMeta);
626 }
627 
628 SfxPoolItem * SwFmtMeta::Clone( SfxItemPool * /*pPool*/ ) const
629 {
630     // if this is indeed a copy, then DoCopy must be called later!
631     return (m_pMeta) // #i105148# pool default may be cloned also!
632         ? new SwFmtMeta( m_pMeta, Which() ) : new SwFmtMeta( Which() );
633 }
634 
635 void SwFmtMeta::SetTxtAttr(SwTxtMeta * const i_pTxtAttr)
636 {
637     OSL_ENSURE(!(m_pTxtAttr && i_pTxtAttr),
638         "SwFmtMeta::SetTxtAttr: already has text attribute?");
639     OSL_ENSURE(  m_pTxtAttr || i_pTxtAttr ,
640         "SwFmtMeta::SetTxtAttr: no attribute to remove?");
641     m_pTxtAttr = i_pTxtAttr;
642     OSL_ENSURE(m_pMeta, "inserted SwFmtMeta has no sw::Meta?");
643     // the sw::Meta must be able to find the current text attribute!
644     if (m_pMeta)
645     {
646         if (i_pTxtAttr)
647         {
648             m_pMeta->SetFmtMeta(this);
649         }
650         else if (m_pMeta->GetFmtMeta() == this)
651         {   // text attribute gone => de-register from text node!
652             NotifyChangeTxtNode(0);
653             m_pMeta->SetFmtMeta(0);
654         }
655     }
656 }
657 
658 void SwFmtMeta::NotifyChangeTxtNode(SwTxtNode *const pTxtNode)
659 {
660     // N.B.: do not reset m_pTxtAttr here: see call in nodes.cxx,
661     // where the hint is not deleted!
662     OSL_ENSURE(m_pMeta, "SwFmtMeta::NotifyChangeTxtNode: no Meta?");
663     if (m_pMeta && (m_pMeta->GetFmtMeta() == this))
664     {   // do not call Modify, that would call SwXMeta::Modify!
665         m_pMeta->NotifyChangeTxtNode(pTxtNode);
666     }
667 }
668 
669 // this SwFmtMeta has been cloned and points at the same sw::Meta as the source
670 // this method copies the sw::Meta
671 void SwFmtMeta::DoCopy(::sw::MetaFieldManager & i_rTargetDocManager,
672         SwTxtNode & i_rTargetTxtNode)
673 {
674     OSL_ENSURE(m_pMeta, "DoCopy called for SwFmtMeta with no sw::Meta?");
675     if (m_pMeta)
676     {
677         const ::boost::shared_ptr< ::sw::Meta> pOriginal( m_pMeta );
678         if (RES_TXTATR_META == Which())
679         {
680             m_pMeta.reset( new ::sw::Meta(this) );
681         }
682         else
683         {
684             ::sw::MetaField *const pMetaField(
685                 static_cast< ::sw::MetaField* >(pOriginal.get()));
686             m_pMeta = i_rTargetDocManager.makeMetaField( this,
687                 pMetaField->m_nNumberFormat, pMetaField->IsFixedLanguage() );
688         }
689         // Meta must have a text node before calling RegisterAsCopyOf
690         m_pMeta->NotifyChangeTxtNode(& i_rTargetTxtNode);
691         // this cannot be done in Clone: a Clone is not necessarily a copy!
692         m_pMeta->RegisterAsCopyOf(*pOriginal);
693     }
694 }
695 
696 
697 namespace sw {
698 
699 /*************************************************************************
700  class sw::Meta
701  ************************************************************************/
702 
703 Meta::Meta(SwFmtMeta * const i_pFmt)
704     : ::sfx2::Metadatable()
705     , SwModify()
706     , m_pFmt( i_pFmt )
707 {
708 }
709 
710 Meta::~Meta()
711 {
712 }
713 
714 SwTxtMeta * Meta::GetTxtAttr() const
715 {
716     return (m_pFmt) ? m_pFmt->GetTxtAttr() : 0;
717 }
718 
719 SwTxtNode * Meta::GetTxtNode() const
720 {
721     return m_pTxtNode;
722 }
723 
724 void Meta::NotifyChangeTxtNodeImpl()
725 {
726     if (m_pTxtNode && (GetRegisteredIn() != m_pTxtNode))
727     {
728         m_pTxtNode->Add(this);
729     }
730     else if (!m_pTxtNode && GetRegisteredIn())
731     {
732         GetRegisteredInNonConst()->Remove(this);
733     }
734 }
735 
736 void Meta::NotifyChangeTxtNode(SwTxtNode *const pTxtNode)
737 {
738     m_pTxtNode = pTxtNode;
739     NotifyChangeTxtNodeImpl();
740     if (!pTxtNode) // text node gone? invalidate UNO object!
741     {
742         SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
743             &static_cast<SwModify&>(*this) ); // cast to base class!
744         this->Modify(&aMsgHint, &aMsgHint);
745     }
746 }
747 
748 // SwClient
749 void Meta::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew )
750 {
751     NotifyClients(pOld, pNew);
752     if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
753     {   // invalidate cached uno object
754         SetXMeta(uno::Reference<rdf::XMetadatable>(0));
755     }
756 }
757 
758 // sfx2::Metadatable
759 ::sfx2::IXmlIdRegistry& Meta::GetRegistry()
760 {
761     SwTxtNode * const pTxtNode( GetTxtNode() );
762     // GetRegistry may only be called on a meta that is actually in the
763     // document, which means it has a pointer to its text node
764     OSL_ENSURE(pTxtNode, "ERROR: GetRegistry: no text node?");
765     if (!pTxtNode)
766         throw uno::RuntimeException();
767     return pTxtNode->GetRegistry();
768 }
769 
770 bool Meta::IsInClipboard() const
771 {
772     const SwTxtNode * const pTxtNode( GetTxtNode() );
773 // no text node: in UNDO  OSL_ENSURE(pTxtNode, "IsInClipboard: no text node?");
774     return (pTxtNode) ? pTxtNode->IsInClipboard() : false;
775 }
776 
777 bool Meta::IsInUndo() const
778 {
779     const SwTxtNode * const pTxtNode( GetTxtNode() );
780 // no text node: in UNDO  OSL_ENSURE(pTxtNode, "IsInUndo: no text node?");
781     return (pTxtNode) ? pTxtNode->IsInUndo() : true;
782 }
783 
784 bool Meta::IsInContent() const
785 {
786     const SwTxtNode * const pTxtNode( GetTxtNode() );
787     OSL_ENSURE(pTxtNode, "IsInContent: no text node?");
788     return (pTxtNode) ? pTxtNode->IsInContent() : true;
789 }
790 
791 ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable >
792 Meta::MakeUnoObject()
793 {
794     return SwXMeta::CreateXMeta(*this);
795 }
796 
797 /*************************************************************************
798  class sw::MetaField
799  ************************************************************************/
800 
801 MetaField::MetaField(SwFmtMeta * const i_pFmt,
802             const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
803     : Meta(i_pFmt)
804     , m_nNumberFormat( nNumberFormat )
805     , m_bIsFixedLanguage( bIsFixedLanguage )
806 {
807 }
808 
809 void MetaField::GetPrefixAndSuffix(
810         ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix)
811 {
812     try
813     {
814         const uno::Reference<rdf::XMetadatable> xMetaField( MakeUnoObject() );
815         OSL_ENSURE(dynamic_cast<SwXMetaField*>(xMetaField.get()),
816                 "GetPrefixAndSuffix: no SwXMetaField?");
817         if (xMetaField.is())
818         {
819             SwTxtNode * const pTxtNode( GetTxtNode() );
820             SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
821             const uno::Reference<frame::XModel> xModel(
822                 (pShell) ? pShell->GetModel() : 0,  uno::UNO_SET_THROW);
823             getPrefixAndSuffix(xModel, xMetaField, o_pPrefix, o_pSuffix);
824         }
825     } catch (uno::Exception) {
826         OSL_ENSURE(false, "exception?");
827     }
828 }
829 
830 sal_uInt32 MetaField::GetNumberFormat(::rtl::OUString const & rContent) const
831 {
832     //TODO: this probably lacks treatment for some special cases
833     sal_uInt32 nNumberFormat( m_nNumberFormat );
834     SwTxtNode * const pTxtNode( GetTxtNode() );
835     if (pTxtNode)
836     {
837         SvNumberFormatter *const pNumberFormatter(
838                 pTxtNode->GetDoc()->GetNumberFormatter() );
839         double number;
840         (void) pNumberFormatter->IsNumberFormat(
841                 rContent, nNumberFormat, number );
842     }
843     return nNumberFormat;
844 }
845 
846 void MetaField::SetNumberFormat(sal_uInt32 nNumberFormat)
847 {
848     // effectively, the member is only a default:
849     // GetNumberFormat checks if the text actually conforms
850     m_nNumberFormat = nNumberFormat;
851 }
852 
853 
854 /*************************************************************************
855  class sw::MetaFieldManager
856  ************************************************************************/
857 
858 
859 MetaFieldManager::MetaFieldManager()
860 {
861 }
862 
863 ::boost::shared_ptr<MetaField>
864 MetaFieldManager::makeMetaField(SwFmtMeta * const i_pFmt,
865         const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
866 {
867     const ::boost::shared_ptr<MetaField> pMetaField(
868         new MetaField(i_pFmt, nNumberFormat, bIsFixedLanguage) );
869     m_MetaFields.push_back(pMetaField);
870     return pMetaField;
871 }
872 
873 struct IsInUndo
874 {
875     bool operator()(::boost::weak_ptr<MetaField> const & pMetaField) {
876         return pMetaField.lock()->IsInUndo();
877     }
878 };
879 
880 struct MakeUnoObject
881 {
882     uno::Reference<text::XTextField>
883     operator()(::boost::weak_ptr<MetaField> const & pMetaField) {
884         return uno::Reference<text::XTextField>(
885                 pMetaField.lock()->MakeUnoObject(), uno::UNO_QUERY);
886     }
887 };
888 
889 ::std::vector< uno::Reference<text::XTextField> >
890 MetaFieldManager::getMetaFields()
891 {
892     // erase deleted fields
893     const MetaFieldList_t::iterator iter(
894         ::std::remove_if(m_MetaFields.begin(), m_MetaFields.end(),
895             ::boost::bind(&::boost::weak_ptr<MetaField>::expired, _1)));
896     m_MetaFields.erase(iter, m_MetaFields.end());
897     // filter out fields in UNDO
898     MetaFieldList_t filtered(m_MetaFields.size());
899     const MetaFieldList_t::iterator iter2(
900     ::std::remove_copy_if(m_MetaFields.begin(), m_MetaFields.end(),
901         filtered.begin(), IsInUndo()));
902     filtered.erase(iter2, filtered.end());
903     // create uno objects
904     ::std::vector< uno::Reference<text::XTextField> > ret(filtered.size());
905     ::std::transform(filtered.begin(), filtered.end(), ret.begin(),
906             MakeUnoObject());
907     return ret;
908 }
909 
910 } // namespace sw
911 
912 
913