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 #ifdef PRECOMPILED 31 #include "ui_pch.hxx" 32 #endif 33 34 35 #include <hintids.hxx> 36 #ifndef _VIEW_HXX 37 #include <view.hxx> 38 #endif 39 #include <wrtsh.hxx> 40 #include <swundo.hxx> // fuer Undo-Ids 41 #ifndef _GLOBALS_HRC 42 #include <globals.hrc> 43 #endif 44 #include <splargs.hxx> 45 46 47 #ifndef _MSGBOX_HXX //autogen 48 #include <vcl/msgbox.hxx> 49 #endif 50 #include <editeng/unolingu.hxx> 51 #include <editeng/langitem.hxx> 52 #include <editeng/fontitem.hxx> 53 #include <rtl/ustring.hxx> 54 #include <com/sun/star/text/RubyAdjust.hpp> 55 #include <hhcwrp.hxx> 56 #include <sdrhhcwrap.hxx> 57 #include <doc.hxx> 58 #include <docsh.hxx> 59 #include <txatritr.hxx> 60 #include <mdiexp.hxx> // Progress 61 #include <edtwin.hxx> 62 #include <crsskip.hxx> 63 #include <index.hxx> 64 #include <pam.hxx> 65 #include <swcrsr.hxx> 66 #include <viscrs.hxx> 67 #include <ndtxt.hxx> 68 #include <fmtruby.hxx> 69 #include <breakit.hxx> 70 #include <docsh.hxx> 71 72 #ifndef _OLMENU_HRC 73 #include <olmenu.hrc> 74 #endif 75 76 #include <unomid.h> 77 78 using ::rtl::OUString; 79 using namespace ::com::sun::star; 80 using namespace ::com::sun::star::text; 81 using namespace ::com::sun::star::uno; 82 using namespace ::com::sun::star::linguistic2; 83 using namespace ::com::sun::star::i18n; 84 85 #define CHAR_PAR_BRK ((sal_Char) 0x0D) 86 87 ////////////////////////////////////////////////////////////////////// 88 // Beschreibung: Ggf. Rahmen/Objektshell abschalten 89 90 static void lcl_ActivateTextShell( SwWrtShell & rWrtSh ) 91 { 92 if( rWrtSh.IsSelFrmMode() || rWrtSh.IsObjSelected() ) 93 rWrtSh.EnterStdMode(); 94 } 95 96 ////////////////////////////////////////////////////////////////////// 97 98 class SwKeepConversionDirectionStateContext 99 { 100 public: 101 SwKeepConversionDirectionStateContext() 102 { 103 //!! hack to transport the current conversion direction state settings 104 //!! into the next incarnation that iterates over the drawing objets 105 //!! ( see SwHHCWrapper::~SwHHCWrapper() ) 106 editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( sal_True ); 107 } 108 109 ~SwKeepConversionDirectionStateContext() 110 { 111 editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( sal_False ); 112 } 113 }; 114 115 ////////////////////////////////////////////////////////////////////// 116 117 SwHHCWrapper::SwHHCWrapper( 118 SwView* pSwView, 119 const uno::Reference< lang::XMultiServiceFactory >& rxMSF, 120 LanguageType nSourceLanguage, 121 LanguageType nTargetLanguage, 122 const Font *pTargetFont, 123 sal_Int32 nConvOptions, 124 sal_Bool bIsInteractive, 125 sal_Bool bStart, sal_Bool bOther, sal_Bool bSelection ) : 126 editeng::HangulHanjaConversion( &pSwView->GetEditWin(), rxMSF, 127 SvxCreateLocale( nSourceLanguage ), 128 SvxCreateLocale( nTargetLanguage ), 129 pTargetFont, 130 nConvOptions, 131 bIsInteractive ), 132 rWrtShell( pSwView->GetWrtShell() ) 133 { 134 pConvArgs = 0; 135 nLastPos = 0; 136 nUnitOffset = 0; 137 138 pView = pSwView; 139 pWin = &pSwView->GetEditWin(); 140 bIsDrawObj = sal_False; 141 bIsStart = bStart; 142 bIsOtherCntnt = bStartChk = bOther; 143 bIsConvSpecial = sal_True; 144 bIsSelection = bSelection; 145 bInfoBox = sal_False; 146 bStartDone = bOther || bStart; 147 bEndDone = sal_False; 148 // bLastRet = sal_True; 149 nPageCount = nPageStart = 0; 150 } 151 152 153 SwHHCWrapper::~SwHHCWrapper() 154 { 155 delete pConvArgs; 156 157 rWrtShell.SetCareWin( NULL ); 158 159 // check for existence of a draw view which means that there are 160 // (or previously were) draw objects present in the document. 161 // I.e. we like to check those too. 162 if ( IsDrawObj() /*&& bLastRet*/ && pView->GetWrtShell().HasDrawView() ) 163 { 164 Cursor *pSave = pView->GetWindow()->GetCursor(); 165 { 166 SwKeepConversionDirectionStateContext aContext; 167 168 SdrHHCWrapper aSdrConvWrap( pView, GetSourceLanguage(), 169 GetTargetLanguage(), GetTargetFont(), 170 GetConversionOptions(), IsInteractive() ); 171 aSdrConvWrap.StartTextConversion(); 172 } 173 pView->GetWindow()->SetCursor( pSave ); 174 } 175 176 if( nPageCount ) 177 ::EndProgress( pView->GetDocShell() ); 178 179 // finally for chinese translation we need to change the the documents 180 // default language and font to the new ones to be used. 181 LanguageType nTargetLang = GetTargetLanguage(); 182 if (IsChinese( nTargetLang )) 183 { 184 SwDoc *pDoc = pView->GetDocShell()->GetDoc(); 185 186 //!! Note: This also effects the default language of text boxes (EditEngine/EditView) !! 187 pDoc->SetDefault( SvxLanguageItem( nTargetLang, RES_CHRATR_CJK_LANGUAGE ) ); 188 // 189 const Font *pFont = GetTargetFont(); 190 if (pFont) 191 { 192 SvxFontItem aFontItem( pFont->GetFamily(), pFont->GetName(), 193 pFont->GetStyleName(), pFont->GetPitch(), 194 pFont->GetCharSet(), RES_CHRATR_CJK_FONT ); 195 pDoc->SetDefault( aFontItem ); 196 } 197 198 } 199 200 /* 201 if( bInfoBox ) 202 InfoBox(&pView->GetEditWin(), String(SW_RES(STR_SPELL_OK)) ).Execute(); 203 */ 204 } 205 206 207 void SwHHCWrapper::GetNextPortion( 208 ::rtl::OUString& rNextPortion, 209 LanguageType& rLangOfPortion, 210 sal_Bool bAllowChanges ) 211 { 212 pConvArgs->bAllowImplicitChangesForNotConvertibleText = bAllowChanges; 213 214 FindConvText_impl(); 215 rNextPortion = pConvArgs->aConvText; 216 rLangOfPortion = pConvArgs->nConvTextLang; 217 218 nUnitOffset = 0; 219 220 // build last pos from currently selected text 221 SwPaM* pCrsr = rWrtShell.GetCrsr(); 222 nLastPos = pCrsr->Start()->nContent.GetIndex(); 223 } 224 225 226 void SwHHCWrapper::SelectNewUnit_impl( sal_Int32 nUnitStart, sal_Int32 nUnitEnd ) 227 { 228 SwPaM *pCrsr = rWrtShell.GetCrsr(); 229 pCrsr->GetPoint()->nContent = nLastPos; 230 pCrsr->DeleteMark(); 231 232 rWrtShell.Right( CRSR_SKIP_CHARS, /*bExpand*/ sal_False, 233 (sal_uInt16) (nUnitOffset + nUnitStart), sal_True ); 234 pCrsr->SetMark(); 235 rWrtShell.Right( CRSR_SKIP_CHARS, /*bExpand*/ sal_True, 236 (sal_uInt16) (nUnitEnd - nUnitStart), sal_True ); 237 // end selection now. Otherwise SHIFT+HOME (extending the selection) 238 // won't work when the dialog is closed without any replacement. 239 // (see #116346#) 240 rWrtShell.EndSelect(); 241 } 242 243 244 void SwHHCWrapper::HandleNewUnit( 245 const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd ) 246 { 247 DBG_ASSERT( nUnitStart >= 0 && nUnitEnd >= nUnitStart, "wrong arguments" ); 248 if (!(0 <= nUnitStart && nUnitStart <= nUnitEnd)) 249 return; 250 251 lcl_ActivateTextShell( rWrtShell ); 252 253 rWrtShell.StartAllAction(); 254 255 // select current unit 256 SelectNewUnit_impl( nUnitStart, nUnitEnd ); 257 258 rWrtShell.EndAllAction(); 259 } 260 261 262 void SwHHCWrapper::ChangeText( const String &rNewText, 263 const OUString& rOrigText, 264 const uno::Sequence< sal_Int32 > *pOffsets, 265 SwPaM *pCrsr ) 266 { 267 //!! please see also TextConvWrapper::ChangeText with is a modified 268 //!! copy of this code 269 270 DBG_ASSERT( rNewText.Len() != 0, "unexpected empty string" ); 271 if (rNewText.Len() == 0) 272 return; 273 274 if (pOffsets && pCrsr) // try to keep as much attributation as possible ? 275 { 276 // remember cursor start position for later setting of the cursor 277 const SwPosition *pStart = pCrsr->Start(); 278 const xub_StrLen nStartIndex = pStart->nContent.GetIndex(); 279 const SwNodeIndex aStartNodeIndex = pStart->nNode; 280 SwTxtNode *pStartTxtNode = aStartNodeIndex.GetNode().GetTxtNode(); 281 282 const sal_Int32 nIndices = pOffsets->getLength(); 283 const sal_Int32 *pIndices = pOffsets->getConstArray(); 284 xub_StrLen nConvTextLen = rNewText.Len(); 285 xub_StrLen nPos = 0; 286 xub_StrLen nChgPos = STRING_NOTFOUND; 287 xub_StrLen nChgLen = 0; 288 xub_StrLen nConvChgPos = STRING_NOTFOUND; 289 xub_StrLen nConvChgLen = 0; 290 291 // offset to calculate the position in the text taking into 292 // account that text may have been replaced with new text of 293 // different length. Negative values allowed! 294 long nCorrectionOffset = 0; 295 296 DBG_ASSERT(nIndices == 0 || nIndices == nConvTextLen, 297 "mismatch between string length and sequence length!" ); 298 299 // find all substrings that need to be replaced (and only those) 300 while (sal_True) 301 { 302 // get index in original text that matches nPos in new text 303 xub_StrLen nIndex; 304 if (nPos < nConvTextLen) 305 nIndex = (sal_Int32) nPos < nIndices ? (xub_StrLen) pIndices[nPos] : nPos; 306 else 307 { 308 nPos = nConvTextLen; 309 nIndex = static_cast< xub_StrLen >( rOrigText.getLength() ); 310 } 311 312 if (rOrigText.getStr()[nIndex] == rNewText.GetChar(nPos) || 313 nPos == nConvTextLen /* end of string also terminates non-matching char sequence */) 314 { 315 // substring that needs to be replaced found? 316 if (nChgPos != STRING_NOTFOUND && nConvChgPos != STRING_NOTFOUND) 317 { 318 nChgLen = nIndex - nChgPos; 319 nConvChgLen = nPos - nConvChgPos; 320 #ifdef DEBUG 321 String aInOrig( rOrigText.copy( nChgPos, nChgLen ) ); 322 #endif 323 String aInNew( rNewText.Copy( nConvChgPos, nConvChgLen ) ); 324 325 // set selection to sub string to be replaced in original text 326 xub_StrLen nChgInNodeStartIndex = static_cast< xub_StrLen >( nStartIndex + nCorrectionOffset + nChgPos ); 327 DBG_ASSERT( rWrtShell.GetCrsr()->HasMark(), "cursor misplaced (nothing selected)" ); 328 rWrtShell.GetCrsr()->GetMark()->nContent.Assign( pStartTxtNode, nChgInNodeStartIndex ); 329 rWrtShell.GetCrsr()->GetPoint()->nContent.Assign( pStartTxtNode, nChgInNodeStartIndex + nChgLen ); 330 #ifdef DEBUG 331 String aSelTxt1( rWrtShell.GetSelTxt() ); 332 #endif 333 334 // replace selected sub string with the corresponding 335 // sub string from the new text while keeping as 336 // much from the attributes as possible 337 ChangeText_impl( aInNew, sal_True ); 338 339 nCorrectionOffset += nConvChgLen - nChgLen; 340 341 nChgPos = STRING_NOTFOUND; 342 nConvChgPos = STRING_NOTFOUND; 343 } 344 } 345 else 346 { 347 // begin of non-matching char sequence found ? 348 if (nChgPos == STRING_NOTFOUND && nConvChgPos == STRING_NOTFOUND) 349 { 350 nChgPos = nIndex; 351 nConvChgPos = nPos; 352 } 353 } 354 if (nPos >= nConvTextLen) 355 break; 356 ++nPos; 357 } 358 359 // set cursor to the end of all the new text 360 // (as it would happen after ChangeText_impl (Delete and Insert) 361 // of the whole text in the 'else' branch below) 362 rWrtShell.ClearMark(); 363 rWrtShell.GetCrsr()->Start()->nContent.Assign( pStartTxtNode, nStartIndex + nConvTextLen ); 364 } 365 else 366 { 367 ChangeText_impl( rNewText, sal_False ); 368 } 369 } 370 371 372 void SwHHCWrapper::ChangeText_impl( const String &rNewText, sal_Bool bKeepAttributes ) 373 { 374 if (bKeepAttributes) 375 { 376 // get item set with all relevant attributes 377 sal_uInt16 aRanges[] = { 378 RES_CHRATR_BEGIN, RES_FRMATR_END, 379 0, 0, 0 }; 380 SfxItemSet aItemSet( rWrtShell.GetAttrPool(), aRanges ); 381 // get all attributes spanning the whole selection in order to 382 // restore those for the new text 383 rWrtShell.GetCurAttr( aItemSet ); 384 385 #ifdef DEBUG 386 String aSelTxt1( rWrtShell.GetSelTxt() ); 387 #endif 388 rWrtShell.Delete(); 389 rWrtShell.Insert( rNewText ); 390 391 // select new inserted text (currently the Point is right after the new text) 392 if (!rWrtShell.GetCrsr()->HasMark()) 393 rWrtShell.GetCrsr()->SetMark(); 394 SwPosition *pMark = rWrtShell.GetCrsr()->GetMark(); 395 pMark->nContent = pMark->nContent.GetIndex() - rNewText.Len(); 396 #ifdef DEBUG 397 String aSelTxt2( rWrtShell.GetSelTxt() ); 398 #endif 399 400 // since 'SetAttr' below functions like merging with the attributes 401 // from the itemset with any existing ones we have to get rid of all 402 // all attributes now. (Those attributes that may take effect left 403 // to the position where the new text gets inserted after the old text 404 // was deleted) 405 rWrtShell.ResetAttr(); 406 // apply previously saved attributes to new text 407 rWrtShell.SetAttr( aItemSet ); 408 } 409 else 410 { 411 rWrtShell.Delete(); 412 rWrtShell.Insert( rNewText ); 413 } 414 } 415 416 417 void SwHHCWrapper::ReplaceUnit( 418 const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd, 419 const ::rtl::OUString& rOrigText, 420 const OUString& rReplaceWith, 421 const uno::Sequence< sal_Int32 > &rOffsets, 422 ReplacementAction eAction, 423 LanguageType *pNewUnitLanguage ) 424 { 425 static OUString aBracketedStart( C2U( "(" ) ); 426 static OUString aBracketedEnd( C2U( ")" ) ); 427 428 DBG_ASSERT( nUnitStart >= 0 && nUnitEnd >= nUnitStart, "wrong arguments" ); 429 if (!(nUnitStart >= 0 && nUnitEnd >= nUnitStart)) 430 return; 431 432 lcl_ActivateTextShell( rWrtShell ); 433 434 // Das aktuelle Wort austauschen 435 rWrtShell.StartAllAction(); 436 437 // select current unit 438 SelectNewUnit_impl( nUnitStart, nUnitEnd ); 439 440 OUString aOrigTxt( rWrtShell.GetSelTxt() ); 441 OUString aNewTxt( rReplaceWith ); 442 DBG_ASSERT( aOrigTxt == rOrigText, "!! text mismatch !!" ); 443 SwFmtRuby *pRuby = 0; 444 sal_Bool bRubyBelow = sal_False; 445 String aNewOrigText; 446 switch (eAction) 447 { 448 case eExchange : 449 break; 450 case eReplacementBracketed : 451 { 452 (((aNewTxt = aOrigTxt) += aBracketedStart) += rReplaceWith) += aBracketedEnd; 453 } 454 break; 455 case eOriginalBracketed : 456 { 457 (((aNewTxt = rReplaceWith) += aBracketedStart) += aOrigTxt) += aBracketedEnd; 458 } 459 break; 460 case eReplacementAbove : 461 { 462 pRuby = new SwFmtRuby( rReplaceWith ); 463 } 464 break; 465 case eOriginalAbove : 466 { 467 pRuby = new SwFmtRuby( aOrigTxt ); 468 aNewOrigText = rReplaceWith; 469 } 470 break; 471 case eReplacementBelow : 472 { 473 pRuby = new SwFmtRuby( rReplaceWith ); 474 bRubyBelow = sal_True; 475 } 476 break; 477 case eOriginalBelow : 478 { 479 pRuby = new SwFmtRuby( aOrigTxt ); 480 aNewOrigText = rReplaceWith; 481 bRubyBelow = sal_True; 482 } 483 break; 484 default: 485 DBG_ERROR( "unexpected case" ); 486 } 487 nUnitOffset += nUnitStart + aNewTxt.getLength(); 488 489 if (pRuby) 490 { 491 rWrtShell.StartUndo( UNDO_SETRUBYATTR ); 492 if (aNewOrigText.Len()) 493 { 494 // according to FT we currently should not bother about keeping 495 // attributes in Hangul/Hanja conversion 496 ChangeText( aNewOrigText, rOrigText, NULL, NULL ); 497 498 //!! since Delete, Insert in 'ChangeText' do not set the WrtShells 499 //!! bInSelect flag 500 //!! back to false we do it now manually in order for the selection 501 //!! to be done properly in the following call to Left. 502 // We didn't fix it in Delete and Insert since it is currently 503 // unclear if someone depends on this incorrect behvaiour 504 // of the flag. 505 rWrtShell.EndSelect(); 506 507 rWrtShell.Left( 0, sal_True, aNewOrigText.Len(), sal_True, sal_True ); 508 } 509 510 pRuby->SetPosition( bRubyBelow ); 511 pRuby->SetAdjustment( RubyAdjust_CENTER ); 512 //!! the following seem not to be needed 513 //pRuby->SetCharFmtName( const String& rNm ); 514 //pRuby->SetCharFmtId( sal_uInt16 nNew ); 515 #ifdef DEBUG 516 SwPaM *pPaM = rWrtShell.GetCrsr(); 517 (void)pPaM; 518 #endif 519 rWrtShell.SetAttr(*pRuby); 520 delete pRuby; 521 rWrtShell.EndUndo( UNDO_SETRUBYATTR ); 522 } 523 else 524 { 525 rWrtShell.StartUndo( UNDO_OVERWRITE ); 526 527 // according to FT we should currently not bother about keeping 528 // attributes in Hangul/Hanja conversion and leave that untouched. 529 // Thus we do this only for Chinese translation... 530 sal_Bool bIsChineseConversion = IsChinese( GetSourceLanguage() ); 531 if (bIsChineseConversion) 532 ChangeText( aNewTxt, rOrigText, &rOffsets, rWrtShell.GetCrsr() ); 533 else 534 ChangeText( aNewTxt, rOrigText, NULL, NULL ); 535 536 // change language and font if necessary 537 if (bIsChineseConversion) 538 { 539 rWrtShell.SetMark(); 540 rWrtShell.GetCrsr()->GetMark()->nContent -= (xub_StrLen) aNewTxt.getLength(); 541 542 DBG_ASSERT( GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED || GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL, 543 "SwHHCWrapper::ReplaceUnit : unexpected target language" ); 544 545 sal_uInt16 aRanges[] = { 546 RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, 547 RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT, 548 0, 0, 0 }; 549 550 SfxItemSet aSet( rWrtShell.GetAttrPool(), aRanges ); 551 if (pNewUnitLanguage) 552 { 553 //DBG_ASSERT(!IsSimilarChinese( *pNewUnitLanguage, nOldLang ), 554 // "similar language should not be changed!"); 555 aSet.Put( SvxLanguageItem( *pNewUnitLanguage, RES_CHRATR_CJK_LANGUAGE ) ); 556 } 557 558 const Font *pTargetFont = GetTargetFont(); 559 DBG_ASSERT( pTargetFont, "target font missing?" ); 560 if (pTargetFont && pNewUnitLanguage) 561 { 562 SvxFontItem aFontItem = (SvxFontItem&) aSet.Get( RES_CHRATR_CJK_FONT ); 563 aFontItem.SetFamilyName( pTargetFont->GetName()); 564 aFontItem.SetFamily( pTargetFont->GetFamily()); 565 aFontItem.SetStyleName( pTargetFont->GetStyleName()); 566 aFontItem.SetPitch( pTargetFont->GetPitch()); 567 aFontItem.SetCharSet( pTargetFont->GetCharSet() ); 568 aSet.Put( aFontItem ); 569 } 570 571 rWrtShell.SetAttr( aSet ); 572 573 rWrtShell.ClearMark(); 574 } 575 576 rWrtShell.EndUndo( UNDO_OVERWRITE ); 577 } 578 579 rWrtShell.EndAllAction(); 580 } 581 582 583 sal_Bool SwHHCWrapper::HasRubySupport() const 584 { 585 return sal_True; 586 } 587 588 589 void SwHHCWrapper::Convert() 590 { 591 DBG_ASSERT( pConvArgs == 0, "NULL pointer expected" ); 592 { 593 SwPaM *pCrsr = pView->GetWrtShell().GetCrsr(); 594 SwPosition* pSttPos = pCrsr->Start(); 595 SwPosition* pEndPos = pCrsr->End(); 596 597 598 if (pSttPos->nNode.GetNode().IsTxtNode() && 599 pEndPos->nNode.GetNode().IsTxtNode()) 600 { 601 pConvArgs = new SwConversionArgs( GetSourceLanguage(), 602 pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent, 603 pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent ); 604 } 605 else // we are not in the text (maybe a graphic or OLE object is selected) let's start from the top 606 { 607 // get PaM that points to the start of the document 608 SwNode& rNode = pView->GetDocShell()->GetDoc()->GetNodes().GetEndOfContent(); 609 SwPaM aPam(rNode); 610 aPam.Move( fnMoveBackward, fnGoDoc ); // move to start of document 611 612 pSttPos = aPam.GetPoint(); //! using a PaM here makes sure we will get only text nodes 613 SwTxtNode *pTxtNode = pSttPos->nNode.GetNode().GetTxtNode(); 614 // just in case we check anyway... 615 if (!pTxtNode || !pTxtNode->IsTxtNode()) 616 return; 617 pConvArgs = new SwConversionArgs( GetSourceLanguage(), 618 pTxtNode, pSttPos->nContent, 619 pTxtNode, pSttPos->nContent ); 620 } 621 DBG_ASSERT( pConvArgs->pStartNode && pConvArgs->pStartNode->IsTxtNode(), 622 "failed to get proper start text node" ); 623 DBG_ASSERT( pConvArgs->pEndNode && pConvArgs->pEndNode->IsTxtNode(), 624 "failed to get proper end text node" ); 625 626 // chinese conversion specific settings 627 DBG_ASSERT( IsChinese( GetSourceLanguage() ) == IsChinese( GetTargetLanguage() ), 628 "source and target language mismatch?" ); 629 if (IsChinese( GetTargetLanguage() )) 630 { 631 pConvArgs->nConvTargetLang = GetTargetLanguage(); 632 pConvArgs->pTargetFont = GetTargetFont(); 633 pConvArgs->bAllowImplicitChangesForNotConvertibleText = sal_True; 634 } 635 636 // if it is not just a selection and we are about to begin 637 // with the current conversion for the very first time 638 // we need to find the start of the current (initial) 639 // convertible unit in order for the text conversion to give 640 // the correct result for that. Since it is easier to obtain 641 // the start of the word we use that though. 642 if (!pCrsr->HasMark()) // is not a selection? 643 { 644 // since #118246 / #117803 still occurs if the cursor is placed 645 // between the two chinese characters to be converted (because both 646 // of them are words on their own!) using the word boundary here does 647 // not work. Thus since chinese conversion is not interactive we start 648 // at the begin of the paragraph to solve the problem, i.e. have the 649 // TextConversion service get those charcters together in the same call. 650 xub_StrLen nStartIdx = STRING_MAXLEN; 651 if (editeng::HangulHanjaConversion::IsChinese( GetSourceLanguage() ) ) 652 nStartIdx = 0; 653 else 654 { 655 OUString aText( pConvArgs->pStartNode->GetTxt() ); 656 long nPos = pConvArgs->pStartIdx->GetIndex(); 657 Boundary aBoundary( pBreakIt->GetBreakIter()-> 658 getWordBoundary( aText, nPos, pBreakIt->GetLocale( pConvArgs->nConvSrcLang ), 659 WordType::DICTIONARY_WORD, sal_True ) ); 660 661 // valid result found? 662 if (aBoundary.startPos < aText.getLength() && 663 aBoundary.startPos != aBoundary.endPos) 664 { 665 nStartIdx = static_cast< xub_StrLen >(aBoundary.startPos ); 666 } 667 } 668 669 if (STRING_MAXLEN != nStartIdx) 670 *pConvArgs->pStartIdx = nStartIdx; 671 } 672 } 673 674 if ( bIsOtherCntnt ) 675 ConvStart_impl( pConvArgs, SVX_SPELL_OTHER ); 676 else 677 { 678 bStartChk = sal_False; 679 ConvStart_impl( pConvArgs, SVX_SPELL_BODY_END ); 680 } 681 682 ConvertDocument(); 683 684 ConvEnd_impl( pConvArgs ); 685 } 686 687 688 sal_Bool SwHHCWrapper::ConvNext_impl( ) 689 { 690 //! modified version of SvxSpellWrapper::SpellNext 691 692 // Keine Richtungsaenderung, also ist der gewuenschte Bereich ( bStartChk ) 693 // vollstaendig abgearbeitet. 694 if( bStartChk ) 695 bStartDone = sal_True; 696 else 697 bEndDone = sal_True; 698 699 if( bIsOtherCntnt && bStartDone && bEndDone ) // Dokument komplett geprueft? 700 { 701 bInfoBox = sal_True; 702 return sal_False; 703 } 704 705 //ResMgr* pMgr = DIALOG_MGR(); 706 sal_Bool bGoOn = sal_False; 707 708 if ( bIsOtherCntnt ) 709 { 710 bStartChk = sal_False; 711 ConvStart_impl( pConvArgs, SVX_SPELL_BODY ); 712 bGoOn = sal_True; 713 } 714 else if ( bStartDone && bEndDone ) 715 { 716 // Bodybereich erledigt, Frage nach Sonderbereich 717 if( bIsConvSpecial && HasOtherCnt_impl() ) 718 { 719 ConvStart_impl( pConvArgs, SVX_SPELL_OTHER ); 720 bIsOtherCntnt = bGoOn = sal_True; 721 } 722 else 723 bInfoBox = sal_True; 724 } 725 else 726 { 727 // Ein BODY_Bereich erledigt, Frage nach dem anderen BODY_Bereich 728 /* 729 //pWin->LeaveWait(); 730 731 sal_uInt16 nResId = RID_SVXQB_CONTINUE; 732 QueryBox aBox( pWin, ResId( nResId, pMgr ) ); 733 if ( aBox.Execute() != RET_YES ) 734 { 735 // Verzicht auf den anderen Bereich, ggf. Frage nach Sonderbereich 736 //pWin->EnterWait(); 737 bStartDone = bEndDone = sal_True; 738 return SpellNext(); 739 } 740 else 741 { 742 */ 743 bStartChk = !bStartDone; 744 ConvStart_impl( pConvArgs, bStartChk ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END ); 745 bGoOn = sal_True; 746 /* 747 } 748 pWin->EnterWait(); 749 */ 750 } 751 return bGoOn; 752 } 753 754 755 sal_Bool SwHHCWrapper::FindConvText_impl() 756 { 757 //! modified version of SvxSpellWrapper::FindSpellError 758 759 //ShowLanguageErrors(); 760 761 sal_Bool bFound = sal_False; 762 763 pWin->EnterWait(); 764 sal_Bool bConv = sal_True; 765 766 while ( bConv ) 767 { 768 bFound = ConvContinue_impl( pConvArgs ); 769 if (bFound) 770 { 771 bConv = sal_False; 772 } 773 else 774 { 775 ConvEnd_impl( pConvArgs ); 776 bConv = ConvNext_impl(); 777 } 778 } 779 pWin->LeaveWait(); 780 return bFound; 781 } 782 783 784 sal_Bool SwHHCWrapper::HasOtherCnt_impl() 785 { 786 return bIsSelection ? sal_False : rWrtShell.HasOtherCnt(); 787 } 788 789 790 void SwHHCWrapper::ConvStart_impl( SwConversionArgs /* [out] */ *pConversionArgs, SvxSpellArea eArea ) 791 { 792 SetDrawObj( SVX_SPELL_OTHER == eArea ); 793 pView->SpellStart( eArea, bStartDone, bEndDone, /* [out] */ pConversionArgs ); 794 } 795 796 797 void SwHHCWrapper::ConvEnd_impl( SwConversionArgs *pConversionArgs ) 798 { 799 pView->SpellEnd( pConversionArgs ); 800 //ShowLanguageErrors(); 801 } 802 803 804 sal_Bool SwHHCWrapper::ConvContinue_impl( SwConversionArgs *pConversionArgs ) 805 { 806 sal_Bool bProgress = !bIsDrawObj && !bIsSelection; 807 // bLastRet = aConvText.getLength() == 0; 808 pConversionArgs->aConvText = OUString(); 809 pConversionArgs->nConvTextLang = LANGUAGE_NONE; 810 uno::Any aRet = bProgress ? 811 pView->GetWrtShell().SpellContinue( &nPageCount, &nPageStart, pConversionArgs ) : 812 pView->GetWrtShell().SpellContinue( &nPageCount, NULL, pConversionArgs ); 813 //aRet >>= aConvText; 814 return pConversionArgs->aConvText.getLength() != 0; 815 } 816 817 ////////////////////////////////////////////////////////////////////// 818 819