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