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