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