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( ) throw(uno::RuntimeException)
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( ) throw(uno::RuntimeException)
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 ) throw(uno::RuntimeException)
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() throw (css::uno::RuntimeException)
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) throw (uno::RuntimeException)
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) throw (css::uno::RuntimeException)
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() throw (uno::RuntimeException)
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 ) throw (uno::RuntimeException)
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 ) throw (uno::RuntimeException)
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() throw (uno::RuntimeException)
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 throw (uno::RuntimeException, lang::IllegalArgumentException)
190 {
191 vos::OGuard aGuard(Application::GetSolarMutex());
192 if (!mpTxtNode)
193 return SvxCreateLocale( LANGUAGE_NONE );
194
195 const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
196 return aLocale;
197 }
198
199 // text::XFlatParagraph:
getPrimaryLanguageOfText(::sal_Int32 nPos,::sal_Int32 nLen)200 lang::Locale SAL_CALL SwXFlatParagraph::getPrimaryLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
201 throw (uno::RuntimeException, lang::IllegalArgumentException)
202 {
203 vos::OGuard aGuard(Application::GetSolarMutex());
204
205 if (!mpTxtNode)
206 return SvxCreateLocale( LANGUAGE_NONE );
207
208 const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
209 return aLocale;
210 }
211
212 // text::XFlatParagraph:
changeText(::sal_Int32 nPos,::sal_Int32 nLen,const::rtl::OUString & aNewText,const css::uno::Sequence<css::beans::PropertyValue> & aAttributes)213 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)
214 {
215 vos::OGuard aGuard(Application::GetSolarMutex());
216
217 if ( !mpTxtNode )
218 return;
219
220 SwTxtNode* pOldTxtNode = mpTxtNode;
221
222 SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
223
224 UnoActionContext aAction( mpTxtNode->GetDoc() );
225
226 const uno::Reference< text::XTextRange > xRange =
227 SwXTextRange::CreateXTextRange(
228 *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
229 uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
230 if ( xPropSet.is() )
231 {
232 for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
233 xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
234 }
235
236 mpTxtNode = pOldTxtNode; // setPropertyValue() modifies this. We restore the old state.
237
238 IDocumentContentOperations* pIDCO = mpTxtNode->getIDocumentContentOperations();
239 pIDCO->ReplaceRange( aPaM, aNewText, false );
240
241 mpTxtNode = 0;
242 }
243
244 // text::XFlatParagraph:
changeAttributes(::sal_Int32 nPos,::sal_Int32 nLen,const css::uno::Sequence<css::beans::PropertyValue> & aAttributes)245 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)
246 {
247 vos::OGuard aGuard(Application::GetSolarMutex());
248
249 if ( !mpTxtNode )
250 return;
251
252 SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
253
254 UnoActionContext aAction( mpTxtNode->GetDoc() );
255
256 const uno::Reference< text::XTextRange > xRange =
257 SwXTextRange::CreateXTextRange(
258 *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
259 uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
260 if ( xPropSet.is() )
261 {
262 for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
263 xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
264 }
265
266 mpTxtNode = 0;
267 }
268
269 // text::XFlatParagraph:
getLanguagePortions()270 css::uno::Sequence< ::sal_Int32 > SAL_CALL SwXFlatParagraph::getLanguagePortions() throw (css::uno::RuntimeException)
271 {
272 vos::OGuard aGuard(Application::GetSolarMutex());
273 return css::uno::Sequence< ::sal_Int32>();
274 }
275
276
277 const uno::Sequence< sal_Int8 >&
getUnoTunnelId()278 SwXFlatParagraph::getUnoTunnelId()
279 {
280 static uno::Sequence<sal_Int8> aSeq(CreateUnoTunnelId());
281 return aSeq;
282 }
283
284
285 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rId)286 SwXFlatParagraph::getSomething(
287 const uno::Sequence< sal_Int8 >& rId)
288 throw (uno::RuntimeException)
289 {
290 return sw::UnoTunnelImpl(rId, this);
291 }
292
293
294 /******************************************************************************
295 * SwXFlatParagraphIterator
296 ******************************************************************************/
297
SwXFlatParagraphIterator(SwDoc & rDoc,sal_Int32 nType,sal_Bool bAutomatic)298 SwXFlatParagraphIterator::SwXFlatParagraphIterator( SwDoc& rDoc, sal_Int32 nType, sal_Bool bAutomatic )
299 : mpDoc( &rDoc ),
300 mnType( nType ),
301 mbAutomatic( bAutomatic ),
302 mnCurrentNode( 0 ),
303 mnStartNode( 0 ),
304 mnEndNode( rDoc.GetNodes().Count() ),
305 mbWrapped( sal_False )
306 {
307 //mnStartNode = mnCurrentNode = get node from current cursor TODO!
308
309 // register as listener and get notified when document is closed
310 mpDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD )->Add(this);
311 }
312
~SwXFlatParagraphIterator()313 SwXFlatParagraphIterator::~SwXFlatParagraphIterator()
314 {
315 }
316
317
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)318 void SwXFlatParagraphIterator::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
319 {
320 ClientModify( this, pOld, pNew );
321 // check if document gets closed...
322 if(!GetRegisteredIn())
323 {
324 vos::OGuard aGuard(Application::GetSolarMutex());
325 mpDoc = 0;
326 }
327 }
328
329
getFirstPara()330 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getFirstPara()
331 throw( uno::RuntimeException )
332 {
333 return getNextPara(); // TODO
334 }
335
getNextPara()336 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getNextPara()
337 throw( uno::RuntimeException )
338 {
339 vos::OGuard aGuard(Application::GetSolarMutex());
340
341 uno::Reference< text::XFlatParagraph > xRet;
342 if (!mpDoc)
343 return xRet;
344
345 SwTxtNode* pRet = 0;
346 if ( mbAutomatic )
347 {
348 ViewShell* pViewShell = 0;
349 mpDoc->GetEditShell( &pViewShell );
350
351 SwPageFrm* pCurrentPage = pViewShell ? pViewShell->Imp()->GetFirstVisPage() : 0;
352 SwPageFrm* pStartPage = pCurrentPage;
353 SwPageFrm* pStopPage = 0;
354
355 while ( pCurrentPage != pStopPage )
356 {
357 if (mnType != text::TextMarkupType::SPELLCHECK || pCurrentPage->IsInvalidSpelling() )
358 {
359 // this method is supposed to return an empty paragraph in case Online Checking is disabled
360 if ( ( mnType == text::TextMarkupType::PROOFREADING || mnType == text::TextMarkupType::SPELLCHECK )
361 && !pViewShell->GetViewOptions()->IsOnlineSpell() )
362 return xRet;
363
364 // search for invalid content:
365 SwCntntFrm* pCnt = pCurrentPage->ContainsCntnt();
366
367 while( pCnt && pCurrentPage->IsAnLower( pCnt ) )
368 {
369 SwTxtNode* pTxtNode = dynamic_cast<SwTxtNode*>( pCnt->GetNode()->GetTxtNode() );
370
371 if ( pTxtNode &&
372 ((mnType == text::TextMarkupType::SPELLCHECK &&
373 pTxtNode->IsWrongDirty()) ||
374 (mnType == text::TextMarkupType::PROOFREADING &&
375 pTxtNode->IsGrammarCheckDirty())) )
376 {
377 pRet = pTxtNode;
378 break;
379 }
380
381 pCnt = pCnt->GetNextCntntFrm();
382 }
383 }
384
385 if ( pRet )
386 break;
387
388 // if there is no invalid text node on the current page,
389 // we validate the page
390 pCurrentPage->ValidateSpelling();
391
392 // proceed with next page, wrap at end of document if required:
393 pCurrentPage = static_cast<SwPageFrm*>(pCurrentPage->GetNext());
394
395 if ( !pCurrentPage && !pStopPage )
396 {
397 pStopPage = pStartPage;
398 pCurrentPage = static_cast<SwPageFrm*>(pViewShell->GetLayout()->Lower());
399 }
400 }
401 }
402 else // non-automatic checking
403 {
404 const SwNodes& rNodes = mpDoc->GetNodes();
405 const sal_uLong nMaxNodes = rNodes.Count();
406
407 while ( mnCurrentNode < mnEndNode && mnCurrentNode < nMaxNodes )
408 {
409 SwNode* pNd = rNodes[ mnCurrentNode ];
410
411 ++mnCurrentNode;
412
413 pRet = dynamic_cast<SwTxtNode*>(pNd);
414 if ( pRet )
415 break;
416
417 if ( mnCurrentNode == mnEndNode && !mbWrapped )
418 {
419 mnCurrentNode = 0;
420 mnEndNode = mnStartNode;
421 }
422 }
423 }
424
425 if ( pRet )
426 {
427 // Expand the string:
428 rtl::OUString aExpandText;
429 const ModelToViewHelper::ConversionMap* pConversionMap =
430 pRet->BuildConversionMap( aExpandText );
431
432 xRet = new SwXFlatParagraph( *pRet, aExpandText, pConversionMap );
433 // keep hard references...
434 m_aFlatParaList.insert( xRet );
435 }
436
437 return xRet;
438 }
439
getLastPara()440 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getLastPara()
441 throw( uno::RuntimeException )
442 {
443 return getNextPara();
444 }
445
getParaAfter(const uno::Reference<text::XFlatParagraph> & xPara)446 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaAfter(const uno::Reference< text::XFlatParagraph > & xPara)
447 throw ( uno::RuntimeException, lang::IllegalArgumentException )
448 {
449 vos::OGuard aGuard(Application::GetSolarMutex());
450
451 uno::Reference< text::XFlatParagraph > xRet;
452 if (!mpDoc)
453 return xRet;
454
455 const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
456 OSL_ASSERT(xFPTunnel.is());
457 SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
458
459 if ( !pFlatParagraph )
460 return xRet;
461
462 const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
463
464 if ( !pCurrentNode )
465 return xRet;
466
467 SwTxtNode* pNextTxtNode = 0;
468 const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
469
470 for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() + 1; nCurrentNode < rNodes.Count(); ++nCurrentNode )
471 {
472 SwNode* pNd = rNodes[ nCurrentNode ];
473 pNextTxtNode = dynamic_cast<SwTxtNode*>(pNd);
474 if ( pNextTxtNode )
475 break;
476 }
477
478 if ( pNextTxtNode )
479 {
480 // Expand the string:
481 rtl::OUString aExpandText;
482 const ModelToViewHelper::ConversionMap* pConversionMap =
483 pNextTxtNode->BuildConversionMap( aExpandText );
484
485 xRet = new SwXFlatParagraph( *pNextTxtNode, aExpandText, pConversionMap );
486 // keep hard references...
487 m_aFlatParaList.insert( xRet );
488 }
489
490 return xRet;
491 }
492
getParaBefore(const uno::Reference<text::XFlatParagraph> & xPara)493 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaBefore(const uno::Reference< text::XFlatParagraph > & xPara )
494 throw ( uno::RuntimeException, lang::IllegalArgumentException )
495 {
496 vos::OGuard aGuard(Application::GetSolarMutex());
497
498 uno::Reference< text::XFlatParagraph > xRet;
499 if (!mpDoc)
500 return xRet;
501
502 const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
503 OSL_ASSERT(xFPTunnel.is());
504 SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
505
506 if ( !pFlatParagraph )
507 return xRet;
508
509 const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
510
511 if ( !pCurrentNode )
512 return xRet;
513
514 SwTxtNode* pPrevTxtNode = 0;
515 const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
516
517 for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() - 1; nCurrentNode > 0; --nCurrentNode )
518 {
519 SwNode* pNd = rNodes[ nCurrentNode ];
520 pPrevTxtNode = dynamic_cast<SwTxtNode*>(pNd);
521 if ( pPrevTxtNode )
522 break;
523 }
524
525 if ( pPrevTxtNode )
526 {
527 // Expand the string:
528 rtl::OUString aExpandText;
529 const ModelToViewHelper::ConversionMap* pConversionMap =
530 pPrevTxtNode->BuildConversionMap( aExpandText );
531
532 xRet = new SwXFlatParagraph( *pPrevTxtNode, aExpandText, pConversionMap );
533 // keep hard references...
534 m_aFlatParaList.insert( xRet );
535 }
536
537 return xRet;
538 }
539