Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <osl/mutex.hxx>
22 : #include <cppuhelper/interfacecontainer.h>
23 : #include <vcl/svapp.hxx>
24 :
25 : #include <unomid.h>
26 : #include <unotextrange.hxx>
27 : #include <unorefmark.hxx>
28 : #include <unotextcursor.hxx>
29 : #include <unomap.hxx>
30 : #include <unocrsr.hxx>
31 : #include <unocrsrhelper.hxx>
32 : #include <doc.hxx>
33 : #include <ndtxt.hxx>
34 : #include <fmtrfmrk.hxx>
35 : #include <txtrfmrk.hxx>
36 : #include <hints.hxx>
37 : #include <comphelper/servicehelper.hxx>
38 :
39 :
40 : using namespace ::com::sun::star;
41 :
42 : /******************************************************************
43 : * SwXReferenceMark
44 : ******************************************************************/
45 176 : class SwXReferenceMark::Impl
46 : : public SwClient
47 : {
48 : private:
49 : ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper
50 : SwXReferenceMark & m_rThis;
51 :
52 : public:
53 : ::cppu::OInterfaceContainerHelper m_EventListeners;
54 : bool m_bIsDescriptor;
55 : SwDoc * m_pDoc;
56 : const SwFmtRefMark * m_pMarkFmt;
57 : OUString m_sMarkName;
58 :
59 88 : Impl( SwXReferenceMark & rThis,
60 : SwDoc *const pDoc, SwFmtRefMark const*const pRefMark)
61 : : SwClient((pDoc) ? pDoc->GetUnoCallBack() : 0)
62 : , m_rThis(rThis)
63 : , m_EventListeners(m_Mutex)
64 : // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
65 : , m_bIsDescriptor((0 == pRefMark) ? true : false)
66 : , m_pDoc(pDoc)
67 88 : , m_pMarkFmt(pRefMark)
68 : {
69 88 : if (pRefMark)
70 : {
71 50 : m_sMarkName = pRefMark->GetRefName();
72 : }
73 88 : }
74 :
75 142 : bool IsValid() const { return 0 != GetRegisteredIn(); }
76 : void InsertRefMark( SwPaM & rPam, SwXTextCursor const*const pCursor );
77 : void Invalidate();
78 : protected:
79 : // SwClient
80 : virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
81 :
82 : };
83 :
84 89 : void SwXReferenceMark::Impl::Invalidate()
85 : {
86 89 : if (IsValid())
87 : {
88 19 : const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
89 : }
90 89 : m_pDoc = 0;
91 89 : m_pMarkFmt = 0;
92 89 : lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(m_rThis));
93 89 : m_EventListeners.disposeAndClear(ev);
94 89 : }
95 :
96 98 : void SwXReferenceMark::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
97 : {
98 98 : ClientModify(this, pOld, pNew);
99 :
100 98 : if (!GetRegisteredIn()) // removed => dispose
101 : {
102 70 : Invalidate();
103 : }
104 28 : else if (pOld)
105 : {
106 28 : switch (pOld->Which())
107 : {
108 : case RES_REFMARK_DELETED:
109 28 : if (static_cast<const void*>(m_pMarkFmt) ==
110 : static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject)
111 : {
112 19 : Invalidate();
113 : }
114 28 : break;
115 : }
116 : }
117 98 : }
118 :
119 88 : SwXReferenceMark::SwXReferenceMark(
120 : SwDoc *const pDoc, SwFmtRefMark const*const pRefMark)
121 88 : : m_pImpl( new SwXReferenceMark::Impl(*this, pDoc, pRefMark) )
122 : {
123 88 : }
124 :
125 176 : SwXReferenceMark::~SwXReferenceMark()
126 : {
127 176 : }
128 :
129 : SwXReferenceMark *
130 4 : SwXReferenceMark::GetReferenceMark(
131 : SwModify const& /*rUnoCB*/, SwFmtRefMark const& /*rMarkFmt*/)
132 : {
133 : // #i105557#: do not iterate over the registered clients: race condition
134 : // to do this properly requires the SwXReferenceMark to register at the
135 : // SwFmtRefMark directly, not at the unocallback
136 4 : return 0;
137 : }
138 :
139 : SwXReferenceMark *
140 4 : SwXReferenceMark::CreateXReferenceMark(
141 : SwDoc & rDoc, SwFmtRefMark const& rMarkFmt)
142 : {
143 : SwXReferenceMark *const pXMark(
144 4 : GetReferenceMark(*rDoc.GetUnoCallBack(), rMarkFmt) );
145 : return (pXMark)
146 : ? pXMark
147 4 : : new SwXReferenceMark(&rDoc, &rMarkFmt);
148 : }
149 :
150 : namespace
151 : {
152 : class theSwXReferenceMarkUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXReferenceMarkUnoTunnelId > {};
153 : }
154 :
155 2698 : const uno::Sequence< sal_Int8 > & SwXReferenceMark::getUnoTunnelId()
156 : {
157 2698 : return theSwXReferenceMarkUnoTunnelId::get().getSeq();
158 : }
159 :
160 : sal_Int64 SAL_CALL
161 66 : SwXReferenceMark::getSomething(const uno::Sequence< sal_Int8 >& rId)
162 : throw (uno::RuntimeException)
163 : {
164 66 : return ::sw::UnoTunnelImpl<SwXReferenceMark>(rId, this);
165 : }
166 :
167 0 : OUString SAL_CALL SwXReferenceMark::getImplementationName()
168 : throw (uno::RuntimeException)
169 : {
170 0 : return OUString("SwXReferenceMark");
171 : }
172 :
173 : static char const*const g_ServicesReferenceMark[] =
174 : {
175 : "com.sun.star.text.TextContent",
176 : "com.sun.star.text.ReferenceMark",
177 : };
178 :
179 : static const size_t g_nServicesReferenceMark(
180 : sizeof(g_ServicesReferenceMark)/sizeof(g_ServicesReferenceMark[0]));
181 :
182 : sal_Bool SAL_CALL
183 0 : SwXReferenceMark::supportsService(const OUString& rServiceName)
184 : throw (uno::RuntimeException)
185 : {
186 : return ::sw::SupportsServiceImpl(
187 0 : g_nServicesReferenceMark, g_ServicesReferenceMark, rServiceName);
188 : }
189 :
190 : uno::Sequence< OUString > SAL_CALL
191 0 : SwXReferenceMark::getSupportedServiceNames()
192 : throw (uno::RuntimeException)
193 : {
194 : return ::sw::GetSupportedServiceNamesImpl(
195 0 : g_nServicesReferenceMark, g_ServicesReferenceMark);
196 : }
197 :
198 : template<typename T> struct NotContainedIn
199 : {
200 : ::std::vector<T> const& m_rVector;
201 0 : explicit NotContainedIn(::std::vector<T> const& rVector)
202 0 : : m_rVector(rVector) { }
203 0 : bool operator() (T const& rT) {
204 0 : return ::std::find(m_rVector.begin(), m_rVector.end(), rT)
205 0 : == m_rVector.end();
206 : }
207 : };
208 :
209 40 : void SwXReferenceMark::Impl::InsertRefMark(SwPaM& rPam,
210 : SwXTextCursor const*const pCursor)
211 : {
212 : //! in some cases when this function is called the pDoc pointer member may have become
213 : //! invalid/deleted thus we obtain the document pointer from rPaM where it should always
214 : //! be valid.
215 40 : SwDoc *pDoc2 = rPam.GetDoc();
216 :
217 40 : UnoActionContext aCont(pDoc2);
218 80 : SwFmtRefMark aRefMark(m_sMarkName);
219 40 : bool bMark = *rPam.GetPoint() != *rPam.GetMark();
220 :
221 66 : const bool bForceExpandHints( (!bMark && pCursor)
222 58 : ? pCursor->IsAtEndOfMeta() : false );
223 : const SetAttrMode nInsertFlags = (bForceExpandHints)
224 : ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
225 : | nsSetAttrMode::SETATTR_DONTEXPAND)
226 40 : : nsSetAttrMode::SETATTR_DONTEXPAND;
227 :
228 80 : ::std::vector<SwTxtAttr *> oldMarks;
229 40 : if (bMark)
230 : {
231 28 : oldMarks = rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
232 28 : rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK);
233 : }
234 :
235 40 : pDoc2->InsertPoolItem( rPam, aRefMark, nInsertFlags );
236 :
237 40 : if( bMark && *rPam.GetPoint() > *rPam.GetMark())
238 : {
239 14 : rPam.Exchange();
240 : }
241 :
242 : // aRefMark was copied into the document pool; now retrieve real format...
243 40 : SwTxtAttr * pTxtAttr(0);
244 40 : if (bMark)
245 : {
246 : // #i107672#
247 : // ensure that we do not retrieve a different mark at the same position
248 : ::std::vector<SwTxtAttr *> const newMarks(
249 : rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
250 14 : rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
251 : ::std::vector<SwTxtAttr *>::const_iterator const iter(
252 : ::std::find_if(newMarks.begin(), newMarks.end(),
253 14 : NotContainedIn<SwTxtAttr *>(oldMarks)));
254 : OSL_ASSERT(newMarks.end() != iter);
255 14 : if (newMarks.end() != iter)
256 : {
257 14 : pTxtAttr = *iter;
258 14 : }
259 : }
260 : else
261 : {
262 26 : SwTxtNode *pTxtNd = rPam.GetNode()->GetTxtNode();
263 : OSL_ASSERT(pTxtNd);
264 : pTxtAttr = pTxtNd ? rPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
265 26 : rPam.GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_REFMARK) : NULL;
266 : }
267 :
268 40 : if (!pTxtAttr)
269 : {
270 : throw uno::RuntimeException(OUString(
271 0 : "SwXReferenceMark::InsertRefMark(): cannot insert attribute"), 0);
272 : }
273 :
274 40 : m_pMarkFmt = &pTxtAttr->GetRefMark();
275 :
276 80 : pDoc2->GetUnoCallBack()->Add(this);
277 40 : }
278 :
279 : void SAL_CALL
280 38 : SwXReferenceMark::attach(const uno::Reference< text::XTextRange > & xTextRange)
281 : throw (lang::IllegalArgumentException, uno::RuntimeException)
282 : {
283 38 : SolarMutexGuard aGuard;
284 :
285 38 : if (!m_pImpl->m_bIsDescriptor)
286 : {
287 0 : throw uno::RuntimeException();
288 : }
289 76 : uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
290 38 : SwXTextRange* pRange = 0;
291 38 : OTextCursorHelper* pCursor = 0;
292 38 : if(xRangeTunnel.is())
293 : {
294 38 : pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
295 : pCursor =
296 38 : ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
297 : }
298 : SwDoc *const pDocument =
299 38 : (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
300 38 : if (!pDocument)
301 : {
302 0 : throw lang::IllegalArgumentException();
303 : }
304 :
305 76 : SwUnoInternalPaM aPam(*pDocument);
306 : //das muss jetzt sal_True liefern
307 38 : ::sw::XTextRangeToSwPaM(aPam, xTextRange);
308 38 : m_pImpl->InsertRefMark(aPam, dynamic_cast<SwXTextCursor*>(pCursor));
309 38 : m_pImpl->m_bIsDescriptor = sal_False;
310 76 : m_pImpl->m_pDoc = pDocument;
311 38 : }
312 :
313 : uno::Reference< text::XTextRange > SAL_CALL
314 1 : SwXReferenceMark::getAnchor() throw (uno::RuntimeException)
315 : {
316 1 : SolarMutexGuard aGuard;
317 :
318 1 : if (m_pImpl->IsValid())
319 : {
320 : SwFmtRefMark const*const pNewMark =
321 1 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
322 1 : if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
323 : {
324 : SwTxtRefMark const*const pTxtMark =
325 1 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
326 2 : if (pTxtMark &&
327 1 : (&pTxtMark->GetTxtNode().GetNodes() ==
328 1 : &m_pImpl->m_pDoc->GetNodes()))
329 : {
330 1 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
331 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
332 1 : const ::std::auto_ptr<SwPaM> pPam( (pTxtMark->GetEnd())
333 0 : ? new SwPaM( rTxtNode, *pTxtMark->GetEnd(),
334 0 : rTxtNode, *pTxtMark->GetStart())
335 1 : : new SwPaM( rTxtNode, *pTxtMark->GetStart()) );
336 : SAL_WNODEPRECATED_DECLARATIONS_POP
337 :
338 : return SwXTextRange::CreateXTextRange(
339 1 : *m_pImpl->m_pDoc, *pPam->Start(), pPam->End());
340 : }
341 : }
342 : }
343 0 : return 0;
344 : }
345 :
346 1 : void SAL_CALL SwXReferenceMark::dispose() throw (uno::RuntimeException)
347 : {
348 1 : SolarMutexGuard aGuard;
349 1 : if (m_pImpl->IsValid())
350 : {
351 : SwFmtRefMark const*const pNewMark =
352 1 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
353 1 : if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
354 : {
355 : SwTxtRefMark const*const pTxtMark =
356 1 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
357 2 : if (pTxtMark &&
358 1 : (&pTxtMark->GetTxtNode().GetNodes() ==
359 1 : &m_pImpl->m_pDoc->GetNodes()))
360 : {
361 1 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
362 1 : xub_StrLen nStt = *pTxtMark->GetStart(),
363 1 : nEnd = pTxtMark->GetEnd() ? *pTxtMark->GetEnd()
364 1 : : nStt + 1;
365 :
366 1 : SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
367 1 : m_pImpl->m_pDoc->DeleteAndJoin( aPam );
368 : }
369 : }
370 : }
371 0 : else if (m_pImpl->m_bIsDescriptor)
372 : {
373 0 : m_pImpl->Invalidate();
374 1 : }
375 1 : }
376 :
377 2 : void SAL_CALL SwXReferenceMark::addEventListener(
378 : const uno::Reference< lang::XEventListener > & xListener)
379 : throw (uno::RuntimeException)
380 : {
381 : // no need to lock here as m_pImpl is const and container threadsafe
382 2 : m_pImpl->m_EventListeners.addInterface(xListener);
383 2 : }
384 :
385 1 : void SAL_CALL SwXReferenceMark::removeEventListener(
386 : const uno::Reference< lang::XEventListener > & xListener)
387 : throw (uno::RuntimeException)
388 : {
389 : // no need to lock here as m_pImpl is const and container threadsafe
390 1 : m_pImpl->m_EventListeners.removeInterface(xListener);
391 1 : }
392 :
393 49 : OUString SAL_CALL SwXReferenceMark::getName()
394 : throw (uno::RuntimeException)
395 : {
396 49 : SolarMutexGuard aGuard;
397 196 : if (!m_pImpl->IsValid() ||
398 196 : !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName))
399 : {
400 0 : throw uno::RuntimeException();
401 : }
402 49 : return m_pImpl->m_sMarkName;
403 : }
404 :
405 39 : void SAL_CALL SwXReferenceMark::setName(const OUString& rName)
406 : throw (uno::RuntimeException)
407 : {
408 39 : SolarMutexGuard aGuard;
409 39 : if (m_pImpl->m_bIsDescriptor)
410 : {
411 37 : m_pImpl->m_sMarkName = rName;
412 : }
413 : else
414 : {
415 6 : if (!m_pImpl->IsValid()
416 6 : || !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName)
417 8 : || m_pImpl->m_pDoc->GetRefMark(rName))
418 : {
419 0 : throw uno::RuntimeException();
420 : }
421 : SwFmtRefMark const*const pCurMark =
422 2 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
423 4 : if ((rName != m_pImpl->m_sMarkName)
424 2 : && pCurMark && (pCurMark == m_pImpl->m_pMarkFmt))
425 : {
426 2 : const UnoActionContext aCont(m_pImpl->m_pDoc);
427 : SwTxtRefMark const*const pTxtMark =
428 2 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
429 4 : if (pTxtMark &&
430 2 : (&pTxtMark->GetTxtNode().GetNodes() ==
431 2 : &m_pImpl->m_pDoc->GetNodes()))
432 : {
433 2 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
434 2 : xub_StrLen nStt = *pTxtMark->GetStart(),
435 2 : nEnd = pTxtMark->GetEnd() ? *pTxtMark->GetEnd()
436 2 : : nStt + 1;
437 :
438 2 : SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
439 : // deletes the m_pImpl->m_pDoc member in the SwXReferenceMark!
440 2 : m_pImpl->m_pDoc->DeleteAndJoin( aPam );
441 : // The aPam will keep the correct and functional doc though
442 :
443 2 : m_pImpl->m_sMarkName = rName;
444 : //create a new one
445 2 : m_pImpl->InsertRefMark( aPam, 0 );
446 2 : m_pImpl->m_pDoc = aPam.GetDoc();
447 2 : }
448 : }
449 39 : }
450 39 : }
451 :
452 : uno::Reference< beans::XPropertySetInfo > SAL_CALL
453 0 : SwXReferenceMark::getPropertySetInfo() throw (uno::RuntimeException)
454 : {
455 0 : SolarMutexGuard g;
456 :
457 : static uno::Reference< beans::XPropertySetInfo > xRef =
458 : aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH_EXTENSIONS)
459 0 : ->getPropertySetInfo();
460 0 : return xRef;
461 : }
462 :
463 0 : void SAL_CALL SwXReferenceMark::setPropertyValue(
464 : const OUString& /*rPropertyName*/, const uno::Any& /*rValue*/ )
465 : throw (beans::UnknownPropertyException, beans::PropertyVetoException,
466 : lang::IllegalArgumentException, lang::WrappedTargetException,
467 : uno::RuntimeException)
468 : {
469 0 : throw lang::IllegalArgumentException();
470 : }
471 :
472 : uno::Any SAL_CALL
473 0 : SwXReferenceMark::getPropertyValue(const OUString& rPropertyName)
474 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
475 : uno::RuntimeException)
476 : {
477 : // does not seem to need SolarMutex
478 0 : uno::Any aRet;
479 0 : if (! ::sw::GetDefaultTextContentValue(aRet, rPropertyName))
480 : {
481 0 : throw beans::UnknownPropertyException();
482 : }
483 0 : return aRet;
484 : }
485 :
486 0 : void SAL_CALL SwXReferenceMark::addPropertyChangeListener(
487 : const OUString& /*rPropertyName*/,
488 : const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
489 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
490 : uno::RuntimeException)
491 : {
492 : OSL_FAIL("SwXReferenceMark::addPropertyChangeListener(): not implemented");
493 0 : }
494 :
495 0 : void SAL_CALL SwXReferenceMark::removePropertyChangeListener(
496 : const OUString& /*rPropertyName*/,
497 : const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
498 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
499 : uno::RuntimeException)
500 : {
501 : OSL_FAIL("SwXReferenceMark::removePropertyChangeListener(): not implemented");
502 0 : }
503 :
504 0 : void SAL_CALL SwXReferenceMark::addVetoableChangeListener(
505 : const OUString& /*rPropertyName*/,
506 : const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
507 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
508 : uno::RuntimeException)
509 : {
510 : OSL_FAIL("SwXReferenceMark::addVetoableChangeListener(): not implemented");
511 0 : }
512 :
513 0 : void SAL_CALL SwXReferenceMark::removeVetoableChangeListener(
514 : const OUString& /*rPropertyName*/,
515 : const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
516 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
517 : uno::RuntimeException)
518 : {
519 : OSL_FAIL("SwXReferenceMark::removeVetoableChangeListener(): not implemented");
520 0 : }
521 :
522 : #include <com/sun/star/lang/DisposedException.hpp>
523 : #include <unometa.hxx>
524 : #include <unotext.hxx>
525 : #include <unoport.hxx>
526 : #include <txtatr.hxx>
527 : #include <fmtmeta.hxx>
528 : #include <docsh.hxx>
529 :
530 : /******************************************************************
531 : * SwXMetaText
532 : ******************************************************************/
533 155 : class SwXMetaText
534 : : public SwXText
535 : {
536 : private:
537 : SwXMeta & m_rMeta;
538 :
539 : virtual void PrepareForAttach(uno::Reference< text::XTextRange > & xRange,
540 : const SwPaM & rPam);
541 :
542 : virtual bool CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
543 : throw (lang::IllegalArgumentException, uno::RuntimeException);
544 :
545 : protected:
546 : virtual const SwStartNode *GetStartNode() const;
547 : virtual uno::Reference< text::XTextCursor >
548 : CreateCursor() throw (uno::RuntimeException);
549 :
550 : public:
551 : SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta);
552 :
553 : /// make available for SwXMeta
554 91 : void Invalidate() { SwXText::Invalidate(); };
555 :
556 : // XInterface
557 0 : virtual void SAL_CALL acquire() throw()
558 0 : { OSL_FAIL("ERROR: SwXMetaText::acquire"); }
559 0 : virtual void SAL_CALL release() throw()
560 0 : { OSL_FAIL("ERROR: SwXMetaText::release"); }
561 :
562 : // XTypeProvider
563 : virtual uno::Sequence< sal_Int8 > SAL_CALL
564 : getImplementationId() throw (uno::RuntimeException);
565 :
566 : // XText
567 : virtual uno::Reference< text::XTextCursor > SAL_CALL
568 : createTextCursor() throw (uno::RuntimeException);
569 : virtual uno::Reference< text::XTextCursor > SAL_CALL
570 : createTextCursorByRange(
571 : const uno::Reference< text::XTextRange > & xTextPosition)
572 : throw (uno::RuntimeException);
573 :
574 91 : SwXMeta & GetXMeta() { return m_rMeta; }
575 :
576 : };
577 :
578 155 : SwXMetaText::SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta)
579 : : SwXText(&rDoc, CURSOR_META)
580 155 : , m_rMeta(rMeta)
581 : {
582 155 : }
583 :
584 71 : const SwStartNode *SwXMetaText::GetStartNode() const
585 : {
586 : SwXText const * const pParent(
587 71 : dynamic_cast<SwXText*>(m_rMeta.GetParentText().get()));
588 71 : return (pParent) ? pParent->GetStartNode() : 0;
589 : }
590 :
591 20 : void SwXMetaText::PrepareForAttach( uno::Reference<text::XTextRange> & xRange,
592 : const SwPaM & rPam)
593 : {
594 : // create a new cursor to prevent modifying SwXTextRange
595 : xRange = static_cast<text::XWordCursor*>(
596 20 : new SwXTextCursor(*GetDoc(), &m_rMeta, CURSOR_META, *rPam.GetPoint(),
597 20 : (rPam.HasMark()) ? rPam.GetMark() : 0));
598 20 : }
599 :
600 47 : bool SwXMetaText::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
601 : throw (lang::IllegalArgumentException, uno::RuntimeException)
602 : {
603 47 : return m_rMeta.CheckForOwnMemberMeta(rPam, bAbsorb);
604 : }
605 :
606 150 : uno::Reference< text::XTextCursor > SwXMetaText::CreateCursor()
607 : throw (uno::RuntimeException)
608 : {
609 150 : uno::Reference< text::XTextCursor > xRet;
610 150 : if (IsValid())
611 : {
612 : SwTxtNode * pTxtNode;
613 : xub_StrLen nMetaStart;
614 : xub_StrLen nMetaEnd;
615 : const bool bSuccess(
616 149 : m_rMeta.SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
617 149 : if (bSuccess)
618 : {
619 149 : SwPosition aPos(*pTxtNode, nMetaStart);
620 : xRet = static_cast<text::XWordCursor*>(
621 149 : new SwXTextCursor(*GetDoc(), &m_rMeta, CURSOR_META, aPos));
622 : }
623 : }
624 150 : return xRet;
625 : }
626 :
627 : uno::Sequence<sal_Int8> SAL_CALL
628 0 : SwXMetaText::getImplementationId() throw (uno::RuntimeException)
629 : {
630 0 : return m_rMeta.getImplementationId();
631 : }
632 :
633 : // XText
634 : uno::Reference< text::XTextCursor > SAL_CALL
635 15 : SwXMetaText::createTextCursor() throw (uno::RuntimeException)
636 : {
637 15 : return CreateCursor();
638 : }
639 :
640 : uno::Reference< text::XTextCursor > SAL_CALL
641 3 : SwXMetaText::createTextCursorByRange(
642 : const uno::Reference<text::XTextRange> & xTextPosition)
643 : throw (uno::RuntimeException)
644 : {
645 3 : const uno::Reference<text::XTextCursor> xCursor( CreateCursor() );
646 3 : xCursor->gotoRange(xTextPosition, sal_False);
647 2 : return xCursor;
648 : }
649 :
650 : /******************************************************************
651 : * SwXMeta
652 : ******************************************************************/
653 : // the Meta has a cached list of text portions for its contents
654 : // this list is created by SwXTextPortionEnumeration
655 : // the Meta listens at the SwTxtNode and throws away the cache when it changes
656 310 : class SwXMeta::Impl
657 : : public SwClient
658 : {
659 : private:
660 : ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper
661 :
662 : public:
663 : ::cppu::OInterfaceContainerHelper m_EventListeners;
664 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
665 : ::std::auto_ptr<const TextRangeList_t> m_pTextPortions;
666 : SAL_WNODEPRECATED_DECLARATIONS_POP
667 : // 3 possible states: not attached, attached, disposed
668 : bool m_bIsDisposed;
669 : bool m_bIsDescriptor;
670 : uno::Reference<text::XText> m_xParentText;
671 : SwXMetaText m_Text;
672 :
673 155 : Impl( SwXMeta & rThis, SwDoc & rDoc,
674 : ::sw::Meta * const pMeta,
675 : uno::Reference<text::XText> const& xParentText,
676 : TextRangeList_t const * const pPortions)
677 : : SwClient(pMeta)
678 : , m_EventListeners(m_Mutex)
679 : , m_pTextPortions( pPortions )
680 : , m_bIsDisposed( false )
681 : // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
682 : , m_bIsDescriptor((0 == pMeta) ? true : false)
683 : , m_xParentText(xParentText)
684 155 : , m_Text(rDoc, rThis)
685 : {
686 155 : }
687 :
688 : inline const ::sw::Meta * GetMeta() const;
689 : // only for SwXMetaField!
690 : inline const ::sw::MetaField * GetMetaField() const;
691 : protected:
692 : // SwClient
693 : virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
694 :
695 : };
696 :
697 1369 : inline const ::sw::Meta * SwXMeta::Impl::GetMeta() const
698 : {
699 1369 : return static_cast< const ::sw::Meta * >(GetRegisteredIn());
700 : }
701 :
702 : // SwModify
703 928 : void SwXMeta::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
704 : {
705 928 : m_pTextPortions.reset(); // throw away cache (SwTxtNode changed)
706 :
707 928 : ClientModify(this, pOld, pNew);
708 :
709 928 : if (!GetRegisteredIn()) // removed => dispose
710 : {
711 91 : m_bIsDisposed = true;
712 : lang::EventObject const ev(
713 91 : static_cast< ::cppu::OWeakObject&>(m_Text.GetXMeta()));
714 91 : m_EventListeners.disposeAndClear(ev);
715 91 : m_Text.Invalidate();
716 : }
717 928 : }
718 :
719 72 : uno::Reference<text::XText> SwXMeta::GetParentText() const
720 : {
721 72 : return m_pImpl->m_xParentText;
722 : }
723 :
724 58 : SwXMeta::SwXMeta(SwDoc *const pDoc, ::sw::Meta *const pMeta,
725 : uno::Reference<text::XText> const& xParentText,
726 : TextRangeList_t const*const pPortions)
727 58 : : m_pImpl( new SwXMeta::Impl(*this, *pDoc, pMeta, xParentText, pPortions) )
728 : {
729 58 : }
730 :
731 97 : SwXMeta::SwXMeta(SwDoc *const pDoc)
732 97 : : m_pImpl( new SwXMeta::Impl(*this, *pDoc, 0, 0, 0) )
733 : {
734 97 : }
735 :
736 244 : SwXMeta::~SwXMeta()
737 : {
738 244 : }
739 :
740 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
741 : uno::Reference<rdf::XMetadatable>
742 241 : SwXMeta::CreateXMeta(::sw::Meta & rMeta,
743 : uno::Reference<text::XText> const& i_xParent,
744 : ::std::auto_ptr<TextRangeList_t const> pPortions)
745 : {
746 : // re-use existing SwXMeta
747 : // #i105557#: do not iterate over the registered clients: race condition
748 241 : uno::Reference<rdf::XMetadatable> xMeta(rMeta.GetXMeta());
749 241 : if (xMeta.is())
750 : {
751 183 : if (pPortions.get()) // set cache in the XMeta to the given portions
752 : {
753 139 : const uno::Reference<lang::XUnoTunnel> xUT(xMeta, uno::UNO_QUERY);
754 : SwXMeta *const pXMeta(
755 139 : ::sw::UnoTunnelGetImplementation<SwXMeta>(xUT));
756 : OSL_ENSURE(pXMeta, "no pXMeta?");
757 : // NB: the meta must always be created with the complete content
758 : // if SwXTextPortionEnumeration is created for a selection,
759 : // it must be checked that the Meta is contained in the selection!
760 139 : pXMeta->m_pImpl->m_pTextPortions = pPortions;
761 : // ??? is this necessary?
762 139 : if (pXMeta->m_pImpl->m_xParentText.get() != i_xParent.get())
763 : {
764 : OSL_FAIL("SwXMeta with different parent?");
765 0 : pXMeta->m_pImpl->m_xParentText.set(i_xParent);
766 139 : }
767 : }
768 183 : return xMeta;
769 : }
770 :
771 : // create new SwXMeta
772 58 : SwTxtNode * const pTxtNode( rMeta.GetTxtNode() );
773 : OSL_ENSURE(pTxtNode, "CreateXMeta: no text node?");
774 58 : if (!pTxtNode) { return 0; }
775 116 : uno::Reference<text::XText> xParentText(i_xParent);
776 58 : if (!xParentText.is())
777 : {
778 22 : SwTxtMeta * const pTxtAttr( rMeta.GetTxtAttr() );
779 : OSL_ENSURE(pTxtAttr, "CreateXMeta: no text attr?");
780 22 : if (!pTxtAttr) { return 0; }
781 22 : const SwPosition aPos(*pTxtNode, *pTxtAttr->GetStart());
782 22 : xParentText.set( ::sw::CreateParentXText(*pTxtNode->GetDoc(), aPos) );
783 : }
784 58 : if (!xParentText.is()) { return 0; }
785 58 : SwXMeta *const pXMeta( (RES_TXTATR_META == rMeta.GetFmtMeta()->Which())
786 18 : ? new SwXMeta (pTxtNode->GetDoc(), &rMeta, xParentText,
787 18 : pPortions.release()) // temporarily un-auto_ptr :-(
788 40 : : new SwXMetaField(pTxtNode->GetDoc(), &rMeta, xParentText,
789 134 : pPortions.release()));
790 : // this is why the constructor is private: need to acquire pXMeta here
791 58 : xMeta.set(pXMeta);
792 : // in order to initialize the weak pointer cache in the core object
793 58 : rMeta.SetXMeta(xMeta);
794 299 : return xMeta;
795 : }
796 : SAL_WNODEPRECATED_DECLARATIONS_POP
797 :
798 705 : bool SwXMeta::SetContentRange(
799 : SwTxtNode *& rpNode, xub_StrLen & rStart, xub_StrLen & rEnd ) const
800 : {
801 705 : ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
802 705 : if (pMeta)
803 : {
804 705 : SwTxtMeta const * const pTxtAttr( pMeta->GetTxtAttr() );
805 705 : if (pTxtAttr)
806 : {
807 705 : rpNode = pMeta->GetTxtNode();
808 705 : if (rpNode)
809 : {
810 : // rStart points at the first position _within_ the meta!
811 705 : rStart = *pTxtAttr->GetStart() + 1;
812 705 : rEnd = *pTxtAttr->GetEnd();
813 705 : return true;
814 : }
815 : }
816 : }
817 0 : return false;
818 : }
819 :
820 78 : bool SwXMeta::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
821 : throw (lang::IllegalArgumentException, uno::RuntimeException)
822 : {
823 : SwTxtNode * pTxtNode;
824 : xub_StrLen nMetaStart;
825 : xub_StrLen nMetaEnd;
826 78 : const bool bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
827 : OSL_ENSURE(bSuccess, "no pam?");
828 78 : if (!bSuccess)
829 0 : throw lang::DisposedException();
830 :
831 78 : SwPosition const * const pStartPos( rPam.Start() );
832 78 : if (&pStartPos->nNode.GetNode() != pTxtNode)
833 : {
834 : throw lang::IllegalArgumentException(
835 : "trying to insert into a nesting text content, but start "
836 : "of text range not in same paragraph as text content",
837 3 : 0, 0);
838 : }
839 75 : bool bForceExpandHints(false);
840 75 : const xub_StrLen nStartPos(pStartPos->nContent.GetIndex());
841 : // not <= but < because nMetaStart is behind dummy char!
842 : // not >= but > because == means insert at end!
843 75 : if ((nStartPos < nMetaStart) || (nStartPos > nMetaEnd))
844 : {
845 : throw lang::IllegalArgumentException(
846 : "trying to insert into a nesting text content, but start "
847 : "of text range not inside text content",
848 0 : 0, 0);
849 : }
850 75 : else if (nStartPos == nMetaEnd)
851 : {
852 19 : bForceExpandHints = true;
853 : }
854 75 : if (rPam.HasMark() && bAbsorb)
855 : {
856 39 : SwPosition const * const pEndPos( rPam.End() );
857 39 : if (&pEndPos->nNode.GetNode() != pTxtNode)
858 : {
859 : throw lang::IllegalArgumentException(
860 : "trying to insert into a nesting text content, but end "
861 : "of text range not in same paragraph as text content",
862 0 : 0, 0);
863 : }
864 39 : const xub_StrLen nEndPos(pEndPos->nContent.GetIndex());
865 : // not <= but < because nMetaStart is behind dummy char!
866 : // not >= but > because == means insert at end!
867 39 : if ((nEndPos < nMetaStart) || (nEndPos > nMetaEnd))
868 : {
869 : throw lang::IllegalArgumentException(
870 : "trying to insert into a nesting text content, but end "
871 : "of text range not inside text content",
872 0 : 0, 0);
873 : }
874 39 : else if (nEndPos == nMetaEnd)
875 : {
876 33 : bForceExpandHints = true;
877 : }
878 : }
879 75 : return bForceExpandHints;
880 : }
881 :
882 : namespace
883 : {
884 : class theSwXMetaUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXMetaUnoTunnelId > {};
885 : }
886 :
887 3228 : const uno::Sequence< sal_Int8 > & SwXMeta::getUnoTunnelId()
888 : {
889 3228 : return theSwXMetaUnoTunnelId::get().getSeq();
890 : }
891 :
892 : // XUnoTunnel
893 : sal_Int64 SAL_CALL
894 457 : SwXMeta::getSomething( const uno::Sequence< sal_Int8 > & i_rId )
895 : throw (uno::RuntimeException)
896 : {
897 457 : return ::sw::UnoTunnelImpl<SwXMeta>(i_rId, this);
898 : }
899 :
900 : // XServiceInfo
901 : OUString SAL_CALL
902 0 : SwXMeta::getImplementationName() throw (uno::RuntimeException)
903 : {
904 0 : return OUString("SwXMeta");
905 : }
906 :
907 : static char const*const g_ServicesMeta[] =
908 : {
909 : "com.sun.star.text.TextContent",
910 : "com.sun.star.text.InContentMetadata",
911 : };
912 :
913 : static const size_t g_nServicesMeta(
914 : sizeof(g_ServicesMeta)/sizeof(g_ServicesMeta[0]));
915 :
916 : sal_Bool SAL_CALL
917 10 : SwXMeta::supportsService(const OUString& rServiceName)
918 : throw (uno::RuntimeException)
919 : {
920 : return ::sw::SupportsServiceImpl(
921 10 : g_nServicesMeta, g_ServicesMeta, rServiceName);
922 : }
923 :
924 : uno::Sequence< OUString > SAL_CALL
925 0 : SwXMeta::getSupportedServiceNames() throw (uno::RuntimeException)
926 : {
927 0 : return ::sw::GetSupportedServiceNamesImpl(g_nServicesMeta, g_ServicesMeta);
928 : }
929 :
930 : // XComponent
931 : void SAL_CALL
932 0 : SwXMeta::addEventListener(
933 : uno::Reference< lang::XEventListener> const & xListener )
934 : throw (uno::RuntimeException)
935 : {
936 : // no need to lock here as m_pImpl is const and container threadsafe
937 0 : m_pImpl->m_EventListeners.addInterface(xListener);
938 0 : }
939 :
940 : void SAL_CALL
941 0 : SwXMeta::removeEventListener(
942 : uno::Reference< lang::XEventListener> const & xListener )
943 : throw (uno::RuntimeException)
944 : {
945 : // no need to lock here as m_pImpl is const and container threadsafe
946 0 : m_pImpl->m_EventListeners.removeInterface(xListener);
947 0 : }
948 :
949 : void SAL_CALL
950 1 : SwXMeta::dispose() throw (uno::RuntimeException)
951 : {
952 1 : SolarMutexGuard g;
953 :
954 1 : if (m_pImpl->m_bIsDescriptor)
955 : {
956 0 : m_pImpl->m_pTextPortions.reset();
957 0 : lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(*this));
958 0 : m_pImpl->m_EventListeners.disposeAndClear(ev);
959 0 : m_pImpl->m_bIsDisposed = true;
960 0 : m_pImpl->m_Text.Invalidate();
961 : }
962 1 : else if (!m_pImpl->m_bIsDisposed)
963 : {
964 : SwTxtNode * pTxtNode;
965 : xub_StrLen nMetaStart;
966 : xub_StrLen nMetaEnd;
967 1 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
968 : OSL_ENSURE(bSuccess, "no pam?");
969 1 : if (bSuccess)
970 : {
971 : // -1 because of CH_TXTATR
972 1 : SwPaM aPam( *pTxtNode, nMetaStart - 1, *pTxtNode, nMetaEnd );
973 1 : SwDoc * const pDoc( pTxtNode->GetDoc() );
974 1 : pDoc->DeleteAndJoin( aPam );
975 :
976 : // removal should call Modify and do the dispose
977 1 : OSL_ENSURE(m_pImpl->m_bIsDisposed, "zombie meta");
978 : }
979 1 : }
980 1 : }
981 :
982 : void SAL_CALL
983 97 : SwXMeta::AttachImpl(const uno::Reference< text::XTextRange > & i_xTextRange,
984 : const sal_uInt16 i_nWhich)
985 : throw (lang::IllegalArgumentException, uno::RuntimeException)
986 : {
987 97 : SolarMutexGuard g;
988 :
989 97 : if (m_pImpl->m_bIsDisposed)
990 : {
991 0 : throw lang::DisposedException();
992 : }
993 97 : if (!m_pImpl->m_bIsDescriptor)
994 : {
995 : throw uno::RuntimeException(
996 : OUString("SwXMeta::attach(): already attached"),
997 0 : static_cast< ::cppu::OWeakObject* >(this));
998 : }
999 :
1000 194 : uno::Reference<lang::XUnoTunnel> xRangeTunnel(i_xTextRange, uno::UNO_QUERY);
1001 97 : if (!xRangeTunnel.is())
1002 : {
1003 : throw lang::IllegalArgumentException(
1004 : OUString("SwXMeta::attach(): argument is no XUnoTunnel"),
1005 0 : static_cast< ::cppu::OWeakObject* >(this), 0);
1006 : }
1007 : SwXTextRange *const pRange(
1008 97 : ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel));
1009 : OTextCursorHelper *const pCursor( (pRange) ? 0 :
1010 97 : ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel));
1011 97 : if (!pRange && !pCursor)
1012 : {
1013 : throw lang::IllegalArgumentException(
1014 : OUString("SwXMeta::attach(): argument not supported type"),
1015 0 : static_cast< ::cppu::OWeakObject* >(this), 0);
1016 : }
1017 :
1018 : SwDoc * const pDoc(
1019 97 : pRange ? pRange->GetDoc() : pCursor->GetDoc());
1020 97 : if (!pDoc)
1021 : {
1022 : throw lang::IllegalArgumentException(
1023 : OUString("SwXMeta::attach(): argument has no SwDoc"),
1024 0 : static_cast< ::cppu::OWeakObject* >(this), 0);
1025 : }
1026 :
1027 194 : SwUnoInternalPaM aPam(*pDoc);
1028 97 : ::sw::XTextRangeToSwPaM(aPam, i_xTextRange);
1029 :
1030 194 : UnoActionContext aContext(pDoc);
1031 :
1032 : SwXTextCursor const*const pTextCursor(
1033 97 : dynamic_cast<SwXTextCursor*>(pCursor));
1034 : const bool bForceExpandHints((pTextCursor)
1035 97 : ? pTextCursor->IsAtEndOfMeta() : false);
1036 : const SetAttrMode nInsertFlags( (bForceExpandHints)
1037 : ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
1038 : | nsSetAttrMode::SETATTR_DONTEXPAND)
1039 97 : : nsSetAttrMode::SETATTR_DONTEXPAND );
1040 :
1041 : const ::boost::shared_ptr< ::sw::Meta> pMeta( (RES_TXTATR_META == i_nWhich)
1042 0 : ? ::boost::shared_ptr< ::sw::Meta>( new ::sw::Meta() )
1043 : : ::boost::shared_ptr< ::sw::Meta>(
1044 194 : pDoc->GetMetaFieldManager().makeMetaField()) );
1045 194 : SwFmtMeta meta(pMeta, i_nWhich); // this is cloned by Insert!
1046 97 : const bool bSuccess( pDoc->InsertPoolItem( aPam, meta, nInsertFlags ) );
1047 97 : SwTxtAttr * const pTxtAttr( pMeta->GetTxtAttr() );
1048 97 : if (!bSuccess)
1049 : {
1050 : throw lang::IllegalArgumentException(
1051 : OUString("SwXMeta::attach(): cannot create meta: range invalid?"),
1052 2 : static_cast< ::cppu::OWeakObject* >(this), 1);
1053 : }
1054 95 : if (!pTxtAttr)
1055 : {
1056 : OSL_FAIL("meta inserted, but has no text attribute?");
1057 : throw uno::RuntimeException(
1058 : OUString("SwXMeta::attach(): cannot create meta"),
1059 0 : static_cast< ::cppu::OWeakObject* >(this));
1060 : }
1061 :
1062 95 : pMeta->Add(m_pImpl.get());
1063 95 : pMeta->SetXMeta(uno::Reference<rdf::XMetadatable>(this));
1064 :
1065 95 : m_pImpl->m_xParentText = ::sw::CreateParentXText(*pDoc, *aPam.GetPoint());
1066 :
1067 192 : m_pImpl->m_bIsDescriptor = false;
1068 95 : }
1069 :
1070 : // XTextContent
1071 : void SAL_CALL
1072 71 : SwXMeta::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
1073 : throw (lang::IllegalArgumentException, uno::RuntimeException)
1074 : {
1075 71 : return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_META);
1076 : }
1077 :
1078 : uno::Reference< text::XTextRange > SAL_CALL
1079 23 : SwXMeta::getAnchor() throw (uno::RuntimeException)
1080 : {
1081 23 : SolarMutexGuard g;
1082 :
1083 23 : if (m_pImpl->m_bIsDisposed)
1084 : {
1085 0 : throw lang::DisposedException();
1086 : }
1087 23 : if (m_pImpl->m_bIsDescriptor)
1088 : {
1089 : throw uno::RuntimeException(
1090 : OUString("SwXMeta::getAnchor(): not inserted"),
1091 0 : static_cast< ::cppu::OWeakObject* >(this));
1092 : }
1093 :
1094 : SwTxtNode * pTxtNode;
1095 : xub_StrLen nMetaStart;
1096 : xub_StrLen nMetaEnd;
1097 23 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
1098 : OSL_ENSURE(bSuccess, "no pam?");
1099 23 : if (!bSuccess)
1100 : {
1101 : throw lang::DisposedException(
1102 : OUString("SwXMeta::getAnchor(): not attached"),
1103 0 : static_cast< ::cppu::OWeakObject* >(this));
1104 : }
1105 :
1106 46 : const SwPosition start(*pTxtNode, nMetaStart - 1); // -1 due to CH_TXTATR
1107 46 : const SwPosition end(*pTxtNode, nMetaEnd);
1108 46 : return SwXTextRange::CreateXTextRange(*pTxtNode->GetDoc(), start, &end);
1109 : }
1110 :
1111 : // XTextRange
1112 : uno::Reference< text::XText > SAL_CALL
1113 1 : SwXMeta::getText() throw (uno::RuntimeException)
1114 : {
1115 1 : SolarMutexGuard g;
1116 1 : return this;
1117 : }
1118 :
1119 : uno::Reference< text::XTextRange > SAL_CALL
1120 34 : SwXMeta::getStart() throw (uno::RuntimeException)
1121 : {
1122 34 : SolarMutexGuard g;
1123 34 : return m_pImpl->m_Text.getStart();
1124 : }
1125 :
1126 : uno::Reference< text::XTextRange > SAL_CALL
1127 31 : SwXMeta::getEnd() throw (uno::RuntimeException)
1128 : {
1129 31 : SolarMutexGuard g;
1130 31 : return m_pImpl->m_Text.getEnd();
1131 : }
1132 :
1133 : OUString SAL_CALL
1134 40 : SwXMeta::getString() throw (uno::RuntimeException)
1135 : {
1136 40 : SolarMutexGuard g;
1137 40 : return m_pImpl->m_Text.getString();
1138 : }
1139 :
1140 : void SAL_CALL
1141 27 : SwXMeta::setString(const OUString& rString) throw (uno::RuntimeException)
1142 : {
1143 27 : SolarMutexGuard g;
1144 27 : return m_pImpl->m_Text.setString(rString);
1145 : }
1146 :
1147 : // XSimpleText
1148 : uno::Reference< text::XTextCursor > SAL_CALL
1149 15 : SwXMeta::createTextCursor() throw (uno::RuntimeException)
1150 : {
1151 15 : SolarMutexGuard g;
1152 15 : return m_pImpl->m_Text.createTextCursor();
1153 : }
1154 :
1155 : uno::Reference< text::XTextCursor > SAL_CALL
1156 3 : SwXMeta::createTextCursorByRange(
1157 : const uno::Reference<text::XTextRange> & xTextPosition)
1158 : throw (uno::RuntimeException)
1159 : {
1160 3 : SolarMutexGuard g;
1161 3 : return m_pImpl->m_Text.createTextCursorByRange(xTextPosition);
1162 : }
1163 :
1164 : void SAL_CALL
1165 4 : SwXMeta::insertString(const uno::Reference<text::XTextRange> & xRange,
1166 : const OUString& rString, sal_Bool bAbsorb)
1167 : throw (uno::RuntimeException)
1168 : {
1169 4 : SolarMutexGuard g;
1170 4 : return m_pImpl->m_Text.insertString(xRange, rString, bAbsorb);
1171 : }
1172 :
1173 : void SAL_CALL
1174 4 : SwXMeta::insertControlCharacter(const uno::Reference<text::XTextRange> & xRange,
1175 : sal_Int16 nControlCharacter, sal_Bool bAbsorb)
1176 : throw (lang::IllegalArgumentException, uno::RuntimeException)
1177 : {
1178 4 : SolarMutexGuard g;
1179 4 : return m_pImpl->m_Text.insertControlCharacter(xRange, nControlCharacter,
1180 4 : bAbsorb);
1181 : }
1182 :
1183 : // XText
1184 : void SAL_CALL
1185 43 : SwXMeta::insertTextContent( const uno::Reference<text::XTextRange> & xRange,
1186 : const uno::Reference<text::XTextContent> & xContent, sal_Bool bAbsorb)
1187 : throw (lang::IllegalArgumentException, uno::RuntimeException)
1188 : {
1189 43 : SolarMutexGuard g;
1190 43 : return m_pImpl->m_Text.insertTextContent(xRange, xContent, bAbsorb);
1191 : }
1192 :
1193 : void SAL_CALL
1194 2 : SwXMeta::removeTextContent(
1195 : const uno::Reference< text::XTextContent > & xContent)
1196 : throw (container::NoSuchElementException, uno::RuntimeException)
1197 : {
1198 2 : SolarMutexGuard g;
1199 2 : return m_pImpl->m_Text.removeTextContent(xContent);
1200 : }
1201 :
1202 : // XChild
1203 : uno::Reference< uno::XInterface > SAL_CALL
1204 6 : SwXMeta::getParent() throw (uno::RuntimeException)
1205 : {
1206 6 : SolarMutexGuard g;
1207 : SwTxtNode * pTxtNode;
1208 : xub_StrLen nMetaStart;
1209 : xub_StrLen nMetaEnd;
1210 6 : bool const bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
1211 : OSL_ENSURE(bSuccess, "no pam?");
1212 6 : if (!bSuccess) { throw lang::DisposedException(); }
1213 : // in order to prevent getting this meta, subtract 1 from nMetaStart;
1214 : // so we get the index of the dummy character, and we exclude it
1215 : // by calling GetTxtAttrAt(_, _, PARENT) in GetNestedTextContent
1216 : uno::Reference<text::XTextContent> const xRet(
1217 : SwUnoCursorHelper::GetNestedTextContent(*pTxtNode, nMetaStart - 1,
1218 12 : true) );
1219 12 : return xRet;
1220 : }
1221 :
1222 : void SAL_CALL
1223 1 : SwXMeta::setParent(uno::Reference< uno::XInterface > const& /*xParent*/)
1224 : throw (uno::RuntimeException, lang::NoSupportException)
1225 : {
1226 1 : throw lang::NoSupportException("setting parent not supported", *this);
1227 : }
1228 :
1229 : // XElementAccess
1230 : uno::Type SAL_CALL
1231 0 : SwXMeta::getElementType() throw (uno::RuntimeException)
1232 : {
1233 0 : return text::XTextRange::static_type();
1234 : }
1235 :
1236 : sal_Bool SAL_CALL
1237 0 : SwXMeta::hasElements() throw (uno::RuntimeException)
1238 : {
1239 0 : SolarMutexGuard g;
1240 :
1241 0 : return m_pImpl->GetRegisteredIn() ? sal_True : sal_False;
1242 : }
1243 :
1244 : // XEnumerationAccess
1245 : uno::Reference< container::XEnumeration > SAL_CALL
1246 176 : SwXMeta::createEnumeration() throw (uno::RuntimeException)
1247 : {
1248 176 : SolarMutexGuard g;
1249 :
1250 176 : if (m_pImpl->m_bIsDisposed)
1251 : {
1252 0 : throw lang::DisposedException();
1253 : }
1254 176 : if (m_pImpl->m_bIsDescriptor)
1255 : {
1256 : throw uno::RuntimeException(
1257 : OUString("createEnumeration(): not inserted"),
1258 0 : static_cast< ::cppu::OWeakObject* >(this));
1259 : }
1260 :
1261 : SwTxtNode * pTxtNode;
1262 : xub_StrLen nMetaStart;
1263 : xub_StrLen nMetaEnd;
1264 176 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
1265 : OSL_ENSURE(bSuccess, "no pam?");
1266 176 : if (!bSuccess)
1267 0 : throw lang::DisposedException();
1268 :
1269 352 : SwPaM aPam(*pTxtNode, nMetaStart);
1270 :
1271 176 : if (!m_pImpl->m_pTextPortions.get())
1272 : {
1273 : return new SwXTextPortionEnumeration(
1274 1 : aPam, GetParentText(), nMetaStart, nMetaEnd);
1275 : }
1276 : else // cached!
1277 : {
1278 175 : return new SwXTextPortionEnumeration(aPam, *m_pImpl->m_pTextPortions);
1279 176 : }
1280 : }
1281 :
1282 : // MetadatableMixin
1283 533 : ::sfx2::Metadatable* SwXMeta::GetCoreObject()
1284 : {
1285 533 : return const_cast< ::sw::Meta * >(m_pImpl->GetMeta());
1286 : }
1287 :
1288 131 : uno::Reference<frame::XModel> SwXMeta::GetModel()
1289 : {
1290 131 : ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
1291 131 : if (pMeta)
1292 : {
1293 131 : SwTxtNode const * const pTxtNode( pMeta->GetTxtNode() );
1294 131 : if (pTxtNode)
1295 : {
1296 131 : SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
1297 131 : return (pShell) ? pShell->GetModel() : 0;
1298 : }
1299 : }
1300 0 : return 0;
1301 : }
1302 :
1303 : /******************************************************************
1304 : * SwXMetaField
1305 : ******************************************************************/
1306 47 : inline const ::sw::MetaField * SwXMeta::Impl::GetMetaField() const
1307 : {
1308 47 : return static_cast< const ::sw::MetaField * >(GetRegisteredIn());
1309 : }
1310 :
1311 40 : SwXMetaField::SwXMetaField(SwDoc *const pDoc, ::sw::Meta *const pMeta,
1312 : uno::Reference<text::XText> const& xParentText,
1313 : TextRangeList_t const*const pPortions)
1314 40 : : SwXMetaField_Base(pDoc, pMeta, xParentText, pPortions)
1315 : {
1316 : OSL_ENSURE(pMeta && dynamic_cast< ::sw::MetaField* >(pMeta),
1317 : "SwXMetaField created for wrong hint!");
1318 40 : }
1319 :
1320 26 : SwXMetaField::SwXMetaField(SwDoc *const pDoc)
1321 26 : : SwXMetaField_Base(pDoc)
1322 : {
1323 26 : }
1324 :
1325 132 : SwXMetaField::~SwXMetaField()
1326 : {
1327 132 : }
1328 :
1329 : // XServiceInfo
1330 : OUString SAL_CALL
1331 0 : SwXMetaField::getImplementationName() throw (uno::RuntimeException)
1332 : {
1333 0 : return OUString("SwXMetaField");
1334 : }
1335 :
1336 : static char const*const g_ServicesMetaField[] =
1337 : {
1338 : "com.sun.star.text.TextContent",
1339 : "com.sun.star.text.TextField",
1340 : "com.sun.star.text.textfield.MetadataField",
1341 : };
1342 :
1343 : static const size_t g_nServicesMetaField(
1344 : sizeof(g_ServicesMetaField)/sizeof(g_ServicesMetaField[0]));
1345 :
1346 : sal_Bool SAL_CALL
1347 20 : SwXMetaField::supportsService(const OUString& rServiceName)
1348 : throw (uno::RuntimeException)
1349 : {
1350 : return ::sw::SupportsServiceImpl(
1351 20 : g_nServicesMetaField, g_ServicesMetaField, rServiceName);
1352 : }
1353 :
1354 : uno::Sequence< OUString > SAL_CALL
1355 20 : SwXMetaField::getSupportedServiceNames() throw (uno::RuntimeException)
1356 : {
1357 : return ::sw::GetSupportedServiceNamesImpl(
1358 20 : g_nServicesMetaField, g_ServicesMetaField);
1359 : }
1360 :
1361 : // XComponent
1362 : void SAL_CALL
1363 0 : SwXMetaField::addEventListener(
1364 : uno::Reference< lang::XEventListener> const & xListener )
1365 : throw (uno::RuntimeException)
1366 : {
1367 0 : return SwXMeta::addEventListener(xListener);
1368 : }
1369 :
1370 : void SAL_CALL
1371 0 : SwXMetaField::removeEventListener(
1372 : uno::Reference< lang::XEventListener> const & xListener )
1373 : throw (uno::RuntimeException)
1374 : {
1375 0 : return SwXMeta::removeEventListener(xListener);
1376 : }
1377 :
1378 : void SAL_CALL
1379 0 : SwXMetaField::dispose() throw (uno::RuntimeException)
1380 : {
1381 0 : return SwXMeta::dispose();
1382 : }
1383 :
1384 : // XTextContent
1385 : void SAL_CALL
1386 26 : SwXMetaField::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
1387 : throw (lang::IllegalArgumentException, uno::RuntimeException)
1388 : {
1389 26 : return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_METAFIELD);
1390 : }
1391 :
1392 : uno::Reference< text::XTextRange > SAL_CALL
1393 20 : SwXMetaField::getAnchor() throw (uno::RuntimeException)
1394 : {
1395 20 : return SwXMeta::getAnchor();
1396 : }
1397 :
1398 : // XPropertySet
1399 : uno::Reference< beans::XPropertySetInfo > SAL_CALL
1400 17 : SwXMetaField::getPropertySetInfo() throw (uno::RuntimeException)
1401 : {
1402 17 : SolarMutexGuard g;
1403 :
1404 : static uno::Reference< beans::XPropertySetInfo > xRef(
1405 : aSwMapProvider.GetPropertySet(PROPERTY_MAP_METAFIELD)
1406 17 : ->getPropertySetInfo() );
1407 17 : return xRef;
1408 : }
1409 :
1410 : void SAL_CALL
1411 10 : SwXMetaField::setPropertyValue(
1412 : const OUString& rPropertyName, const uno::Any& rValue)
1413 : throw (beans::UnknownPropertyException, beans::PropertyVetoException,
1414 : lang::IllegalArgumentException, lang::WrappedTargetException,
1415 : uno::RuntimeException)
1416 : {
1417 10 : SolarMutexGuard g;
1418 :
1419 : ::sw::MetaField * const pMeta(
1420 10 : const_cast< ::sw::MetaField * >(m_pImpl->GetMetaField()) );
1421 10 : if (!pMeta)
1422 0 : throw lang::DisposedException();
1423 :
1424 10 : if ( rPropertyName == "NumberFormat" )
1425 : {
1426 5 : sal_Int32 nNumberFormat(0);
1427 5 : if (rValue >>= nNumberFormat)
1428 : {
1429 5 : pMeta->SetNumberFormat(static_cast<sal_uInt32>(nNumberFormat));
1430 : }
1431 : }
1432 5 : else if ( rPropertyName == "IsFixedLanguage" )
1433 : {
1434 5 : bool b(false);
1435 5 : if (rValue >>= b)
1436 : {
1437 5 : pMeta->SetIsFixedLanguage(b);
1438 : }
1439 : }
1440 : else
1441 : {
1442 0 : throw beans::UnknownPropertyException();
1443 10 : }
1444 10 : }
1445 :
1446 : uno::Any SAL_CALL
1447 37 : SwXMetaField::getPropertyValue(const OUString& rPropertyName)
1448 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1449 : uno::RuntimeException)
1450 : {
1451 37 : SolarMutexGuard g;
1452 :
1453 37 : ::sw::MetaField const * const pMeta( m_pImpl->GetMetaField() );
1454 37 : if (!pMeta)
1455 0 : throw lang::DisposedException();
1456 :
1457 37 : uno::Any any;
1458 :
1459 37 : if ( rPropertyName == "NumberFormat" )
1460 : {
1461 24 : const OUString text( getPresentation(sal_False) );
1462 24 : any <<= static_cast<sal_Int32>(pMeta->GetNumberFormat(text));
1463 : }
1464 13 : else if ( rPropertyName == "IsFixedLanguage" )
1465 : {
1466 3 : any <<= pMeta->IsFixedLanguage();
1467 : }
1468 : else
1469 : {
1470 10 : throw beans::UnknownPropertyException();
1471 : }
1472 :
1473 37 : return any;
1474 : }
1475 :
1476 : void SAL_CALL
1477 0 : SwXMetaField::addPropertyChangeListener(
1478 : const OUString& /*rPropertyName*/,
1479 : const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1480 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1481 : uno::RuntimeException)
1482 : {
1483 : OSL_FAIL("SwXMetaField::addPropertyChangeListener(): not implemented");
1484 0 : }
1485 :
1486 : void SAL_CALL
1487 0 : SwXMetaField::removePropertyChangeListener(
1488 : const OUString& /*rPropertyName*/,
1489 : const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1490 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1491 : uno::RuntimeException)
1492 : {
1493 : OSL_FAIL("SwXMetaField::removePropertyChangeListener(): not implemented");
1494 0 : }
1495 :
1496 : void SAL_CALL
1497 0 : SwXMetaField::addVetoableChangeListener(
1498 : const OUString& /*rPropertyName*/,
1499 : const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1500 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1501 : uno::RuntimeException)
1502 : {
1503 : OSL_FAIL("SwXMetaField::addVetoableChangeListener(): not implemented");
1504 0 : }
1505 :
1506 : void SAL_CALL
1507 0 : SwXMetaField::removeVetoableChangeListener(
1508 : const OUString& /*rPropertyName*/,
1509 : const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1510 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1511 : uno::RuntimeException)
1512 : {
1513 : OSL_FAIL("SwXMetaField::removeVetoableChangeListener(): not implemented");
1514 0 : }
1515 :
1516 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
1517 : #include <com/sun/star/rdf/Statement.hpp>
1518 : #include <com/sun/star/rdf/URI.hpp>
1519 : #include <com/sun/star/rdf/URIs.hpp>
1520 : #include <com/sun/star/rdf/XLiteral.hpp>
1521 : #include <com/sun/star/rdf/XRepositorySupplier.hpp>
1522 : #include <comphelper/processfactory.hxx>
1523 :
1524 : static uno::Reference<rdf::XURI> const&
1525 110 : lcl_getURI(const bool bPrefix)
1526 : {
1527 : static uno::Reference< uno::XComponentContext > xContext(
1528 110 : ::comphelper::getProcessComponentContext());
1529 : static uno::Reference< rdf::XURI > xOdfPrefix(
1530 : rdf::URI::createKnown(xContext, rdf::URIs::ODF_PREFIX),
1531 110 : uno::UNO_SET_THROW);
1532 : static uno::Reference< rdf::XURI > xOdfSuffix(
1533 : rdf::URI::createKnown(xContext, rdf::URIs::ODF_SUFFIX),
1534 110 : uno::UNO_SET_THROW);
1535 110 : return (bPrefix) ? xOdfPrefix : xOdfSuffix;
1536 : }
1537 :
1538 : static OUString
1539 110 : lcl_getPrefixOrSuffix(
1540 : uno::Reference<rdf::XRepository> const & xRepository,
1541 : uno::Reference<rdf::XResource> const & xMetaField,
1542 : uno::Reference<rdf::XURI> const & xPredicate)
1543 : {
1544 : const uno::Reference<container::XEnumeration> xEnum(
1545 110 : xRepository->getStatements(xMetaField, xPredicate, 0),
1546 110 : uno::UNO_SET_THROW);
1547 220 : while (xEnum->hasMoreElements()) {
1548 68 : rdf::Statement stmt;
1549 68 : if (!(xEnum->nextElement() >>= stmt)) {
1550 0 : throw uno::RuntimeException();
1551 : }
1552 : const uno::Reference<rdf::XLiteral> xObject(stmt.Object,
1553 68 : uno::UNO_QUERY);
1554 68 : if (!xObject.is()) continue;
1555 68 : if (xEnum->hasMoreElements()) {
1556 : OSL_TRACE("ignoring other odf:Prefix/odf:Suffix statements");
1557 : }
1558 68 : return xObject->getValue();
1559 0 : }
1560 42 : return OUString();
1561 : }
1562 :
1563 : void
1564 75 : getPrefixAndSuffix(
1565 : const uno::Reference<frame::XModel>& xModel,
1566 : const uno::Reference<rdf::XMetadatable>& xMetaField,
1567 : OUString *const o_pPrefix, OUString *const o_pSuffix)
1568 : {
1569 : try {
1570 : const uno::Reference<rdf::XRepositorySupplier> xRS(
1571 75 : xModel, uno::UNO_QUERY_THROW);
1572 : const uno::Reference<rdf::XRepository> xRepo(
1573 150 : xRS->getRDFRepository(), uno::UNO_SET_THROW);
1574 : const uno::Reference<rdf::XResource> xMeta(
1575 150 : xMetaField, uno::UNO_QUERY_THROW);
1576 75 : if (o_pPrefix)
1577 : {
1578 55 : *o_pPrefix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(true));
1579 : }
1580 75 : if (o_pSuffix)
1581 : {
1582 55 : *o_pSuffix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(false));
1583 75 : }
1584 0 : } catch (uno::RuntimeException &) {
1585 0 : throw;
1586 0 : } catch (const uno::Exception & e) {
1587 : throw lang::WrappedTargetRuntimeException(
1588 : OUString("getPrefixAndSuffix: exception"),
1589 0 : 0, uno::makeAny(e));
1590 : }
1591 75 : }
1592 :
1593 : // XTextField
1594 : OUString SAL_CALL
1595 35 : SwXMetaField::getPresentation(sal_Bool bShowCommand)
1596 : throw (uno::RuntimeException)
1597 : {
1598 35 : SolarMutexGuard g;
1599 :
1600 35 : if (bShowCommand)
1601 : {
1602 : //FIXME ?
1603 0 : return OUString();
1604 : }
1605 : else
1606 : {
1607 : // getString should check if this is invalid
1608 35 : const OUString content( this->getString() );
1609 70 : OUString prefix;
1610 70 : OUString suffix;
1611 35 : getPrefixAndSuffix(GetModel(), this, &prefix, &suffix);
1612 70 : return prefix + content + suffix;
1613 35 : }
1614 99 : }
1615 :
1616 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|