Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <editeng/unolingu.hxx>
22 :
23 : #include <unobaseclass.hxx>
24 : #include <unoflatpara.hxx>
25 :
26 : #include <osl/mutex.hxx>
27 : #include <vcl/svapp.hxx>
28 : #include <com/sun/star/text/TextMarkupType.hpp>
29 : #include <unotextmarkup.hxx>
30 : #include <ndtxt.hxx>
31 : #include <doc.hxx>
32 : #include <docsh.hxx>
33 : #include <viewsh.hxx>
34 : #include <viewimp.hxx>
35 : #include <breakit.hxx>
36 : #include <pam.hxx>
37 : #include <unotextrange.hxx>
38 : #include <pagefrm.hxx>
39 : #include <cntfrm.hxx>
40 : #include <rootfrm.hxx>
41 : #include <poolfmt.hxx>
42 : #include <pagedesc.hxx>
43 : #include <IGrammarContact.hxx>
44 : #include <viewopt.hxx>
45 : #include <comphelper/servicehelper.hxx>
46 :
47 : using namespace ::com::sun::star;
48 :
49 : /******************************************************************************
50 : * SwXFlatParagraph
51 : ******************************************************************************/
52 :
53 0 : SwXFlatParagraph::SwXFlatParagraph( SwTxtNode& rTxtNode, rtl::OUString aExpandText, const ModelToViewHelper& rMap ) :
54 : SwXTextMarkup( rTxtNode, rMap ),
55 0 : maExpandText( aExpandText )
56 : {
57 0 : }
58 :
59 0 : SwXFlatParagraph::~SwXFlatParagraph()
60 : {
61 0 : }
62 :
63 0 : uno::Sequence< uno::Type > SwXFlatParagraph::getTypes( ) throw(uno::RuntimeException)
64 : {
65 0 : uno::Sequence< uno::Type > aTypes = SwXTextMarkup::getTypes();
66 0 : aTypes.realloc( aTypes.getLength() + 1 );
67 0 : aTypes[aTypes.getLength()-1] = ::getCppuType((uno::Reference< text::XFlatParagraph >*)0);
68 0 : return aTypes;
69 : }
70 :
71 : namespace
72 : {
73 : class theSwXFlatParagraphImplementationId : public rtl::Static< UnoTunnelIdInit, theSwXFlatParagraphImplementationId > {};
74 : }
75 :
76 0 : uno::Sequence< sal_Int8 > SwXFlatParagraph::getImplementationId( ) throw(uno::RuntimeException)
77 : {
78 0 : return theSwXFlatParagraphImplementationId::get().getSeq();
79 : }
80 :
81 0 : uno::Any SAL_CALL SwXFlatParagraph::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException)
82 : {
83 0 : if ( rType == ::getCppuType((uno::Reference< text::XFlatParagraph >*)0) )
84 : {
85 0 : return uno::makeAny( uno::Reference < text::XFlatParagraph >(this) );
86 : }
87 : else
88 0 : return SwXTextMarkup::queryInterface( rType );
89 : }
90 :
91 0 : void SAL_CALL SwXFlatParagraph::acquire() throw()
92 : {
93 0 : SwXTextMarkup::acquire();
94 0 : }
95 :
96 0 : void SAL_CALL SwXFlatParagraph::release() throw()
97 : {
98 0 : SwXTextMarkup::release();
99 0 : }
100 :
101 0 : const SwTxtNode* SwXFlatParagraph::getTxtNode() const
102 : {
103 0 : return mpTxtNode;
104 : }
105 :
106 0 : css::uno::Reference< css::container::XStringKeyMap > SAL_CALL SwXFlatParagraph::getMarkupInfoContainer() throw (css::uno::RuntimeException)
107 : {
108 0 : return SwXTextMarkup::getMarkupInfoContainer();
109 : }
110 :
111 0 : void SAL_CALL SwXFlatParagraph::commitTextMarkup(::sal_Int32 nType, const ::rtl::OUString & rIdentifier, ::sal_Int32 nStart, ::sal_Int32 nLength, const css::uno::Reference< css::container::XStringKeyMap > & rxMarkupInfoContainer) throw (css::uno::RuntimeException)
112 : {
113 0 : SolarMutexGuard aGuard;
114 0 : SwXTextMarkup::commitTextMarkup( nType, rIdentifier, nStart, nLength, rxMarkupInfoContainer );
115 0 : }
116 :
117 : // text::XFlatParagraph:
118 0 : ::rtl::OUString SAL_CALL SwXFlatParagraph::getText() throw (uno::RuntimeException)
119 : {
120 0 : return maExpandText;
121 : }
122 :
123 : // text::XFlatParagraph:
124 0 : void SAL_CALL SwXFlatParagraph::setChecked( ::sal_Int32 nType, ::sal_Bool bVal ) throw (uno::RuntimeException)
125 : {
126 0 : SolarMutexGuard aGuard;
127 :
128 0 : if ( mpTxtNode )
129 : {
130 0 : if ( text::TextMarkupType::SPELLCHECK == nType )
131 0 : mpTxtNode->SetWrongDirty( !bVal );
132 0 : else if ( text::TextMarkupType::SMARTTAG == nType )
133 0 : mpTxtNode->SetSmartTagDirty( !bVal );
134 0 : else if( text::TextMarkupType::PROOFREADING == nType )
135 : {
136 0 : mpTxtNode->SetGrammarCheckDirty( !bVal );
137 0 : if( bVal )
138 0 : ::finishGrammarCheck( *mpTxtNode );
139 : }
140 0 : }
141 0 : }
142 :
143 : // text::XFlatParagraph:
144 0 : ::sal_Bool SAL_CALL SwXFlatParagraph::isChecked( ::sal_Int32 nType ) throw (uno::RuntimeException)
145 : {
146 0 : SolarMutexGuard aGuard;
147 0 : if ( mpTxtNode )
148 : {
149 0 : if ( text::TextMarkupType::SPELLCHECK == nType )
150 0 : return mpTxtNode->IsWrongDirty();
151 0 : else if ( text::TextMarkupType::PROOFREADING == nType )
152 0 : return mpTxtNode->IsGrammarCheckDirty();
153 0 : else if ( text::TextMarkupType::SMARTTAG == nType )
154 0 : return mpTxtNode->IsSmartTagDirty();
155 : }
156 :
157 0 : return sal_False;
158 : }
159 :
160 : // text::XFlatParagraph:
161 0 : ::sal_Bool SAL_CALL SwXFlatParagraph::isModified() throw (uno::RuntimeException)
162 : {
163 0 : SolarMutexGuard aGuard;
164 0 : return 0 == mpTxtNode;
165 : }
166 :
167 : // text::XFlatParagraph:
168 0 : lang::Locale SAL_CALL SwXFlatParagraph::getLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
169 : throw (uno::RuntimeException, lang::IllegalArgumentException)
170 : {
171 0 : SolarMutexGuard aGuard;
172 0 : if (!mpTxtNode)
173 0 : return LanguageTag( LANGUAGE_NONE ).getLocale();
174 :
175 0 : const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
176 0 : return aLocale;
177 : }
178 :
179 : // text::XFlatParagraph:
180 0 : lang::Locale SAL_CALL SwXFlatParagraph::getPrimaryLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
181 : throw (uno::RuntimeException, lang::IllegalArgumentException)
182 : {
183 0 : SolarMutexGuard aGuard;
184 :
185 0 : if (!mpTxtNode)
186 0 : return LanguageTag( LANGUAGE_NONE ).getLocale();
187 :
188 0 : const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
189 0 : return aLocale;
190 : }
191 :
192 : // text::XFlatParagraph:
193 0 : void SAL_CALL SwXFlatParagraph::changeText(::sal_Int32 nPos, ::sal_Int32 nLen, const ::rtl::OUString & aNewText, const css::uno::Sequence< css::beans::PropertyValue > & aAttributes) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
194 : {
195 0 : SolarMutexGuard aGuard;
196 :
197 0 : if ( !mpTxtNode )
198 0 : return;
199 :
200 0 : SwTxtNode* pOldTxtNode = mpTxtNode;
201 :
202 0 : SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
203 :
204 0 : UnoActionContext aAction( mpTxtNode->GetDoc() );
205 :
206 : const uno::Reference< text::XTextRange > xRange =
207 : SwXTextRange::CreateXTextRange(
208 0 : *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
209 0 : uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
210 0 : if ( xPropSet.is() )
211 : {
212 0 : for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
213 0 : xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
214 : }
215 :
216 0 : mpTxtNode = pOldTxtNode; // setPropertyValue() modifies this. We restore the old state.
217 :
218 0 : IDocumentContentOperations* pIDCO = mpTxtNode->getIDocumentContentOperations();
219 0 : pIDCO->ReplaceRange( aPaM, aNewText, false );
220 :
221 0 : mpTxtNode = 0;
222 : }
223 :
224 : // text::XFlatParagraph:
225 0 : void SAL_CALL SwXFlatParagraph::changeAttributes(::sal_Int32 nPos, ::sal_Int32 nLen, const css::uno::Sequence< css::beans::PropertyValue > & aAttributes) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
226 : {
227 0 : SolarMutexGuard aGuard;
228 :
229 0 : if ( !mpTxtNode )
230 0 : return;
231 :
232 0 : SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
233 :
234 0 : UnoActionContext aAction( mpTxtNode->GetDoc() );
235 :
236 : const uno::Reference< text::XTextRange > xRange =
237 : SwXTextRange::CreateXTextRange(
238 0 : *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
239 0 : uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
240 0 : if ( xPropSet.is() )
241 : {
242 0 : for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
243 0 : xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
244 : }
245 :
246 0 : mpTxtNode = 0;
247 : }
248 :
249 : // text::XFlatParagraph:
250 0 : css::uno::Sequence< ::sal_Int32 > SAL_CALL SwXFlatParagraph::getLanguagePortions() throw (css::uno::RuntimeException)
251 : {
252 0 : SolarMutexGuard aGuard;
253 0 : return css::uno::Sequence< ::sal_Int32>();
254 : }
255 :
256 : namespace
257 : {
258 : class theSwXFlatParagraphUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXFlatParagraphUnoTunnelId > {};
259 : }
260 :
261 : const uno::Sequence< sal_Int8 >&
262 0 : SwXFlatParagraph::getUnoTunnelId()
263 : {
264 0 : return theSwXFlatParagraphUnoTunnelId::get().getSeq();
265 : }
266 :
267 : sal_Int64 SAL_CALL
268 0 : SwXFlatParagraph::getSomething(
269 : const uno::Sequence< sal_Int8 >& rId)
270 : throw (uno::RuntimeException)
271 : {
272 0 : return sw::UnoTunnelImpl(rId, this);
273 : }
274 :
275 :
276 : /******************************************************************************
277 : * SwXFlatParagraphIterator
278 : ******************************************************************************/
279 :
280 0 : SwXFlatParagraphIterator::SwXFlatParagraphIterator( SwDoc& rDoc, sal_Int32 nType, sal_Bool bAutomatic )
281 : : mpDoc( &rDoc ),
282 : mnType( nType ),
283 : mbAutomatic( bAutomatic ),
284 : mnCurrentNode( 0 ),
285 : mnStartNode( 0 ),
286 0 : mnEndNode( rDoc.GetNodes().Count() ),
287 0 : mbWrapped( sal_False )
288 : {
289 : //mnStartNode = mnCurrentNode = get node from current cursor TODO!
290 :
291 : // register as listener and get notified when document is closed
292 0 : mpDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD )->Add(this);
293 0 : }
294 :
295 0 : SwXFlatParagraphIterator::~SwXFlatParagraphIterator()
296 : {
297 0 : }
298 :
299 :
300 0 : void SwXFlatParagraphIterator::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
301 : {
302 0 : ClientModify( this, pOld, pNew );
303 : // check if document gets closed...
304 0 : if(!GetRegisteredIn())
305 : {
306 0 : SolarMutexGuard aGuard;
307 0 : mpDoc = 0;
308 : }
309 0 : }
310 :
311 :
312 0 : uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getFirstPara()
313 : throw( uno::RuntimeException )
314 : {
315 0 : return getNextPara(); // TODO
316 : }
317 :
318 0 : uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getNextPara()
319 : throw( uno::RuntimeException )
320 : {
321 0 : SolarMutexGuard aGuard;
322 :
323 0 : uno::Reference< text::XFlatParagraph > xRet;
324 0 : if (!mpDoc)
325 : return xRet;
326 :
327 0 : SwTxtNode* pRet = 0;
328 0 : if ( mbAutomatic )
329 : {
330 0 : ViewShell* pViewShell = 0;
331 0 : mpDoc->GetEditShell( &pViewShell );
332 :
333 0 : SwPageFrm* pCurrentPage = pViewShell ? pViewShell->Imp()->GetFirstVisPage() : 0;
334 0 : SwPageFrm* pStartPage = pCurrentPage;
335 0 : SwPageFrm* pStopPage = 0;
336 :
337 0 : while ( pCurrentPage != pStopPage )
338 : {
339 0 : if (mnType != text::TextMarkupType::SPELLCHECK || pCurrentPage->IsInvalidSpelling() )
340 : {
341 : // this method is supposed to return an empty paragraph in case Online Checking is disabled
342 0 : if ( ( mnType == text::TextMarkupType::PROOFREADING || mnType == text::TextMarkupType::SPELLCHECK )
343 0 : && !pViewShell->GetViewOptions()->IsOnlineSpell() )
344 : return xRet;
345 :
346 : // search for invalid content:
347 0 : SwCntntFrm* pCnt = pCurrentPage->ContainsCntnt();
348 :
349 0 : while( pCnt && pCurrentPage->IsAnLower( pCnt ) )
350 : {
351 0 : SwTxtNode* pTxtNode = dynamic_cast<SwTxtNode*>( pCnt->GetNode()->GetTxtNode() );
352 :
353 0 : if ( pTxtNode &&
354 : ((mnType == text::TextMarkupType::SPELLCHECK &&
355 0 : pTxtNode->IsWrongDirty()) ||
356 : (mnType == text::TextMarkupType::PROOFREADING &&
357 0 : pTxtNode->IsGrammarCheckDirty())) )
358 : {
359 0 : pRet = pTxtNode;
360 0 : break;
361 : }
362 :
363 0 : pCnt = pCnt->GetNextCntntFrm();
364 : }
365 : }
366 :
367 0 : if ( pRet )
368 0 : break;
369 :
370 : // if there is no invalid text node on the current page,
371 : // we validate the page
372 0 : pCurrentPage->ValidateSpelling();
373 :
374 : // proceed with next page, wrap at end of document if required:
375 0 : pCurrentPage = static_cast<SwPageFrm*>(pCurrentPage->GetNext());
376 :
377 0 : if ( !pCurrentPage && !pStopPage )
378 : {
379 0 : pStopPage = pStartPage;
380 0 : pCurrentPage = static_cast<SwPageFrm*>(pViewShell->GetLayout()->Lower());
381 : }
382 : }
383 : }
384 : else // non-automatic checking
385 : {
386 0 : const SwNodes& rNodes = mpDoc->GetNodes();
387 0 : const sal_uLong nMaxNodes = rNodes.Count();
388 :
389 0 : while ( mnCurrentNode < mnEndNode && mnCurrentNode < nMaxNodes )
390 : {
391 0 : SwNode* pNd = rNodes[ mnCurrentNode ];
392 :
393 0 : ++mnCurrentNode;
394 :
395 0 : pRet = dynamic_cast<SwTxtNode*>(pNd);
396 0 : if ( pRet )
397 0 : break;
398 :
399 0 : if ( mnCurrentNode == mnEndNode && !mbWrapped )
400 : {
401 0 : mnCurrentNode = 0;
402 0 : mnEndNode = mnStartNode;
403 : }
404 : }
405 : }
406 :
407 0 : if ( pRet )
408 : {
409 : // Expand the string:
410 0 : const ModelToViewHelper aConversionMap(*pRet);
411 0 : rtl::OUString aExpandText = aConversionMap.getViewText();
412 :
413 0 : xRet = new SwXFlatParagraph( *pRet, aExpandText, aConversionMap );
414 : // keep hard references...
415 0 : m_aFlatParaList.insert( xRet );
416 : }
417 :
418 0 : return xRet;
419 : }
420 :
421 0 : uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getLastPara()
422 : throw( uno::RuntimeException )
423 : {
424 0 : return getNextPara();
425 : }
426 :
427 0 : uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaAfter(const uno::Reference< text::XFlatParagraph > & xPara)
428 : throw ( uno::RuntimeException, lang::IllegalArgumentException )
429 : {
430 0 : SolarMutexGuard aGuard;
431 :
432 0 : uno::Reference< text::XFlatParagraph > xRet;
433 0 : if (!mpDoc)
434 : return xRet;
435 :
436 0 : const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
437 : OSL_ASSERT(xFPTunnel.is());
438 0 : SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
439 :
440 0 : if ( !pFlatParagraph )
441 : return xRet;
442 :
443 0 : const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
444 :
445 0 : if ( !pCurrentNode )
446 : return xRet;
447 :
448 0 : SwTxtNode* pNextTxtNode = 0;
449 0 : const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
450 :
451 0 : for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() + 1; nCurrentNode < rNodes.Count(); ++nCurrentNode )
452 : {
453 0 : SwNode* pNd = rNodes[ nCurrentNode ];
454 0 : pNextTxtNode = dynamic_cast<SwTxtNode*>(pNd);
455 0 : if ( pNextTxtNode )
456 0 : break;
457 : }
458 :
459 0 : if ( pNextTxtNode )
460 : {
461 : // Expand the string:
462 0 : const ModelToViewHelper aConversionMap(*pNextTxtNode);
463 0 : rtl::OUString aExpandText = aConversionMap.getViewText();
464 :
465 0 : xRet = new SwXFlatParagraph( *pNextTxtNode, aExpandText, aConversionMap );
466 : // keep hard references...
467 0 : m_aFlatParaList.insert( xRet );
468 : }
469 :
470 0 : return xRet;
471 : }
472 :
473 0 : uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaBefore(const uno::Reference< text::XFlatParagraph > & xPara )
474 : throw ( uno::RuntimeException, lang::IllegalArgumentException )
475 : {
476 0 : SolarMutexGuard aGuard;
477 :
478 0 : uno::Reference< text::XFlatParagraph > xRet;
479 0 : if (!mpDoc)
480 : return xRet;
481 :
482 0 : const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
483 : OSL_ASSERT(xFPTunnel.is());
484 0 : SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
485 :
486 0 : if ( !pFlatParagraph )
487 : return xRet;
488 :
489 0 : const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
490 :
491 0 : if ( !pCurrentNode )
492 : return xRet;
493 :
494 0 : SwTxtNode* pPrevTxtNode = 0;
495 0 : const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
496 :
497 0 : for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() - 1; nCurrentNode > 0; --nCurrentNode )
498 : {
499 0 : SwNode* pNd = rNodes[ nCurrentNode ];
500 0 : pPrevTxtNode = dynamic_cast<SwTxtNode*>(pNd);
501 0 : if ( pPrevTxtNode )
502 0 : break;
503 : }
504 :
505 0 : if ( pPrevTxtNode )
506 : {
507 : // Expand the string:
508 0 : const ModelToViewHelper aConversionMap(*pPrevTxtNode);
509 0 : rtl::OUString aExpandText = aConversionMap.getViewText();
510 :
511 0 : xRet = new SwXFlatParagraph( *pPrevTxtNode, aExpandText, aConversionMap );
512 : // keep hard references...
513 0 : m_aFlatParaList.insert( xRet );
514 : }
515 :
516 0 : return xRet;
517 : }
518 :
519 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|