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 : #include <osl/mutex.hxx>
21 : #include <cppuhelper/interfacecontainer.h>
22 : #include <cppuhelper/supportsservice.hxx>
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 : using namespace ::com::sun::star;
40 :
41 : /******************************************************************
42 : * SwXReferenceMark
43 : ******************************************************************/
44 176 : class SwXReferenceMark::Impl
45 : : public SwClient
46 : {
47 : private:
48 : ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper
49 : SwXReferenceMark & m_rThis;
50 :
51 : public:
52 : ::cppu::OInterfaceContainerHelper m_EventListeners;
53 : bool m_bIsDescriptor;
54 : SwDoc * m_pDoc;
55 : const SwFmtRefMark * m_pMarkFmt;
56 : OUString m_sMarkName;
57 :
58 88 : Impl( SwXReferenceMark & rThis,
59 : SwDoc *const pDoc, SwFmtRefMark const*const pRefMark)
60 : : SwClient((pDoc) ? pDoc->GetUnoCallBack() : 0)
61 : , m_rThis(rThis)
62 : , m_EventListeners(m_Mutex)
63 : // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
64 : , m_bIsDescriptor((0 == pRefMark) ? true : false)
65 : , m_pDoc(pDoc)
66 88 : , m_pMarkFmt(pRefMark)
67 : {
68 88 : if (pRefMark)
69 : {
70 50 : m_sMarkName = pRefMark->GetRefName();
71 : }
72 88 : }
73 :
74 143 : bool IsValid() const { return 0 != GetRegisteredIn(); }
75 : void InsertRefMark( SwPaM & rPam, SwXTextCursor const*const pCursor );
76 : void Invalidate();
77 : protected:
78 : // SwClient
79 : virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew) SAL_OVERRIDE;
80 :
81 : };
82 :
83 90 : void SwXReferenceMark::Impl::Invalidate()
84 : {
85 90 : if (IsValid())
86 : {
87 19 : const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
88 : }
89 90 : m_pDoc = 0;
90 90 : m_pMarkFmt = 0;
91 90 : lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(m_rThis));
92 90 : m_EventListeners.disposeAndClear(ev);
93 90 : }
94 :
95 99 : void SwXReferenceMark::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
96 : {
97 99 : ClientModify(this, pOld, pNew);
98 :
99 99 : if (!GetRegisteredIn()) // removed => dispose
100 : {
101 71 : Invalidate();
102 : }
103 28 : else if (pOld)
104 : {
105 28 : switch (pOld->Which())
106 : {
107 : case RES_REFMARK_DELETED:
108 28 : if (static_cast<const void*>(m_pMarkFmt) ==
109 : static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject)
110 : {
111 19 : Invalidate();
112 : }
113 28 : break;
114 : }
115 : }
116 99 : }
117 :
118 88 : SwXReferenceMark::SwXReferenceMark(
119 : SwDoc *const pDoc, SwFmtRefMark const*const pRefMark)
120 88 : : m_pImpl( new SwXReferenceMark::Impl(*this, pDoc, pRefMark) )
121 : {
122 88 : }
123 :
124 176 : SwXReferenceMark::~SwXReferenceMark()
125 : {
126 176 : }
127 :
128 : SwXReferenceMark *
129 4 : SwXReferenceMark::GetReferenceMark(
130 : SwModify const& /*rUnoCB*/, SwFmtRefMark const& /*rMarkFmt*/)
131 : {
132 : // #i105557#: do not iterate over the registered clients: race condition
133 : // to do this properly requires the SwXReferenceMark to register at the
134 : // SwFmtRefMark directly, not at the unocallback
135 4 : return 0;
136 : }
137 :
138 : SwXReferenceMark *
139 4 : SwXReferenceMark::CreateXReferenceMark(
140 : SwDoc & rDoc, SwFmtRefMark const& rMarkFmt)
141 : {
142 : SwXReferenceMark *const pXMark(
143 4 : GetReferenceMark(*rDoc.GetUnoCallBack(), rMarkFmt) );
144 : return (pXMark)
145 : ? pXMark
146 4 : : new SwXReferenceMark(&rDoc, &rMarkFmt);
147 : }
148 :
149 : namespace
150 : {
151 : class theSwXReferenceMarkUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXReferenceMarkUnoTunnelId > {};
152 : }
153 :
154 7279 : const uno::Sequence< sal_Int8 > & SwXReferenceMark::getUnoTunnelId()
155 : {
156 7279 : return theSwXReferenceMarkUnoTunnelId::get().getSeq();
157 : }
158 :
159 : sal_Int64 SAL_CALL
160 66 : SwXReferenceMark::getSomething(const uno::Sequence< sal_Int8 >& rId)
161 : throw (uno::RuntimeException, std::exception)
162 : {
163 66 : return ::sw::UnoTunnelImpl<SwXReferenceMark>(rId, this);
164 : }
165 :
166 0 : OUString SAL_CALL SwXReferenceMark::getImplementationName()
167 : throw (uno::RuntimeException, std::exception)
168 : {
169 0 : return OUString("SwXReferenceMark");
170 : }
171 :
172 : static char const*const g_ServicesReferenceMark[] =
173 : {
174 : "com.sun.star.text.TextContent",
175 : "com.sun.star.text.ReferenceMark",
176 : };
177 :
178 : static const size_t g_nServicesReferenceMark(
179 : sizeof(g_ServicesReferenceMark)/sizeof(g_ServicesReferenceMark[0]));
180 :
181 : sal_Bool SAL_CALL
182 0 : SwXReferenceMark::supportsService(const OUString& rServiceName)
183 : throw (uno::RuntimeException, std::exception)
184 : {
185 0 : return cppu::supportsService(this, rServiceName);
186 : }
187 :
188 : uno::Sequence< OUString > SAL_CALL
189 0 : SwXReferenceMark::getSupportedServiceNames()
190 : throw (uno::RuntimeException, std::exception)
191 : {
192 : return ::sw::GetSupportedServiceNamesImpl(
193 0 : g_nServicesReferenceMark, g_ServicesReferenceMark);
194 : }
195 :
196 : template<typename T> struct NotContainedIn
197 : {
198 : ::std::vector<T> const& m_rVector;
199 0 : explicit NotContainedIn(::std::vector<T> const& rVector)
200 0 : : m_rVector(rVector) { }
201 0 : bool operator() (T const& rT) {
202 0 : return ::std::find(m_rVector.begin(), m_rVector.end(), rT)
203 0 : == m_rVector.end();
204 : }
205 : };
206 :
207 40 : void SwXReferenceMark::Impl::InsertRefMark(SwPaM& rPam,
208 : SwXTextCursor const*const pCursor)
209 : {
210 : //! in some cases when this function is called the pDoc pointer member may have become
211 : //! invalid/deleted thus we obtain the document pointer from rPaM where it should always
212 : //! be valid.
213 40 : SwDoc *pDoc2 = rPam.GetDoc();
214 :
215 40 : UnoActionContext aCont(pDoc2);
216 80 : SwFmtRefMark aRefMark(m_sMarkName);
217 40 : bool bMark = *rPam.GetPoint() != *rPam.GetMark();
218 :
219 66 : const bool bForceExpandHints( (!bMark && pCursor)
220 58 : ? pCursor->IsAtEndOfMeta() : false );
221 : const SetAttrMode nInsertFlags = (bForceExpandHints)
222 : ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
223 : | nsSetAttrMode::SETATTR_DONTEXPAND)
224 40 : : nsSetAttrMode::SETATTR_DONTEXPAND;
225 :
226 80 : ::std::vector<SwTxtAttr *> oldMarks;
227 40 : if (bMark)
228 : {
229 28 : oldMarks = rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
230 28 : rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK);
231 : }
232 :
233 40 : pDoc2->InsertPoolItem( rPam, aRefMark, nInsertFlags );
234 :
235 40 : if( bMark && *rPam.GetPoint() > *rPam.GetMark())
236 : {
237 14 : rPam.Exchange();
238 : }
239 :
240 : // aRefMark was copied into the document pool; now retrieve real format...
241 40 : SwTxtAttr * pTxtAttr(0);
242 40 : if (bMark)
243 : {
244 : // #i107672#
245 : // ensure that we do not retrieve a different mark at the same position
246 : ::std::vector<SwTxtAttr *> const newMarks(
247 : rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
248 14 : rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
249 : ::std::vector<SwTxtAttr *>::const_iterator const iter(
250 : ::std::find_if(newMarks.begin(), newMarks.end(),
251 14 : NotContainedIn<SwTxtAttr *>(oldMarks)));
252 : OSL_ASSERT(newMarks.end() != iter);
253 14 : if (newMarks.end() != iter)
254 : {
255 14 : pTxtAttr = *iter;
256 14 : }
257 : }
258 : else
259 : {
260 26 : SwTxtNode *pTxtNd = rPam.GetNode()->GetTxtNode();
261 : OSL_ASSERT(pTxtNd);
262 : pTxtAttr = pTxtNd ? rPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
263 26 : rPam.GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_REFMARK) : NULL;
264 : }
265 :
266 40 : if (!pTxtAttr)
267 : {
268 : throw uno::RuntimeException(OUString(
269 0 : "SwXReferenceMark::InsertRefMark(): cannot insert attribute"), 0);
270 : }
271 :
272 40 : m_pMarkFmt = &pTxtAttr->GetRefMark();
273 :
274 80 : pDoc2->GetUnoCallBack()->Add(this);
275 40 : }
276 :
277 : void SAL_CALL
278 38 : SwXReferenceMark::attach(const uno::Reference< text::XTextRange > & xTextRange)
279 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
280 : {
281 38 : SolarMutexGuard aGuard;
282 :
283 38 : if (!m_pImpl->m_bIsDescriptor)
284 : {
285 0 : throw uno::RuntimeException();
286 : }
287 76 : uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
288 38 : SwXTextRange* pRange = 0;
289 38 : OTextCursorHelper* pCursor = 0;
290 38 : if(xRangeTunnel.is())
291 : {
292 38 : pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
293 : pCursor =
294 38 : ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
295 : }
296 : SwDoc *const pDocument =
297 38 : (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
298 38 : if (!pDocument)
299 : {
300 0 : throw lang::IllegalArgumentException();
301 : }
302 :
303 76 : SwUnoInternalPaM aPam(*pDocument);
304 : //das muss jetzt sal_True liefern
305 38 : ::sw::XTextRangeToSwPaM(aPam, xTextRange);
306 38 : m_pImpl->InsertRefMark(aPam, dynamic_cast<SwXTextCursor*>(pCursor));
307 38 : m_pImpl->m_bIsDescriptor = false;
308 76 : m_pImpl->m_pDoc = pDocument;
309 38 : }
310 :
311 : uno::Reference< text::XTextRange > SAL_CALL
312 1 : SwXReferenceMark::getAnchor() throw (uno::RuntimeException, std::exception)
313 : {
314 1 : SolarMutexGuard aGuard;
315 :
316 1 : if (m_pImpl->IsValid())
317 : {
318 : SwFmtRefMark const*const pNewMark =
319 1 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
320 1 : if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
321 : {
322 : SwTxtRefMark const*const pTxtMark =
323 1 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
324 2 : if (pTxtMark &&
325 1 : (&pTxtMark->GetTxtNode().GetNodes() ==
326 1 : &m_pImpl->m_pDoc->GetNodes()))
327 : {
328 1 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
329 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
330 1 : const ::std::auto_ptr<SwPaM> pPam( (pTxtMark->End())
331 0 : ? new SwPaM( rTxtNode, *pTxtMark->End(),
332 0 : rTxtNode, *pTxtMark->GetStart())
333 1 : : new SwPaM( rTxtNode, *pTxtMark->GetStart()) );
334 : SAL_WNODEPRECATED_DECLARATIONS_POP
335 :
336 : return SwXTextRange::CreateXTextRange(
337 1 : *m_pImpl->m_pDoc, *pPam->Start(), pPam->End());
338 : }
339 : }
340 : }
341 0 : return 0;
342 : }
343 :
344 1 : void SAL_CALL SwXReferenceMark::dispose() throw (uno::RuntimeException, std::exception)
345 : {
346 1 : SolarMutexGuard aGuard;
347 1 : if (m_pImpl->IsValid())
348 : {
349 : SwFmtRefMark const*const pNewMark =
350 1 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
351 1 : if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
352 : {
353 : SwTxtRefMark const*const pTxtMark =
354 1 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
355 2 : if (pTxtMark &&
356 1 : (&pTxtMark->GetTxtNode().GetNodes() ==
357 1 : &m_pImpl->m_pDoc->GetNodes()))
358 : {
359 1 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
360 1 : const sal_Int32 nStt = *pTxtMark->GetStart();
361 1 : const sal_Int32 nEnd = pTxtMark->End()
362 0 : ? *pTxtMark->End()
363 1 : : nStt + 1;
364 :
365 1 : SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
366 1 : m_pImpl->m_pDoc->DeleteAndJoin( aPam );
367 : }
368 : }
369 : }
370 0 : else if (m_pImpl->m_bIsDescriptor)
371 : {
372 0 : m_pImpl->Invalidate();
373 1 : }
374 1 : }
375 :
376 2 : void SAL_CALL SwXReferenceMark::addEventListener(
377 : const uno::Reference< lang::XEventListener > & xListener)
378 : throw (uno::RuntimeException, std::exception)
379 : {
380 : // no need to lock here as m_pImpl is const and container threadsafe
381 2 : m_pImpl->m_EventListeners.addInterface(xListener);
382 2 : }
383 :
384 1 : void SAL_CALL SwXReferenceMark::removeEventListener(
385 : const uno::Reference< lang::XEventListener > & xListener)
386 : throw (uno::RuntimeException, std::exception)
387 : {
388 : // no need to lock here as m_pImpl is const and container threadsafe
389 1 : m_pImpl->m_EventListeners.removeInterface(xListener);
390 1 : }
391 :
392 49 : OUString SAL_CALL SwXReferenceMark::getName()
393 : throw (uno::RuntimeException, std::exception)
394 : {
395 49 : SolarMutexGuard aGuard;
396 98 : if (!m_pImpl->IsValid() ||
397 49 : !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName))
398 : {
399 0 : throw uno::RuntimeException();
400 : }
401 49 : return m_pImpl->m_sMarkName;
402 : }
403 :
404 39 : void SAL_CALL SwXReferenceMark::setName(const OUString& rName)
405 : throw (uno::RuntimeException, std::exception)
406 : {
407 39 : SolarMutexGuard aGuard;
408 39 : if (m_pImpl->m_bIsDescriptor)
409 : {
410 37 : m_pImpl->m_sMarkName = rName;
411 : }
412 : else
413 : {
414 4 : if (!m_pImpl->IsValid()
415 2 : || !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName)
416 4 : || m_pImpl->m_pDoc->GetRefMark(rName))
417 : {
418 0 : throw uno::RuntimeException();
419 : }
420 : SwFmtRefMark const*const pCurMark =
421 2 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
422 4 : if ((rName != m_pImpl->m_sMarkName)
423 2 : && pCurMark && (pCurMark == m_pImpl->m_pMarkFmt))
424 : {
425 2 : const UnoActionContext aCont(m_pImpl->m_pDoc);
426 : SwTxtRefMark const*const pTxtMark =
427 2 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
428 4 : if (pTxtMark &&
429 2 : (&pTxtMark->GetTxtNode().GetNodes() ==
430 2 : &m_pImpl->m_pDoc->GetNodes()))
431 : {
432 2 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
433 2 : const sal_Int32 nStt = *pTxtMark->GetStart();
434 2 : const sal_Int32 nEnd = pTxtMark->End()
435 0 : ? *pTxtMark->End()
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, std::exception)
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, std::exception)
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, std::exception)
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, std::exception)
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, std::exception)
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, std::exception)
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, std::exception)
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 139 : 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) SAL_OVERRIDE;
541 :
542 : virtual bool CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
543 : throw (lang::IllegalArgumentException, uno::RuntimeException) SAL_OVERRIDE;
544 :
545 : protected:
546 : virtual const SwStartNode *GetStartNode() const SAL_OVERRIDE;
547 : virtual uno::Reference< text::XTextCursor >
548 : CreateCursor() throw (uno::RuntimeException) SAL_OVERRIDE;
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() SAL_OVERRIDE
558 0 : { OSL_FAIL("ERROR: SwXMetaText::acquire"); }
559 0 : virtual void SAL_CALL release() throw() SAL_OVERRIDE
560 0 : { OSL_FAIL("ERROR: SwXMetaText::release"); }
561 :
562 : // XTypeProvider
563 : virtual uno::Sequence< sal_Int8 > SAL_CALL
564 : getImplementationId() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
565 :
566 : // XText
567 : virtual uno::Reference< text::XTextCursor > SAL_CALL
568 : createTextCursor() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
569 : virtual uno::Reference< text::XTextCursor > SAL_CALL
570 : createTextCursorByRange(
571 : const uno::Reference< text::XTextRange > & xTextPosition)
572 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
573 :
574 91 : SwXMeta & GetXMeta() { return m_rMeta; }
575 :
576 : };
577 :
578 139 : SwXMetaText::SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta)
579 : : SwXText(&rDoc, CURSOR_META)
580 139 : , m_rMeta(rMeta)
581 : {
582 139 : }
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 : sal_Int32 nMetaStart;
614 : sal_Int32 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, std::exception)
629 : {
630 0 : return css::uno::Sequence<sal_Int8>();
631 : }
632 :
633 : // XText
634 : uno::Reference< text::XTextCursor > SAL_CALL
635 15 : SwXMetaText::createTextCursor() throw (uno::RuntimeException, std::exception)
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, std::exception)
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 278 : 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 139 : 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 139 : , m_Text(rDoc, rThis)
685 : {
686 139 : }
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) SAL_OVERRIDE;
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 42 : SwXMeta::SwXMeta(SwDoc *const pDoc, ::sw::Meta *const pMeta,
725 : uno::Reference<text::XText> const& xParentText,
726 : TextRangeList_t const*const pPortions)
727 42 : : m_pImpl( new SwXMeta::Impl(*this, *pDoc, pMeta, xParentText, pPortions) )
728 : {
729 42 : }
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 228 : SwXMeta::~SwXMeta()
737 : {
738 228 : }
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 199 : 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 199 : return xMeta;
769 : }
770 :
771 : // create new SwXMeta
772 42 : SwTxtNode * const pTxtNode( rMeta.GetTxtNode() );
773 : OSL_ENSURE(pTxtNode, "CreateXMeta: no text node?");
774 42 : if (!pTxtNode) { return 0; }
775 84 : uno::Reference<text::XText> xParentText(i_xParent);
776 42 : if (!xParentText.is())
777 : {
778 6 : SwTxtMeta * const pTxtAttr( rMeta.GetTxtAttr() );
779 : OSL_ENSURE(pTxtAttr, "CreateXMeta: no text attr?");
780 6 : if (!pTxtAttr) { return 0; }
781 6 : const SwPosition aPos(*pTxtNode, *pTxtAttr->GetStart());
782 6 : xParentText.set( ::sw::CreateParentXText(*pTxtNode->GetDoc(), aPos) );
783 : }
784 42 : if (!xParentText.is()) { return 0; }
785 42 : 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 24 : : new SwXMetaField(pTxtNode->GetDoc(), &rMeta, xParentText,
789 102 : pPortions.release()));
790 : // this is why the constructor is private: need to acquire pXMeta here
791 42 : xMeta.set(pXMeta);
792 : // in order to initialize the weak pointer cache in the core object
793 42 : rMeta.SetXMeta(xMeta);
794 283 : return xMeta;
795 : }
796 : SAL_WNODEPRECATED_DECLARATIONS_POP
797 :
798 705 : bool SwXMeta::SetContentRange(
799 : SwTxtNode *& rpNode, sal_Int32 & rStart, sal_Int32 & 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->End();
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 : sal_Int32 nMetaStart;
825 : sal_Int32 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 sal_Int32 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 sal_Int32 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 7809 : const uno::Sequence< sal_Int8 > & SwXMeta::getUnoTunnelId()
888 : {
889 7809 : 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, std::exception)
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, std::exception)
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, std::exception)
919 : {
920 10 : return cppu::supportsService(this, rServiceName);
921 : }
922 :
923 : uno::Sequence< OUString > SAL_CALL
924 10 : SwXMeta::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
925 : {
926 10 : return ::sw::GetSupportedServiceNamesImpl(g_nServicesMeta, g_ServicesMeta);
927 : }
928 :
929 : // XComponent
930 : void SAL_CALL
931 0 : SwXMeta::addEventListener(
932 : uno::Reference< lang::XEventListener> const & xListener )
933 : throw (uno::RuntimeException, std::exception)
934 : {
935 : // no need to lock here as m_pImpl is const and container threadsafe
936 0 : m_pImpl->m_EventListeners.addInterface(xListener);
937 0 : }
938 :
939 : void SAL_CALL
940 0 : SwXMeta::removeEventListener(
941 : uno::Reference< lang::XEventListener> const & xListener )
942 : throw (uno::RuntimeException, std::exception)
943 : {
944 : // no need to lock here as m_pImpl is const and container threadsafe
945 0 : m_pImpl->m_EventListeners.removeInterface(xListener);
946 0 : }
947 :
948 : void SAL_CALL
949 1 : SwXMeta::dispose() throw (uno::RuntimeException, std::exception)
950 : {
951 1 : SolarMutexGuard g;
952 :
953 1 : if (m_pImpl->m_bIsDescriptor)
954 : {
955 0 : m_pImpl->m_pTextPortions.reset();
956 0 : lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(*this));
957 0 : m_pImpl->m_EventListeners.disposeAndClear(ev);
958 0 : m_pImpl->m_bIsDisposed = true;
959 0 : m_pImpl->m_Text.Invalidate();
960 : }
961 1 : else if (!m_pImpl->m_bIsDisposed)
962 : {
963 : SwTxtNode * pTxtNode;
964 : sal_Int32 nMetaStart;
965 : sal_Int32 nMetaEnd;
966 1 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
967 : OSL_ENSURE(bSuccess, "no pam?");
968 1 : if (bSuccess)
969 : {
970 : // -1 because of CH_TXTATR
971 1 : SwPaM aPam( *pTxtNode, nMetaStart - 1, *pTxtNode, nMetaEnd );
972 1 : SwDoc * const pDoc( pTxtNode->GetDoc() );
973 1 : pDoc->DeleteAndJoin( aPam );
974 :
975 : // removal should call Modify and do the dispose
976 1 : OSL_ENSURE(m_pImpl->m_bIsDisposed, "zombie meta");
977 : }
978 1 : }
979 1 : }
980 :
981 : void SAL_CALL
982 97 : SwXMeta::AttachImpl(const uno::Reference< text::XTextRange > & i_xTextRange,
983 : const sal_uInt16 i_nWhich)
984 : throw (lang::IllegalArgumentException, uno::RuntimeException)
985 : {
986 97 : SolarMutexGuard g;
987 :
988 97 : if (m_pImpl->m_bIsDisposed)
989 : {
990 0 : throw lang::DisposedException();
991 : }
992 97 : if (!m_pImpl->m_bIsDescriptor)
993 : {
994 : throw uno::RuntimeException(
995 : OUString("SwXMeta::attach(): already attached"),
996 0 : static_cast< ::cppu::OWeakObject* >(this));
997 : }
998 :
999 194 : uno::Reference<lang::XUnoTunnel> xRangeTunnel(i_xTextRange, uno::UNO_QUERY);
1000 97 : if (!xRangeTunnel.is())
1001 : {
1002 : throw lang::IllegalArgumentException(
1003 : OUString("SwXMeta::attach(): argument is no XUnoTunnel"),
1004 0 : static_cast< ::cppu::OWeakObject* >(this), 0);
1005 : }
1006 : SwXTextRange *const pRange(
1007 97 : ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel));
1008 : OTextCursorHelper *const pCursor( (pRange) ? 0 :
1009 97 : ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel));
1010 97 : if (!pRange && !pCursor)
1011 : {
1012 : throw lang::IllegalArgumentException(
1013 : OUString("SwXMeta::attach(): argument not supported type"),
1014 0 : static_cast< ::cppu::OWeakObject* >(this), 0);
1015 : }
1016 :
1017 : SwDoc * const pDoc(
1018 97 : pRange ? pRange->GetDoc() : pCursor->GetDoc());
1019 97 : if (!pDoc)
1020 : {
1021 : throw lang::IllegalArgumentException(
1022 : OUString("SwXMeta::attach(): argument has no SwDoc"),
1023 0 : static_cast< ::cppu::OWeakObject* >(this), 0);
1024 : }
1025 :
1026 194 : SwUnoInternalPaM aPam(*pDoc);
1027 97 : ::sw::XTextRangeToSwPaM(aPam, i_xTextRange);
1028 :
1029 194 : UnoActionContext aContext(pDoc);
1030 :
1031 : SwXTextCursor const*const pTextCursor(
1032 97 : dynamic_cast<SwXTextCursor*>(pCursor));
1033 : const bool bForceExpandHints((pTextCursor)
1034 97 : ? pTextCursor->IsAtEndOfMeta() : false);
1035 : const SetAttrMode nInsertFlags( (bForceExpandHints)
1036 : ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
1037 : | nsSetAttrMode::SETATTR_DONTEXPAND)
1038 97 : : nsSetAttrMode::SETATTR_DONTEXPAND );
1039 :
1040 : const ::boost::shared_ptr< ::sw::Meta> pMeta( (RES_TXTATR_META == i_nWhich)
1041 0 : ? ::boost::shared_ptr< ::sw::Meta>( new ::sw::Meta() )
1042 : : ::boost::shared_ptr< ::sw::Meta>(
1043 194 : pDoc->GetMetaFieldManager().makeMetaField()) );
1044 194 : SwFmtMeta meta(pMeta, i_nWhich); // this is cloned by Insert!
1045 97 : const bool bSuccess( pDoc->InsertPoolItem( aPam, meta, nInsertFlags ) );
1046 97 : SwTxtAttr * const pTxtAttr( pMeta->GetTxtAttr() );
1047 97 : if (!bSuccess)
1048 : {
1049 : throw lang::IllegalArgumentException(
1050 : OUString("SwXMeta::attach(): cannot create meta: range invalid?"),
1051 2 : static_cast< ::cppu::OWeakObject* >(this), 1);
1052 : }
1053 95 : if (!pTxtAttr)
1054 : {
1055 : OSL_FAIL("meta inserted, but has no text attribute?");
1056 : throw uno::RuntimeException(
1057 : OUString("SwXMeta::attach(): cannot create meta"),
1058 0 : static_cast< ::cppu::OWeakObject* >(this));
1059 : }
1060 :
1061 95 : pMeta->Add(m_pImpl.get());
1062 95 : pMeta->SetXMeta(uno::Reference<rdf::XMetadatable>(this));
1063 :
1064 95 : m_pImpl->m_xParentText = ::sw::CreateParentXText(*pDoc, *aPam.GetPoint());
1065 :
1066 192 : m_pImpl->m_bIsDescriptor = false;
1067 95 : }
1068 :
1069 : // XTextContent
1070 : void SAL_CALL
1071 71 : SwXMeta::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
1072 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
1073 : {
1074 71 : return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_META);
1075 : }
1076 :
1077 : uno::Reference< text::XTextRange > SAL_CALL
1078 23 : SwXMeta::getAnchor() throw (uno::RuntimeException, std::exception)
1079 : {
1080 23 : SolarMutexGuard g;
1081 :
1082 23 : if (m_pImpl->m_bIsDisposed)
1083 : {
1084 0 : throw lang::DisposedException();
1085 : }
1086 23 : if (m_pImpl->m_bIsDescriptor)
1087 : {
1088 : throw uno::RuntimeException(
1089 : OUString("SwXMeta::getAnchor(): not inserted"),
1090 0 : static_cast< ::cppu::OWeakObject* >(this));
1091 : }
1092 :
1093 : SwTxtNode * pTxtNode;
1094 : sal_Int32 nMetaStart;
1095 : sal_Int32 nMetaEnd;
1096 23 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
1097 : OSL_ENSURE(bSuccess, "no pam?");
1098 23 : if (!bSuccess)
1099 : {
1100 : throw lang::DisposedException(
1101 : OUString("SwXMeta::getAnchor(): not attached"),
1102 0 : static_cast< ::cppu::OWeakObject* >(this));
1103 : }
1104 :
1105 46 : const SwPosition start(*pTxtNode, nMetaStart - 1); // -1 due to CH_TXTATR
1106 46 : const SwPosition end(*pTxtNode, nMetaEnd);
1107 46 : return SwXTextRange::CreateXTextRange(*pTxtNode->GetDoc(), start, &end);
1108 : }
1109 :
1110 : // XTextRange
1111 : uno::Reference< text::XText > SAL_CALL
1112 1 : SwXMeta::getText() throw (uno::RuntimeException, std::exception)
1113 : {
1114 1 : SolarMutexGuard g;
1115 1 : return this;
1116 : }
1117 :
1118 : uno::Reference< text::XTextRange > SAL_CALL
1119 34 : SwXMeta::getStart() throw (uno::RuntimeException, std::exception)
1120 : {
1121 34 : SolarMutexGuard g;
1122 34 : return m_pImpl->m_Text.getStart();
1123 : }
1124 :
1125 : uno::Reference< text::XTextRange > SAL_CALL
1126 31 : SwXMeta::getEnd() throw (uno::RuntimeException, std::exception)
1127 : {
1128 31 : SolarMutexGuard g;
1129 31 : return m_pImpl->m_Text.getEnd();
1130 : }
1131 :
1132 : OUString SAL_CALL
1133 40 : SwXMeta::getString() throw (uno::RuntimeException, std::exception)
1134 : {
1135 40 : SolarMutexGuard g;
1136 40 : return m_pImpl->m_Text.getString();
1137 : }
1138 :
1139 : void SAL_CALL
1140 27 : SwXMeta::setString(const OUString& rString) throw (uno::RuntimeException, std::exception)
1141 : {
1142 27 : SolarMutexGuard g;
1143 27 : return m_pImpl->m_Text.setString(rString);
1144 : }
1145 :
1146 : // XSimpleText
1147 : uno::Reference< text::XTextCursor > SAL_CALL
1148 15 : SwXMeta::createTextCursor() throw (uno::RuntimeException, std::exception)
1149 : {
1150 15 : SolarMutexGuard g;
1151 15 : return m_pImpl->m_Text.createTextCursor();
1152 : }
1153 :
1154 : uno::Reference< text::XTextCursor > SAL_CALL
1155 3 : SwXMeta::createTextCursorByRange(
1156 : const uno::Reference<text::XTextRange> & xTextPosition)
1157 : throw (uno::RuntimeException, std::exception)
1158 : {
1159 3 : SolarMutexGuard g;
1160 3 : return m_pImpl->m_Text.createTextCursorByRange(xTextPosition);
1161 : }
1162 :
1163 : void SAL_CALL
1164 4 : SwXMeta::insertString(const uno::Reference<text::XTextRange> & xRange,
1165 : const OUString& rString, sal_Bool bAbsorb)
1166 : throw (uno::RuntimeException, std::exception)
1167 : {
1168 4 : SolarMutexGuard g;
1169 4 : return m_pImpl->m_Text.insertString(xRange, rString, bAbsorb);
1170 : }
1171 :
1172 : void SAL_CALL
1173 4 : SwXMeta::insertControlCharacter(const uno::Reference<text::XTextRange> & xRange,
1174 : sal_Int16 nControlCharacter, sal_Bool bAbsorb)
1175 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
1176 : {
1177 4 : SolarMutexGuard g;
1178 4 : return m_pImpl->m_Text.insertControlCharacter(xRange, nControlCharacter,
1179 8 : bAbsorb);
1180 : }
1181 :
1182 : // XText
1183 : void SAL_CALL
1184 43 : SwXMeta::insertTextContent( const uno::Reference<text::XTextRange> & xRange,
1185 : const uno::Reference<text::XTextContent> & xContent, sal_Bool bAbsorb)
1186 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
1187 : {
1188 43 : SolarMutexGuard g;
1189 43 : return m_pImpl->m_Text.insertTextContent(xRange, xContent, bAbsorb);
1190 : }
1191 :
1192 : void SAL_CALL
1193 2 : SwXMeta::removeTextContent(
1194 : const uno::Reference< text::XTextContent > & xContent)
1195 : throw (container::NoSuchElementException, uno::RuntimeException, std::exception)
1196 : {
1197 2 : SolarMutexGuard g;
1198 2 : return m_pImpl->m_Text.removeTextContent(xContent);
1199 : }
1200 :
1201 : // XChild
1202 : uno::Reference< uno::XInterface > SAL_CALL
1203 6 : SwXMeta::getParent() throw (uno::RuntimeException, std::exception)
1204 : {
1205 6 : SolarMutexGuard g;
1206 : SwTxtNode * pTxtNode;
1207 : sal_Int32 nMetaStart;
1208 : sal_Int32 nMetaEnd;
1209 6 : bool const bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
1210 : OSL_ENSURE(bSuccess, "no pam?");
1211 6 : if (!bSuccess) { throw lang::DisposedException(); }
1212 : // in order to prevent getting this meta, subtract 1 from nMetaStart;
1213 : // so we get the index of the dummy character, and we exclude it
1214 : // by calling GetTxtAttrAt(_, _, PARENT) in GetNestedTextContent
1215 : uno::Reference<text::XTextContent> const xRet(
1216 : SwUnoCursorHelper::GetNestedTextContent(*pTxtNode, nMetaStart - 1,
1217 12 : true) );
1218 12 : return xRet;
1219 : }
1220 :
1221 : void SAL_CALL
1222 1 : SwXMeta::setParent(uno::Reference< uno::XInterface > const& /*xParent*/)
1223 : throw (uno::RuntimeException, lang::NoSupportException, std::exception)
1224 : {
1225 1 : throw lang::NoSupportException("setting parent not supported", *this);
1226 : }
1227 :
1228 : // XElementAccess
1229 : uno::Type SAL_CALL
1230 0 : SwXMeta::getElementType() throw (uno::RuntimeException, std::exception)
1231 : {
1232 0 : return cppu::UnoType<text::XTextRange>::get();
1233 : }
1234 :
1235 : sal_Bool SAL_CALL
1236 0 : SwXMeta::hasElements() throw (uno::RuntimeException, std::exception)
1237 : {
1238 0 : SolarMutexGuard g;
1239 :
1240 0 : return m_pImpl->GetRegisteredIn() ? sal_True : sal_False;
1241 : }
1242 :
1243 : // XEnumerationAccess
1244 : uno::Reference< container::XEnumeration > SAL_CALL
1245 176 : SwXMeta::createEnumeration() throw (uno::RuntimeException, std::exception)
1246 : {
1247 176 : SolarMutexGuard g;
1248 :
1249 176 : if (m_pImpl->m_bIsDisposed)
1250 : {
1251 0 : throw lang::DisposedException();
1252 : }
1253 176 : if (m_pImpl->m_bIsDescriptor)
1254 : {
1255 : throw uno::RuntimeException(
1256 : OUString("createEnumeration(): not inserted"),
1257 0 : static_cast< ::cppu::OWeakObject* >(this));
1258 : }
1259 :
1260 : SwTxtNode * pTxtNode;
1261 : sal_Int32 nMetaStart;
1262 : sal_Int32 nMetaEnd;
1263 176 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
1264 : OSL_ENSURE(bSuccess, "no pam?");
1265 176 : if (!bSuccess)
1266 0 : throw lang::DisposedException();
1267 :
1268 352 : SwPaM aPam(*pTxtNode, nMetaStart);
1269 :
1270 176 : if (!m_pImpl->m_pTextPortions.get())
1271 : {
1272 : return new SwXTextPortionEnumeration(
1273 1 : aPam, GetParentText(), nMetaStart, nMetaEnd);
1274 : }
1275 : else // cached!
1276 : {
1277 175 : return new SwXTextPortionEnumeration(aPam, *m_pImpl->m_pTextPortions);
1278 176 : }
1279 : }
1280 :
1281 : // MetadatableMixin
1282 533 : ::sfx2::Metadatable* SwXMeta::GetCoreObject()
1283 : {
1284 533 : return const_cast< ::sw::Meta * >(m_pImpl->GetMeta());
1285 : }
1286 :
1287 131 : uno::Reference<frame::XModel> SwXMeta::GetModel()
1288 : {
1289 131 : ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
1290 131 : if (pMeta)
1291 : {
1292 131 : SwTxtNode const * const pTxtNode( pMeta->GetTxtNode() );
1293 131 : if (pTxtNode)
1294 : {
1295 131 : SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
1296 131 : return (pShell) ? pShell->GetModel() : 0;
1297 : }
1298 : }
1299 0 : return 0;
1300 : }
1301 :
1302 : /******************************************************************
1303 : * SwXMetaField
1304 : ******************************************************************/
1305 47 : inline const ::sw::MetaField * SwXMeta::Impl::GetMetaField() const
1306 : {
1307 47 : return static_cast< const ::sw::MetaField * >(GetRegisteredIn());
1308 : }
1309 :
1310 24 : SwXMetaField::SwXMetaField(SwDoc *const pDoc, ::sw::Meta *const pMeta,
1311 : uno::Reference<text::XText> const& xParentText,
1312 : TextRangeList_t const*const pPortions)
1313 24 : : SwXMetaField_Base(pDoc, pMeta, xParentText, pPortions)
1314 : {
1315 : OSL_ENSURE(pMeta && dynamic_cast< ::sw::MetaField* >(pMeta),
1316 : "SwXMetaField created for wrong hint!");
1317 24 : }
1318 :
1319 26 : SwXMetaField::SwXMetaField(SwDoc *const pDoc)
1320 26 : : SwXMetaField_Base(pDoc)
1321 : {
1322 26 : }
1323 :
1324 100 : SwXMetaField::~SwXMetaField()
1325 : {
1326 100 : }
1327 :
1328 : // XServiceInfo
1329 : OUString SAL_CALL
1330 0 : SwXMetaField::getImplementationName() throw (uno::RuntimeException, std::exception)
1331 : {
1332 0 : return OUString("SwXMetaField");
1333 : }
1334 :
1335 : static char const*const g_ServicesMetaField[] =
1336 : {
1337 : "com.sun.star.text.TextContent",
1338 : "com.sun.star.text.TextField",
1339 : "com.sun.star.text.textfield.MetadataField",
1340 : };
1341 :
1342 : static const size_t g_nServicesMetaField(
1343 : sizeof(g_ServicesMetaField)/sizeof(g_ServicesMetaField[0]));
1344 :
1345 : sal_Bool SAL_CALL
1346 20 : SwXMetaField::supportsService(const OUString& rServiceName)
1347 : throw (uno::RuntimeException, std::exception)
1348 : {
1349 20 : return cppu::supportsService(this, rServiceName);
1350 : }
1351 :
1352 : uno::Sequence< OUString > SAL_CALL
1353 40 : SwXMetaField::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
1354 : {
1355 : return ::sw::GetSupportedServiceNamesImpl(
1356 40 : g_nServicesMetaField, g_ServicesMetaField);
1357 : }
1358 :
1359 : // XComponent
1360 : void SAL_CALL
1361 0 : SwXMetaField::addEventListener(
1362 : uno::Reference< lang::XEventListener> const & xListener )
1363 : throw (uno::RuntimeException, std::exception)
1364 : {
1365 0 : return SwXMeta::addEventListener(xListener);
1366 : }
1367 :
1368 : void SAL_CALL
1369 0 : SwXMetaField::removeEventListener(
1370 : uno::Reference< lang::XEventListener> const & xListener )
1371 : throw (uno::RuntimeException, std::exception)
1372 : {
1373 0 : return SwXMeta::removeEventListener(xListener);
1374 : }
1375 :
1376 : void SAL_CALL
1377 0 : SwXMetaField::dispose() throw (uno::RuntimeException, std::exception)
1378 : {
1379 0 : return SwXMeta::dispose();
1380 : }
1381 :
1382 : // XTextContent
1383 : void SAL_CALL
1384 26 : SwXMetaField::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
1385 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
1386 : {
1387 26 : return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_METAFIELD);
1388 : }
1389 :
1390 : uno::Reference< text::XTextRange > SAL_CALL
1391 20 : SwXMetaField::getAnchor() throw (uno::RuntimeException, std::exception)
1392 : {
1393 20 : return SwXMeta::getAnchor();
1394 : }
1395 :
1396 : // XPropertySet
1397 : uno::Reference< beans::XPropertySetInfo > SAL_CALL
1398 17 : SwXMetaField::getPropertySetInfo() throw (uno::RuntimeException, std::exception)
1399 : {
1400 17 : SolarMutexGuard g;
1401 :
1402 : static uno::Reference< beans::XPropertySetInfo > xRef(
1403 : aSwMapProvider.GetPropertySet(PROPERTY_MAP_METAFIELD)
1404 17 : ->getPropertySetInfo() );
1405 17 : return xRef;
1406 : }
1407 :
1408 : void SAL_CALL
1409 10 : SwXMetaField::setPropertyValue(
1410 : const OUString& rPropertyName, const uno::Any& rValue)
1411 : throw (beans::UnknownPropertyException, beans::PropertyVetoException,
1412 : lang::IllegalArgumentException, lang::WrappedTargetException,
1413 : uno::RuntimeException, std::exception)
1414 : {
1415 10 : SolarMutexGuard g;
1416 :
1417 : ::sw::MetaField * const pMeta(
1418 10 : const_cast< ::sw::MetaField * >(m_pImpl->GetMetaField()) );
1419 10 : if (!pMeta)
1420 0 : throw lang::DisposedException();
1421 :
1422 10 : if ( rPropertyName == "NumberFormat" )
1423 : {
1424 5 : sal_Int32 nNumberFormat(0);
1425 5 : if (rValue >>= nNumberFormat)
1426 : {
1427 5 : pMeta->SetNumberFormat(static_cast<sal_uInt32>(nNumberFormat));
1428 : }
1429 : }
1430 5 : else if ( rPropertyName == "IsFixedLanguage" )
1431 : {
1432 5 : bool b(false);
1433 5 : if (rValue >>= b)
1434 : {
1435 5 : pMeta->SetIsFixedLanguage(b);
1436 : }
1437 : }
1438 : else
1439 : {
1440 0 : throw beans::UnknownPropertyException();
1441 10 : }
1442 10 : }
1443 :
1444 : uno::Any SAL_CALL
1445 37 : SwXMetaField::getPropertyValue(const OUString& rPropertyName)
1446 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1447 : uno::RuntimeException, std::exception)
1448 : {
1449 37 : SolarMutexGuard g;
1450 :
1451 37 : ::sw::MetaField const * const pMeta( m_pImpl->GetMetaField() );
1452 37 : if (!pMeta)
1453 0 : throw lang::DisposedException();
1454 :
1455 37 : uno::Any any;
1456 :
1457 37 : if ( rPropertyName == "NumberFormat" )
1458 : {
1459 24 : const OUString text( getPresentation(sal_False) );
1460 24 : any <<= static_cast<sal_Int32>(pMeta->GetNumberFormat(text));
1461 : }
1462 13 : else if ( rPropertyName == "IsFixedLanguage" )
1463 : {
1464 3 : any <<= pMeta->IsFixedLanguage();
1465 : }
1466 : else
1467 : {
1468 10 : throw beans::UnknownPropertyException();
1469 : }
1470 :
1471 37 : return any;
1472 : }
1473 :
1474 : void SAL_CALL
1475 0 : SwXMetaField::addPropertyChangeListener(
1476 : const OUString& /*rPropertyName*/,
1477 : const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1478 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1479 : uno::RuntimeException, std::exception)
1480 : {
1481 : OSL_FAIL("SwXMetaField::addPropertyChangeListener(): not implemented");
1482 0 : }
1483 :
1484 : void SAL_CALL
1485 0 : SwXMetaField::removePropertyChangeListener(
1486 : const OUString& /*rPropertyName*/,
1487 : const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1488 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1489 : uno::RuntimeException, std::exception)
1490 : {
1491 : OSL_FAIL("SwXMetaField::removePropertyChangeListener(): not implemented");
1492 0 : }
1493 :
1494 : void SAL_CALL
1495 0 : SwXMetaField::addVetoableChangeListener(
1496 : const OUString& /*rPropertyName*/,
1497 : const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1498 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1499 : uno::RuntimeException, std::exception)
1500 : {
1501 : OSL_FAIL("SwXMetaField::addVetoableChangeListener(): not implemented");
1502 0 : }
1503 :
1504 : void SAL_CALL
1505 0 : SwXMetaField::removeVetoableChangeListener(
1506 : const OUString& /*rPropertyName*/,
1507 : const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1508 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1509 : uno::RuntimeException, std::exception)
1510 : {
1511 : OSL_FAIL("SwXMetaField::removeVetoableChangeListener(): not implemented");
1512 0 : }
1513 :
1514 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
1515 : #include <com/sun/star/rdf/Statement.hpp>
1516 : #include <com/sun/star/rdf/URI.hpp>
1517 : #include <com/sun/star/rdf/URIs.hpp>
1518 : #include <com/sun/star/rdf/XLiteral.hpp>
1519 : #include <com/sun/star/rdf/XRepositorySupplier.hpp>
1520 : #include <comphelper/processfactory.hxx>
1521 :
1522 : static uno::Reference<rdf::XURI> const&
1523 110 : lcl_getURI(const bool bPrefix)
1524 : {
1525 : static uno::Reference< uno::XComponentContext > xContext(
1526 110 : ::comphelper::getProcessComponentContext());
1527 : static uno::Reference< rdf::XURI > xOdfPrefix(
1528 : rdf::URI::createKnown(xContext, rdf::URIs::ODF_PREFIX),
1529 110 : uno::UNO_SET_THROW);
1530 : static uno::Reference< rdf::XURI > xOdfSuffix(
1531 : rdf::URI::createKnown(xContext, rdf::URIs::ODF_SUFFIX),
1532 110 : uno::UNO_SET_THROW);
1533 110 : return (bPrefix) ? xOdfPrefix : xOdfSuffix;
1534 : }
1535 :
1536 : static OUString
1537 110 : lcl_getPrefixOrSuffix(
1538 : uno::Reference<rdf::XRepository> const & xRepository,
1539 : uno::Reference<rdf::XResource> const & xMetaField,
1540 : uno::Reference<rdf::XURI> const & xPredicate)
1541 : {
1542 : const uno::Reference<container::XEnumeration> xEnum(
1543 110 : xRepository->getStatements(xMetaField, xPredicate, 0),
1544 110 : uno::UNO_SET_THROW);
1545 220 : while (xEnum->hasMoreElements()) {
1546 68 : rdf::Statement stmt;
1547 68 : if (!(xEnum->nextElement() >>= stmt)) {
1548 0 : throw uno::RuntimeException();
1549 : }
1550 : const uno::Reference<rdf::XLiteral> xObject(stmt.Object,
1551 68 : uno::UNO_QUERY);
1552 68 : if (!xObject.is()) continue;
1553 68 : if (xEnum->hasMoreElements()) {
1554 : OSL_TRACE("ignoring other odf:Prefix/odf:Suffix statements");
1555 : }
1556 68 : return xObject->getValue();
1557 0 : }
1558 42 : return OUString();
1559 : }
1560 :
1561 : void
1562 75 : getPrefixAndSuffix(
1563 : const uno::Reference<frame::XModel>& xModel,
1564 : const uno::Reference<rdf::XMetadatable>& xMetaField,
1565 : OUString *const o_pPrefix, OUString *const o_pSuffix)
1566 : {
1567 : try {
1568 : const uno::Reference<rdf::XRepositorySupplier> xRS(
1569 75 : xModel, uno::UNO_QUERY_THROW);
1570 : const uno::Reference<rdf::XRepository> xRepo(
1571 150 : xRS->getRDFRepository(), uno::UNO_SET_THROW);
1572 : const uno::Reference<rdf::XResource> xMeta(
1573 150 : xMetaField, uno::UNO_QUERY_THROW);
1574 75 : if (o_pPrefix)
1575 : {
1576 55 : *o_pPrefix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(true));
1577 : }
1578 75 : if (o_pSuffix)
1579 : {
1580 55 : *o_pSuffix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(false));
1581 75 : }
1582 0 : } catch (uno::RuntimeException &) {
1583 0 : throw;
1584 0 : } catch (const uno::Exception & e) {
1585 : throw lang::WrappedTargetRuntimeException(
1586 : OUString("getPrefixAndSuffix: exception"),
1587 0 : 0, uno::makeAny(e));
1588 : }
1589 75 : }
1590 :
1591 : // XTextField
1592 : OUString SAL_CALL
1593 35 : SwXMetaField::getPresentation(sal_Bool bShowCommand)
1594 : throw (uno::RuntimeException, std::exception)
1595 : {
1596 35 : SolarMutexGuard g;
1597 :
1598 35 : if (bShowCommand)
1599 : {
1600 : //FIXME ?
1601 0 : return OUString();
1602 : }
1603 : else
1604 : {
1605 : // getString should check if this is invalid
1606 35 : const OUString content( this->getString() );
1607 70 : OUString prefix;
1608 70 : OUString suffix;
1609 35 : getPrefixAndSuffix(GetModel(), this, &prefix, &suffix);
1610 70 : return prefix + content + suffix;
1611 35 : }
1612 : }
1613 :
1614 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|