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 288 : 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 SwFmtRefMark * m_pMarkFmt;
57 : OUString m_sMarkName;
58 :
59 144 : Impl( SwDoc *const pDoc, SwFmtRefMark *const pRefMark)
60 : : SwClient(pRefMark)
61 : , m_EventListeners(m_Mutex)
62 144 : , m_bIsDescriptor(0 == pRefMark)
63 : , m_pDoc(pDoc)
64 288 : , m_pMarkFmt(pRefMark)
65 : {
66 144 : if (pRefMark)
67 : {
68 68 : m_sMarkName = pRefMark->GetRefName();
69 : }
70 144 : }
71 :
72 254 : 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 148 : void SwXReferenceMark::Impl::Invalidate()
82 : {
83 148 : if (IsValid())
84 : {
85 0 : const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
86 : }
87 148 : m_pDoc = 0;
88 148 : m_pMarkFmt = 0;
89 148 : uno::Reference<uno::XInterface> const xThis(m_wThis);
90 148 : if (!xThis.is())
91 : { // fdo#72695: if UNO object is already dead, don't revive it with event
92 148 : return;
93 : }
94 296 : lang::EventObject const ev(xThis);
95 296 : m_EventListeners.disposeAndClear(ev);
96 : }
97 :
98 148 : void SwXReferenceMark::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
99 : {
100 148 : ClientModify(this, pOld, pNew);
101 :
102 148 : if (!GetRegisteredIn()) // removed => dispose
103 : {
104 148 : Invalidate();
105 : }
106 148 : }
107 :
108 144 : SwXReferenceMark::SwXReferenceMark(
109 : SwDoc *const pDoc, SwFmtRefMark *const pRefMark)
110 144 : : m_pImpl( new SwXReferenceMark::Impl(pDoc, pRefMark) )
111 : {
112 144 : }
113 :
114 288 : SwXReferenceMark::~SwXReferenceMark()
115 : {
116 288 : }
117 :
118 : uno::Reference<text::XTextContent>
119 176 : SwXReferenceMark::CreateXReferenceMark(
120 : SwDoc & rDoc, SwFmtRefMark *const pMarkFmt)
121 : {
122 : // i#105557: do not iterate over the registered clients: race condition
123 176 : uno::Reference<text::XTextContent> xMark;
124 176 : if (pMarkFmt)
125 : {
126 100 : xMark = pMarkFmt->GetXRefMark();
127 : }
128 176 : if (!xMark.is())
129 : {
130 144 : SwXReferenceMark *const pMark(new SwXReferenceMark(&rDoc, pMarkFmt));
131 144 : xMark.set(pMark);
132 144 : if (pMarkFmt)
133 : {
134 68 : pMarkFmt->SetXRefMark(xMark);
135 : }
136 : // need a permanent Reference to initialize m_wThis
137 144 : pMark->m_pImpl->m_wThis = xMark;
138 : }
139 176 : return xMark;
140 : }
141 :
142 : namespace
143 : {
144 : class theSwXReferenceMarkUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXReferenceMarkUnoTunnelId > {};
145 : }
146 :
147 18388 : const uno::Sequence< sal_Int8 > & SwXReferenceMark::getUnoTunnelId()
148 : {
149 18388 : return theSwXReferenceMarkUnoTunnelId::get().getSeq();
150 : }
151 :
152 : sal_Int64 SAL_CALL
153 132 : SwXReferenceMark::getSomething(const uno::Sequence< sal_Int8 >& rId)
154 : throw (uno::RuntimeException, std::exception)
155 : {
156 132 : 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 80 : 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 80 : SwDoc *pDoc2 = rPam.GetDoc();
207 :
208 80 : UnoActionContext aCont(pDoc2);
209 160 : SwFmtRefMark aRefMark(m_sMarkName);
210 80 : bool bMark = *rPam.GetPoint() != *rPam.GetMark();
211 :
212 80 : const bool bForceExpandHints( !bMark && pCursor && pCursor->IsAtEndOfMeta() );
213 : const SetAttrMode nInsertFlags = (bForceExpandHints)
214 : ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
215 : | nsSetAttrMode::SETATTR_DONTEXPAND)
216 80 : : nsSetAttrMode::SETATTR_DONTEXPAND;
217 :
218 160 : ::std::vector<SwTxtAttr *> oldMarks;
219 80 : if (bMark)
220 : {
221 56 : oldMarks = rPam.GetNode().GetTxtNode()->GetTxtAttrsAt(
222 56 : rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK);
223 : }
224 :
225 80 : pDoc2->getIDocumentContentOperations().InsertPoolItem( rPam, aRefMark, nInsertFlags );
226 :
227 80 : if( bMark && *rPam.GetPoint() > *rPam.GetMark())
228 : {
229 28 : rPam.Exchange();
230 : }
231 :
232 : // aRefMark was copied into the document pool; now retrieve real format...
233 80 : SwTxtAttr * pTxtAttr(0);
234 80 : if (bMark)
235 : {
236 : // #i107672#
237 : // ensure that we do not retrieve a different mark at the same position
238 : ::std::vector<SwTxtAttr *> const newMarks(
239 28 : rPam.GetNode().GetTxtNode()->GetTxtAttrsAt(
240 56 : rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
241 : ::std::vector<SwTxtAttr *>::const_iterator const iter(
242 : ::std::find_if(newMarks.begin(), newMarks.end(),
243 28 : NotContainedIn<SwTxtAttr *>(oldMarks)));
244 : OSL_ASSERT(newMarks.end() != iter);
245 28 : if (newMarks.end() != iter)
246 : {
247 28 : pTxtAttr = *iter;
248 28 : }
249 : }
250 : else
251 : {
252 52 : SwTxtNode *pTxtNd = rPam.GetNode().GetTxtNode();
253 : OSL_ASSERT(pTxtNd);
254 52 : pTxtAttr = pTxtNd ? rPam.GetNode().GetTxtNode()->GetTxtAttrForCharAt(
255 104 : rPam.GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_REFMARK) : NULL;
256 : }
257 :
258 80 : if (!pTxtAttr)
259 : {
260 : throw uno::RuntimeException(
261 0 : "SwXReferenceMark::InsertRefMark(): cannot insert attribute", 0);
262 : }
263 :
264 80 : m_pMarkFmt = &pTxtAttr->GetRefMark();
265 :
266 160 : const_cast<SwFmtRefMark*>(m_pMarkFmt)->Add(this);
267 80 : }
268 :
269 : void SAL_CALL
270 76 : SwXReferenceMark::attach(const uno::Reference< text::XTextRange > & xTextRange)
271 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
272 : {
273 76 : SolarMutexGuard aGuard;
274 :
275 76 : if (!m_pImpl->m_bIsDescriptor)
276 : {
277 0 : throw uno::RuntimeException();
278 : }
279 152 : uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
280 76 : SwXTextRange* pRange = 0;
281 76 : OTextCursorHelper* pCursor = 0;
282 76 : if(xRangeTunnel.is())
283 : {
284 76 : pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
285 : pCursor =
286 76 : ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
287 : }
288 : SwDoc *const pDocument =
289 76 : (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
290 76 : if (!pDocument)
291 : {
292 0 : throw lang::IllegalArgumentException();
293 : }
294 :
295 152 : SwUnoInternalPaM aPam(*pDocument);
296 : // this now needs to return TRUE
297 76 : ::sw::XTextRangeToSwPaM(aPam, xTextRange);
298 76 : m_pImpl->InsertRefMark(aPam, dynamic_cast<SwXTextCursor*>(pCursor));
299 76 : m_pImpl->m_bIsDescriptor = false;
300 152 : m_pImpl->m_pDoc = pDocument;
301 76 : }
302 :
303 : uno::Reference< text::XTextRange > SAL_CALL
304 2 : SwXReferenceMark::getAnchor() throw (uno::RuntimeException, std::exception)
305 : {
306 2 : SolarMutexGuard aGuard;
307 :
308 2 : if (m_pImpl->IsValid())
309 : {
310 : SwFmtRefMark const*const pNewMark =
311 2 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
312 2 : if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
313 : {
314 : SwTxtRefMark const*const pTxtMark =
315 2 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
316 4 : if (pTxtMark &&
317 2 : (&pTxtMark->GetTxtNode().GetNodes() ==
318 2 : &m_pImpl->m_pDoc->GetNodes()))
319 : {
320 2 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
321 2 : const ::std::unique_ptr<SwPaM> pPam( (pTxtMark->End())
322 0 : ? new SwPaM( rTxtNode, *pTxtMark->End(),
323 0 : rTxtNode, pTxtMark->GetStart())
324 2 : : new SwPaM( rTxtNode, pTxtMark->GetStart()) );
325 :
326 : return SwXTextRange::CreateXTextRange(
327 2 : *m_pImpl->m_pDoc, *pPam->Start(), pPam->End());
328 : }
329 : }
330 : }
331 0 : return 0;
332 : }
333 :
334 2 : void SAL_CALL SwXReferenceMark::dispose() throw (uno::RuntimeException, std::exception)
335 : {
336 2 : SolarMutexGuard aGuard;
337 2 : if (m_pImpl->IsValid())
338 : {
339 : SwFmtRefMark const*const pNewMark =
340 2 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
341 2 : if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
342 : {
343 : SwTxtRefMark const*const pTxtMark =
344 2 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
345 4 : if (pTxtMark &&
346 2 : (&pTxtMark->GetTxtNode().GetNodes() ==
347 2 : &m_pImpl->m_pDoc->GetNodes()))
348 : {
349 2 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
350 2 : const sal_Int32 nStt = pTxtMark->GetStart();
351 2 : const sal_Int32 nEnd = pTxtMark->End()
352 0 : ? *pTxtMark->End()
353 2 : : nStt + 1;
354 :
355 2 : SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
356 2 : 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 2 : }
364 2 : }
365 :
366 4 : 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 4 : m_pImpl->m_EventListeners.addInterface(xListener);
372 4 : }
373 :
374 2 : 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 2 : m_pImpl->m_EventListeners.removeInterface(xListener);
380 2 : }
381 :
382 98 : OUString SAL_CALL SwXReferenceMark::getName()
383 : throw (uno::RuntimeException, std::exception)
384 : {
385 98 : SolarMutexGuard aGuard;
386 196 : if (!m_pImpl->IsValid() ||
387 98 : !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName))
388 : {
389 0 : throw uno::RuntimeException();
390 : }
391 98 : return m_pImpl->m_sMarkName;
392 : }
393 :
394 78 : void SAL_CALL SwXReferenceMark::setName(const OUString& rName)
395 : throw (uno::RuntimeException, std::exception)
396 : {
397 78 : SolarMutexGuard aGuard;
398 78 : if (m_pImpl->m_bIsDescriptor)
399 : {
400 74 : m_pImpl->m_sMarkName = rName;
401 : }
402 : else
403 : {
404 8 : if (!m_pImpl->IsValid()
405 4 : || !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName)
406 8 : || m_pImpl->m_pDoc->GetRefMark(rName))
407 : {
408 0 : throw uno::RuntimeException();
409 : }
410 : SwFmtRefMark const*const pCurMark =
411 4 : m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
412 8 : if ((rName != m_pImpl->m_sMarkName)
413 4 : && pCurMark && (pCurMark == m_pImpl->m_pMarkFmt))
414 : {
415 4 : const UnoActionContext aCont(m_pImpl->m_pDoc);
416 : SwTxtRefMark const*const pTxtMark =
417 4 : m_pImpl->m_pMarkFmt->GetTxtRefMark();
418 8 : if (pTxtMark &&
419 4 : (&pTxtMark->GetTxtNode().GetNodes() ==
420 4 : &m_pImpl->m_pDoc->GetNodes()))
421 : {
422 4 : SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
423 4 : const sal_Int32 nStt = pTxtMark->GetStart();
424 4 : const sal_Int32 nEnd = pTxtMark->End()
425 0 : ? *pTxtMark->End()
426 4 : : nStt + 1;
427 :
428 4 : SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
429 : // deletes the m_pImpl->m_pDoc member in the SwXReferenceMark!
430 4 : m_pImpl->m_pDoc->getIDocumentContentOperations().DeleteAndJoin( aPam );
431 : // The aPam will keep the correct and functional doc though
432 :
433 4 : m_pImpl->m_sMarkName = rName;
434 : //create a new one
435 4 : m_pImpl->InsertRefMark( aPam, 0 );
436 4 : m_pImpl->m_pDoc = aPam.GetDoc();
437 4 : }
438 : }
439 78 : }
440 78 : }
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 278 : 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 180 : void Invalidate() { SwXText::Invalidate(); };
542 :
543 : // XInterface
544 0 : virtual void SAL_CALL acquire() throw() SAL_OVERRIDE
545 0 : { OSL_FAIL("ERROR: SwXMetaText::acquire"); }
546 0 : virtual void SAL_CALL release() throw() SAL_OVERRIDE
547 0 : { OSL_FAIL("ERROR: SwXMetaText::release"); }
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 278 : SwXMetaText::SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta)
564 : : SwXText(&rDoc, CURSOR_META)
565 278 : , m_rMeta(rMeta)
566 : {
567 278 : }
568 :
569 142 : const SwStartNode *SwXMetaText::GetStartNode() const
570 : {
571 : SwXText const * const pParent(
572 142 : dynamic_cast<SwXText*>(m_rMeta.GetParentText().get()));
573 142 : return (pParent) ? pParent->GetStartNode() : 0;
574 : }
575 :
576 40 : 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 40 : new SwXTextCursor(*GetDoc(), &m_rMeta, CURSOR_META, *rPam.GetPoint(),
582 40 : (rPam.HasMark()) ? rPam.GetMark() : 0));
583 40 : }
584 :
585 94 : bool SwXMetaText::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
586 : throw (lang::IllegalArgumentException, uno::RuntimeException)
587 : {
588 94 : return m_rMeta.CheckForOwnMemberMeta(rPam, bAbsorb);
589 : }
590 :
591 300 : uno::Reference< text::XTextCursor > SwXMetaText::CreateCursor()
592 : throw (uno::RuntimeException)
593 : {
594 300 : uno::Reference< text::XTextCursor > xRet;
595 300 : if (IsValid())
596 : {
597 : SwTxtNode * pTxtNode;
598 : sal_Int32 nMetaStart;
599 : sal_Int32 nMetaEnd;
600 : const bool bSuccess(
601 298 : m_rMeta.SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
602 298 : if (bSuccess)
603 : {
604 298 : SwPosition aPos(*pTxtNode, nMetaStart);
605 : xRet = static_cast<text::XWordCursor*>(
606 298 : new SwXTextCursor(*GetDoc(), &m_rMeta, CURSOR_META, aPos));
607 : }
608 : }
609 300 : 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 30 : SwXMetaText::createTextCursor() throw (uno::RuntimeException, std::exception)
621 : {
622 30 : return CreateCursor();
623 : }
624 :
625 : uno::Reference< text::XTextCursor > SAL_CALL
626 6 : SwXMetaText::createTextCursorByRange(
627 : const uno::Reference<text::XTextRange> & xTextPosition)
628 : throw (uno::RuntimeException, std::exception)
629 : {
630 6 : const uno::Reference<text::XTextCursor> xCursor( CreateCursor() );
631 6 : xCursor->gotoRange(xTextPosition, sal_False);
632 4 : 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 SwTxtNode and throws away the cache when it changes
638 556 : 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 278 : 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 278 : , m_bIsDescriptor(0 == pMeta)
663 : , m_xParentText(xParentText)
664 556 : , m_Text(rDoc, rThis)
665 : {
666 278 : }
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 2738 : inline const ::sw::Meta * SwXMeta::Impl::GetMeta() const
678 : {
679 2738 : return static_cast< const ::sw::Meta * >(GetRegisteredIn());
680 : }
681 :
682 : // SwModify
683 1842 : void SwXMeta::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
684 : {
685 1842 : m_pTextPortions.reset(); // throw away cache (SwTxtNode changed)
686 :
687 1842 : ClientModify(this, pOld, pNew);
688 :
689 1842 : if (GetRegisteredIn())
690 : {
691 3324 : return; // core object still alive
692 : }
693 :
694 180 : m_bIsDisposed = true;
695 180 : m_Text.Invalidate();
696 180 : uno::Reference<uno::XInterface> const xThis(m_wThis);
697 180 : if (!xThis.is())
698 : { // fdo#72695: if UNO object is already dead, don't revive it with event
699 0 : return;
700 : }
701 360 : lang::EventObject const ev(xThis);
702 360 : m_EventListeners.disposeAndClear(ev);
703 : }
704 :
705 144 : uno::Reference<text::XText> SwXMeta::GetParentText() const
706 : {
707 144 : return m_pImpl->m_xParentText;
708 : }
709 :
710 84 : SwXMeta::SwXMeta(SwDoc *const pDoc, ::sw::Meta *const pMeta,
711 : uno::Reference<text::XText> const& xParentText,
712 : TextRangeList_t const*const pPortions)
713 84 : : m_pImpl( new SwXMeta::Impl(*this, *pDoc, pMeta, xParentText, pPortions) )
714 : {
715 84 : }
716 :
717 194 : SwXMeta::SwXMeta(SwDoc *const pDoc)
718 194 : : m_pImpl( new SwXMeta::Impl(*this, *pDoc, 0, 0, 0) )
719 : {
720 194 : }
721 :
722 456 : SwXMeta::~SwXMeta()
723 : {
724 456 : }
725 :
726 : uno::Reference<rdf::XMetadatable>
727 194 : SwXMeta::CreateXMeta(SwDoc & rDoc, bool const isField)
728 : {
729 : SwXMeta *const pXMeta((isField)
730 194 : ? new SwXMetaField(& rDoc) : new SwXMeta(& rDoc));
731 : // this is why the constructor is private: need to acquire pXMeta here
732 194 : uno::Reference<rdf::XMetadatable> const xMeta(pXMeta);
733 : // need a permanent Reference to initialize m_wThis
734 194 : pXMeta->m_pImpl->m_wThis = xMeta;
735 194 : return xMeta;
736 : }
737 :
738 : uno::Reference<rdf::XMetadatable>
739 482 : 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 482 : uno::Reference<rdf::XMetadatable> xMeta(rMeta.GetXMeta());
746 482 : if (xMeta.is())
747 : {
748 398 : if (pPortions.get()) // set cache in the XMeta to the given portions
749 : {
750 278 : const uno::Reference<lang::XUnoTunnel> xUT(xMeta, uno::UNO_QUERY);
751 : SwXMeta *const pXMeta(
752 278 : ::sw::UnoTunnelGetImplementation<SwXMeta>(xUT));
753 : OSL_ENSURE(pXMeta, "no 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 278 : pXMeta->m_pImpl->m_pTextPortions = std::move(pPortions);
758 : // ??? is this necessary?
759 278 : if (pXMeta->m_pImpl->m_xParentText.get() != i_xParent.get())
760 : {
761 : OSL_FAIL("SwXMeta with different parent?");
762 0 : pXMeta->m_pImpl->m_xParentText.set(i_xParent);
763 278 : }
764 : }
765 398 : return xMeta;
766 : }
767 :
768 : // create new SwXMeta
769 84 : SwTxtNode * const pTxtNode( rMeta.GetTxtNode() );
770 : OSL_ENSURE(pTxtNode, "CreateXMeta: no text node?");
771 84 : if (!pTxtNode) { return 0; }
772 168 : uno::Reference<text::XText> xParentText(i_xParent);
773 84 : if (!xParentText.is())
774 : {
775 12 : SwTxtMeta * const pTxtAttr( rMeta.GetTxtAttr() );
776 : OSL_ENSURE(pTxtAttr, "CreateXMeta: no text attr?");
777 12 : if (!pTxtAttr) { return 0; }
778 12 : const SwPosition aPos(*pTxtNode, pTxtAttr->GetStart());
779 12 : xParentText.set( ::sw::CreateParentXText(*pTxtNode->GetDoc(), aPos) );
780 : }
781 84 : if (!xParentText.is()) { return 0; }
782 84 : SwXMeta *const pXMeta( (RES_TXTATR_META == rMeta.GetFmtMeta()->Which())
783 36 : ? new SwXMeta (pTxtNode->GetDoc(), &rMeta, xParentText,
784 36 : pPortions.release()) // temporarily un-unique_ptr :-(
785 48 : : new SwXMetaField(pTxtNode->GetDoc(), &rMeta, xParentText,
786 204 : pPortions.release()));
787 : // this is why the constructor is private: need to acquire pXMeta here
788 84 : xMeta.set(pXMeta);
789 : // in order to initialize the weak pointer cache in the core object
790 84 : rMeta.SetXMeta(xMeta);
791 : // need a permanent Reference to initialize m_wThis
792 84 : pXMeta->m_pImpl->m_wThis = xMeta;
793 566 : return xMeta;
794 : }
795 :
796 1410 : bool SwXMeta::SetContentRange(
797 : SwTxtNode *& rpNode, sal_Int32 & rStart, sal_Int32 & rEnd ) const
798 : {
799 1410 : ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
800 1410 : if (pMeta)
801 : {
802 1410 : SwTxtMeta const * const pTxtAttr( pMeta->GetTxtAttr() );
803 1410 : if (pTxtAttr)
804 : {
805 1410 : rpNode = pMeta->GetTxtNode();
806 1410 : if (rpNode)
807 : {
808 : // rStart points at the first position _within_ the meta!
809 1410 : rStart = pTxtAttr->GetStart() + 1;
810 1410 : rEnd = *pTxtAttr->End();
811 1410 : return true;
812 : }
813 : }
814 : }
815 0 : return false;
816 : }
817 :
818 156 : bool SwXMeta::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
819 : throw (lang::IllegalArgumentException, uno::RuntimeException)
820 : {
821 : SwTxtNode * pTxtNode;
822 : sal_Int32 nMetaStart;
823 : sal_Int32 nMetaEnd;
824 156 : const bool bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
825 : OSL_ENSURE(bSuccess, "no pam?");
826 156 : if (!bSuccess)
827 0 : throw lang::DisposedException();
828 :
829 156 : SwPosition const * const pStartPos( rPam.Start() );
830 156 : if (&pStartPos->nNode.GetNode() != pTxtNode)
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 6 : 0, 0);
836 : }
837 150 : bool bForceExpandHints(false);
838 150 : 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 150 : 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 150 : else if (nStartPos == nMetaEnd)
849 : {
850 38 : bForceExpandHints = true;
851 : }
852 150 : if (rPam.HasMark() && bAbsorb)
853 : {
854 78 : SwPosition const * const pEndPos( rPam.End() );
855 78 : if (&pEndPos->nNode.GetNode() != pTxtNode)
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 78 : 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 78 : 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 78 : else if (nEndPos == nMetaEnd)
873 : {
874 66 : bForceExpandHints = true;
875 : }
876 : }
877 150 : return bForceExpandHints;
878 : }
879 :
880 : namespace
881 : {
882 : class theSwXMetaUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXMetaUnoTunnelId > {};
883 : }
884 :
885 19448 : const uno::Sequence< sal_Int8 > & SwXMeta::getUnoTunnelId()
886 : {
887 19448 : return theSwXMetaUnoTunnelId::get().getSeq();
888 : }
889 :
890 : // XUnoTunnel
891 : sal_Int64 SAL_CALL
892 914 : SwXMeta::getSomething( const uno::Sequence< sal_Int8 > & i_rId )
893 : throw (uno::RuntimeException, std::exception)
894 : {
895 914 : 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 20 : SwXMeta::supportsService(const OUString& rServiceName)
916 : throw (uno::RuntimeException, std::exception)
917 : {
918 20 : return cppu::supportsService(this, rServiceName);
919 : }
920 :
921 : uno::Sequence< OUString > SAL_CALL
922 20 : SwXMeta::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
923 : {
924 20 : 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 2 : SwXMeta::dispose() throw (uno::RuntimeException, std::exception)
948 : {
949 2 : SolarMutexGuard g;
950 :
951 2 : 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 2 : else if (!m_pImpl->m_bIsDisposed)
960 : {
961 : SwTxtNode * pTxtNode;
962 : sal_Int32 nMetaStart;
963 : sal_Int32 nMetaEnd;
964 2 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
965 : OSL_ENSURE(bSuccess, "no pam?");
966 2 : if (bSuccess)
967 : {
968 : // -1 because of CH_TXTATR
969 2 : SwPaM aPam( *pTxtNode, nMetaStart - 1, *pTxtNode, nMetaEnd );
970 2 : SwDoc * const pDoc( pTxtNode->GetDoc() );
971 2 : pDoc->getIDocumentContentOperations().DeleteAndJoin( aPam );
972 :
973 : // removal should call Modify and do the dispose
974 2 : OSL_ENSURE(m_pImpl->m_bIsDisposed, "zombie meta");
975 : }
976 2 : }
977 2 : }
978 :
979 : void SAL_CALL
980 194 : SwXMeta::AttachImpl(const uno::Reference< text::XTextRange > & i_xTextRange,
981 : const sal_uInt16 i_nWhich)
982 : throw (lang::IllegalArgumentException, uno::RuntimeException)
983 : {
984 194 : SolarMutexGuard g;
985 :
986 194 : if (m_pImpl->m_bIsDisposed)
987 : {
988 0 : throw lang::DisposedException();
989 : }
990 194 : 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 388 : uno::Reference<lang::XUnoTunnel> xRangeTunnel(i_xTextRange, uno::UNO_QUERY);
998 194 : 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 194 : ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel));
1006 : OTextCursorHelper *const pCursor( (pRange) ? 0 :
1007 194 : ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel));
1008 194 : 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 194 : pRange ? pRange->GetDoc() : pCursor->GetDoc());
1017 194 : 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 388 : SwUnoInternalPaM aPam(*pDoc);
1025 194 : ::sw::XTextRangeToSwPaM(aPam, i_xTextRange);
1026 :
1027 388 : UnoActionContext aContext(pDoc);
1028 :
1029 : SwXTextCursor const*const pTextCursor(
1030 194 : dynamic_cast<SwXTextCursor*>(pCursor));
1031 194 : const bool bForceExpandHints(pTextCursor && pTextCursor->IsAtEndOfMeta());
1032 : const SetAttrMode nInsertFlags( (bForceExpandHints)
1033 : ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
1034 : | nsSetAttrMode::SETATTR_DONTEXPAND)
1035 194 : : nsSetAttrMode::SETATTR_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 388 : pDoc->GetMetaFieldManager().makeMetaField()) );
1041 388 : SwFmtMeta meta(pMeta, i_nWhich); // this is cloned by Insert!
1042 194 : const bool bSuccess( pDoc->getIDocumentContentOperations().InsertPoolItem( aPam, meta, nInsertFlags ) );
1043 194 : SwTxtAttr * const pTxtAttr( pMeta->GetTxtAttr() );
1044 194 : if (!bSuccess)
1045 : {
1046 : throw lang::IllegalArgumentException(
1047 : "SwXMeta::attach(): cannot create meta: range invalid?",
1048 4 : static_cast< ::cppu::OWeakObject* >(this), 1);
1049 : }
1050 190 : if (!pTxtAttr)
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 190 : pMeta->Add(m_pImpl.get());
1059 190 : pMeta->SetXMeta(uno::Reference<rdf::XMetadatable>(this));
1060 :
1061 190 : m_pImpl->m_xParentText = ::sw::CreateParentXText(*pDoc, *aPam.GetPoint());
1062 :
1063 384 : m_pImpl->m_bIsDescriptor = false;
1064 190 : }
1065 :
1066 : // XTextContent
1067 : void SAL_CALL
1068 142 : SwXMeta::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
1069 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
1070 : {
1071 142 : return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_META);
1072 : }
1073 :
1074 : uno::Reference< text::XTextRange > SAL_CALL
1075 46 : SwXMeta::getAnchor() throw (uno::RuntimeException, std::exception)
1076 : {
1077 46 : SolarMutexGuard g;
1078 :
1079 46 : if (m_pImpl->m_bIsDisposed)
1080 : {
1081 0 : throw lang::DisposedException();
1082 : }
1083 46 : 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 : SwTxtNode * pTxtNode;
1091 : sal_Int32 nMetaStart;
1092 : sal_Int32 nMetaEnd;
1093 46 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
1094 : OSL_ENSURE(bSuccess, "no pam?");
1095 46 : if (!bSuccess)
1096 : {
1097 : throw lang::DisposedException(
1098 : "SwXMeta::getAnchor(): not attached",
1099 0 : static_cast< ::cppu::OWeakObject* >(this));
1100 : }
1101 :
1102 92 : const SwPosition start(*pTxtNode, nMetaStart - 1); // -1 due to CH_TXTATR
1103 92 : const SwPosition end(*pTxtNode, nMetaEnd);
1104 92 : return SwXTextRange::CreateXTextRange(*pTxtNode->GetDoc(), start, &end);
1105 : }
1106 :
1107 : // XTextRange
1108 : uno::Reference< text::XText > SAL_CALL
1109 2 : SwXMeta::getText() throw (uno::RuntimeException, std::exception)
1110 : {
1111 2 : SolarMutexGuard g;
1112 2 : return this;
1113 : }
1114 :
1115 : uno::Reference< text::XTextRange > SAL_CALL
1116 68 : SwXMeta::getStart() throw (uno::RuntimeException, std::exception)
1117 : {
1118 68 : SolarMutexGuard g;
1119 68 : return m_pImpl->m_Text.getStart();
1120 : }
1121 :
1122 : uno::Reference< text::XTextRange > SAL_CALL
1123 62 : SwXMeta::getEnd() throw (uno::RuntimeException, std::exception)
1124 : {
1125 62 : SolarMutexGuard g;
1126 62 : return m_pImpl->m_Text.getEnd();
1127 : }
1128 :
1129 : OUString SAL_CALL
1130 80 : SwXMeta::getString() throw (uno::RuntimeException, std::exception)
1131 : {
1132 80 : SolarMutexGuard g;
1133 80 : return m_pImpl->m_Text.getString();
1134 : }
1135 :
1136 : void SAL_CALL
1137 54 : SwXMeta::setString(const OUString& rString) throw (uno::RuntimeException, std::exception)
1138 : {
1139 54 : SolarMutexGuard g;
1140 54 : return m_pImpl->m_Text.setString(rString);
1141 : }
1142 :
1143 : // XSimpleText
1144 : uno::Reference< text::XTextCursor > SAL_CALL
1145 30 : SwXMeta::createTextCursor() throw (uno::RuntimeException, std::exception)
1146 : {
1147 30 : SolarMutexGuard g;
1148 30 : return m_pImpl->m_Text.createTextCursor();
1149 : }
1150 :
1151 : uno::Reference< text::XTextCursor > SAL_CALL
1152 6 : SwXMeta::createTextCursorByRange(
1153 : const uno::Reference<text::XTextRange> & xTextPosition)
1154 : throw (uno::RuntimeException, std::exception)
1155 : {
1156 6 : SolarMutexGuard g;
1157 6 : return m_pImpl->m_Text.createTextCursorByRange(xTextPosition);
1158 : }
1159 :
1160 : void SAL_CALL
1161 8 : SwXMeta::insertString(const uno::Reference<text::XTextRange> & xRange,
1162 : const OUString& rString, sal_Bool bAbsorb)
1163 : throw (uno::RuntimeException, std::exception)
1164 : {
1165 8 : SolarMutexGuard g;
1166 8 : return m_pImpl->m_Text.insertString(xRange, rString, bAbsorb);
1167 : }
1168 :
1169 : void SAL_CALL
1170 8 : 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 8 : SolarMutexGuard g;
1175 8 : return m_pImpl->m_Text.insertControlCharacter(xRange, nControlCharacter,
1176 16 : bAbsorb);
1177 : }
1178 :
1179 : // XText
1180 : void SAL_CALL
1181 86 : 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 86 : SolarMutexGuard g;
1186 86 : return m_pImpl->m_Text.insertTextContent(xRange, xContent, bAbsorb);
1187 : }
1188 :
1189 : void SAL_CALL
1190 4 : SwXMeta::removeTextContent(
1191 : const uno::Reference< text::XTextContent > & xContent)
1192 : throw (container::NoSuchElementException, uno::RuntimeException, std::exception)
1193 : {
1194 4 : SolarMutexGuard g;
1195 4 : return m_pImpl->m_Text.removeTextContent(xContent);
1196 : }
1197 :
1198 : // XChild
1199 : uno::Reference< uno::XInterface > SAL_CALL
1200 12 : SwXMeta::getParent() throw (uno::RuntimeException, std::exception)
1201 : {
1202 12 : SolarMutexGuard g;
1203 : SwTxtNode * pTxtNode;
1204 : sal_Int32 nMetaStart;
1205 : sal_Int32 nMetaEnd;
1206 12 : bool const bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
1207 : OSL_ENSURE(bSuccess, "no pam?");
1208 12 : 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 GetTxtAttrAt(_, _, PARENT) in GetNestedTextContent
1212 : uno::Reference<text::XTextContent> const xRet(
1213 : SwUnoCursorHelper::GetNestedTextContent(*pTxtNode, nMetaStart - 1,
1214 24 : true) );
1215 24 : return xRet;
1216 : }
1217 :
1218 : void SAL_CALL
1219 2 : SwXMeta::setParent(uno::Reference< uno::XInterface > const& /*xParent*/)
1220 : throw (uno::RuntimeException, lang::NoSupportException, std::exception)
1221 : {
1222 2 : 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() ? sal_True : sal_False;
1238 : }
1239 :
1240 : // XEnumerationAccess
1241 : uno::Reference< container::XEnumeration > SAL_CALL
1242 352 : SwXMeta::createEnumeration() throw (uno::RuntimeException, std::exception)
1243 : {
1244 352 : SolarMutexGuard g;
1245 :
1246 352 : if (m_pImpl->m_bIsDisposed)
1247 : {
1248 0 : throw lang::DisposedException();
1249 : }
1250 352 : if (m_pImpl->m_bIsDescriptor)
1251 : {
1252 : throw uno::RuntimeException(
1253 : "createEnumeration(): not inserted",
1254 0 : static_cast< ::cppu::OWeakObject* >(this));
1255 : }
1256 :
1257 : SwTxtNode * pTxtNode;
1258 : sal_Int32 nMetaStart;
1259 : sal_Int32 nMetaEnd;
1260 352 : const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
1261 : OSL_ENSURE(bSuccess, "no pam?");
1262 352 : if (!bSuccess)
1263 0 : throw lang::DisposedException();
1264 :
1265 704 : SwPaM aPam(*pTxtNode, nMetaStart);
1266 :
1267 352 : if (!m_pImpl->m_pTextPortions.get())
1268 : {
1269 : return new SwXTextPortionEnumeration(
1270 2 : aPam, GetParentText(), nMetaStart, nMetaEnd);
1271 : }
1272 : else // cached!
1273 : {
1274 350 : return new SwXTextPortionEnumeration(aPam, *m_pImpl->m_pTextPortions);
1275 352 : }
1276 : }
1277 :
1278 : // MetadatableMixin
1279 1066 : ::sfx2::Metadatable* SwXMeta::GetCoreObject()
1280 : {
1281 1066 : return const_cast< ::sw::Meta * >(m_pImpl->GetMeta());
1282 : }
1283 :
1284 262 : uno::Reference<frame::XModel> SwXMeta::GetModel()
1285 : {
1286 262 : ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
1287 262 : if (pMeta)
1288 : {
1289 262 : SwTxtNode const * const pTxtNode( pMeta->GetTxtNode() );
1290 262 : if (pTxtNode)
1291 : {
1292 262 : SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
1293 262 : return (pShell) ? pShell->GetModel() : 0;
1294 : }
1295 : }
1296 0 : return 0;
1297 : }
1298 :
1299 94 : inline const ::sw::MetaField * SwXMeta::Impl::GetMetaField() const
1300 : {
1301 94 : return static_cast< const ::sw::MetaField * >(GetRegisteredIn());
1302 : }
1303 :
1304 48 : SwXMetaField::SwXMetaField(SwDoc *const pDoc, ::sw::Meta *const pMeta,
1305 : uno::Reference<text::XText> const& xParentText,
1306 : TextRangeList_t const*const pPortions)
1307 48 : : SwXMetaField_Base(pDoc, pMeta, xParentText, pPortions)
1308 : {
1309 : OSL_ENSURE(pMeta && dynamic_cast< ::sw::MetaField* >(pMeta),
1310 : "SwXMetaField created for wrong hint!");
1311 48 : }
1312 :
1313 52 : SwXMetaField::SwXMetaField(SwDoc *const pDoc)
1314 52 : : SwXMetaField_Base(pDoc)
1315 : {
1316 52 : }
1317 :
1318 200 : SwXMetaField::~SwXMetaField()
1319 : {
1320 200 : }
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 40 : SwXMetaField::supportsService(const OUString& rServiceName)
1341 : throw (uno::RuntimeException, std::exception)
1342 : {
1343 40 : return cppu::supportsService(this, rServiceName);
1344 : }
1345 :
1346 : uno::Sequence< OUString > SAL_CALL
1347 80 : SwXMetaField::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
1348 : {
1349 : return ::sw::GetSupportedServiceNamesImpl(
1350 80 : 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 52 : SwXMetaField::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
1379 : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
1380 : {
1381 52 : return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_METAFIELD);
1382 : }
1383 :
1384 : uno::Reference< text::XTextRange > SAL_CALL
1385 40 : SwXMetaField::getAnchor() throw (uno::RuntimeException, std::exception)
1386 : {
1387 40 : return SwXMeta::getAnchor();
1388 : }
1389 :
1390 : // XPropertySet
1391 : uno::Reference< beans::XPropertySetInfo > SAL_CALL
1392 34 : SwXMetaField::getPropertySetInfo() throw (uno::RuntimeException, std::exception)
1393 : {
1394 34 : SolarMutexGuard g;
1395 :
1396 : static uno::Reference< beans::XPropertySetInfo > xRef(
1397 : aSwMapProvider.GetPropertySet(PROPERTY_MAP_METAFIELD)
1398 34 : ->getPropertySetInfo() );
1399 34 : return xRef;
1400 : }
1401 :
1402 : void SAL_CALL
1403 20 : 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 20 : SolarMutexGuard g;
1410 :
1411 : ::sw::MetaField * const pMeta(
1412 20 : const_cast< ::sw::MetaField * >(m_pImpl->GetMetaField()) );
1413 20 : if (!pMeta)
1414 0 : throw lang::DisposedException();
1415 :
1416 20 : if ( rPropertyName == "NumberFormat" )
1417 : {
1418 10 : sal_Int32 nNumberFormat(0);
1419 10 : if (rValue >>= nNumberFormat)
1420 : {
1421 10 : pMeta->SetNumberFormat(static_cast<sal_uInt32>(nNumberFormat));
1422 : }
1423 : }
1424 10 : else if ( rPropertyName == "IsFixedLanguage" )
1425 : {
1426 10 : bool b(false);
1427 10 : if (rValue >>= b)
1428 : {
1429 10 : pMeta->SetIsFixedLanguage(b);
1430 : }
1431 : }
1432 : else
1433 : {
1434 0 : throw beans::UnknownPropertyException();
1435 20 : }
1436 20 : }
1437 :
1438 : uno::Any SAL_CALL
1439 74 : SwXMetaField::getPropertyValue(const OUString& rPropertyName)
1440 : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1441 : uno::RuntimeException, std::exception)
1442 : {
1443 74 : SolarMutexGuard g;
1444 :
1445 74 : ::sw::MetaField const * const pMeta( m_pImpl->GetMetaField() );
1446 74 : if (!pMeta)
1447 0 : throw lang::DisposedException();
1448 :
1449 74 : uno::Any any;
1450 :
1451 74 : if ( rPropertyName == "NumberFormat" )
1452 : {
1453 48 : const OUString text( getPresentation(sal_False) );
1454 48 : any <<= static_cast<sal_Int32>(pMeta->GetNumberFormat(text));
1455 : }
1456 26 : else if ( rPropertyName == "IsFixedLanguage" )
1457 : {
1458 6 : any <<= pMeta->IsFixedLanguage();
1459 : }
1460 : else
1461 : {
1462 20 : throw beans::UnknownPropertyException();
1463 : }
1464 :
1465 74 : 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 220 : lcl_getURI(const bool bPrefix)
1518 : {
1519 : static uno::Reference< uno::XComponentContext > xContext(
1520 220 : ::comphelper::getProcessComponentContext());
1521 : static uno::Reference< rdf::XURI > xOdfPrefix(
1522 : rdf::URI::createKnown(xContext, rdf::URIs::ODF_PREFIX),
1523 220 : uno::UNO_SET_THROW);
1524 : static uno::Reference< rdf::XURI > xOdfSuffix(
1525 : rdf::URI::createKnown(xContext, rdf::URIs::ODF_SUFFIX),
1526 220 : uno::UNO_SET_THROW);
1527 220 : return (bPrefix) ? xOdfPrefix : xOdfSuffix;
1528 : }
1529 :
1530 : static OUString
1531 220 : 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 220 : xRepository->getStatements(xMetaField, xPredicate, 0),
1538 220 : uno::UNO_SET_THROW);
1539 440 : while (xEnum->hasMoreElements()) {
1540 136 : rdf::Statement stmt;
1541 136 : if (!(xEnum->nextElement() >>= stmt)) {
1542 0 : throw uno::RuntimeException();
1543 : }
1544 : const uno::Reference<rdf::XLiteral> xObject(stmt.Object,
1545 136 : uno::UNO_QUERY);
1546 136 : if (!xObject.is()) continue;
1547 136 : if (xEnum->hasMoreElements()) {
1548 : OSL_TRACE("ignoring other odf:Prefix/odf:Suffix statements");
1549 : }
1550 136 : return xObject->getValue();
1551 0 : }
1552 84 : return OUString();
1553 : }
1554 :
1555 : void
1556 150 : 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 150 : xModel, uno::UNO_QUERY_THROW);
1564 : const uno::Reference<rdf::XRepository> xRepo(
1565 300 : xRS->getRDFRepository(), uno::UNO_SET_THROW);
1566 : const uno::Reference<rdf::XResource> xMeta(
1567 300 : xMetaField, uno::UNO_QUERY_THROW);
1568 150 : if (o_pPrefix)
1569 : {
1570 110 : *o_pPrefix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(true));
1571 : }
1572 150 : if (o_pSuffix)
1573 : {
1574 110 : *o_pSuffix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(false));
1575 150 : }
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 150 : }
1584 :
1585 : // XTextField
1586 : OUString SAL_CALL
1587 70 : SwXMetaField::getPresentation(sal_Bool bShowCommand)
1588 : throw (uno::RuntimeException, std::exception)
1589 : {
1590 70 : SolarMutexGuard g;
1591 :
1592 70 : if (bShowCommand)
1593 : {
1594 : //FIXME ?
1595 0 : return OUString();
1596 : }
1597 : else
1598 : {
1599 : // getString should check if this is invalid
1600 70 : const OUString content( this->getString() );
1601 140 : OUString prefix;
1602 140 : OUString suffix;
1603 70 : getPrefixAndSuffix(GetModel(), this, &prefix, &suffix);
1604 140 : return prefix + content + suffix;
1605 70 : }
1606 270 : }
1607 :
1608 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|