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