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