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