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( ) 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( ) 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 ) 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() 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) 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) 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() 139 { 140 return maExpandText; 141 } 142 143 // text::XFlatParagraph: 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: 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: 181 ::sal_Bool SAL_CALL SwXFlatParagraph::isModified() 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 { 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: 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: 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: 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: 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 >& 276 SwXFlatParagraph::getUnoTunnelId() 277 { 278 static uno::Sequence<sal_Int8> aSeq(CreateUnoTunnelId()); 279 return aSeq; 280 } 281 282 283 sal_Int64 SAL_CALL 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 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 310 SwXFlatParagraphIterator::~SwXFlatParagraphIterator() 311 { 312 } 313 314 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 327 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getFirstPara() 328 { 329 return getNextPara(); // TODO 330 } 331 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 435 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getLastPara() 436 { 437 return getNextPara(); 438 } 439 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 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