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 62 SwXFlatParagraph::SwXFlatParagraph( SwTxtNode& rTxtNode, rtl::OUString aExpandText, const ModelToViewHelper::ConversionMap* pMap ) : 63 SwXTextMarkup( rTxtNode, pMap ), 64 maExpandText( aExpandText ) 65 { 66 } 67 68 SwXFlatParagraph::~SwXFlatParagraph() 69 { 70 } 71 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 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 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 103 void SAL_CALL SwXFlatParagraph::acquire() throw() 104 { 105 SwXTextMarkup::acquire(); 106 } 107 108 void SAL_CALL SwXFlatParagraph::release() throw() 109 { 110 SwXTextMarkup::release(); 111 } 112 113 const SwTxtNode* SwXFlatParagraph::getTxtNode() const 114 { 115 return mpTxtNode; 116 } 117 118 css::uno::Reference< css::container::XStringKeyMap > SAL_CALL SwXFlatParagraph::getMarkupInfoContainer() throw (css::uno::RuntimeException) 119 { 120 return SwXTextMarkup::getMarkupInfoContainer(); 121 } 122 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 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: 138 ::rtl::OUString SAL_CALL SwXFlatParagraph::getText() throw (uno::RuntimeException) 139 { 140 return maExpandText; 141 } 142 143 // text::XFlatParagraph: 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: 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: 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: 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: 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: 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: 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: 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 >& 278 SwXFlatParagraph::getUnoTunnelId() 279 { 280 static uno::Sequence<sal_Int8> aSeq(CreateUnoTunnelId()); 281 return aSeq; 282 } 283 284 285 sal_Int64 SAL_CALL 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 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 313 SwXFlatParagraphIterator::~SwXFlatParagraphIterator() 314 { 315 } 316 317 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 330 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getFirstPara() 331 throw( uno::RuntimeException ) 332 { 333 return getNextPara(); // TODO 334 } 335 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 440 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getLastPara() 441 throw( uno::RuntimeException ) 442 { 443 return getNextPara(); 444 } 445 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 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